001 package org.apache.commons.ognl.enhance; 002 003 /* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022 import org.apache.commons.ognl.Node; 023 import org.apache.commons.ognl.OgnlContext; 024 025 import java.lang.reflect.Method; 026 027 /** 028 * Core interface implemented by expression compiler instances. 029 */ 030 public interface OgnlExpressionCompiler 031 { 032 033 /** Static constant used in conjunction with {@link OgnlContext} to store temporary references. */ 034 String ROOT_TYPE = "-ognl-root-type"; 035 036 /** 037 * The core method executed to compile a specific expression. It is expected that this expression always return a 038 * {@link Node} with a non null {@link org.apache.commons.ognl.Node#getAccessor()} instance - unless an exception is 039 * thrown by the method or the statement wasn't compilable in this instance because of missing/null objects in the 040 * expression. These instances may in some cases continue to call this compilation method until the expression is 041 * resolvable. 042 * 043 * @param context The context of execution. 044 * @param expression The pre-parsed root expression node to compile. 045 * @param root The root object for the expression - may be null in many instances so some implementations may exit 046 * @throws Exception If an error occurs compiling the expression and no strategy has been implemented to handle 047 * incremental expression compilation for incomplete expression members. 048 */ 049 void compileExpression( OgnlContext context, Node expression, Object root ) 050 throws Exception; 051 052 /** 053 * Gets a javassist safe class string for the given class instance. This is especially useful for handling array vs. 054 * normal class casting strings. 055 * 056 * @param clazz The class to get a string equivalent javassist compatible string reference for. 057 * @return The string equivalent of the class. 058 */ 059 String getClassName( Class<?> clazz ); 060 061 /** 062 * Used in places where the preferred {@link #getSuperOrInterfaceClass(java.lang.reflect.Method, Class)} isn't 063 * possible because the method isn't known for a class. Attempts to upcast the given class to the next available 064 * non-private accessible class so that compiled expressions can reference the interface class of an instance so as 065 * not to be compiled in to overly specific statements. 066 * 067 * @param clazz The class to attempt to find a compatible interface for. 068 * @return The same class if no higher level interface could be matched against or the interface equivalent class. 069 */ 070 Class<?> getInterfaceClass( Class<?> clazz ); 071 072 /** 073 * For the given {@link Method} and class finds the highest level interface class this combination can be cast to. 074 * 075 * @param m The method the class must implement. 076 * @param clazz The current class being worked with. 077 * @return The highest level interface / class that the referenced {@link Method} is declared in. 078 */ 079 Class<?> getSuperOrInterfaceClass( Method m, Class<?> clazz ); 080 081 /** 082 * For a given root object type returns the base class type to be used in root referenced expressions. This helps in 083 * some instances where the root objects themselves are compiled javassist instances that need more generic class 084 * equivalents to cast to. 085 * 086 * @param rootNode The root expression node. 087 * @param context The current execution context. 088 * @return The root expression class type to cast to for this node. 089 */ 090 Class<?> getRootExpressionClass( Node rootNode, OgnlContext context ); 091 092 /** 093 * Used primarily by AST types like {@link org.apache.commons.ognl.ASTChain} where <code>foo.bar.id</code> type 094 * references may need to be cast multiple times in order to properly resolve the members in a compiled statement. 095 * <p> 096 * This method should be using the various {@link org.apache.commons.ognl.OgnlContext#getCurrentType()} / 097 * {@link org.apache.commons.ognl.OgnlContext#getCurrentAccessor()} methods to inspect the type stack and properly 098 * cast to the right classes - but only when necessary. 099 * </p> 100 * 101 * @param context The current execution context. 102 * @param expression The node being checked for casting. 103 * @param body The java source string generated by the given node. 104 * @return The body string parameter plus any additional casting syntax needed to make the expression resolvable. 105 */ 106 String castExpression( OgnlContext context, Node expression, String body ); 107 108 /** 109 * Method is used for expressions where multiple inner parameter method calls in generated java source strings cause 110 * javassit failures. It is hacky and cumbersome to have to generate expressions this way but it's the only current 111 * known way to make javassist happy. 112 * <p> 113 * Takes an expression block generated by a node and creates a new method on the base object being compiled so that 114 * sufficiently complicated sub expression blocks can be broken out in to distinct methods to be referenced by the 115 * core accessor / setter methods in the base compiled root object. 116 * </p> 117 * 118 * @param context The current execution context. 119 * @param expression The java source expression to dump in to a seperate method reference. 120 * @param type The return type that should be specified for the new method. 121 * @return The method name that will be used to reference the sub expression in place of the actual sub expression 122 * itself. 123 */ 124 String createLocalReference( OgnlContext context, String expression, Class<?> type ); 125 }