class RhinoPipe extends FixedForwardPipe {

	@Override
	public PipeRunResult doPipe(Message message, IPipeLineSession session) throws PipeRunException {
		//INIT
		String eol = System.getProperty("line.separator");
		if (message==null || message.isEmpty()) {
			//No input from previous pipes. We will use filename and or string input.
	        if ((StringUtils.isEmpty(fileInput)) && inputString==null && isLookupAtRuntime()) {  // No input from file or input string. Nowhere to GO!
				throw new PipeRunException(this,getLogPrefix(session)+"No input specified anywhere. No string input, no file input and no previous pipe input");
	        }
		}
		
		
		//Default console bindings. Used to map javascript commands to java commands as CONSTANT
		//Console bindings do not work in Rhino. To print from jslib use java.lang.System.out.print("hello world!");
		
		//Get the input from the file at Run Time
		if (StringUtils.isNotEmpty(getFileName()) && isLookupAtRuntime()) {
			URL resource = null;
			try {
				resource = ClassUtils.getResourceURL(getConfigurationClassLoader(), getFileName());
			} catch (Throwable e) {
				throw new PipeRunException(this,getLogPrefix(session)+"got exception searching for ["+getFileName()+"]", e);
			}
			if (resource==null) {
				throw new PipeRunException(this,getLogPrefix(session)+"cannot find resource ["+getFileName()+"]");
			}
			try {
				fileInput = Misc.resourceToString(resource, SystemUtils.LINE_SEPARATOR);
			} catch (Throwable e) {
				throw new PipeRunException(this,getLogPrefix(session)+"got exception loading ["+getFileName()+"]", e);
			}
		}
		//Get all params as input
		if (getParameterList()!=null) {
			ParameterValueList pvl;
			try {
				pvl = getParameterList().getValues(message, session);
			} catch (ParameterException e) {
				throw new PipeRunException(this,getLogPrefix(session)+"exception extracting parameters",e);
			}
			for (int i=0; i<pvl.size(); i++) {
				ParameterValue pv = pvl.getParameterValue(i);
				paramsInput = pv.asStringValue("") + eol + paramsInput ;
			}
		}

		String javascriptcode = "Packages.java;" + eol;
		if (fileInput != null) {
			javascriptcode = javascriptcode + fileInput;
		}
		if (paramsInput != null) {
			javascriptcode = paramsInput + eol + javascriptcode;
		}
		String stringResult = (String) javascriptcode;
		stringResult = "INPUTSTREAM used in case of ERROR" + eol + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + eol + stringResult;
		// Start your engines
		// Rhino engine Ok.
		Context cx = Context.enter();
		Scriptable scope = cx.initStandardObjects();
		if(isDebug()) {
			log.debug("debug active");
			cx.setLanguageVersion(Context.VERSION_1_2);
			cx.setGeneratingDebug(true);
		}
		
		// Load javascript factory with javascript functions from file, stringinput and paraminput
		String jsResult = "";
		try {

			cx.evaluateString(scope, javascriptcode, "jsScript", 1, null);
			Function fct = (Function) scope.get(jsfunctionName, scope);
			// Object result = fct.call(cx, scope, scope, new
			// Object[]{jsfunctionArguments});
			Object result = fct.call(cx, scope, scope, new Object[] { message.asObject() });

			jsResult = (String) Context.jsToJava(result, String.class);
			if (isDebug() && log.isDebugEnabled()) {
				log.debug(getLogPrefix(session)+"jsResult ["+ jsResult+"]");
			}


		} catch (EcmaError ex) {
			throw new PipeRunException(this, "org.mozilla.javascript.EcmaError -> ", ex);
		} finally {
			Context.exit();
		}
		// Use the result
		if ( jsResult != null) {
			stringResult =jsResult;
		}
		if (StringUtils.isEmpty(getSessionKey())) {
			return new PipeRunResult(getForward(), stringResult);
		} else {
			session.put(getSessionKey(), stringResult);
			return new PipeRunResult(getForward(), message);
		}
	}

}