View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.jexl3;
18  
19  import java.util.concurrent.Callable;
20  
21  /**
22   * Exposes a synchronized call to a script and synchronizes access to get/set methods.
23   */
24  public class SynchronizedContext extends MapContext implements JexlContext.AnnotationProcessor {
25      private final JexlContext context;
26  
27      public SynchronizedContext(final JexlContext ctxt) {
28          this.context = ctxt;
29      }
30  
31      /**
32       * Calls a script synchronized by an object monitor.
33       * @param var the object used for sync
34       * @param script the script
35       * @return the script value
36       */
37      public Object call(final Object var, final JexlScript script) {
38          final String[] parms = script.getParameters();
39          final boolean varisarg = parms != null && parms.length == 1;
40          if (var == null) {
41              return varisarg ? script.execute(context, var) : script.execute(context);
42          }
43          synchronized (var) {
44              return varisarg ? script.execute(context, var) : script.execute(context);
45          }
46      }
47  
48      @Override
49      public Object get(final String name) {
50          synchronized (this) {
51              return super.get(name);
52          }
53      }
54  
55      @Override
56      public void set(final String name, final Object value) {
57          synchronized (this) {
58              super.set(name, value);
59          }
60      }
61  
62      @Override
63      public Object processAnnotation(final String name, final Object[] args, final Callable<Object> statement) throws Exception {
64          if ("synchronized".equals(name)) {
65              final Object arg = args[0];
66              synchronized(arg) {
67                  return statement.call();
68              }
69          }
70          throw new IllegalArgumentException("unknown annotation " + name);
71      }
72  
73  }