/**
   * Load and parse the BeanShell script via {@link BshScriptUtils}.
   *
   * @see BshScriptUtils#createBshObject(String, Class[], ClassLoader)
   */
  @Override
  public Object getScriptedObject(ScriptSource scriptSource, Class<?>... actualInterfaces)
      throws IOException, ScriptCompilationException {

    try {
      Class<?> clazz;

      synchronized (this.scriptClassMonitor) {
        boolean requiresScriptEvaluation =
            (this.wasModifiedForTypeCheck && this.scriptClass == null);
        this.wasModifiedForTypeCheck = false;

        if (scriptSource.isModified() || requiresScriptEvaluation) {
          // New script content: Let's check whether it evaluates to a Class.
          Object result =
              BshScriptUtils.evaluateBshScript(
                  scriptSource.getScriptAsString(), actualInterfaces, this.beanClassLoader);
          if (result instanceof Class) {
            // A Class: We'll cache the Class here and create an instance
            // outside of the synchronized block.
            this.scriptClass = (Class) result;
          } else {
            // Not a Class: OK, we'll simply create BeanShell objects
            // through evaluating the script for every call later on.
            // For this first-time check, let's simply return the
            // already evaluated object.
            return result;
          }
        }
        clazz = this.scriptClass;
      }

      if (clazz != null) {
        // A Class: We need to create an instance for every call.
        try {
          return clazz.newInstance();
        } catch (Throwable ex) {
          throw new ScriptCompilationException(
              scriptSource, "Could not instantiate script class: " + clazz.getName(), ex);
        }
      } else {
        // Not a Class: We need to evaluate the script for every call.
        return BshScriptUtils.createBshObject(
            scriptSource.getScriptAsString(), actualInterfaces, this.beanClassLoader);
      }
    } catch (EvalError ex) {
      throw new ScriptCompilationException(scriptSource, ex);
    }
  }
  @Override
  public Class<?> getScriptedObjectType(ScriptSource scriptSource)
      throws IOException, ScriptCompilationException {

    try {
      synchronized (this.scriptClassMonitor) {
        if (scriptSource.isModified()) {
          // New script content: Let's check whether it evaluates to a Class.
          this.wasModifiedForTypeCheck = true;
          this.scriptClass =
              BshScriptUtils.determineBshObjectType(
                  scriptSource.getScriptAsString(), this.beanClassLoader);
        }
        return this.scriptClass;
      }
    } catch (EvalError ex) {
      throw new ScriptCompilationException(scriptSource, ex);
    }
  }