View Javadoc

1   /*
2    * Copyright [2007] [University Corporation for Advanced Internet Development, Inc.]
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package edu.internet2.middleware.shibboleth.common.attribute.filtering.provider.match.basic;
18  
19  import javax.script.Compilable;
20  import javax.script.CompiledScript;
21  import javax.script.ScriptContext;
22  import javax.script.ScriptEngine;
23  import javax.script.ScriptEngineManager;
24  import javax.script.ScriptException;
25  import javax.script.SimpleScriptContext;
26  
27  import org.opensaml.xml.util.DatatypeHelper;
28  import org.slf4j.Logger;
29  import org.slf4j.LoggerFactory;
30  
31  import edu.internet2.middleware.shibboleth.common.attribute.filtering.provider.FilterProcessingException;
32  import edu.internet2.middleware.shibboleth.common.attribute.filtering.provider.ShibbolethFilteringContext;
33  
34  /**
35   * Match function based on a JSR-268 script.
36   */
37  public class ScriptMatchFunctor extends AbstractMatchFunctor {
38  
39      /** Class logger. */
40      private final Logger log = LoggerFactory.getLogger(ScriptMatchFunctor.class);
41  
42      /** The scripting language. */
43      private String scriptLanguage;
44  
45      /** The script to execute. */
46      private String script;
47  
48      /** The script engine to execute the script. */
49      private ScriptEngine scriptEngine;
50  
51      /** The compiled form of the script, if the script engine supports compiling. */
52      private CompiledScript compiledScript;
53  
54      /**
55       * Constructor.
56       * 
57       * @param language the scripting language
58       * @param newScript the script to execute
59       */
60      public ScriptMatchFunctor(String language, String newScript) {
61          scriptLanguage = language;
62          script = newScript;
63  
64          ScriptEngineManager sem = new ScriptEngineManager();
65          scriptEngine = sem.getEngineByName(scriptLanguage);
66          compileScript();
67      }
68  
69      /** {@inheritDoc} */
70      protected boolean doEvaluateValue(ShibbolethFilteringContext filterContext, String attributeId,
71              Object attributeValue) throws FilterProcessingException {
72          ScriptContext context = getScriptContext(filterContext, attributeId, attributeValue);
73          return executeScript(context);
74      }
75  
76      /** {@inheritDoc} */
77      protected boolean doEvaluatePolicyRequirement(ShibbolethFilteringContext filterContext)
78              throws FilterProcessingException {
79          ScriptContext context = getScriptContext(filterContext, null, null);
80          return executeScript(context);
81      }
82  
83      /** Compiles the script if the scripting engine supports it. */
84      protected void compileScript() {
85          if (DatatypeHelper.isEmpty(script)) {
86              return;
87          }
88  
89          try {
90              if (scriptEngine != null && scriptEngine instanceof Compilable) {
91                  compiledScript = ((Compilable) scriptEngine).compile(script);
92              }
93          } catch (ScriptException e) {
94              compiledScript = null;
95              log.warn("Unable to pre-compile JSR-268 script: " + script, e);
96          }
97      }
98  
99      /**
100      * Creates the script execution context from the resolution context.
101      * 
102      * @param filterContext current resolution context
103      * @param attributeId ID of the attribute currently being evaluted
104      * @param attributeValue attribute currently being validated
105      * 
106      * @return constructed script context
107      */
108     protected ScriptContext getScriptContext(ShibbolethFilteringContext filterContext, String attributeId,
109             Object attributeValue) {
110         SimpleScriptContext scriptContext = new SimpleScriptContext();
111         scriptContext.setAttribute("filterContext", filterContext, ScriptContext.ENGINE_SCOPE);
112         scriptContext.setAttribute("attributeId", attributeId, ScriptContext.ENGINE_SCOPE);
113         scriptContext.setAttribute("attributeValue", attributeValue, ScriptContext.ENGINE_SCOPE);
114         return scriptContext;
115     }
116 
117     /**
118      * Executes the functor's script.
119      * 
120      * @param scriptContext the script execution context
121      * 
122      * @return the result of the script
123      * 
124      * @throws FilterProcessingException thrown if there is a problem evaluating the script
125      */
126     protected Boolean executeScript(ScriptContext scriptContext) throws FilterProcessingException {
127         Boolean result;
128         try {
129             if (compiledScript != null) {
130                 result = (Boolean) compiledScript.eval(scriptContext);
131             } else {
132                 result = (Boolean) scriptEngine.eval(script, scriptContext);
133             }
134 
135             if (result != null) {
136                 return result.booleanValue();
137             } else {
138                 return Boolean.FALSE;
139             }
140         } catch (ScriptException e) {
141             throw new FilterProcessingException("Unable to execute match functor script", e);
142         }
143     }
144 }