View Javadoc

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