mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Merge from HEAD into WCM-DEV2. Also fixes build breakage in
jndi-client and catalina-virtual that I introduced earlier. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/WCM-DEV2/root@3393 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -266,11 +266,18 @@ public class AlfrescoNavigationHandler extends NavigationHandler
|
||||
|
||||
if (dispatchContext != null)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Using dispatch context for dialog lookup: " +
|
||||
dispatchContext.getType().toString());
|
||||
|
||||
// use the node to perform the lookup (this will include the global section)
|
||||
config = configSvc.getConfig(dispatchContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Looking up dialog in global config");
|
||||
|
||||
// just use the global
|
||||
config = configSvc.getGlobalConfig();
|
||||
}
|
||||
@@ -306,11 +313,18 @@ public class AlfrescoNavigationHandler extends NavigationHandler
|
||||
|
||||
if (dispatchContext != null)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Using dispatch context for wizard lookup: " +
|
||||
dispatchContext.getType().toString());
|
||||
|
||||
// use the node to perform the lookup (this will include the global section)
|
||||
config = configSvc.getConfig(dispatchContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Looking up wizard in global config");
|
||||
|
||||
// just use the global
|
||||
config = configSvc.getGlobalConfig();
|
||||
}
|
||||
|
@@ -38,6 +38,7 @@ import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.web.app.servlet.AuthenticationHelper;
|
||||
import org.alfresco.web.app.servlet.FacesHelper;
|
||||
import org.alfresco.web.bean.ErrorBean;
|
||||
import org.alfresco.web.bean.dashboard.DashboardManager;
|
||||
import org.alfresco.web.bean.dialog.DialogManager;
|
||||
import org.alfresco.web.bean.repository.User;
|
||||
import org.alfresco.web.bean.wizard.WizardManager;
|
||||
@@ -189,6 +190,16 @@ public class Application
|
||||
return (WizardManager)FacesHelper.getManagedBean(FacesContext.getCurrentInstance(), "WizardManager");
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the DashboardManager managed bean
|
||||
*
|
||||
* @return DashboardManager bean
|
||||
*/
|
||||
public static DashboardManager getDashboardManager()
|
||||
{
|
||||
return (DashboardManager)FacesHelper.getManagedBean(FacesContext.getCurrentInstance(), "DashboardManager");
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the configured error page for the application
|
||||
*
|
||||
|
@@ -66,10 +66,10 @@ public abstract class BaseServlet extends HttpServlet
|
||||
static
|
||||
{
|
||||
validRedirectJSPs.add("/jsp/browse/browse.jsp");
|
||||
validRedirectJSPs.add("/jsp/browse/dashboard.jsp");
|
||||
validRedirectJSPs.add("/jsp/admin/admin-console.jsp");
|
||||
validRedirectJSPs.add("/jsp/admin/node-browser.jsp");
|
||||
validRedirectJSPs.add("/jsp/admin/store-browser.jsp");
|
||||
validRedirectJSPs.add("/jsp/users/user-console.jsp");
|
||||
validRedirectJSPs.add("/jsp/categories/categories.jsp");
|
||||
validRedirectJSPs.add("/jsp/dialog/about.jsp");
|
||||
validRedirectJSPs.add("/jsp/dialog/advanced-search.jsp");
|
||||
@@ -77,6 +77,7 @@ public abstract class BaseServlet extends HttpServlet
|
||||
validRedirectJSPs.add("/jsp/forums/forums.jsp");
|
||||
validRedirectJSPs.add("/jsp/users/users.jsp");
|
||||
validRedirectJSPs.add("/jsp/trashcan/trash-list.jsp");
|
||||
validRedirectJSPs.add("/jsp/dashboards/container.jsp");
|
||||
}
|
||||
|
||||
private static Log logger = LogFactory.getLog(BaseServlet.class);
|
||||
@@ -103,8 +104,22 @@ public abstract class BaseServlet extends HttpServlet
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public AuthenticationStatus servletAuthenticate(HttpServletRequest req, HttpServletResponse res)
|
||||
public AuthenticationStatus servletAuthenticate(HttpServletRequest req, HttpServletResponse res)
|
||||
throws IOException
|
||||
{
|
||||
return servletAuthenticate(req, res, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform an authentication for the servlet request URI. Processing any "ticket" or
|
||||
* "guest" URL arguments.
|
||||
*
|
||||
* @return AuthenticationStatus
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public AuthenticationStatus servletAuthenticate(HttpServletRequest req, HttpServletResponse res,
|
||||
boolean redirectToLoginPage) throws IOException
|
||||
{
|
||||
AuthenticationStatus status;
|
||||
|
||||
@@ -124,9 +139,9 @@ public abstract class BaseServlet extends HttpServlet
|
||||
}
|
||||
status = AuthenticationHelper.authenticate(getServletContext(), req, res, forceGuest);
|
||||
}
|
||||
if (status == AuthenticationStatus.Failure)
|
||||
if (status == AuthenticationStatus.Failure && redirectToLoginPage)
|
||||
{
|
||||
// authentication failed - now need to display the login page to the user
|
||||
// authentication failed - now need to display the login page to the user, if asked to
|
||||
redirectToLoginPage(req, res, getServletContext());
|
||||
}
|
||||
|
||||
|
@@ -47,7 +47,7 @@ import org.apache.commons.logging.LogFactory;
|
||||
* The 'processor-name' identifies the command processor to execute the command. For example the
|
||||
* 'workflow' processor will execute workflow commands upon a node (e.g. "approve" or "reject").
|
||||
* For example:
|
||||
* <pre>/alfresco/command/workflow/approve/workspace/SpacesStore/0000-0000-0000-0000
|
||||
* <pre>/alfresco/command/workflow/approve/workspace/SpacesStore/0000-0000-0000-0000</pre>
|
||||
* The store protocol, followed by the store ID, followed by the content Node Id used to
|
||||
* identify the node to execute the workflow action upon.
|
||||
* <p>
|
||||
|
@@ -261,7 +261,8 @@ public class TemplateContentServlet extends BaseServlet
|
||||
private Object getModel(ServiceRegistry services, HttpServletRequest req, NodeRef templateRef, NodeRef nodeRef)
|
||||
{
|
||||
// build FreeMarker default model and merge
|
||||
Map root = DefaultModelHelper.buildDefaultModel(services, Application.getCurrentUser(req.getSession()));
|
||||
Map root = DefaultModelHelper.buildDefaultModel(
|
||||
services, Application.getCurrentUser(req.getSession()), templateRef);
|
||||
|
||||
// put the current NodeRef in as "space" and "document"
|
||||
TemplateNode node = new TemplateNode(nodeRef, services, this.imageResolver);
|
||||
|
@@ -0,0 +1,37 @@
|
||||
package org.alfresco.web.app.servlet.ajax;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* Interface for all Ajax commands executed by this servlet.
|
||||
*
|
||||
* The method is responsible for invoking the underlying managed bean
|
||||
* and dealing with the response.
|
||||
*
|
||||
* @author gavinc
|
||||
*/
|
||||
public interface AjaxCommand
|
||||
{
|
||||
/**
|
||||
* Invokes the relevant method on the bean represented by the given
|
||||
* expression. Parameters required to call the method can be retrieved
|
||||
* from the request.
|
||||
*
|
||||
* Currently the content type of the response will always be text/html, in the
|
||||
* future sublcasses may provide a mechanism to allow the content type to be set
|
||||
* dynamically.
|
||||
*
|
||||
* @param facesContext FacesContext
|
||||
* @param expression The binding expression
|
||||
* @param request The request
|
||||
* @param response The response
|
||||
*/
|
||||
public abstract void execute(FacesContext facesContext, String expression,
|
||||
HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException;
|
||||
}
|
184
source/java/org/alfresco/web/app/servlet/ajax/AjaxServlet.java
Normal file
184
source/java/org/alfresco/web/app/servlet/ajax/AjaxServlet.java
Normal file
@@ -0,0 +1,184 @@
|
||||
package org.alfresco.web.app.servlet.ajax;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.web.app.servlet.AuthenticationStatus;
|
||||
import org.alfresco.web.app.servlet.BaseServlet;
|
||||
import org.alfresco.web.app.servlet.FacesHelper;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Servlet responsible for processing AJAX requests.
|
||||
*
|
||||
* The URL to the servlet should be in the form:
|
||||
* <pre>/alfresco/ajax/command/Bean.binding.expression</pre>
|
||||
* <p>
|
||||
* See http://wiki.alfresco.com/wiki/AJAX_Support for details.
|
||||
* <p>
|
||||
* Like most Alfresco servlets, the URL may be followed by a valid 'ticket' argument for authentication:
|
||||
* ?ticket=1234567890
|
||||
*
|
||||
* @author gavinc
|
||||
*/
|
||||
public class AjaxServlet extends BaseServlet
|
||||
{
|
||||
public static final String AJAX_LOG_KEY = "alfresco.ajax";
|
||||
|
||||
protected enum Command { invoke, get, set};
|
||||
|
||||
private static final long serialVersionUID = -7654769105419391840L;
|
||||
private static Log logger = LogFactory.getLog(AJAX_LOG_KEY);
|
||||
private static Log headersLogger = LogFactory.getLog(AJAX_LOG_KEY + ".headers");
|
||||
private static Log perfLogger = LogFactory.getLog(AJAX_LOG_KEY + ".performance");
|
||||
|
||||
/**
|
||||
* @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
|
||||
*/
|
||||
protected void service(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException
|
||||
{
|
||||
long startTime = 0;
|
||||
|
||||
try
|
||||
{
|
||||
String uri = request.getRequestURI();
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
String queryString = request.getQueryString();
|
||||
logger.debug("Processing URL: " + uri +
|
||||
((queryString != null && queryString.length() > 0) ? ("?" + queryString) : ""));
|
||||
}
|
||||
|
||||
// dump the request headers
|
||||
if (headersLogger.isDebugEnabled())
|
||||
{
|
||||
Enumeration headers = request.getHeaderNames();
|
||||
while (headers.hasMoreElements())
|
||||
{
|
||||
String name = (String)headers.nextElement();
|
||||
headersLogger.debug(name + ": " + request.getHeader(name));
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the user is authenticated, if not throw an error to return the
|
||||
// 500 Internal Server Error code back to the client
|
||||
AuthenticationStatus status = servletAuthenticate(request, response, false);
|
||||
if (status == AuthenticationStatus.Failure)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Access Denied: User not authenticated");
|
||||
}
|
||||
|
||||
uri = uri.substring(request.getContextPath().length());
|
||||
StringTokenizer t = new StringTokenizer(uri, "/");
|
||||
int tokenCount = t.countTokens();
|
||||
if (tokenCount < 3)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Servlet URL did not contain all required args: " + uri);
|
||||
}
|
||||
|
||||
// skip the servlet name
|
||||
t.nextToken();
|
||||
|
||||
// retrieve the command from the URL
|
||||
String commandName = t.nextToken();
|
||||
|
||||
// retrieve the binding expression from the URL
|
||||
String expression = t.nextToken();
|
||||
|
||||
// setup the faces context
|
||||
FacesContext facesContext = FacesHelper.getFacesContext(request, response, getServletContext());
|
||||
|
||||
// start a timer
|
||||
if (perfLogger.isDebugEnabled())
|
||||
startTime = System.currentTimeMillis();
|
||||
|
||||
// instantiate the relevant command
|
||||
AjaxCommand command = null;
|
||||
if (Command.invoke.toString().equals(commandName))
|
||||
{
|
||||
command = new InvokeCommand();
|
||||
}
|
||||
else if (Command.get.toString().equals(commandName))
|
||||
{
|
||||
command = new GetCommand();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Unrecognised command received: " + commandName);
|
||||
}
|
||||
|
||||
// execute the command
|
||||
command.execute(facesContext, expression, request, response);
|
||||
}
|
||||
catch (RuntimeException error)
|
||||
{
|
||||
handleError(response, error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// measure the time taken
|
||||
if (perfLogger.isDebugEnabled())
|
||||
{
|
||||
long endTime = System.currentTimeMillis();
|
||||
perfLogger.debug("Time to execute command: " + (endTime - startTime) + "ms");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles any error that occurs during the execution of the servlet
|
||||
*
|
||||
* @param response The response
|
||||
* @param cause The cause of the error
|
||||
*/
|
||||
protected void handleError(HttpServletResponse response, RuntimeException cause)
|
||||
throws ServletException, IOException
|
||||
{
|
||||
// if we can send back the 500 error with the error from the top of the
|
||||
// stack as the error status message.
|
||||
|
||||
// NOTE: if we use the built in support for generating error pages for
|
||||
// 500 errors we can tailor the output for AJAX calls so that the
|
||||
// body of the response can be used to show the error details.
|
||||
|
||||
if (!response.isCommitted())
|
||||
{
|
||||
// dump the error if debugging is enabled
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.error(cause);
|
||||
Throwable theCause = cause.getCause();
|
||||
if (theCause != null)
|
||||
{
|
||||
logger.error("caused by: ", theCause);
|
||||
}
|
||||
}
|
||||
|
||||
// extract a message from the exception
|
||||
String msg = cause.getMessage();
|
||||
if (msg == null)
|
||||
{
|
||||
msg = cause.toString();
|
||||
}
|
||||
|
||||
// send the error
|
||||
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
// the response has already been comitted, not much we can do but
|
||||
// let the error through and let the container deal with it
|
||||
throw cause;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,19 @@
|
||||
package org.alfresco.web.app.servlet.ajax;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Base class for all Ajax based commands
|
||||
*
|
||||
* @author gavinc
|
||||
*/
|
||||
public abstract class BaseAjaxCommand implements AjaxCommand
|
||||
{
|
||||
protected static Log logger = LogFactory.getLog(AjaxServlet.AJAX_LOG_KEY);
|
||||
|
||||
public String makeBindingExpression(String expression)
|
||||
{
|
||||
return "#{" + expression + "}";
|
||||
}
|
||||
}
|
@@ -0,0 +1,69 @@
|
||||
package org.alfresco.web.app.servlet.ajax;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.el.ValueBinding;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.transaction.UserTransaction;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.web.bean.repository.Repository;
|
||||
|
||||
/**
|
||||
* Command that executes the given value binding expression.
|
||||
* <p>
|
||||
* This command is intended to be used for calling existing managed
|
||||
* bean methods. The result of the value binding is added to
|
||||
* the response as is i.e. by calling toString().
|
||||
* The content type of the response is always text/html.
|
||||
*
|
||||
* @author gavinc
|
||||
*/
|
||||
public class GetCommand extends BaseAjaxCommand
|
||||
{
|
||||
public void execute(FacesContext facesContext, String expression,
|
||||
HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException
|
||||
{
|
||||
// create the JSF binding expression
|
||||
String bindingExpr = makeBindingExpression(expression);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Retrieving value from value binding: " + bindingExpr);
|
||||
|
||||
UserTransaction tx = null;
|
||||
try
|
||||
{
|
||||
// create the value binding
|
||||
ValueBinding binding = facesContext.getApplication().
|
||||
createValueBinding(bindingExpr);
|
||||
|
||||
if (binding != null)
|
||||
{
|
||||
// setup the transaction
|
||||
tx = Repository.getUserTransaction(facesContext, true);
|
||||
tx.begin();
|
||||
|
||||
// get the value from the value binding
|
||||
Object value = binding.getValue(facesContext);
|
||||
if (value != null)
|
||||
{
|
||||
response.getWriter().write(value.toString());
|
||||
}
|
||||
|
||||
// commit
|
||||
tx.commit();
|
||||
}
|
||||
}
|
||||
catch (Throwable err)
|
||||
{
|
||||
// rollback the transaction
|
||||
try { if (tx != null) {tx.rollback();} } catch (Exception ex) {}
|
||||
|
||||
throw new AlfrescoRuntimeException("Failed to retrieve value: " + err.getMessage(), err);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,97 @@
|
||||
package org.alfresco.web.app.servlet.ajax;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
|
||||
import javax.faces.FactoryFinder;
|
||||
import javax.faces.component.UIViewRoot;
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.context.ResponseWriter;
|
||||
import javax.faces.el.MethodBinding;
|
||||
import javax.faces.render.RenderKit;
|
||||
import javax.faces.render.RenderKitFactory;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.transaction.UserTransaction;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.web.bean.repository.Repository;
|
||||
|
||||
/**
|
||||
* Command that invokes the method represented by the expression.
|
||||
* <p>
|
||||
* The managed bean method called is responsible for writing the response
|
||||
* by getting hold of the JSF ResponseWriter. Parameters can also be
|
||||
* retrieved via the JSF ExternalContext object.
|
||||
* <p>
|
||||
* In a future release (if required) annotations may be used to state
|
||||
* what content type to use for the response.
|
||||
*
|
||||
* @author gavinc
|
||||
*/
|
||||
public class InvokeCommand extends BaseAjaxCommand
|
||||
{
|
||||
public void execute(FacesContext facesContext, String expression,
|
||||
HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException
|
||||
{
|
||||
// setup the JSF response writer.
|
||||
|
||||
// NOTE: it doesn't seem to matter what the content type of the response is (at least with Dojo),
|
||||
// it determines it's behaviour from the mimetype specified in the AJAX call on the client,
|
||||
// therefore, for now we will always return a content type of text/html.
|
||||
// In the future we may use annotations on the method to be called to specify what content
|
||||
// type should be used for the response.
|
||||
|
||||
OutputStream os = response.getOutputStream();
|
||||
UIViewRoot viewRoot = facesContext.getViewRoot();
|
||||
RenderKitFactory renderFactory = (RenderKitFactory)FactoryFinder.
|
||||
getFactory(FactoryFinder.RENDER_KIT_FACTORY);
|
||||
RenderKit renderKit = renderFactory.getRenderKit(facesContext,
|
||||
viewRoot.getRenderKitId());
|
||||
ResponseWriter writer = renderKit.createResponseWriter(
|
||||
new OutputStreamWriter(os), MimetypeMap.MIMETYPE_HTML, "UTF-8");
|
||||
facesContext.setResponseWriter(writer);
|
||||
response.setContentType(writer.getContentType());
|
||||
|
||||
// create the JSF binding expression
|
||||
String bindingExpr = makeBindingExpression(expression);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Invoking method represented by " + bindingExpr);
|
||||
|
||||
UserTransaction tx = null;
|
||||
try
|
||||
{
|
||||
// create the method binding from the expression
|
||||
MethodBinding binding = facesContext.getApplication().createMethodBinding(
|
||||
bindingExpr, new Class[] {});
|
||||
|
||||
if (binding != null)
|
||||
{
|
||||
// setup the transaction
|
||||
tx = Repository.getUserTransaction(facesContext);
|
||||
tx.begin();
|
||||
|
||||
// invoke the method
|
||||
binding.invoke(facesContext, new Object[] {});
|
||||
|
||||
// commit
|
||||
tx.commit();
|
||||
}
|
||||
}
|
||||
catch (Throwable err)
|
||||
{
|
||||
// rollback the transaction
|
||||
try { if (tx != null) {tx.rollback();} } catch (Exception ex) {}
|
||||
|
||||
throw new AlfrescoRuntimeException("Failed to execute method: " + err.getMessage(), err);
|
||||
}
|
||||
|
||||
// force the output back to the client
|
||||
writer.close();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user