| Nested Class Summary: |
|---|
| public static class | VelocityGenerator.ChainedContext | Velocity context implementation specific to the Servlet environment.
It provides the following special features:
- puts the request, response, session, and servlet context objects
into the Velocity context for direct access, and keeps them
read-only
- supports a read-only toolbox of view tools
- auto-searches servlet request attributes, session attributes and
servlet context attribues for objects
The {@link #internalGet(String key)} method implements the following search order
for objects:
- servlet request, servlet response, servlet session, servlet context
- toolbox
- local hashtable of objects (traditional use)
- servlet request attribues, servlet session attribute, servlet context
attributes
The purpose of this class is to make it easy for web designer to work
with Java servlet based web applications. They do not need to be concerned
with the concepts of request, session or application attributes and the
live time of objects in these scopes.
Note that the put() method always puts objects into the local hashtable.
Acknowledge: the source code is borrowed from the jakarta-velocity-tools
project with slight modifications. |
| public static class | VelocityGenerator.JSIntrospector | Velocity Introspector that supports Rhino JavaScript objects
as well as Java Objects |
| public static class | VelocityGenerator.TemplateLoader | Velocity {@link org.apache.velocity.runtime.resource.loader.ResourceLoader}
implementation to load template resources using Cocoon's
{@link SourceResolver}. This class is created by the Velocity
framework via the ResourceLoaderFactory. |
| Method from org.apache.cocoon.generation.VelocityGenerator Detail: |
public void configure(Configuration configuration) throws ConfigurationException {
this.resolverContext = new DefaultContext();
this.tmplEngine = new VelocityEngine();
// Set up a JavaScript introspector for the Cocoon flow layer
this.tmplEngine.setProperty(org.apache.velocity.runtime.RuntimeConstants.UBERSPECT_CLASSNAME,
JSIntrospector.class.getName());
this.tmplEngine.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM, this);
// First set up our default 'cocoon' resource loader
this.tmplEngine.setProperty("cocoon.resource.loader.class",
TemplateLoader.class.getName());
this.tmplEngine.setProperty("cocoon.resource.loader.cache",
configuration.getAttribute("usecache", "false"));
this.tmplEngine.setProperty("cocoon.resource.loader.modificationCheckInterval",
configuration.getAttribute("checkInterval", "0"));
this.tmplEngine.setProperty("cocoon.resource.loader.context",
this.resolverContext);
// Read in any additional properties to pass to the VelocityEngine during initialization
Configuration[] properties = configuration.getChildren("property");
for (int i = 0; i < properties.length; ++i) {
Configuration c = properties[i];
String name = c.getAttribute("name");
// Disallow setting of certain properties
if (name.startsWith("runtime.log")
|| name.indexOf(".resource.loader.") != -1) {
if (getLogger().isInfoEnabled()) {
getLogger().info("ignoring disallowed property '" + name + "'.");
}
continue;
}
this.tmplEngine.setProperty(name, c.getAttribute("value"));
}
// Now read in any additional Velocity resource loaders
List resourceLoaders = new ArrayList();
Configuration[] loaders = configuration.getChildren("resource-loader");
for (int i = 0; i < loaders.length; ++i) {
Configuration loader = loaders[i];
String name = loader.getAttribute("name");
if (name.equals("cocoon")) {
if (getLogger().isInfoEnabled()) {
getLogger().info("'cocoon' resource loader already defined.");
}
continue;
}
resourceLoaders.add(name);
String prefix = name + ".resource.loader.";
String type = loader.getAttribute("class");
this.tmplEngine.setProperty(prefix + "class", type);
Configuration[] loaderProperties = loader.getChildren("property");
for (int j = 0; j < loaderProperties.length; j++) {
Configuration c = loaderProperties[j];
String propName = c.getAttribute("name");
this.tmplEngine.setProperty(prefix + propName, c.getAttribute("value"));
}
}
// Velocity expects resource loaders as CSV list
//
StringBuffer buffer = new StringBuffer("cocoon");
for (Iterator it = resourceLoaders.iterator(); it.hasNext();) {
buffer.append(',");
buffer.append((String) it.next());
}
tmplEngine.setProperty(RuntimeConstants.RESOURCE_LOADER, buffer.toString());
}
Read any additional objects to export to the Velocity context
from the configuration. |
public void generate() throws IOException, SAXException, ProcessingException {
// Guard against calling generate before setup.
if (!activeFlag) {
throw new IllegalStateException("generate called on sitemap component before setup.");
}
SAXParser parser = null;
StringWriter w = new StringWriter();
try {
parser = (SAXParser) this.manager.lookup(SAXParser.ROLE);
if (getLogger().isDebugEnabled()) {
getLogger().debug("Processing File: " + super.source);
}
if (!tmplEngineInitialized) {
tmplEngine.init();
tmplEngineInitialized = true;
}
/* lets render a template */
this.tmplEngine.mergeTemplate(super.source, velocityContext, w);
InputSource xmlInput =
new InputSource(new StringReader(w.toString()));
xmlInput.setSystemId(super.source);
parser.parse(xmlInput, this.xmlConsumer);
} catch (IOException e) {
getLogger().warn("VelocityGenerator.generate()", e);
throw new ResourceNotFoundException("Could not get Resource for VelocityGenerator", e);
} catch (SAXParseException e) {
int line = e.getLineNumber();
int column = e.getColumnNumber();
if (line < = 0) {
line = Integer.MAX_VALUE;
}
BufferedReader reader =
new BufferedReader(new StringReader(w.toString()));
StringBuffer message = new StringBuffer(e.getMessage());
message.append(" In generated document:\n");
for (int i = 0; i < line; i++) {
String lineStr = reader.readLine();
if (lineStr == null) {
break;
}
message.append(lineStr);
message.append("\n");
}
if (column > 0) {
message.append(StringUtils.leftPad("^\n", column + 1));
}
SAXException pe = new SAXParseException(message.toString(),
e.getPublicId(),
"(Document generated from template "+e.getSystemId() + ")",
e.getLineNumber(),
e.getColumnNumber(),
null);
getLogger().error("VelocityGenerator.generate()", pe);
throw pe;
} catch (SAXException e) {
getLogger().error("VelocityGenerator.generate()", e);
throw e;
} catch (ServiceException e) {
getLogger().error("Could not get parser", e);
throw new ProcessingException("Exception in VelocityGenerator.generate()", e);
} catch (ProcessingException e) {
throw e;
} catch (Exception e) {
getLogger().error("Could not get parser", e);
throw new ProcessingException("Exception in VelocityGenerator.generate()", e);
} finally {
this.manager.release(parser);
}
}
Generate XML data using Velocity template. |
public void init(RuntimeServices rs) throws Exception {
}
This implementation does nothing. |
public void initialize() throws Exception {
//this.tmplEngine.init();
}
|
public void logVelocityMessage(int level,
String message) {
switch (level) {
case LogSystem.WARN_ID:
getLogger().warn(message);
break;
case LogSystem.INFO_ID:
getLogger().info(message);
break;
case LogSystem.DEBUG_ID:
getLogger().debug(message);
break;
case LogSystem.ERROR_ID:
getLogger().error(message);
break;
default :
getLogger().info(message);
break;
}
}
Pass along Velocity log messages to our configured logger. |
public void recycle() {
this.activeFlag = false;
// Recycle all the Source objects resolved/used by our resource loader
try {
Map sourceCache = (Map) this.resolverContext.get(CONTEXT_SOURCE_CACHE_KEY);
for (Iterator it = sourceCache.values().iterator(); it.hasNext();) {
this.resolver.release((Source) it.next());
}
} catch (ContextException ignore) {
}
this.velocityContext = null;
super.recycle();
}
Free up the VelocityContext associated with the pipeline, and
release any Source objects resolved by the resource loader. |
public void setup(SourceResolver resolver,
Map objectModel,
String src,
Parameters params) throws IOException, SAXException, ProcessingException {
if (activeFlag) {
throw new IllegalStateException("setup called on recyclable sitemap component before properly recycling previous state");
}
super.setup(resolver, objectModel, src, params);
// Pass along the SourceResolver to the Velocity resource loader
this.resolverContext.put(CONTEXT_RESOLVER_KEY, resolver);
this.resolverContext.put(CONTEXT_SOURCE_CACHE_KEY, new HashMap());
// FIXME: Initialize the Velocity context. Use objectModel to pass these
final Object bean = FlowHelper.getContextObject(objectModel);
if (bean != null) {
final WebContinuation kont = FlowHelper.getWebContinuation(objectModel);
// Hack? I use JXPath to determine the properties of the bean object
final JXPathBeanInfo bi = JXPathIntrospector.getBeanInfo(bean.getClass());
DynamicPropertyHandler h = null;
final PropertyDescriptor[] props;
if (bi.isDynamic()) {
Class cl = bi.getDynamicPropertyHandlerClass();
try {
h = (DynamicPropertyHandler) cl.newInstance();
} catch (Exception exc) {
exc.printStackTrace();
h = null;
}
props = null;
} else {
h = null;
props = bi.getPropertyDescriptors();
}
final DynamicPropertyHandler handler = h;
this.velocityContext = new Context() {
public Object put(String key, Object value) {
if (key.equals("flowContext")
|| key.equals("continuation")) {
return value;
}
if (handler != null) {
handler.setProperty(bean, key, value);
return value;
} else {
for (int i = 0; i < props.length; i++) {
if (props[i].getName().equals(key)) {
try {
return props[i].getWriteMethod().invoke(bean, new Object[]{value});
} catch (Exception ignored) {
break;
}
}
}
return value;
}
}
public boolean containsKey(Object key) {
if (key.equals("flowContext")
|| key.equals("continuation")) {
return true;
}
if (handler != null) {
String[] result = handler.getPropertyNames(bean);
for (int i = 0; i < result.length; i++) {
if (key.equals(result[i])) {
return true;
}
}
} else {
for (int i = 0; i < props.length; i++) {
if (key.equals(props[i].getName())) {
return true;
}
}
}
return false;
}
public Object[] getKeys() {
Object[] result = null;
if (handler != null) {
result = handler.getPropertyNames(bean);
} else {
result = new Object[props.length];
for (int i = 0; i < props.length; i++) {
result[i] = props[i].getName();
}
}
Set set = new HashSet();
for (int i = 0; i < result.length; i++) {
set.add(result[i]);
}
set.add("flowContext");
set.add("continuation");
result = new Object[set.size()];
set.toArray(result);
return result;
}
public Object get(String key) {
if (key.equals("flowContext")) {
return bean;
}
if (key.equals("continuation")) {
return kont;
}
if (handler != null) {
return handler.getProperty(bean, key);
} else {
for (int i = 0; i < props.length; i++) {
if (props[i].getName().equals(key)) {
try {
return props[i].getReadMethod().invoke(bean, null);
} catch (Exception ignored) {
break;
}
}
}
return null;
}
}
public Object remove(Object key) {
// not implemented
return key;
}
};
}
this.velocityContext =
new ChainedContext (this.velocityContext,
ObjectModelHelper.getRequest(objectModel),
ObjectModelHelper.getResponse(objectModel),
ObjectModelHelper.getContext(objectModel),
params);
this.velocityContext.put("template", src);
this.activeFlag = true;
}
|