Load a class from an AAR in Axis2

Posted on January 8, 2008

0


Each service is loaded by its own classloader in Axis2, in order to get classes defined in for example AAR package, you need to have service class loader first:

public static ClassLoader getServiceClassLoader() {
  MessageContext ctx = MessageContext.getCurrentMessageContext();
  return ctx.getAxisService().getClassLoader();
}

Below is the class I used to load resources/classes from an AAR/JAR:

package com.nordea.emarkets.webservice.util;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarInputStream;

import org.apache.commons.beanutils.MethodUtils;
import org.apache.log4j.Logger;

public class ResourceLoaderUtil {
  private final static Logger logger = Logger
      .getLogger(ResourceLoaderUtil.class);

  public static InputStream loadServiceDocFromAar(String serviceGroupName)
      throws IOException {
    String path = getAbsolutePathOfAar(serviceGroupName);
    if (path == null || !(new File(path).exists())) {
      throw new IOException("File " + path
          + " cannot be found in local file system!");
    }
    try {
      JarFile jarFile = new JarFile(path);
      Enumeration<JarEntry> entries = jarFile.entries();
      while (entries.hasMoreElements()) {
        JarEntry jarEntry = entries.nextElement();
        if (jarEntry == null) {
          break;
        }
        logger.debug("The jar entry name is " + jarEntry.getName()
            + "!");
        if (jarEntry.getName().endsWith(".pdf")) {
          // The PDF document
          return jarFile.getInputStream(jarEntry);
        }
     }
    } catch (Exception e) {
      throw new IOException(
          "Error when reading pdf description document.");
    }
    return null;
  }

  public static String getAbsolutePathOfAar(String serviceGroupName)
      throws IOException {
    ClassLoader cld = SoapUtil.getServiceClassLoader();
    if (cld == null) {
      throw new IOException("Can't get class loader in context.");
    }
    URL servicesUrl = cld.getResource("/../services/");
    logger.debug("The retrieved URL of services directory is "
        + servicesUrl + "!");
    File servicesDir = new File(servicesUrl.getFile());
    logger.debug("The file is " + servicesDir.getAbsolutePath()
        + ", is exsit " + servicesDir.exists() + " is Directory? "
        + servicesDir.isDirectory());
    File[] aars = servicesDir.listFiles();
    logger.debug("Total number of AAR found is " + aars.length + "!");
    for (int i = 0; i < aars.length; i++) {
      logger.info("Found an AAR with name " + aars[i] + "!");
      if (aars[i].getName().equals(serviceGroupName + ".aar")) {
        return aars[i].getAbsolutePath();
      }
    }
    return null;
  }

  public static Class[] getClassesInPackage(String pckgname)
      throws ClassNotFoundException {
    // This is used to find the file locally from Eclipse.
    ArrayList classes = new ArrayList();
    ClassLoader cld = getCurrentClassLoader();
    String path = pckgname.replace('.', '/');
    URL resource = cld.getResource(path);
    logger.debug("The path to pack " + pckgname + " is " + resource + "!");
   File directory = new File(resource.getFile());
    if (directory.exists()) {
      String[] files = directory.list();
      for (int i = 0; i < files.length; i++) {
        if (files[i].endsWith(".class")) {
          classes.add(Class.forName(pckgname + '.'
              + files[i].substring(0, files[i].length() - 6)));
        }
      }
    } else {
      throw new ClassNotFoundException(pckgname
          + " does not appear to be a valid package");
    }
    Class[] res = new Class[classes.size()];
    classes.toArray(res);
    return res;
  }

  public static Class[] getClassesInPackageFromAar(String pckgname)
      throws IOException {
    // Get a File object for the package
   File directory = null;
    String pathToAar = getAbsolutePathOfAar(SoapUtil.getServiceGroupName());

    if (pathToAar == null || !(new File(pathToAar).exists())) {
      throw new IOException("File " + pathToAar
          + " cannot be found in local file system!");
    }
    return getClasseInPackageFromJar(pathToAar, pckgname);
  }

  public static Class[] getClasseInPackageFromJar(String jarName,
      String pckgName) {
    ArrayList classes = new ArrayList();
    pckgName = pckgName.replaceAll("\\.", "/");
    try {
      JarInputStream jarFile = new JarInputStream(new FileInputStream(
          jarName));
      logger.debug("The jar file retrieved " + jarFile + "!");
     JarEntry jarEntry;
      while (true) {
       jarEntry = jarFile.getNextJarEntry();
       if (jarEntry == null) {
          break;
        }
        logger.debug("The jar entry name is " + jarEntry.getName()
            + "!");
        if ((jarEntry.getName().startsWith(pckgName))
            && (jarEntry.getName().endsWith(".class"))) {
          String className = jarEntry.getName().substring(0,
              jarEntry.getName().length() - 6);
         logger.info("Class " + className
             + " loaded dynamically by ReflectionUtil!");
          classes.add(Class.forName(className.replaceAll("/", ".")));
        }
     }
    } catch (Exception e) {
      e.printStackTrace();
    }
   Class[] classesArray = new Class[classes.size()];
    classes.toArray(classesArray);
   return classesArray;
 }

  // This method is only used when the web app is outside Tomcat
  private static ClassLoader getCurrentClassLoader() {
   return Thread.currentThread().getContextClassLoader();
  }
}
Posted in: Development