Uploaded image for project: 'Velocity'
  1. Velocity
  2. VELOCITY-818

Case-insensitive matching ${object.methodName} == ${object.methodname} == ${object.methodName}

    Details

    • Type: New Feature
    • Status: Closed
    • Priority: Major
    • Resolution: Won't Fix
    • Affects Version/s: 1.7
    • Fix Version/s: None
    • Component/s: Engine
    • Labels:

      Description

      I thought I would share the following code with the Apache Velocity community.

      Currently there is no easy way for Velocity to do a case-insensitive match on a property or method. Below is my implementation to achieve this.

      VelocityContext velocityContext = new VelocityContext();
      {
      context.put( "aNumericValue", "1234567890" );
      }

      If String template = Then String evaluatedTemplate =
      ${aNumericValue} 1234567890
      ${anumericvalue} 1234567890
      ${anumericValue} 1234567890
      ${aNumericvalue} 1234567890
      ${aNumericValue.toString()} 1234567890
      ${anumericvalue.tostring()} 1234567890

      – Setup Snippet –
      Properties p = new Properties();

      p.setProperty( RuntimeConstants.INPUT_ENCODING, DEFAULT_ENCODING );
      p.setProperty( RuntimeConstants.OUTPUT_ENCODING, DEFAULT_ENCODING );

      p.setProperty( RuntimeConstants.UBERSPECT_CLASSNAME,
      "custom.CustomSecureUberspector" ); //$NON-NLS-1$

      VelocityEngine engine = new VelocityEngine( p );
      engine.init();

      RuntimeInstance ri = new RuntimeInstance();
      ri.init( p );
      uberspector = (CustomSecureUberspector)ri.getUberspect();

      – Setup Snippet –

      – Call Snippet –
      VelocityContext velocityContext = new VelocityContext();
      {
      context.put( "aNumericValue", "1234567890" );
      }

      EventCartridge eventCartridge = new EventCartridge();
      eventCartridge.addEventHandler( new SloppyNameReferenceEventHandler( uberspector ) );
      eventCartridge.addEventHandler( new NullValueReferenceInsertionEventHandler() );
      eventCartridge.attachToContext( velocityContext );

      String template = "${aNumericvalue}";
      StringWriter velocityWriter = new StringWriter();
      velocityEngine.evaluate( velocityContext, velocityWriter, "LOG", template );
      String evaluatedTemplate = velocityWriter.toString();

      – Call Snippet –

      – Supporting Classes Snippet –

      package custom;

      import org.apache.velocity.util.introspection.SecureIntrospectorImpl;
      import org.apache.velocity.util.introspection.SecureUberspector;

      public class CustomSecureUberspector extends SecureUberspector
      {
      public SecureIntrospectorImpl getSecureIntrospector()

      { return (SecureIntrospectorImpl)introspector; }

      }

      package custom;

      import java.lang.reflect.Method;
      import java.util.ArrayList;
      import java.util.List;

      import org.apache.velocity.app.event.InvalidReferenceEventHandler;
      import org.apache.velocity.context.Context;
      import org.apache.velocity.util.introspection.Info;
      import org.apache.velocity.util.introspection.SecureIntrospectorImpl;

      import custom.CustomSecureUberspector;

      @SuppressWarnings(

      { "unused" }

      )
      public class SloppyNameReferenceEventHandler implements InvalidReferenceEventHandler
      {

      protected CustomSecureUberspector uberspector;

      public SloppyNameReferenceEventHandler( CustomSecureUberspector uberspector )

      { this.uberspector = uberspector; }

      @Override
      public Object invalidGetMethod( Context context, String reference, Object object, String property, Info info )
      {

      try

      { return callMethod( object, property ); }

      catch ( Exception e )

      { return null; }

      }


      @Override
      public boolean invalidSetMethod( Context context, String leftReference, String rightReference, Info info )
      { // Do nothing return false; }


      @Override
      public Object invalidMethod( Context context, String reference, Object object, String method, Info info )
      {

      try
      { return callMethod( object, method ); }
      catch ( Exception e )
      { return null; }

      }

      protected Object callMethod( Object object, String method )
      throws Exception
      {
      if ( null == object || null == method )

      { return null; }

      List<String> possibleMethodMatches = findCaseInsensitiveMethodsForObject( object, method, "get" + method ); //$NON-NLS-1$

      SecureIntrospectorImpl secureIntrospectorImpl = uberspector.getSecureIntrospector();

      for ( String possibleMethodMatch : possibleMethodMatches )
      {
      if ( secureIntrospectorImpl.checkObjectExecutePermission( object.getClass(), possibleMethodMatch ) )
      {
      Method[] objectMethods = object.getClass().getMethods();
      for ( int i = 0; i < objectMethods.length; i++ )
      {
      if ( possibleMethodMatch.equals( objectMethods[i].getName() ) )

      { return objectMethods[i].invoke( object ); }

      }
      }
      }

      return null;
      }

      @SuppressWarnings( "static-method" )
      protected List<String> findCaseInsensitiveMethodsForObject( Object object, String ... methodNames )
      {
      List<String> methodMatches = new ArrayList<String>();

      Method[] methods = object.getClass().getMethods();
      for ( int i = 0; i < methods.length; i++ )
      {

      String objectMethodName = methods[i].getName();
      String objectMethodNameInLowerCase = objectMethodName.toLowerCase();

      for ( int j = 0; j < methodNames.length; j++ )
      {
      if ( objectMethodNameInLowerCase.equals( methodNames[j].toLowerCase() ) )

      { methodMatches.add( objectMethodName ); }

      }

      }

      return methodMatches;
      }

      }

      package custom;

      import org.apache.velocity.app.event.ReferenceInsertionEventHandler;

      public class NullValueReferenceInsertionEventHandler implements ReferenceInsertionEventHandler
      {

      @Override
      public Object referenceInsert( String reference, Object value )
      {

      if ( null == value )

      { return String.valueOf( reference ); }

      return value;

      }
      }

      – Supporting Classes Snippet –

        Attachments

          Activity

            People

            • Assignee:
              Unassigned
              Reporter:
              marks1900 Mark S
            • Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Time Tracking

                Estimated:
                Original Estimate - 4h
                4h
                Remaining:
                Remaining Estimate - 4h
                4h
                Logged:
                Time Spent - Not Specified
                Not Specified