blob: 1af33fe0b761b5aeeab32a5380bf8f62b5a5e478 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 1998, 2008 Oracle. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* dclarke - Dynamic Persistence INCUBATION - Enhancement 200045
* http://wiki.eclipse.org/EclipseLink/Development/JPA/Dynamic
*
* This code is being developed under INCUBATION and is not currently included
* in the automated EclipseLink build. The API in this code may change, or
* may never be included in the product. Please provide feedback through mailing
* lists or the bug database.
******************************************************************************/
package org.eclipse.persistence.testing.tests.dynamic;
import static junit.framework.Assert.*;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import org.eclipse.persistence.dynamic.DynamicClassLoader;
import org.eclipse.persistence.dynamic.DynamicClassWriter;
import org.eclipse.persistence.dynamic.DynamicEntity;
import org.eclipse.persistence.exceptions.DynamicException;
import org.eclipse.persistence.internal.dynamic.*;
import org.eclipse.persistence.internal.helper.ConversionManager;
import org.eclipse.persistence.internal.helper.SerializationHelper;
import org.junit.Test;
public class DynamicClassLoaderTests {
@Test
public void constructor() throws Exception {
DynamicClassLoader dcl = new DynamicClassLoader(null);
assertNull(dcl.getParent());
dcl.createDynamicClass("java.lang.String");
try {
dcl.createDynamicClass("test.MyClass");
} catch (NoClassDefFoundError e) {
return;
}
fail("Expected NoClassDefFoundError not thrown");
}
@Test
public void loadClass_DynamicEntityImpl() throws Exception {
DynamicClassLoader dcl = new DynamicClassLoader(Thread.currentThread().getContextClassLoader());
dcl.addClass("test.MyClass");
Class dynamicClass = dcl.loadClass("test.MyClass");
assertNotNull(dynamicClass);
assertEquals("test.MyClass", dynamicClass.getName());
assertSame(DynamicEntityImpl.class, dynamicClass.getSuperclass());
assertSame(dynamicClass, dcl.loadClass("test.MyClass"));
ConversionManager.setDefaultLoader(dcl);
ConversionManager.getDefaultManager().setLoader(dcl);
assertSame(dynamicClass, ConversionManager.getDefaultManager().convertClassNameToClass("test.MyClass"));
assertSame(dynamicClass, ConversionManager.getDefaultManager().convertObject("test.MyClass", Class.class));
assertSame(dynamicClass, ConversionManager.getDefaultLoader().loadClass("test.MyClass"));
assertSame(dynamicClass, ConversionManager.loadClass("test.MyClass"));
InstantiationException instEx = null;
try {
dynamicClass.newInstance();
} catch (InstantiationException ie) {
instEx = ie;
}
assertNotNull("InstantiationException not thrown as expected for default constructor", instEx);
Constructor[] constructors = dynamicClass.getConstructors();
assertEquals(1, constructors.length);
assertEquals(1, constructors[0].getParameterTypes().length);
assertEquals(DynamicTypeImpl.class, constructors[0].getParameterTypes()[0]);
Constructor<DynamicEntity> constructor = dynamicClass.getDeclaredConstructor(new Class[] { DynamicTypeImpl.class });
assertNotNull(constructor);
constructor = dynamicClass.getConstructor(new Class[] { DynamicTypeImpl.class });
assertNotNull(constructor);
}
@Test
public void createDynamicClass_DynamicEntityImpl() throws Exception {
DynamicClassLoader dcl = new DynamicClassLoader(Thread.currentThread().getContextClassLoader());
Class dynamicClass = dcl.createDynamicClass("test.MyClass");
assertNotNull(dynamicClass);
assertEquals("test.MyClass", dynamicClass.getName());
assertSame(DynamicEntityImpl.class, dynamicClass.getSuperclass());
assertSame(dynamicClass, dcl.loadClass("test.MyClass"));
ConversionManager.setDefaultLoader(dcl);
ConversionManager.getDefaultManager().setLoader(dcl);
assertSame(dynamicClass, ConversionManager.getDefaultManager().convertClassNameToClass("test.MyClass"));
assertSame(dynamicClass, ConversionManager.getDefaultManager().convertObject("test.MyClass", Class.class));
assertSame(dynamicClass, ConversionManager.getDefaultLoader().loadClass("test.MyClass"));
assertSame(dynamicClass, ConversionManager.loadClass("test.MyClass"));
InstantiationException instEx = null;
try {
dynamicClass.newInstance();
} catch (InstantiationException ie) {
instEx = ie;
}
assertNotNull("InstantiationException not thrown as expected for default constructor", instEx);
Constructor[] constructors = dynamicClass.getConstructors();
assertEquals(1, constructors.length);
assertEquals(1, constructors[0].getParameterTypes().length);
assertEquals(DynamicTypeImpl.class, constructors[0].getParameterTypes()[0]);
Constructor<DynamicEntity> constructor = dynamicClass.getDeclaredConstructor(new Class[] { DynamicTypeImpl.class });
assertNotNull(constructor);
constructor = dynamicClass.getConstructor(new Class[] { DynamicTypeImpl.class });
assertNotNull(constructor);
}
@Test
public void createDynamicClass_Twice() throws Exception {
DynamicClassLoader dcl = new DynamicClassLoader(Thread.currentThread().getContextClassLoader());
assertNull(dcl.getClassWriter("test.MyClass"));
Class dynamicClass = dcl.createDynamicClass("test.MyClass");
assertNotNull(dynamicClass);
assertEquals("test.MyClass", dynamicClass.getName());
DynamicClassWriter writer = dcl.getClassWriter("test.MyClass");
assertNotNull(writer);
Class dynamicClass2 = dcl.createDynamicClass("test.MyClass");
assertSame(dynamicClass, dynamicClass2);
DynamicClassWriter writer2 = dcl.getClassWriter("test.MyClass");
assertNotNull(writer);
assertSame(writer, writer2);
}
@Test
public void defaultWriter() throws Exception {
DynamicClassLoader dcl = new DynamicClassLoader(Thread.currentThread().getContextClassLoader());
assertEquals(DynamicClassWriter.class, dcl.getDefaultWriter().getClass());
}
@Test
public void loadClass_DefaultConstructor() throws Exception {
DynamicClassLoader dcl = new DynamicClassLoader(Thread.currentThread().getContextClassLoader());
dcl.addClass("test.MyClass", DefaultConstructor.class);
Class dynamicClass = dcl.loadClass("test.MyClass");
assertNotNull(dynamicClass);
assertSame(dynamicClass, dcl.loadClass("test.MyClass"));
assertSame(DefaultConstructor.class, dynamicClass.getSuperclass());
DefaultConstructor entity = (DefaultConstructor) dynamicClass.newInstance();
assertNotNull(entity);
}
@Test
public void loadClass_StringConstructor() throws Exception {
DynamicClassLoader dcl = new DynamicClassLoader(Thread.currentThread().getContextClassLoader());
dcl.addClass("test.MyClass", StringConstructor.class);
Class dynamicClass = dcl.loadClass("test.MyClass");
assertNotNull(dynamicClass);
assertSame(dynamicClass, dcl.loadClass("test.MyClass"));
assertSame(StringConstructor.class, dynamicClass.getSuperclass());
InstantiationException instEx = null;
try {
dynamicClass.newInstance();
} catch (InstantiationException ie) {
instEx = ie;
}
assertNotNull("InstantiationException not thrown as expected for default constructor", instEx);
Constructor[] constructors = dynamicClass.getConstructors();
assertEquals(1, constructors.length);
assertEquals(1, constructors[0].getParameterTypes().length);
assertEquals(String.class, constructors[0].getParameterTypes()[0]);
}
@Test
public void loadClass_WriteReplace() throws Exception {
DynamicClassLoader dcl = new DynamicClassLoader(Thread.currentThread().getContextClassLoader());
dcl.addClass("test.MyClass", WriteReplace.class);
Class dynamicClass = dcl.loadClass("test.MyClass");
assertNotNull(dynamicClass);
assertEquals("test.MyClass", dynamicClass.getName());
assertSame(WriteReplace.class, dynamicClass.getSuperclass());
assertSame(dynamicClass, dcl.loadClass("test.MyClass"));
WriteReplace entity = (WriteReplace) dynamicClass.newInstance();
assertNotNull(entity);
byte[] entityBytes = SerializationHelper.serialize(entity);
byte[] stringBytes = SerializationHelper.serialize(entity.getClass().getName());
assertEquals(stringBytes.length, entityBytes.length);
for (int index = 0; index < stringBytes.length; index++) {
assertEquals(stringBytes[index], entityBytes[index]);
}
Object deserializedValue = SerializationHelper.deserialize(entityBytes);
assertNotNull(deserializedValue);
assertEquals(String.class, deserializedValue.getClass());
assertEquals(dynamicClass.getName(), deserializedValue);
}
@Test
public void createDynamicClass_WriteReplace() throws Exception {
DynamicClassLoader dcl = new DynamicClassLoader(Thread.currentThread().getContextClassLoader());
Class dynamicClass = dcl.createDynamicClass("test.MyClass", WriteReplace.class);
assertNotNull(dynamicClass);
assertEquals("test.MyClass", dynamicClass.getName());
assertSame(WriteReplace.class, dynamicClass.getSuperclass());
assertSame(dynamicClass, dcl.loadClass("test.MyClass"));
WriteReplace entity = (WriteReplace) dynamicClass.newInstance();
assertNotNull(entity);
byte[] entityBytes = SerializationHelper.serialize(entity);
byte[] stringBytes = SerializationHelper.serialize(entity.getClass().getName());
assertEquals(stringBytes.length, entityBytes.length);
for (int index = 0; index < stringBytes.length; index++) {
assertEquals(stringBytes[index], entityBytes[index]);
}
Object deserializedValue = SerializationHelper.deserialize(entityBytes);
assertNotNull(deserializedValue);
assertEquals(String.class, deserializedValue.getClass());
assertEquals(dynamicClass.getName(), deserializedValue);
}
@Test
public void duplicateAddClassWithSameParent() throws Exception {
DynamicClassLoader dcl = new DynamicClassLoader(Thread.currentThread().getContextClassLoader());
dcl.addClass("test.MyClass", DefaultConstructor.class);
Class dynamicClass = dcl.loadClass("test.MyClass");
assertNotNull(dynamicClass);
assertSame(dynamicClass, dcl.loadClass("test.MyClass"));
assertSame(DefaultConstructor.class, dynamicClass.getSuperclass());
DynamicClassWriter firstWriter = dcl.getClassWriter("test.MyClass");
DefaultConstructor entity = (DefaultConstructor) dynamicClass.newInstance();
assertNotNull(entity);
assertNotNull("DCL does not contain expected writer", dcl.getClassWriter("test.MyClass"));
dcl.addClass("test.MyClass", DefaultConstructor.class);
DynamicClassWriter secondWriter = dcl.getClassWriter("test.MyClass");
assertSame(firstWriter, secondWriter);
}
/**
* Verify that a second request to create a class with the same name and
* different parents fails.
*/
@Test
public void duplicateAddClassWithDifferentParent() throws Exception {
DynamicClassLoader dcl = new DynamicClassLoader(Thread.currentThread().getContextClassLoader());
dcl.addClass("test.MyClass", DefaultConstructor.class);
Class dynamicClass = dcl.loadClass("test.MyClass");
assertNotNull(dynamicClass);
assertSame(dynamicClass, dcl.loadClass("test.MyClass"));
assertSame(DefaultConstructor.class, dynamicClass.getSuperclass());
DefaultConstructor entity = (DefaultConstructor) dynamicClass.newInstance();
assertNotNull(entity);
assertNotNull("DCL does not contain expected writer", dcl.getClassWriter("test.MyClass"));
try {
dcl.addClass("test.MyClass", WriteReplace.class);
} catch (DynamicException de) {
String errorMessage = de.getMessage();
int errorCode = de.getErrorCode();
assertTrue("Incorrect dynamic exception", errorMessage.startsWith("\r\nException Description: Duplicate addClass request with incompatible writer:"));
assertEquals("Unexpected error code", 0, errorCode);
return;
}
fail("No DynamicException thrown for duplicate addClass with different parent");
}
public static class DefaultConstructor {
}
public static class StringConstructor {
public StringConstructor(String arg) {
}
}
public static class WriteReplace implements Serializable {
protected Object writeReplace() throws ObjectStreamException {
return getClass().getName();
}
}
}