You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@velocity.apache.org by cb...@apache.org on 2008/08/21 15:29:01 UTC
svn commit: r687752 - in /velocity/engine/trunk:
src/java/org/apache/velocity/runtime/
src/java/org/apache/velocity/util/introspection/
src/test/org/apache/velocity/test/util/introspection/ xdocs/docs/
Author: cbrisson
Date: Thu Aug 21 06:28:59 2008
New Revision: 687752
URL: http://svn.apache.org/viewvc?rev=687752&view=rev
Log:
Uberspectors chaining, plus default automatic chaining for non chainable uberspectors
Added:
velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/AbstractChainableUberspector.java
velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/ChainableUberspector.java
velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/LinkingUberspector.java
velocity/engine/trunk/src/test/org/apache/velocity/test/util/introspection/ChainedUberspectorsTestCase.java
Modified:
velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeConstants.java
velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeInstance.java
velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/UberspectImpl.java
velocity/engine/trunk/xdocs/docs/developer-guide.xml
Modified: velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeConstants.java
URL: http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeConstants.java?rev=687752&r1=687751&r2=687752&view=diff
==============================================================================
--- velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeConstants.java (original)
+++ velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeConstants.java Thu Aug 21 06:28:59 2008
@@ -288,7 +288,7 @@
/** Default Encoding is ISO-8859-1. */
String ENCODING_DEFAULT = "ISO-8859-1";
- /** key name for uberspector. */
+ /** key name for uberspector. Multiple classnames can be specified,in which case uberspectors will be chained. */
String UBERSPECT_CLASSNAME = "runtime.introspector.uberspect";
/** A comma separated list of packages to restrict access to in the SecureIntrospector. */
Modified: velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeInstance.java
URL: http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeInstance.java?rev=687752&r1=687751&r2=687752&view=diff
==============================================================================
--- velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeInstance.java (original)
+++ velocity/engine/trunk/src/java/org/apache/velocity/runtime/RuntimeInstance.java Thu Aug 21 06:28:59 2008
@@ -63,6 +63,8 @@
import org.apache.velocity.util.introspection.Introspector;
import org.apache.velocity.util.introspection.Uberspect;
import org.apache.velocity.util.introspection.UberspectLoggable;
+import org.apache.velocity.util.introspection.ChainableUberspector;
+import org.apache.velocity.util.introspection.LinkingUberspector;
/**
* This is the Runtime system for Velocity. It is the
@@ -302,10 +304,10 @@
private void initializeIntrospection()
throws Exception
{
- String rm = getString(RuntimeConstants.UBERSPECT_CLASSNAME);
-
- if (rm != null && rm.length() > 0)
+ String[] uberspectors = configuration.getStringArray(RuntimeConstants.UBERSPECT_CLASSNAME);
+ for (int i=0; i <uberspectors.length;i++)
{
+ String rm = uberspectors[i];
Object o = null;
try
@@ -330,32 +332,52 @@
throw new Exception(err);
}
- uberSpect = (Uberspect) o;
+ Uberspect u = (Uberspect)o;
- if (uberSpect instanceof UberspectLoggable)
+ if (u instanceof UberspectLoggable)
{
- ((UberspectLoggable) uberSpect).setLog(getLog());
+ ((UberspectLoggable)u).setLog(getLog());
}
- if (uberSpect instanceof RuntimeServicesAware)
+ if (u instanceof RuntimeServicesAware)
{
- ((RuntimeServicesAware) uberSpect).setRuntimeServices(this);
+ ((RuntimeServicesAware)u).setRuntimeServices(this);
}
-
- uberSpect.init();
- }
- else
- {
- /*
- * someone screwed up. Lets not fool around...
- */
- String err = "It appears that no class was specified as the"
- + " Uberspect. Please ensure that all configuration"
- + " information is correct.";
+ if (uberSpect == null)
+ {
+ uberSpect = u;
+ }
+ else
+ {
+ if (u instanceof ChainableUberspector)
+ {
+ ((ChainableUberspector)u).wrap(uberSpect);
+ uberSpect = u;
+ }
+ else
+ {
+ uberSpect = new LinkingUberspector(uberSpect,u);
+ }
+ }
+ }
- log.error(err);
- throw new Exception(err);
+ if(uberSpect != null)
+ {
+ uberSpect.init();
+ }
+ else
+ {
+ /*
+ * someone screwed up. Lets not fool around...
+ */
+
+ String err = "It appears that no class was specified as the"
+ + " Uberspect. Please ensure that all configuration"
+ + " information is correct.";
+
+ log.error(err);
+ throw new Exception(err);
}
}
Added: velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/AbstractChainableUberspector.java
URL: http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/AbstractChainableUberspector.java?rev=687752&view=auto
==============================================================================
--- velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/AbstractChainableUberspector.java (added)
+++ velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/AbstractChainableUberspector.java Thu Aug 21 06:28:59 2008
@@ -0,0 +1,109 @@
+package org.apache.velocity.util.introspection;
+
+/*
+ * 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.
+ */
+
+import java.util.Iterator;
+
+/**
+ * Default implementation of a {@link ChainableUberspector chainable uberspector} that forwards all calls to the wrapped
+ * uberspector (when that is possible). It should be used as the base class for all chainable uberspectors.
+ *
+ * @version $Id: $
+ * @since 1.6
+ * @see ChainableUberspector
+ */
+public abstract class AbstractChainableUberspector extends UberspectImpl implements ChainableUberspector
+{
+ /** The wrapped (decorated) uberspector. */
+ protected Uberspect inner;
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see ChainableUberspector#wrap(org.apache.velocity.util.introspection.Uberspect)
+ * @see #inner
+ */
+ public void wrap(Uberspect inner)
+ {
+ this.inner = inner;
+ }
+
+ /**
+ * init - the chainable uberspector is responsible for the initialization of the wrapped uberspector
+ *
+ * @see org.apache.velocity.util.introspection.Uberspect#init()
+ */
+ //@Override
+ public void init() throws Exception
+ {
+ if (this.inner != null) {
+ this.inner.init();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.apache.velocity.util.introspection.Uberspect#getIterator(java.lang.Object,
+ * org.apache.velocity.util.introspection.Info)
+ */
+ //@SuppressWarnings("unchecked")
+ //@Override
+ public Iterator getIterator(Object obj, Info i) throws Exception
+ {
+ return (this.inner != null) ? this.inner.getIterator(obj, i) : null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.apache.velocity.util.introspection.Uberspect#getMethod(java.lang.Object, java.lang.String,
+ * java.lang.Object[], org.apache.velocity.util.introspection.Info)
+ */
+ //@Override
+ public VelMethod getMethod(Object obj, String methodName, Object[] args, Info i) throws Exception
+ {
+ return (this.inner != null) ? this.inner.getMethod(obj, methodName, args, i) : null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.apache.velocity.util.introspection.Uberspect#getPropertyGet(java.lang.Object, java.lang.String,
+ * org.apache.velocity.util.introspection.Info)
+ */
+ //@Override
+ public VelPropertyGet getPropertyGet(Object obj, String identifier, Info i) throws Exception
+ {
+ return (this.inner != null) ? this.inner.getPropertyGet(obj, identifier, i) : null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.apache.velocity.util.introspection.Uberspect#getPropertySet(java.lang.Object, java.lang.String,
+ * java.lang.Object, org.apache.velocity.util.introspection.Info)
+ */
+ //@Override
+ public VelPropertySet getPropertySet(Object obj, String identifier, Object arg, Info i) throws Exception
+ {
+ return (this.inner != null) ? this.inner.getPropertySet(obj, identifier, arg, i) : null;
+ }
+}
Added: velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/ChainableUberspector.java
URL: http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/ChainableUberspector.java?rev=687752&view=auto
==============================================================================
--- velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/ChainableUberspector.java (added)
+++ velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/ChainableUberspector.java Thu Aug 21 06:28:59 2008
@@ -0,0 +1,37 @@
+package org.apache.velocity.util.introspection;
+
+/*
+ * 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.
+ */
+
+/**
+ * Interface that marks uberspectors as chainable, meaning that multiple uberspectors can be
+ * combined in a chain (using the Decorator pattern).
+ *
+ * @version $Id: $
+ * @since 1.6
+ */
+public interface ChainableUberspector extends Uberspect
+{
+ /**
+ * Specify the decorated Uberspector
+ *
+ * @param inner The decorated uberspector.
+ */
+ public void wrap(Uberspect inner);
+}
Added: velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/LinkingUberspector.java
URL: http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/LinkingUberspector.java?rev=687752&view=auto
==============================================================================
--- velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/LinkingUberspector.java (added)
+++ velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/LinkingUberspector.java Thu Aug 21 06:28:59 2008
@@ -0,0 +1,101 @@
+package org.apache.velocity.util.introspection;
+
+import java.util.Iterator;
+
+import org.apache.velocity.runtime.RuntimeServices;
+import org.apache.velocity.util.RuntimeServicesAware;
+
+/**
+ * <p>
+ * When the runtime.introspection.uberspect configuration property contains several
+ * uberspector class names, it means those uberspectors will be chained. When an
+ * uberspector in the list other than the leftmost does not implement ChainableUberspector,
+ * then this utility class is used to provide a basic default chaining where the
+ * first non-null result is kept for each introspection call.
+ * </p>
+ *
+ * @since 1.5RC1
+ * @see ChainableUberspector
+ * @version $Id: LinkingUberspector.java 10959 2008-07-01 00:12:29Z sdumitriu $
+ */
+public class LinkingUberspector extends AbstractChainableUberspector
+{
+ private Uberspect leftUberspect;
+ private Uberspect rightUberspect;
+
+ /**
+ * Constructor that takes the two uberspectors to link
+ */
+ public LinkingUberspector(Uberspect left,Uberspect right) {
+ leftUberspect = left;
+ rightUberspect = right;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Init both wrapped uberspectors
+ * </p>
+ *
+ * @see org.apache.velocity.util.introspection.Uberspect#init()
+ */
+ //@Override
+ public void init() throws Exception
+ {
+ leftUberspect.init();
+ rightUberspect.init();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.apache.velocity.util.introspection.Uberspect#getIterator(java.lang.Object,
+ * org.apache.velocity.util.introspection.Info)
+ */
+ //@SuppressWarnings("unchecked")
+ //@Override
+ public Iterator getIterator(Object obj, Info i) throws Exception
+ {
+ Iterator it = leftUberspect.getIterator(obj,i);
+ return it != null ? it : rightUberspect.getIterator(obj,i);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.apache.velocity.util.introspection.Uberspect#getMethod(java.lang.Object, java.lang.String,
+ * java.lang.Object[], org.apache.velocity.util.introspection.Info)
+ */
+ //@Override
+ public VelMethod getMethod(Object obj, String methodName, Object[] args, Info i) throws Exception
+ {
+ VelMethod method = leftUberspect.getMethod(obj,methodName,args,i);
+ return method != null ? method : rightUberspect.getMethod(obj,methodName,args,i);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.apache.velocity.util.introspection.Uberspect#getPropertyGet(java.lang.Object, java.lang.String,
+ * org.apache.velocity.util.introspection.Info)
+ */
+ //@Override
+ public VelPropertyGet getPropertyGet(Object obj, String identifier, Info i) throws Exception
+ {
+ VelPropertyGet getter = leftUberspect.getPropertyGet(obj,identifier,i);
+ return getter != null ? getter : rightUberspect.getPropertyGet(obj,identifier,i);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.apache.velocity.util.introspection.Uberspect#getPropertySet(java.lang.Object, java.lang.String,
+ * java.lang.Object, org.apache.velocity.util.introspection.Info)
+ */
+ //@Override
+ public VelPropertySet getPropertySet(Object obj, String identifier, Object arg, Info i) throws Exception
+ {
+ VelPropertySet setter = leftUberspect.getPropertySet(obj,identifier,arg,i);
+ return setter != null ? setter : rightUberspect.getPropertySet(obj,identifier,arg,i);
+ }
+}
Modified: velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/UberspectImpl.java
URL: http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/UberspectImpl.java?rev=687752&r1=687751&r2=687752&view=diff
==============================================================================
--- velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/UberspectImpl.java (original)
+++ velocity/engine/trunk/src/java/org/apache/velocity/util/introspection/UberspectImpl.java Thu Aug 21 06:28:59 2008
@@ -67,7 +67,7 @@
* makes sure that the log gets set before this is called,
* we can initialize the Introspector using the log object.
*/
- public void init()
+ public void init() throws Exception
{
introspector = new Introspector(log);
}
Added: velocity/engine/trunk/src/test/org/apache/velocity/test/util/introspection/ChainedUberspectorsTestCase.java
URL: http://svn.apache.org/viewvc/velocity/engine/trunk/src/test/org/apache/velocity/test/util/introspection/ChainedUberspectorsTestCase.java?rev=687752&view=auto
==============================================================================
--- velocity/engine/trunk/src/test/org/apache/velocity/test/util/introspection/ChainedUberspectorsTestCase.java (added)
+++ velocity/engine/trunk/src/test/org/apache/velocity/test/util/introspection/ChainedUberspectorsTestCase.java Thu Aug 21 06:28:59 2008
@@ -0,0 +1,93 @@
+package org.apache.velocity.test.util.introspection;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import org.apache.velocity.app.Velocity;
+import org.apache.velocity.runtime.log.NullLogChute;
+import org.apache.velocity.util.introspection.*;
+import org.apache.velocity.test.BaseTestCase;
+import org.apache.velocity.VelocityContext;
+
+import java.io.StringWriter;
+
+/**
+ * Tests uberspectors chaining
+ */
+public class ChainedUberspectorsTestCase extends BaseTestCase {
+
+ public ChainedUberspectorsTestCase(String name)
+ throws Exception
+ {
+ super(name);
+ }
+
+ public static Test suite()
+ {
+ return new TestSuite(ChainedUberspectorsTestCase.class);
+ }
+
+ public void setUp()
+ throws Exception
+ {
+ Velocity.setProperty(Velocity.RUNTIME_LOG_LOGSYSTEM_CLASS, NullLogChute.class.getName());
+ Velocity.addProperty(Velocity.UBERSPECT_CLASSNAME,"org.apache.velocity.util.introspection.UberspectImpl");
+ Velocity.addProperty(Velocity.UBERSPECT_CLASSNAME,"org.apache.velocity.test.util.introspection.ChainedUberspectorsTestCase$ChainedUberspector");
+ Velocity.addProperty(Velocity.UBERSPECT_CLASSNAME,"org.apache.velocity.test.util.introspection.ChainedUberspectorsTestCase$LinkedUberspector");
+ Velocity.init();
+ }
+
+ public void tearDown()
+ {
+ }
+
+ public void testChaining()
+ throws Exception
+ {
+ VelocityContext context = new VelocityContext();
+ context.put("foo",new Foo());
+ StringWriter writer = new StringWriter();
+
+ Velocity.evaluate(context,writer,"test","$foo.zeMethod()");
+ assertEquals(writer.toString(),"ok");
+
+ Velocity.evaluate(context,writer,"test","#set($foo.foo = 'someValue')");
+
+ writer = new StringWriter();
+ Velocity.evaluate(context,writer,"test","$foo.bar");
+ assertEquals(writer.toString(),"someValue");
+
+ writer = new StringWriter();
+ Velocity.evaluate(context,writer,"test","$foo.foo");
+ assertEquals(writer.toString(),"someValue");
+ }
+
+ // replaces getFoo by getBar
+ public static class ChainedUberspector extends AbstractChainableUberspector
+ {
+ public VelPropertySet getPropertySet(Object obj, String identifier, Object arg, Info info) throws Exception
+ {
+ identifier = identifier.replaceAll("foo","bar");
+ return inner.getPropertySet(obj,identifier,arg,info);
+ }
+ }
+
+ // replaces setFoo by setBar
+ public static class LinkedUberspector extends UberspectImpl
+ {
+ public VelPropertyGet getPropertyGet(Object obj, String identifier, Info info) throws Exception
+ {
+ identifier = identifier.replaceAll("foo","bar");
+ return super.getPropertyGet(obj,identifier,info);
+ }
+ }
+
+ public static class Foo
+ {
+ private String bar;
+
+ public String zeMethod() { return "ok"; }
+ public String getBar() { return bar; }
+ public void setBar(String s) { bar = s; }
+ }
+
+}
Modified: velocity/engine/trunk/xdocs/docs/developer-guide.xml
URL: http://svn.apache.org/viewvc/velocity/engine/trunk/xdocs/docs/developer-guide.xml?rev=687752&r1=687751&r2=687752&view=diff
==============================================================================
--- velocity/engine/trunk/xdocs/docs/developer-guide.xml (original)
+++ velocity/engine/trunk/xdocs/docs/developer-guide.xml Thu Aug 21 06:28:59 2008
@@ -1892,9 +1892,14 @@
org.apache.velocity.util.introspection.UberspectImpl</code>
<br/>
This property sets the 'Uberspector', the introspection package that
-handles all introspection strategies for Velocity. The default works just
-fine, so only replace if you have something really interesting and special
-to do.
+handles all introspection strategies for Velocity. You can specify a
+coma-separated list of Uberspector classes, in which case all Uberspectors are
+chained. The default chaining behaviour is to return the first non-null value
+for each introspection call among all provided uberspectors. You can modify
+this behaviour (for instance to restrict access to some methods) by subclassing
+org.apache.velocity.util.introspection.AbstractChainableUberspector (or
+implementing directly
+org.apache.velocity.util.introspection.ChainableUberspector).
</p>
</section>