You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@velocity.apache.org by ge...@apache.org on 2002/04/21 20:41:21 UTC
cvs commit: jakarta-velocity/src/java/org/apache/velocity/util/introspection UberspectImpl.java
geirm 02/04/21 11:41:21
Added: src/java/org/apache/velocity/util/introspection
UberspectImpl.java
Log:
Implemention of the Uberspect interface. Collects into one place the
current code used in Vel for foreach() iterator discovery, method invocation
and property getting / setting
Revision Changes Path
1.1 jakarta-velocity/src/java/org/apache/velocity/util/introspection/UberspectImpl.java
Index: UberspectImpl.java
===================================================================
package org.apache.velocity.util.introspection;
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 2002 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Velocity", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
import org.apache.velocity.util.ArrayIterator;
import org.apache.velocity.util.EnumerationIterator;
import org.apache.velocity.runtime.RuntimeServices;
import org.apache.velocity.runtime.RuntimeLogger;
import org.apache.velocity.runtime.parser.node.AbstractExecutor;
import org.apache.velocity.runtime.parser.node.PropertyExecutor;
import org.apache.velocity.runtime.parser.node.GetExecutor;
import org.apache.velocity.runtime.parser.node.BooleanPropertyExecutor;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.Collection;
import java.util.Map;
import java.util.Enumeration;
import java.util.ArrayList;
/**
* Implementation of Uberspect to provide the default introspective
* functionality of Velocity
*
* @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
* @version $Id: UberspectImpl.java,v 1.1 2002/04/21 18:41:21 geirm Exp $
*/
public class UberspectImpl implements Uberspect, UberspectLoggable
{
/**
* Our runtime logger.
*/
private RuntimeLogger rlog;
/**
* the default Velocity introspector
*/
private static Introspector introspector;
/**
* init - does nothing - we need to have setRuntimeLogger
* called before getting our introspector, as the default
* vel introspector depends upon it.
*/
public void init()
throws Exception
{
}
/**
* Sets the runtime logger - this must be called before anything
* else besides init() as to get the logger. Makes the pull
* model appealing...
*/
public void setRuntimeLogger(RuntimeLogger runtimeLogger)
{
rlog = runtimeLogger;
introspector = new Introspector(rlog);
}
/**
* To support iteratives - #foreach()
*/
public Iterator getIterator(Object obj, Info i)
throws Exception
{
if (obj.getClass().isArray())
{
return new ArrayIterator(obj);
}
else if (obj instanceof Collection)
{
return ((Collection) obj).iterator();
}
else if (obj instanceof Map)
{
return ((Map) obj).values().iterator();
}
else if (obj instanceof Iterator)
{
rlog.warn ("Warning! The iterative "
+ " is an Iterator in the #foreach() loop at ["
+ i.getLine() + "," + i.getColumn() + "]"
+ " in template " + i.getTemplateName()
+ ". Because it's not resetable,"
+ " if used in more than once, this may lead to"
+ " unexpected results.");
return ((Iterator) obj);
}
else if (obj instanceof Enumeration)
{
rlog.warn ("Warning! The iterative "
+ " is an Enumeration in the #foreach() loop at ["
+ i.getLine() + "," + i.getColumn() + "]"
+ " in template " + i.getTemplateName()
+ ". Because it's not resetable,"
+ " if used in more than once, this may lead to"
+ " unexpected results.");
return new EnumerationIterator((Enumeration) obj);
}
/* we have no clue what this is */
rlog.warn ("Could not determine type of iterator in "
+ "#foreach loop "
+ " at [" + i.getLine() + "," + i.getColumn() + "]"
+ " in template " + i.getTemplateName() );
return null;
}
/**
* Method
*/
public VelMethod getMethod(Object obj, String methodName, Object[] args, Info i)
throws Exception
{
if (obj == null)
return null;
Method m = introspector.getMethod(obj.getClass(), methodName, args);
return (m != null) ? new VelMethodImpl(m) : null;
}
/**
* Property getter
*/
public VelPropertyGet getPropertyGet(Object obj, String identifier, Info i)
throws Exception
{
AbstractExecutor executor;
Class claz = obj.getClass();
/*
* first try for a getFoo() type of property
* (also getfoo() )
*/
executor = new PropertyExecutor(rlog,introspector, claz, identifier);
/*
* if that didn't work, look for get("foo")
*/
if (executor.isAlive() == false)
{
executor = new GetExecutor(rlog, introspector, claz, identifier);
}
/*
* finally, look for boolean isFoo()
*/
if( executor.isAlive() == false)
{
executor = new BooleanPropertyExecutor(rlog, introspector, claz, identifier);
}
return (executor != null) ? new VelGetterImpl(executor) : null;
}
/**
* Property setter
*/
public VelPropertySet getPropertySet(Object obj, String identifier, Object arg, Info i)
throws Exception
{
Class claz = obj.getClass();
VelPropertySet vs = null;
VelMethod vm = null;
try
{
/*
* first, we introspect for the set<identifier> setter method
*/
Object[] params = {arg};
try
{
vm = getMethod(obj, "set" + identifier, params, i);
if (vm == null)
{
throw new NoSuchMethodException();
}
}
catch(NoSuchMethodException nsme2)
{
StringBuffer sb = new StringBuffer("set");
sb.append(identifier);
if (Character.isLowerCase( sb.charAt(3)))
{
sb.setCharAt(3, Character.toUpperCase(sb.charAt(3)));
}
else
{
sb.setCharAt(3, Character.toLowerCase(sb.charAt(3)));
}
vm = getMethod(obj, sb.toString(), params, i);
if (vm == null)
{
throw new NoSuchMethodException();
}
}
}
catch (NoSuchMethodException nsme)
{
/*
* right now, we only support the Map interface
*/
if (Map.class.isAssignableFrom(claz))
{
Object[] params = {new Object(), new Object()};
vm = getMethod(obj, "put", params, i);
if (vm!=null)
return new VelSetterImpl(vm, identifier);
}
}
return (vm!=null) ? new VelSetterImpl(vm) : null;
}
/**
* Implementation of VelMethod
*/
public class VelMethodImpl implements VelMethod
{
Method method = null;
public VelMethodImpl(Method m)
{
method = m;
}
private VelMethodImpl()
{
}
public Object invoke(Object o, Object[] params)
throws Exception
{
return method.invoke(o, params);
}
public boolean isCacheable()
{
return true;
}
public String getMethodName()
{
return method.getName();
}
}
public class VelGetterImpl implements VelPropertyGet
{
AbstractExecutor ae = null;
public VelGetterImpl(AbstractExecutor exec)
{
ae = exec;
}
private VelGetterImpl()
{
}
public Object invoke(Object o)
throws Exception
{
return ae.execute(o);
}
public boolean isCacheable()
{
return true;
}
public String getMethodName()
{
return ae.getMethod().getName();
}
}
public class VelSetterImpl implements VelPropertySet
{
VelMethod vm = null;
String putKey = null;
public VelSetterImpl(VelMethod velmethod)
{
this.vm = velmethod;
}
public VelSetterImpl(VelMethod velmethod, String key)
{
this.vm = velmethod;
putKey = key;
}
private VelSetterImpl()
{
}
public Object invoke(Object o, Object value)
throws Exception
{
ArrayList al = new ArrayList();
if (putKey != null)
{
al.add(putKey);
al.add(value);
}
else
{
al.add(value);
}
return vm.invoke(o,al.toArray());
}
public boolean isCacheable()
{
return true;
}
public String getMethodName()
{
return vm.getMethodName();
}
}
}
--
To unsubscribe, e-mail: <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>