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 */ 017 package org.apache.commons.jexl2; 018 019 import java.math.MathContext; 020 021 /** 022 * A derived arithmetic that allows different threads to operate with 023 * different strict/lenient/math modes using the same JexlEngine. 024 * @since 2.1 025 */ 026 public class JexlThreadedArithmetic extends JexlArithmetic { 027 028 /** Holds the threaded version of some arithmetic features. */ 029 static class Features { 030 /** Default ctor. */ 031 Features() {} 032 /** Whether this JexlArithmetic instance behaves in strict or lenient mode. */ 033 private Boolean lenient = null; 034 /** The big decimal math context. */ 035 private MathContext mathContext = null; 036 /** The big decimal scale. */ 037 private Integer mathScale = null; 038 } 039 040 /** 041 * Standard ctor. 042 * @param lenient lenient versus strict evaluation flag 043 */ 044 public JexlThreadedArithmetic(boolean lenient) { 045 super(lenient); 046 } 047 048 /** 049 * Creates a JexlThreadedArithmetic instance. 050 * @param lenient whether this arithmetic is lenient or strict 051 * @param bigdContext the math context instance to use for +,-,/,*,% operations on big decimals. 052 * @param bigdScale the scale used for big decimals. 053 */ 054 public JexlThreadedArithmetic(boolean lenient, MathContext bigdContext, int bigdScale) { 055 super(lenient, bigdContext, bigdScale); 056 } 057 058 /** Whether this JexlArithmetic instance behaves in strict or lenient mode for this thread. */ 059 static final ThreadLocal<Features> FEATURES = new ThreadLocal<Features>() { 060 @Override 061 protected synchronized Features initialValue() { 062 return new Features(); 063 } 064 }; 065 066 067 /** 068 * Overrides the default behavior and sets whether this JexlArithmetic instance triggers errors 069 * during evaluation when null is used as an operand for the current thread. 070 * <p>It is advised to protect calls by either calling JexlThreadedArithmetic.setLenient explicitly 071 * before evaluation or add a try/finally clause resetting the flag to avoid unexpected reuse of the lenient 072 * flag value through thread pools side-effects.</p> 073 * @see JexlEngine#setSilent 074 * @see JexlEngine#setDebug 075 * @param flag true means no JexlException will occur, false allows them, null reverts to default behavior 076 */ 077 public static void setLenient(Boolean flag) { 078 FEATURES.get().lenient = flag; 079 } 080 081 /** 082 * Sets the math scale. 083 * <p>The goal and constraints are the same than for setLenient.</p> 084 * @param scale the scale 085 */ 086 public static void setMathScale(Integer scale) { 087 FEATURES.get().mathScale = scale; 088 } 089 090 /** 091 * Sets the math context. 092 * <p>The goal and constraints are the same than for setLenient.</p> 093 * @param mc the math context 094 */ 095 public static void setMathContext(MathContext mc) { 096 FEATURES.get().mathContext = mc; 097 } 098 099 /** {@inheritDoc} */ 100 @Override 101 public boolean isLenient() { 102 Boolean lenient = FEATURES.get().lenient; 103 return lenient == null ? super.isLenient() : lenient.booleanValue(); 104 } 105 106 @Override 107 public int getMathScale() { 108 Integer scale = FEATURES.get().mathScale; 109 return scale == null ? super.getMathScale() : scale.intValue(); 110 } 111 112 @Override 113 public MathContext getMathContext() { 114 MathContext mc = FEATURES.get().mathContext; 115 return mc == null? super.getMathContext() : mc; 116 } 117 }