alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.axis2.scripting;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.util.ArrayList;

import org.apache.axis2.AxisFault;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.context.ServiceContext;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.receivers.AbstractInOutSyncMessageReceiver;
import org.apache.axis2.scripting.convertors.ConvertorFactory;
import org.apache.axis2.scripting.convertors.OMElementConvertor;
import org.apache.bsf.BSFEngine;
import org.apache.bsf.BSFException;
import org.apache.bsf.BSFManager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * An Axis2 MessageReceiver for invoking script language functions.
 * 
 * The scripting support uses the Apache Bean Scripting Framework (BSF) 
 * so the script may be written in any language supported by BSF. 
 * 
 * There are two ways of defining the script, either in a seperate file
 * or embedded in-line within the services.xml file.
 * 
 * This example shows a services.xml using a seperate script file:
 * <code>
 *   <serviceGroup>
 *     <service ...>
 *       ...
 *       <parameter name="script">scripts/myScript.js
 *     </service>
 *   </serviceGroup>
 * </code>
 * 
 * This example shows a JavaScript function embedded within a services.xml file:
 * <code>
 *   <serviceGroup>
 *     <service ...>
 *       ...
 *       <parameter name="script.js">
 *     </service>
 *   </serviceGroup>
 * </code>
 * 
 * The script language is determined by the file name suffix when using scripts
 * in seperate files or the script parameter name suffix when using inline scripts.
 */
public class ScriptReceiver extends AbstractInOutSyncMessageReceiver {

    public static final String SCRIPT_ATTR = "script";
    public static final String FUNCTION_ATTR = "function";
    public static final String DEFAULT_FUNCTION = "invoke";
    public static final String CONVERTOR_ATTR = "convertor";

    protected static final String BSFENGINE_PROP = ScriptReceiver.class.getName() + "BSFEngine";
    protected static final String CONVERTOR_PROP = ScriptReceiver.class.getName() + "OMElementConvertor";
    public static final String SCRIPT_SRC_PROP = ScriptReceiver.class.getName() + "ScriptSrc";

    private static final Log log = LogFactory.getLog(ScriptModule.class);

    public ScriptReceiver() {
    }

    /**
     * Invokes the service by calling the script function
     */
    public void invokeBusinessLogic(MessageContext inMC, MessageContext outMC) throws AxisFault {
        try {

            log.debug("invoking script service");

            outMC.setEnvelope(getSOAPFactory(inMC).getDefaultEnvelope());

            BSFEngine engine = getBSFEngine(inMC);
            OMElementConvertor convertor = (OMElementConvertor) inMC.getServiceContext().getProperty(CONVERTOR_PROP);

            Parameter scriptFunctionParam = inMC.getAxisService().getParameter(FUNCTION_ATTR);
            String scriptFunction = scriptFunctionParam == null ? DEFAULT_FUNCTION : (String) scriptFunctionParam.getValue();

            ScriptMessageContext inScriptMC = new ScriptMessageContext(inMC, convertor);
            ScriptMessageContext outScriptMC = new ScriptMessageContext(outMC, convertor);
            Object[] args = new Object[] { inScriptMC, outScriptMC };

            engine.call(null, scriptFunction, args);

        } catch (BSFException e) {
            throw AxisFault.makeFault(e);
        }
    }

    /**
     * Gets the BSFEngine for the script service.
     * 
     * The first service invocation creates the BSFEngine and caches
     * it in the Axis2 ServiceContext for reuse by subsequent requests.
     */
    protected BSFEngine getBSFEngine(MessageContext mc) throws AxisFault {
        BSFEngine bsfEngine;
        ServiceContext serviceContext = mc.getServiceContext();
        synchronized (serviceContext) {
            bsfEngine = (BSFEngine) serviceContext.getProperty(BSFENGINE_PROP);
            if (bsfEngine == null) {
                bsfEngine = initScript(mc);
            }
        }
        return bsfEngine;
    }

    /**
     * Initializes the script service by finding the script source code,
     * compiling it in a BSFEngine, and creating an OMElementConvertor
     * for the script.
     */
    protected BSFEngine initScript(MessageContext mc) throws AxisFault {
        log.debug("initializing script service");

        AxisService axisService = mc.getAxisService();

        String scriptName = null;
        String scriptSrc = null;
        Parameter scriptFileParam = axisService.getParameter(SCRIPT_ATTR);
        if (scriptFileParam != null) {
            // the script is defined in a seperate file
            scriptName = ((String) scriptFileParam.getValue()).trim();
            Parameter scriptSrcParam = axisService.getParameter(SCRIPT_SRC_PROP);
            if (scriptSrcParam != null) {
                scriptSrc = (String) scriptSrcParam.getValue();
            } else {
                scriptSrc = readScript(axisService.getClassLoader(), scriptName);
            }
        } else {
            // the script is defined inline within the services.xml
            ArrayList parameters = axisService.getParameters();
            for (int i=0; scriptFileParam == null && i<parameters.size(); i++) {
                Parameter p = (Parameter) parameters.get(i);
                if (p.getName().startsWith("script.")) {
                    scriptFileParam = p;
                    scriptName = p.getName();
                    scriptSrc = (String) p.getValue();
                }
            }
        }
        if (scriptName == null) {
            throw new AxisFault("Missing script parameter");
        }
        
        try {

            String scriptLanguage = BSFManager.getLangFromFilename(scriptName);
            BSFManager bsfManager = new BSFManager();
            bsfManager.setClassLoader(BSFManager.class.getClassLoader());
            bsfManager.declareBean("_AxisService", axisService, AxisService.class);

            BSFEngine bsfEngine = bsfManager.loadScriptingEngine(scriptLanguage);
            bsfEngine.exec(scriptName, 0, 0, scriptSrc);

            ServiceContext serviceContext = mc.getServiceContext();
            serviceContext.setProperty(BSFENGINE_PROP, bsfEngine);

            OMElementConvertor convertor = ConvertorFactory.createOMElementConvertor(axisService, scriptName);
            serviceContext.setProperty(CONVERTOR_PROP, convertor);

            return bsfEngine;

        } catch (BSFException e) {
            throw AxisFault.makeFault(e);
        }
    }

    /**
     * Reads the complete script source code into a String
     */
    protected String readScript(ClassLoader cl, String scriptName) throws AxisFault {
        URL url = cl.getResource(scriptName);
        if (url == null) {
            throw new AxisFault("Script not found: " + scriptName);
        }
        InputStream is;
        try {
            is = url.openStream();
        } catch (IOException e) {
            throw new AxisFault("IOException opening script: " + scriptName, e);
        }
        try {
            Reader reader = new InputStreamReader(is, "UTF-8");
            char[] buffer = new char[1024];
            StringBuffer source = new StringBuffer();
            int count;
            while ((count = reader.read(buffer)) > 0) {
                source.append(buffer, 0, count);
            }
            return source.toString();
        } catch (IOException e) {
            throw new AxisFault("IOException reading script: " + scriptName, e);
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                throw new AxisFault("IOException closing script: " + scriptName, e);
            }
        }
    }
}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.