Lightweight Aspect-Oriented Programming 
by Michael J. Yuan and Norman Richards


Listing One
package Beans;
public class EchoBean implements EchoBeanIface {
  private String _message;
  public EchoBean () {
    _message = "not initialized";
  }
  public String getMessage() {
    return _message;
  }
  public void setMessage(String message) {
    _message = message;
  }
  public String copyrightNotice() {
    return "Copyright Michael Yuan and Norman Richards\n";
  }
}

Listing Two

package Policy;

import java.io.*;
import java.util.*;
import org.w3c.dom.*;
import javax.xml.parsers.*;

// Dynamic policy handler.
public class Policy {
  Document policy = null;
  // Parse policy config file and build a DOM tree.
  public Policy (String path) throws Exception {
    File policyFile = new File( path );
    DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
    policy = docBuilder.parse(policyFile);
    return;
  }
  public void execute(String className, String methodName, String position, 
                           String action, Object [] args) throws Exception {
    if ( policy == null ) {
      throw new Exception("policy error!");
    }
    Element bean = null, method = null;
    // Get all "bean" elements
    NodeList beans = policy.getElementsByTagName("bean");
    // Iterate and find matches for input parameter "className".
    for (int i=0; i<beans.getLength(); i++) {
      Element e = (Element) beans.item(i);
      if ( className.equals(e.getAttribute("className")) ) {
        bean = e;
        break;
      }
    }
    if ( bean == null ) {
      return;
    }
    // Get all "method" elements
    NodeList methods = bean.getElementsByTagName("method");
    // Iterate & find matches for input parameters "methodName" & "position".
    for (int i=0; i<methods.getLength(); i++) {
      Element e = (Element) methods.item(i);
      if ( methodName.equals(e.getAttribute("name")) &&
           position.equals(e.getAttribute("position")) ) {
        method = e;
        break;
      }
    }
    if ( method == null ) {
      return;
    }
    // Act according to "action" attribute.
    if ( action.equals(method.getAttribute("action")) ) {
      String output = (new Date()).toString() + " called " + 
                      className + "." + methodName + " arguments ";
      if ( args == null ) {
        output = output + "NULL";
      } else {
        for (int i=0; i<args.length; i++) {
          output = output + args[i].toString();
        }
      }
      System.out.println(output);
    }
    return;
  }
}


Listing Three

<policy>
  <bean className="Beans.EchoBean">
    <method name="setMessage" action="log" position="before"/>
    <method name="getMessage" action="log" position="after"/>
    <method name="copyrightNotice" action="log" position="after"/>
  </bean>
</policy>


Listing Four
package CustomTags.DynamicProxy;

import java.lang.reflect.Method;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import Policy.*;

// Transparent proxy around any JavaBean to handle policies.
public class BeanProxy implements InvocationHandler {
  Object[] _targets;
  String _beanClassName;
  Policy _policy;
  public BeanProxy(Object[] targets, String beanClassName, Policy policy) {
    _targets = targets;
    _beanClassName = beanClassName;
    _policy = policy;
  }
  // New JavaBean and proxy instance.
  public static Object create (String beanClassName,
                               Policy policy) throws Exception {
    Class beanClass = Class.forName( beanClassName );
    Class beanIfaceClass = Class.forName( beanClassName + "Iface" );
    Object beanObj = beanClass.newInstance();
    Class [] ifaces  = {beanIfaceClass};
    Object [] targets = {beanObj};
    return Proxy.newProxyInstance(BeanProxy.class.getClassLoader(), ifaces,
                             new BeanProxy(targets, beanClassName, policy));
  }
  // All bean methods are invoked through this method.
  public Object invoke(Object proxy, Method method, Object[] args)
                                                 throws Exception {
    Object result;
    _policy.execute(_beanClassName, method.getName(), "before", "log", args);
    result = method.invoke(_targets[0], args);
    _policy.execute(_beanClassName, method.getName(), "after", "log", args);
    return result;
  }
}

Listing Five
package CustomTags.DynamicProxy;
 
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import CustomTags.*;
import Policy.*;
 
// Custom tag handler to initialize a JavaBean and its dynamic proxy.
public class UseBeanProxy extends TagSupport {
  String _beanName;
  String _beanClassName;
  int _scope;
  public void setId(String id) {
    _beanName = id;
  }
  public void setBeanClass(String beanClassName) {
    _beanClassName = beanClassName;
  }
  public void setScope(String scope) {
    try {
      _scope = Utils.getScope( scope );
    } catch (Exception e) {
      System.out.print(e.getMessage());
    }
  }
  public int doStartTag () {
    try {
      // If the named bean instance is already available, do nothing.
      if ( pageContext.getAttribute(_beanName, _scope) != null ) {
        return SKIP_BODY;
      }
      // Get policy object.
      Policy policy = (Policy) pageContext.getAttribute("Policy", 
                                     PageContext.APPLICATION_SCOPE);
      // If this is the first time accessing policy object in this
      // application, create one and store in PageContext.
      if ( policy == null ) {
        String path = pageContext.getServletContext().getRealPath("/");
        policy = new Policy(path + "/WEB-INF/conf/PolicyConf.xml");
        pageContext.setAttribute("Policy", policy, 
                                 PageContext.APPLICATION_SCOPE);
      }
      // Bean instance wrapped in a dynamic proxy.
      Object obj = BeanProxy.create( _beanClassName, policy );
      // Put the proxy instance into PageContext.
      pageContext.setAttribute(_beanName, obj, _scope);
    } catch (Exception e) {
      System.out.print(e.getMessage());
    }
    return SKIP_BODY;
  }

}





4


