Monday, January 19, 2015

Freeswitch mod_java with Launcher

To dynamically load classes in Freeswitch use this Laucher:
/*
 * Launcher.java
 *
 * Created on 13 September 2007, 06:40
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package org.freeswitch;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLConnection;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 *
 * @author dacha
 */
public class Launcher
{
    static
    {
        // Find and load mod_java
        String javaLibraryPaths = System.getProperty("java.library.path");
        String pathSeparator = System.getProperty("path.separator");
        String libraryPaths[] = javaLibraryPaths.split(pathSeparator);
        
        String libraryName = System.mapLibraryName("mod_java");
        int modJavaIndex = libraryName.indexOf("mod_java");
        if (modJavaIndex >= 0)
            libraryName = libraryName.substring(modJavaIndex);
        
        for (String libraryPath : libraryPaths)
        {
            String fullLibraryPath = libraryPath + File.separatorChar + libraryName;
            if (new File(fullLibraryPath).exists())
            {
                System.load(fullLibraryPath);
                break;
            }
        }
    }

    public static void launch(String sessionUuid, String args) throws Exception
    {
        String argv[] = args.split("[ ]");
        if (argv.length == 0)
        {
            System.out.println("Too few arguments to mod java");
            System.out.println("Usage: java /path/to/file.jar fully.qualified.class arg1 arg2 arg3");
            System.out.println("Usage: java fully.qualified.class arg1 arg2 arg3");
            return;
        }
        
        Class klazz=null;

        int argsOffset;
 System.out.println("argv[0]=" + argv[0]);
        if (argv[0].endsWith(".jar") || argv[0].endsWith(".JAR"))
        {
  System.out.println("in jar");
            if (argv.length < 2)
                throw new Exception("Too few arguments: must specify fully qualified class name when loading from JAR file");
     MyClassLoaderFromJar mycjar = new MyClassLoaderFromJar(argv[0]);
     klazz=mycjar.findClass(argv[1]);
            argsOffset = argv[0].length() + argv[1].length() + 2;
        }
        else
        {
          

            //klazz = Class.forName(argv[0]);
          try{
                 ClassLoader parentClassLoader = MyClassLoader.class.getClassLoader();
                 MyClassLoader classLoader = new MyClassLoader(parentClassLoader);
                
                 klazz = classLoader.loadClass(argv[0]);
                 
                
          } catch (Exception e) {
                 System.out.println("notice cannot load class!!!" + e.getMessage());
         }

            argsOffset = argv[0].length() + 1;
        }
        
        Constructor constructor = klazz.getConstructor();
        Object object = constructor.newInstance();
        Method run = klazz.getMethod("run", String.class, String.class);
        String newArgs = "";
        if (argsOffset < args.length())
            newArgs = args.substring(argsOffset);
        run.invoke(object, sessionUuid, newArgs);
    }
}

MyClassLoader class is a helper class that goes into mod_java/src/org/freeswitch along with Launcher

 package org.freeswitch;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.io.*;
import java.net.*;
import java.lang.reflect.*;

class MyClassLoader extends ClassLoader{

        public MyClassLoader(ClassLoader parent) {
            super(parent);
        }

        public Class loadClass(String name) throws ClassNotFoundException {
            System.setSecurityManager(null);

            try {
                System.out.println("in load class");
                String url = "file:/usr/local/freeswitch/scripts/" + name + ".class";
                URL myUrl = new URL(url);
                URLConnection connection = myUrl.openConnection();
                InputStream input = connection.getInputStream();
                ByteArrayOutputStream buffer = new ByteArrayOutputStream();
                int data = input.read();

                while(data != -1){
                    buffer.write(data);
                    data = input.read();
                }

                input.close();

                byte[] classData = buffer.toByteArray();

                Class cl = defineClass(name,
                        classData, 0, classData.length);
                System.out.println("class defined!!!!!!!!!!");
                return cl;

            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }

            return null;
        }
    }

MyClassLoaderFromJar is another helper class to load classes from Jar

 package org.freeswitch;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.io.*;
import java.net.*;
import java.lang.reflect.*;
import java.util.zip.*;
public final class MyClassLoaderFromJar extends ClassLoader {
    private final ZipFile file;

    public MyClassLoaderFromJar(String filename) throws IOException {
        this.file = new ZipFile(filename);
    }

    @Override
    protected Class findClass(String name) throws ClassNotFoundException {
 System.out.println("in find class");
        ZipEntry entry = this.file.getEntry(name.replace('.', '/') + ".class");
        if (entry == null) {
            throw new ClassNotFoundException(name);
        }
 System.out.println("entry=" + entry);
        try {
            byte[] array = new byte[1024];
            InputStream in = this.file.getInputStream(entry);
            ByteArrayOutputStream out = new ByteArrayOutputStream(array.length);
            int length = in.read(array);
            while (length > 0) {
                out.write(array, 0, length);
                length = in.read(array);
            }
     System.out.println("returning class define");
            return defineClass(name, out.toByteArray(), 0, out.size());
        }
        catch (IOException exception) {
            throw new ClassNotFoundException(name, exception);
        }
    }
}

Put these files mod_java/src/org/freeswitch and do "make mod_java-install". The resulting mod_java.so is copied to /usr/local/freeswitch/mod. Note java.conf.xml sets the classpath for all the jars.


No comments:

Post a Comment