org.apache.jetspeed.ajax.AjaxRequestServiceImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jetspeed-portal Show documentation
Show all versions of jetspeed-portal Show documentation
Jetspeed-2 Portal Components
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jetspeed.ajax;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.jetspeed.layout.impl.Constants;
import org.apache.jetspeed.request.RequestContext;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.context.Context;
import org.apache.velocity.tools.generic.EscapeTool;
/**
*
* Provides a generic way to handle a Ajax request/response. Useful for AJAX since
* the processing can be broken down into actions and builders
*/
public class AjaxRequestServiceImpl implements AjaxRequestService
{
protected static final String CONTENT_TYPE = "text/xml";
protected static final String AJAX_PROCESSOR = "AJAX processor";
protected static final String DEFAULT_ERROR = "failure unknown ";
// Name of the parameter that will be used to lookup the
// command object. Default is action.
//
// Sample URL:
// http://localhost/js?pipeline=layout&action=move
//
// In this case the parameter "action" is used to find "move"
// "move" will be used as the key to lookup the object that will
// handle the command
protected static final String URL_PARAMETER_NAME = "action";
/** Logger */
protected Logger log = LoggerFactory.getLogger(AjaxRequestServiceImpl.class);
// Objects that are available to execution. These objects must
// implement either the Action interface or the Builder interface
// or both.
// If the Action interface is implemented, then the run method is called
// If the Build interface is implemented, then the build methods are called
protected Map objects;
// Used to create the response XML
protected VelocityEngine velocityEngine = null;
// Parameter on the URL that will be used to lookup the object
protected String urlParameterName = URL_PARAMETER_NAME;
// Default Action if no action specified
protected String defaultAction = "getpage";
// Handy Velocity Escape Tool (is threadsafe)
protected EscapeTool velocityEscTool = null;
// Spring can be used to inject this information
public AjaxRequestServiceImpl(Map objects, VelocityEngine velocityEngine)
{
this.objects = objects;
this.velocityEngine = velocityEngine;
this.velocityEscTool = new EscapeTool();
}
// Spring can be used to inject this information
public AjaxRequestServiceImpl(Map objects, VelocityEngine velocityEngine,
String urlParameterName)
{
this.objects = objects;
this.velocityEngine = velocityEngine;
this.urlParameterName = urlParameterName;
this.velocityEscTool = new EscapeTool();
}
// This is the entry point for this service
public void process(RequestContext requestContext) throws AJAXException
{
// Lookup the object that is to be used
String objectKey = requestContext.getRequestParameter(urlParameterName);
if (objectKey == null)
{
objectKey = defaultAction;
}
// Get the object associated with this key
Object object = objects.get(objectKey);
if (object != null)
{
Map resultMap = new HashMap();
boolean success = true;
try
{
// Check to see if this object implements the action
// interface
if (object instanceof AjaxAction)
{
success = processAction((AjaxAction) object,
requestContext, resultMap);
}
} catch (Exception e)
{
success = false;
}
try
{
// Check to see if this object implements the builder
// interface
if (object instanceof AjaxBuilder)
{
processBuilder((AjaxBuilder) object, resultMap,
requestContext, success);
}
} catch (Exception e)
{
// The builder failed, return an error response
buildError(requestContext);
}
} else
{
// Log an informational message
log.debug("could not find the object named:" + objectKey);
// Return an error response
buildError(requestContext);
}
}
// Process the action if provided
protected boolean processAction(AjaxAction action,
RequestContext requestContext, Map resultMap)
throws Exception
{
return action.run(requestContext, resultMap);
}
// Process the builder if provided
protected void processBuilder(AjaxBuilder builder, Map inputMap,
RequestContext requestContext, boolean actionSuccessFlag)
{
// Response will always be text/xml
String format = requestContext.getRequestParameter("format");
if (format == null)
{
requestContext.getResponse().setContentType(CONTENT_TYPE);
}
else
{
if (format.equals("json"))
{
requestContext.getResponse().setContentType("text/json");
}
}
try
{
// Ask the builder to construct the context
// Add the input map to the velocity context
boolean result = true;
if (actionSuccessFlag == true)
{
result = builder.buildContext(requestContext, inputMap);
}
else
{
result = builder.buildErrorContext(requestContext, inputMap);
}
Context context = new VelocityContext(inputMap);
context.put("esc", this.velocityEscTool);
// Check to see if we have a valid context
if (result)
{
// Get the name of the template from the builder
String templateName = null;
if (actionSuccessFlag == true)
{
templateName = builder.getTemplate();
}
else
{
templateName = builder.getErrorTemplate();
}
// Get a reader to the velocity template
final InputStream templateStream = this.getClass()
.getClassLoader().getResourceAsStream(templateName);
Reader template = new InputStreamReader(templateStream);
// The results of the velocity template will be stored here
StringWriter stringWriter = new StringWriter();
// Run the velocity template
velocityEngine.evaluate(context, stringWriter,
AJAX_PROCESSOR, template);
// Get the results from the velocity processing
String buffer = stringWriter.getBuffer().toString();
//log.debug("output from AjaxService:" + buffer);
// Put the response XML on the response object
HttpServletResponse response = requestContext.getResponse();
ServletOutputStream sos = response.getOutputStream();
Writer writer = new OutputStreamWriter(sos, "UTF-8");
writer.write(buffer);
writer.flush();
}
else
{
log.error("could not create builder context");
buildError(requestContext);
}
} catch (Exception e)
{
log.error("builder failed", e);
inputMap.put(Constants.REASON, e.toString());
buildError(requestContext);
}
}
// This is the last chance to handle an error to send back to the client
// Send back a generic response. Subclasses may want to override this
// method
protected void buildError(RequestContext requestContext)
{
try
{
requestContext.getResponse().getOutputStream().print(DEFAULT_ERROR);
}
catch (IOException e)
{
// Not much can be done here, an exception while handling an exception
log.error("exception while trying to build an error message", e);
}
}
/**
* @return Returns the objects.
*/
public Map getActionMap()
{
return objects;
}
}