001 package org.apache.commons.ognl; 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.enhance.ExpressionCompiler; 023 import org.apache.commons.ognl.enhance.OgnlExpressionCompiler; 024 import org.apache.commons.ognl.enhance.UnsupportedCompilationException; 025 026 import java.util.ArrayList; 027 import java.util.List; 028 029 /** 030 * $Id: ASTList.java 1194869 2011-10-29 11:10:16Z mcucchiara $ 031 * @author Luke Blanshard (blanshlu@netscape.net) 032 * @author Drew Davidson (drew@ognl.org) 033 */ 034 public class ASTList 035 extends SimpleNode 036 implements NodeType 037 { 038 public ASTList( int id ) 039 { 040 super( id ); 041 } 042 043 public ASTList( OgnlParser p, int id ) 044 { 045 super( p, id ); 046 } 047 048 protected Object getValueBody( OgnlContext context, Object source ) 049 throws OgnlException 050 { 051 List answer = new ArrayList( jjtGetNumChildren() ); 052 for ( int i = 0; i < jjtGetNumChildren(); ++i ) 053 { 054 answer.add( children[i].getValue( context, source ) ); 055 } 056 return answer; 057 } 058 059 public Class getGetterClass() 060 { 061 return null; 062 } 063 064 public Class getSetterClass() 065 { 066 return null; 067 } 068 069 public String toGetSourceString( OgnlContext context, Object target ) 070 { 071 String result = ""; 072 boolean array = false; 073 074 if ( parent != null && ASTCtor.class.isInstance( parent ) && ( (ASTCtor) parent ).isArray() ) 075 { 076 077 array = true; 078 } 079 080 context.setCurrentType( List.class ); 081 context.setCurrentAccessor( List.class ); 082 083 if ( !array ) 084 { 085 if ( jjtGetNumChildren() < 1 ) 086 { 087 return "java.util.Arrays.asList( new Object[0])"; 088 } 089 result += "java.util.Arrays.asList( new Object[] "; 090 } 091 092 result += "{ "; 093 094 try 095 { 096 097 for ( int i = 0; i < jjtGetNumChildren(); ++i ) 098 { 099 if ( i > 0 ) 100 { 101 result = result + ", "; 102 } 103 104 Class prevType = context.getCurrentType(); 105 106 Object objValue = children[i].getValue( context, context.getRoot() ); 107 String value = children[i].toGetSourceString( context, target ); 108 109 // to undo type setting of constants when used as method parameters 110 if ( ASTConst.class.isInstance( children[i] ) ) 111 { 112 113 context.setCurrentType( prevType ); 114 } 115 116 value = ExpressionCompiler.getRootExpression( children[i], target, context ) + value; 117 118 String cast = ""; 119 if ( ExpressionCompiler.shouldCast( children[i] ) ) 120 { 121 122 cast = (String) context.remove( ExpressionCompiler.PRE_CAST ); 123 } 124 if ( cast == null ) 125 { 126 cast = ""; 127 } 128 129 if ( !ASTConst.class.isInstance( children[i] ) ) 130 { 131 value = cast + value; 132 } 133 Class ctorClass = (Class) context.get( "_ctorClass" ); 134 if ( array && ctorClass != null && !ctorClass.isPrimitive() ) 135 { 136 137 Class valueClass = value != null ? value.getClass() : null; 138 if ( NodeType.class.isAssignableFrom( children[i].getClass() ) ) 139 { 140 valueClass = ( (NodeType) children[i] ).getGetterClass(); 141 } 142 final OgnlExpressionCompiler compiler = OgnlRuntime.getCompiler( context ); 143 if ( valueClass != null && ctorClass.isArray() ) 144 { 145 146 value = 147 compiler 148 .createLocalReference( context, "(" + ExpressionCompiler.getCastString( ctorClass ) 149 + ")org.apache.commons.ognl.OgnlOps.toArray(" + value + ", " 150 + ctorClass.getComponentType().getName() + ".class, true)", ctorClass ); 151 152 } 153 else if ( ctorClass.isPrimitive() ) 154 { 155 156 Class wrapClass = OgnlRuntime.getPrimitiveWrapperClass( ctorClass ); 157 158 value = 159 compiler 160 .createLocalReference( context, "((" + wrapClass.getName() 161 + ")org.apache.commons.ognl.OgnlOps.convertValue(" + value + "," 162 + wrapClass.getName() + ".class, true))." + OgnlRuntime.getNumericValueGetter( 163 wrapClass ), ctorClass ); 164 } 165 else if ( ctorClass != Object.class ) 166 { 167 168 value = 169 compiler 170 .createLocalReference( context, "(" + ctorClass.getName() 171 + ")org.apache.commons.ognl.OgnlOps.convertValue(" + value + "," 172 + ctorClass.getName() + ".class)", ctorClass ); 173 174 } 175 else if ( ( NodeType.class.isInstance( children[i] ) 176 && ( (NodeType) children[i] ).getGetterClass() != null 177 && Number.class.isAssignableFrom( ( (NodeType) children[i] ).getGetterClass() ) ) 178 || valueClass.isPrimitive() ) 179 { 180 181 value = " ($w) (" + value + ")"; 182 } 183 else if ( valueClass.isPrimitive() ) 184 { 185 value = "($w) (" + value + ")"; 186 } 187 188 } 189 else if ( ctorClass == null || !ctorClass.isPrimitive() ) 190 { 191 192 value = " ($w) (" + value + ")"; 193 } 194 195 if ( objValue == null || value.length() <= 0 ) 196 { 197 value = "null"; 198 } 199 result += value; 200 } 201 202 } 203 catch ( Throwable t ) 204 { 205 throw OgnlOps.castToRuntime( t ); 206 } 207 208 context.setCurrentType( List.class ); 209 context.setCurrentAccessor( List.class ); 210 211 result += "}"; 212 213 if ( !array ) 214 { 215 result += ")"; 216 } 217 return result; 218 } 219 220 public String toSetSourceString( OgnlContext context, Object target ) 221 { 222 throw new UnsupportedCompilationException( "Can't generate setter for ASTList." ); 223 } 224 225 public <R, P> R accept( NodeVisitor<? extends R, ? super P> visitor, P data ) 226 throws OgnlException 227 { 228 return visitor.visit( this, data ); 229 } 230 }