Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
RE: [aspectj-users] latest incarnation of load-time weaving

The biggest difference in my mind in the 1.5 implementation of load-time
weaving is the ability to handle weaving into different classloaders in a
hierarchy. 

I wanted LTW for a command-line launched Swing app that is (mostly) being
developed in IntelliJ. For that use, there's no convenient way to configure
it to launch via the aj script (barring doing something like renaming the
VM's java script to be aj and having that call realjava). And Intellij
doesn't know how to pass classpath entries via a -D option, so that didn't
work well.

So instead, I wrote a non-delegating weaving classloader that extends the
WeavingClassLoader and that weaves everything that is loadable on the
classpath (and that would be cleaner if some of the private methods therein
were made protected). I've included the code below for any who are
interested.

I also have had good experiences using the AspectJ 5 LTW support from when
it was in a separate branch, although I need to try the updated version from
HEAD. I wrote more about this at
http://rbodkin.blogs.com/ron_bodkins_blog/2005/05/load_time_weavi.html

Ron

/* *******************************************************************
 * Copyright (c) New Aspects on Software.
 * All rights reserved. 
 * This program and the accompanying materials are made available 
 * under the terms of the Common Public License v1.0 
 * which accompanies this distribution and is available at 
 * http://www.eclipse.org/legal/cpl-v10.html 
 *  
 * Contributors: 
 *     Ron Bodkin
 * ******************************************************************/

package com.newaspects.aj.util;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.CodeSource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import org.aspectj.weaver.WeavingURLClassLoader;

/**
 * Subclass of the AspectJ 1.2+ weaving url classloader.
 * This version weaves into classes loaded through its parents, rather than
 * requiring that they not have visibility into the classes on its
classpath...
 * This implementation is just the dreaded non-delegating classloader.
 * It would be nice if we had a Java 1.5-style instrumentation hook
instead...
 */

public class AlwaysWeavingURLClassLoader extends WeavingURLClassLoader {
    public static final boolean traceEnabled =
Boolean.getBoolean("com.newaspects.aj.util.trace");

    /*
     * This constructor is needed when using "-Djava.system.class.loader". 
     */
    public AlwaysWeavingURLClassLoader (ClassLoader parent) {
	this(getURLs(getClassPath()),getURLs(getAspectPath()), parent);
	if (traceEnabled) {
	    System.err.println("? AlwaysWeavingURLClassLoader.<init>(" +
parent + "), # URLs = "+getURLs().length);
	    System.err.println("? AlwaysWeavingURLClassLoader.<init>(" +
parent + ")");

	}
    }
	
    public AlwaysWeavingURLClassLoader (URL[] classURLs, URL[] aspectURLs,
ClassLoader parent) {
	super(classURLs,aspectURLs,parent);
	if (traceEnabled) {
	    System.err.println("? AlwaysWeavingURLClassLoader.<init>()");
	}
    }

    // some lovely copy/paste reuse since these methods aren't protected :-(
    protected static String getAspectPath () {
	return System.getProperty(WEAVING_ASPECT_PATH,"");
    }
	
    protected static String getClassPath () {
	String clpath = System.getProperty(WEAVING_CLASS_PATH, "");
	if ("".equals(clpath)) {
	    clpath = System.getProperty("java.class.path",".");
	    String apath =  getAspectPath();
	    if (!("".equals(apath))) {
		clpath = apath + System.getProperty("path.separator", ":") +
		    clpath;
	    }
	}
	return clpath;
    }
    
    protected static URL[] getURLs (String path) {
	List urlList = new ArrayList();
	for (StringTokenizer t = new
StringTokenizer(path,File.pathSeparator);
	     t.hasMoreTokens();) {
	    String token = t.nextToken().trim();
	    File f = new File(token);
	    try {
		if (f.exists()) {
		    URL url = f.toURL();
		    if (url != null) urlList.add(url);
		}
	    } catch (MalformedURLException e) {}
	}
	
	URL[] urls = new URL[urlList.size()];
	urlList.toArray(urls);
	return urls;
    }

    public Class loadClass(String name, boolean resolve) throws
ClassNotFoundException {
	if (name.startsWith("java.") || name.startsWith("javax.")) {
	    return super.loadClass(name, resolve);
	}
	if (traceEnabled) {
	    System.err.println("?
AlwaysWeavingURLClassLoader.loadCass("+name+")");
	}

	Class c = findLoadedClass(name);
	if (c == null) {
	    try {
	        c = findClass(name);
	    } catch (ClassNotFoundException e) {
		return super.loadClass(name, resolve);
	    }
	}

	if (resolve) {
	    resolveClass(c);
	}
	return c;
    }

    protected Class findClass(String name) throws ClassNotFoundException {
	if (traceEnabled) {
	    System.err.print("?
AlwaysWeavingURLClassLoader.findCass("+name+")");
	}
	Class clazz = super.findClass(name);
	if (traceEnabled) {
	    System.err.println("found = "+ clazz!=null);
	}
	return clazz;
    }

}



Back to the top