class SPELContextPropertyAccessor implements PropertyAccessor {

    private static final Logger LOGGER = LoggerFactory.getLogger(SPELContextPropertyAccessor.class);

    static final SPELContextPropertyAccessor INSTANCE = new SPELContextPropertyAccessor();

    private static final String REQUEST_PARAMETERS_RESTRICTED_VARIABLE_NAME = "param";
    private static final Class<?>[] TARGET_CLASSES = new Class<?>[] { IContext.class };




    SPELContextPropertyAccessor() {
        super();
    }


    public Class<?>[] getSpecificTargetClasses() {
        return TARGET_CLASSES;
    }



    public boolean canRead(final EvaluationContext context, final Object target, final String name)
            throws AccessException {
        if (context instanceof IThymeleafEvaluationContext) {
            if (((IThymeleafEvaluationContext) context).isVariableAccessRestricted()) {
                if (REQUEST_PARAMETERS_RESTRICTED_VARIABLE_NAME.equals(name)) {
                    throw new AccessException(
                            "Access to variable \"" + name + "\" is forbidden in this context. Note some restrictions apply to " +
                            "variable access. For example, direct access to request parameters is forbidden in preprocessing and " +
                            "unescaped expressions, in TEXT template mode, in fragment insertion specifications and " +
                            "in some specific attribute processors.");
                }
            }
        }
        return target != null;
    }



    public TypedValue read(final EvaluationContext evaluationContext, final Object target, final String name)
            throws AccessException {<FILL_FUNCTION_BODY>}




    public boolean canWrite(
            final EvaluationContext context, final Object target, final String name)
            throws AccessException {
        // There should never be a need to write on an IContext during a template execution
        return false;
    }



    public void write(
            final EvaluationContext context, final Object target, final String name, final Object newValue)
            throws AccessException {
        // There should never be a need to write on an IContext during a template execution
        throw new AccessException("Cannot write to " + IContext.class.getName());
    }


}


        if (target == null) {
            throw new AccessException("Cannot read property of null target");
        }

        try {

            final IContext context = (IContext) target;
            return new TypedValue(context.getVariable(name));

        } catch (final ClassCastException e) {
            // This can happen simply because we're applying the same
            // AST tree on a different class (Spring internally caches property accessors).
            // So this exception might be considered "normal" by Spring AST evaluator and
            // just use it to refresh the property accessor cache.
            throw new AccessException("Cannot read target of class " + target.getClass().getName());
        }

    
<no_super_class>