Skip to content

Commit

Permalink
save progress
Browse files Browse the repository at this point in the history
  • Loading branch information
liweinan committed May 24, 2013
1 parent 63a2686 commit 0b30963
Show file tree
Hide file tree
Showing 15 changed files with 194 additions and 108 deletions.
6 changes: 5 additions & 1 deletion .idea/ant.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 24 additions & 9 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,41 +8,56 @@
<artifactId>java-snippets</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
<dep.log4j.version>1.2.17</dep.log4j.version>
<dep.jackson-core.version>2.1.3</dep.jackson-core.version>
<dep.jackson-databind.version>2.1.3</dep.jackson-databind.version>
<dep.junit.version>4.11</dep.junit.version>
<dep.jetty.version>3.2.9.Final</dep.jetty.version>
<dep.jettison.version>1.3.3</dep.jettison.version>
<dep.jaxb-impl.version>2.2.6</dep.jaxb-impl.version>
</properties>

<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.1.3</version>
<version>${dep.jackson-core.version}</version>
</dependency>
<!--<dependency>-->
<!--<groupId>com.fasterxml.jackson.core</groupId>-->
<!--<artifactId>jackson-annotations</artifactId>-->
<!--<version>2.1.3</version>-->
<!--<groupId>com.fasterxml.jackson.core</groupId>-->
<!--<artifactId>jackson-annotations</artifactId>-->
<!--<version>2.1.3</version>-->
<!--</dependency>-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.1.3</version>
<version>${dep.jackson-databind.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<version>${dep.junit.version}</version>
</dependency>
<dependency>
<groupId>org.jboss.netty</groupId>
<artifactId>netty</artifactId>
<version>3.2.9.Final</version>
<version>${dep.jetty.version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.jettison</groupId>
<artifactId>jettison</artifactId>
<version>1.3.3</version>
<version>${dep.jettison.version}</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.2.6</version>
<version>${dep.jaxb-impl.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${dep.log4j.version}</version>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package net.bluedash.snippets.classloader;

import org.jboss.netty.handler.codec.serialization.WeakReferenceMap;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Proxy;
import java.util.List;
import java.util.Map;

/**
* Created with IntelliJ IDEA.
* User: weli
* Date: 5/24/13
* Time: 7:28 PM
* To change this template use File | Settings | File Templates.
*/
public class MultiThreadProductFactory extends ProductFactory {
static protected WeakReferenceMap<Long, Proxy> productProxies; // in multi-thread environment, we need to store each threads' proxy independently.

public static Product newInstance() throws InstantiationException,
IllegalAccessException {
return newInstance(ProductImpl.class);// default implementation
}

public static Product newInstance(Class clazz) throws InstantiationException,
IllegalAccessException {
Product product = (Product) clazz.newInstance(); // default implementation
Product productProxy = ProductInvocationHandler.newInstance(product);
productProxies.put(Long.valueOf(Thread.currentThread().getId()), (Proxy) productProxy);
return productProxy;
}

public static void reload(String productClassPath) throws ClassNotFoundException,
InstantiationException, IllegalAccessException,
NoSuchMethodException, InvocationTargetException {
cl = new SimpleClassLoader(PREFIX + productClassPath);
String binaryName = productClassPath.replace('/', '.') + ".ProductImpl";
Class productImplClass = cl.loadClass(binaryName);

Proxy productProxy = productProxies.get(Thread.currentThread().getId());

if (productProxy != null) {
ProductInvocationHandler productInvocationHandler = (ProductInvocationHandler) Proxy.getInvocationHandler(productProxy);
Product replacement = (Product) productImplClass.newInstance();
productInvocationHandler.setProductInstance(replacement);
}
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package net.bluedash.snippets.classloader;

public interface Product {
public void show();
public String getName();
}
47 changes: 18 additions & 29 deletions src/main/java/net/bluedash/snippets/classloader/ProductFactory.java
Original file line number Diff line number Diff line change
@@ -1,46 +1,35 @@
package net.bluedash.snippets.classloader;

import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;

public class ProductFactory {
static private ClassLoader cl = null;
static private Class implClass = ProductImpl.class; // default class
static private List instances = new ArrayList();
static protected ClassLoader cl = null;
static protected Object productProxy; // we store this because we want to get invocation handler from proxy later

public static Product newInstance() throws InstantiationException,
IllegalAccessException {
Product obj = (Product) implClass.newInstance();
Product anAProxy = (Product) ProductIH.newInstance(obj);
instances.add(new WeakReference(anAProxy));
return anAProxy;
Product product = ProductImpl.class.newInstance(); // default implementation
Product productProxy = ProductInvocationHandler.newInstance(product);
ProductFactory.productProxy = productProxy;
return productProxy;
}

private static final String PREFIX = "target/classes/";
protected static final String PREFIX = "target/classes/";

public static void reload(String dir) throws ClassNotFoundException,
public static void reload(String productClassPath) throws ClassNotFoundException,
InstantiationException, IllegalAccessException,
NoSuchMethodException, InvocationTargetException {
cl = new SimpleClassLoader(PREFIX + dir);
String binaryName = dir.replace('/', '.') + ".ProductImpl";
implClass = cl.loadClass(binaryName);

List newInstances = new ArrayList();

for (int i = 0; i < instances.size(); i++) {
Proxy x = (Proxy) ((WeakReference) instances.get(i)).get();
if (x != null) {
ProductIH aih = (ProductIH) Proxy.getInvocationHandler(x);
Object oldObject = aih.getTarget();
Object replacement = implClass.newInstance();
aih.setTarget(replacement);
newInstances.add(new WeakReference(x));
}
cl = new SimpleClassLoader(PREFIX + productClassPath);
String binaryName = productClassPath.replace('/', '.') + ".ProductImpl";
Class productImplClass = cl.loadClass(binaryName);

Proxy productProxy = (Proxy) ProductFactory.productProxy;
if (productProxy != null) {
ProductInvocationHandler productInvocationHandler = (ProductInvocationHandler) Proxy.getInvocationHandler(productProxy);
Product replacement = (Product) productImplClass.newInstance();
productInvocationHandler.setProductInstance(replacement);
ProductFactory.productProxy = productProxy;
}

instances = newInstances;
}
}
40 changes: 0 additions & 40 deletions src/main/java/net/bluedash/snippets/classloader/ProductIH.java

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@

public class ProductImpl implements Product {

public void show() {
System.out.println("ProductImpl");

}

public String getName() {
return "ProductImpl";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package net.bluedash.snippets.classloader;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

class ProductInvocationHandler implements InvocationHandler {
private Object productInstance = null;
static private Class[] productInterface = { Product.class };

public static Product newInstance(Product productInstance) {
return (Product) Proxy.newProxyInstance(
productInstance.getClass().getClassLoader(), productInterface,
new ProductInvocationHandler(productInstance));
}

private ProductInvocationHandler(Object productInstance) {
this.productInstance = productInstance;
}

public void setProductInstance(Object productInstance) {
this.productInstance = productInstance;
}

public Object getProductInstance() {
return productInstance;
}

public Object invoke(Object t, Method m, Object[] args) throws Throwable {
Object result;
try {
Method _m = productInstance.getClass().getMethod(m.getName());
result = _m.invoke(productInstance);
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
return result;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

public class ProductImpl implements Product {

public void show() {
System.out.println("ProductImpl2");
public String getName() {
return "ProductImpl2";

}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package net.bluedash.snippets.classloader.impl2.impl3;

import net.bluedash.snippets.classloader.Product;

/**
* Created with IntelliJ IDEA.
* User: weli
* Date: 5/24/13
* Time: 7:33 PM
* To change this template use File | Settings | File Templates.
*/
public class ProductImpl implements Product {

public String getName() {
return "ProductImpl3";

}

}
11 changes: 11 additions & 0 deletions src/main/java/net/bluedash/snippets/log4j/PlayWithLog4j.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package net.bluedash.snippets.log4j;

/**
* Created with IntelliJ IDEA.
* User: weli
* Date: 5/24/13
* Time: 4:46 PM
* To change this template use File | Settings | File Templates.
*/
public class PlayWithLog4j {
}
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package net.bluedash.snippets.classloader;


import junit.framework.Assert;
import org.junit.Test;

public class ProductReloadTest {

@Test
public void testProductFactory() throws Exception {
Product product = ProductFactory.newInstance();
Assert.assertEquals("ProductImpl", product.getName());

ProductFactory.reload("net/bluedash/snippets/classloader/impl2");
/* the product is replaced by a new instance */
Assert.assertEquals("ProductImpl2", product.getName());
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package net.bluedash.snippets.classloader;

import junit.framework.Assert;
import net.bluedash.snippets.classloader.SimpleClassLoader;
import org.junit.Test;

Expand Down Expand Up @@ -31,7 +32,7 @@ public void testMultipleLevelClassLoading() throws ClassNotFoundException, NoSuc
ClassLoader cl = new SimpleClassLoader("target/classes/net/bluedash/snippets/classloader/impl2");
Class clazz = cl.loadClass("net.bluedash.snippets.classloader.impl2.ProductImpl");
assertNotNull(clazz);
Method method = clazz.getMethod("show");
method.invoke(clazz.newInstance(), null);
Method method = clazz.getMethod("getName");
Assert.assertEquals("ProductImpl2", method.invoke(clazz.newInstance(), null));
}
}

0 comments on commit 0b30963

Please sign in to comment.