001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.jexl3.internal.introspection; 018 019import org.apache.commons.jexl3.JexlArithmetic; 020import org.apache.commons.jexl3.JexlOperator; 021import org.apache.commons.jexl3.introspection.JexlMethod; 022import org.apache.commons.jexl3.introspection.JexlPropertyGet; 023import org.apache.commons.jexl3.introspection.JexlPropertySet; 024import org.apache.commons.jexl3.introspection.JexlSandbox; 025import org.apache.commons.jexl3.introspection.JexlUberspect; 026 027import java.util.Iterator; 028import java.util.List; 029 030/** 031 * An uberspect that controls usage of properties, methods and constructors through a sandbox. 032 * @since 3.0 033 */ 034public final class SandboxUberspect implements JexlUberspect { 035 /** The base uberspect. */ 036 private final JexlUberspect uberspect; 037 /** The sandbox. */ 038 private final JexlSandbox sandbox; 039 040 /** 041 * A constructor for JexlSandbox uberspect. 042 * @param theUberspect the JexlUberspect to sandbox 043 * @param theSandbox the sandbox which is copied to avoid changes at runtime 044 */ 045 public SandboxUberspect(final JexlUberspect theUberspect, final JexlSandbox theSandbox) { 046 if (theSandbox == null) { 047 throw new NullPointerException("sandbox can not be null"); 048 } 049 if (theUberspect == null) { 050 throw new NullPointerException("uberspect can not be null"); 051 } 052 this.uberspect = theUberspect; 053 this.sandbox = theSandbox.copy(); 054 } 055 056 @Override 057 public void setClassLoader(final ClassLoader loader) { 058 uberspect.setClassLoader(loader); 059 } 060 061 @Override 062 public ClassLoader getClassLoader() { 063 return uberspect.getClassLoader(); 064 } 065 066 @Override 067 public int getVersion() { 068 return uberspect.getVersion(); 069 } 070 071 @Override 072 public JexlMethod getConstructor(final Object ctorHandle, final Object... args) { 073 final String className; 074 if (ctorHandle instanceof Class<?>) { 075 className = sandbox.execute((Class<?>) ctorHandle, ""); 076 } else if (ctorHandle != null) { 077 className = sandbox.execute(ctorHandle.toString(), ""); 078 } else { 079 className = null; 080 } 081 return className != null && className != JexlSandbox.NULL ? uberspect.getConstructor(className, args) : null; 082 } 083 084 @Override 085 public JexlMethod getMethod(final Object obj, final String method, final Object... args) { 086 if (obj != null && method != null) { 087 final Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass(); 088 final String actual = sandbox.execute(clazz, method); 089 if (actual != null && actual != JexlSandbox.NULL) { 090 return uberspect.getMethod(obj, actual, args); 091 } 092 } 093 return null; 094 } 095 096 @Override 097 public List<PropertyResolver> getResolvers(final JexlOperator op, final Object obj) { 098 return uberspect.getResolvers(op, obj); 099 } 100 101 @Override 102 public JexlPropertyGet getPropertyGet(final Object obj, final Object identifier) { 103 return getPropertyGet(null, obj, identifier); 104 } 105 106 @Override 107 public JexlPropertyGet getPropertyGet(final List<PropertyResolver> resolvers, 108 final Object obj, 109 final Object identifier) { 110 if (obj != null) { 111 if (identifier != null) { 112 final String property = identifier.toString(); 113 final String actual = sandbox.read(obj.getClass(), property); 114 if (actual != null) { 115 // no transformation, strict equality: use identifier before string conversion 116 final Object pty = actual == property ? identifier : actual; 117 return uberspect.getPropertyGet(resolvers, obj, pty); 118 } 119 } else { 120 final String actual = sandbox.read(obj.getClass(), null); 121 if (actual != JexlSandbox.NULL) { 122 return uberspect.getPropertyGet(resolvers, obj, null); 123 } 124 } 125 } 126 return null; 127 } 128 129 @Override 130 public JexlPropertySet getPropertySet(final Object obj,final Object identifier,final Object arg) { 131 return getPropertySet(null, obj, identifier, arg); 132 } 133 134 @Override 135 public JexlPropertySet getPropertySet(final List<PropertyResolver> resolvers, 136 final Object obj, 137 final Object identifier, 138 final Object arg) { 139 if (obj != null) { 140 if (identifier != null) { 141 final String property = identifier.toString(); 142 final String actual = sandbox.write(obj.getClass(), property); 143 if (actual != null) { 144 // no transformation, strict equality: use identifier before string conversion 145 final Object pty = actual == property ? identifier : actual; 146 return uberspect.getPropertySet(resolvers, obj, pty, arg); 147 } 148 } else { 149 final String actual = sandbox.write(obj.getClass(), null); 150 if (actual != JexlSandbox.NULL) { 151 return uberspect.getPropertySet(resolvers, obj, null, arg); 152 } 153 } 154 } 155 return null; 156 } 157 158 @Override 159 public Iterator<?> getIterator(final Object obj) { 160 return uberspect.getIterator(obj); 161 } 162 163 @Override 164 public JexlArithmetic.Uberspect getArithmetic(final JexlArithmetic arithmetic) { 165 return uberspect.getArithmetic(arithmetic); 166 } 167}