mirror of https://github.com/apache/openjpa.git
OPENJPA-2035: Backing out previous changes.
git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@1154992 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
6439d3ebdf
commit
45bceaa991
|
@ -18,11 +18,10 @@
|
|||
*/
|
||||
package org.apache.openjpa.kernel;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.util.BitSet;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.openjpa.datacache.DataCache;
|
||||
import org.apache.openjpa.lib.util.J2DoPrivHelper;
|
||||
import org.apache.openjpa.meta.ClassMetaData;
|
||||
import org.apache.openjpa.meta.FieldMetaData;
|
||||
|
||||
|
@ -37,8 +36,7 @@ public class PCDataImpl
|
|||
extends AbstractPCData {
|
||||
|
||||
private final Object _oid;
|
||||
private transient Class<?> _type;
|
||||
private String _typeStr;
|
||||
private final Class<?> _type;
|
||||
private final String _cache;
|
||||
private final Object[] _data;
|
||||
private final BitSet _loaded;
|
||||
|
@ -56,7 +54,6 @@ public class PCDataImpl
|
|||
public PCDataImpl(Object oid, ClassMetaData meta, String name) {
|
||||
_oid = oid;
|
||||
_type = meta.getDescribedType();
|
||||
_typeStr = _type.getName();
|
||||
_cache = name;
|
||||
|
||||
int len = meta.getFields().length;
|
||||
|
@ -69,22 +66,9 @@ public class PCDataImpl
|
|||
}
|
||||
|
||||
public Class<?> getType() {
|
||||
if (_type == null) {
|
||||
ClassLoader ccl = AccessController.doPrivileged(J2DoPrivHelper.getContextClassLoaderAction());
|
||||
try {
|
||||
_type = ccl.loadClass(_typeStr);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
return _type;
|
||||
}
|
||||
|
||||
public void setType(Class<?> t){
|
||||
_type = t;
|
||||
_typeStr = t.getName();
|
||||
}
|
||||
|
||||
public BitSet getLoaded() {
|
||||
return _loaded;
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@ public final class Id
|
|||
else {
|
||||
int dash = str.indexOf(TYPE_VALUE_SEP);
|
||||
try {
|
||||
setManagedInstanceType(Class.forName(str.substring(0, dash), true, loader));
|
||||
type = Class.forName(str.substring(0, dash), true, loader);
|
||||
} catch (Throwable t) {
|
||||
throw new UserException(_loc.get("string-id", str), t);
|
||||
}
|
||||
|
|
|
@ -19,9 +19,7 @@
|
|||
package org.apache.openjpa.util;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.security.AccessController;
|
||||
|
||||
import org.apache.openjpa.lib.util.J2DoPrivHelper;
|
||||
import org.apache.openjpa.lib.util.ReferenceMap;
|
||||
import org.apache.openjpa.lib.util.concurrent.ConcurrentReferenceHashMap;
|
||||
|
||||
|
@ -31,17 +29,16 @@ import org.apache.openjpa.lib.util.concurrent.ConcurrentReferenceHashMap;
|
|||
* @author Steve Kim
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public abstract class OpenJPAId implements Comparable, Serializable {
|
||||
public abstract class OpenJPAId
|
||||
implements Comparable, Serializable {
|
||||
public static final char TYPE_VALUE_SEP = '-';
|
||||
|
||||
// cache the types' generated hash codes
|
||||
private static ConcurrentReferenceHashMap _typeCache =
|
||||
new ConcurrentReferenceHashMap(ReferenceMap.WEAK, ReferenceMap.HARD);
|
||||
|
||||
private transient Class<?> _type;
|
||||
private String _typeStr;
|
||||
|
||||
protected boolean _subs = true;
|
||||
protected Class type;
|
||||
protected boolean subs = true;
|
||||
|
||||
// type hash is based on the least-derived non-object class so that
|
||||
// user-given ids with non-exact types match ids with exact types
|
||||
|
@ -50,31 +47,20 @@ public abstract class OpenJPAId implements Comparable, Serializable {
|
|||
protected OpenJPAId() {
|
||||
}
|
||||
|
||||
protected OpenJPAId(Class<?> type) {
|
||||
_type = type;
|
||||
_typeStr = type.getName();
|
||||
|
||||
protected OpenJPAId(Class type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
protected OpenJPAId(Class<?> type, boolean subs) {
|
||||
_type = type;
|
||||
_typeStr = type.getName();
|
||||
_subs = subs;
|
||||
protected OpenJPAId(Class type, boolean subs) {
|
||||
this.type = type;
|
||||
this.subs = subs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the persistent class which this id instance represents.
|
||||
*/
|
||||
public final Class<?> getType() {
|
||||
if (_type == null) {
|
||||
ClassLoader ccl = AccessController.doPrivileged(J2DoPrivHelper.getContextClassLoaderAction());
|
||||
try {
|
||||
_type = ccl.loadClass(_typeStr);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
return _type;
|
||||
public Class getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -82,22 +68,22 @@ public abstract class OpenJPAId implements Comparable, Serializable {
|
|||
* Defaults to true.
|
||||
*/
|
||||
public boolean hasSubclasses() {
|
||||
return _subs;
|
||||
return subs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the exact type of the described instance once it is known.
|
||||
*/
|
||||
public void setManagedInstanceType(Class<?> type) {
|
||||
public void setManagedInstanceType(Class type) {
|
||||
setManagedInstanceType(type, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the exact type of the described instance once it is known.
|
||||
*/
|
||||
public void setManagedInstanceType(Class<?> type, boolean subs) {
|
||||
_type = type;
|
||||
_subs = subs;
|
||||
public void setManagedInstanceType(Class type, boolean subs) {
|
||||
this.type = type;
|
||||
this.subs = subs;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -121,16 +107,16 @@ public abstract class OpenJPAId implements Comparable, Serializable {
|
|||
*/
|
||||
public int hashCode() {
|
||||
if (_typeHash == 0) {
|
||||
Integer typeHashInt = (Integer) _typeCache.get(getType());
|
||||
Integer typeHashInt = (Integer) _typeCache.get(type);
|
||||
if (typeHashInt == null) {
|
||||
Class<?> base = getType();
|
||||
Class<?> superclass = base.getSuperclass();
|
||||
Class base = type;
|
||||
Class superclass = base.getSuperclass();
|
||||
while (superclass != null && superclass != Object.class) {
|
||||
base = base.getSuperclass();
|
||||
superclass = base.getSuperclass();
|
||||
}
|
||||
_typeHash = base.hashCode();
|
||||
_typeCache.put(getType(), Integer.valueOf(_typeHash));
|
||||
_typeCache.put(type, Integer.valueOf(_typeHash));
|
||||
} else {
|
||||
_typeHash = typeHashInt.intValue();
|
||||
}
|
||||
|
@ -145,12 +131,12 @@ public abstract class OpenJPAId implements Comparable, Serializable {
|
|||
return false;
|
||||
|
||||
OpenJPAId id = (OpenJPAId) o;
|
||||
return idEquals(id)
|
||||
&& (id.getType().isAssignableFrom(getType()) || (_subs && getType().isAssignableFrom(id.getType())));
|
||||
return idEquals(id) && (id.type.isAssignableFrom(type)
|
||||
|| (subs && type.isAssignableFrom(id.type)));
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getType().getName() + TYPE_VALUE_SEP + getIdObject();
|
||||
return type.getName() + TYPE_VALUE_SEP + getIdObject();
|
||||
}
|
||||
|
||||
public int compareTo(Object other) {
|
||||
|
@ -158,6 +144,6 @@ public abstract class OpenJPAId implements Comparable, Serializable {
|
|||
return 0;
|
||||
if (other == null)
|
||||
return 1;
|
||||
return ((Comparable) getIdObject()).compareTo(((OpenJPAId) other).getIdObject());
|
||||
}
|
||||
return ((Comparable) getIdObject()).compareTo(((OpenJPAId) other).getIdObject ());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,171 +0,0 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.openjpa.kernel;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.openjpa.conf.OpenJPAConfiguration;
|
||||
import org.apache.openjpa.enhance.DynamicStorage;
|
||||
import org.apache.openjpa.enhance.DynamicStorageGenerator;
|
||||
import org.apache.openjpa.meta.ClassMetaData;
|
||||
import org.apache.openjpa.meta.JavaTypes;
|
||||
import org.apache.openjpa.meta.MetaDataRepository;
|
||||
import org.apache.openjpa.util.IntId;
|
||||
import org.apache.openjpa.util.OpenJPAId;
|
||||
|
||||
/**
|
||||
* This test ensures that we can stream a PCData and OpenJPAId to a client which may not have the Entities on it's
|
||||
* classpath. In a real use case we would have multiple processes, but for the sake of unit testing this behavior is
|
||||
* simulated via multiple classloaders.
|
||||
*/
|
||||
public class TestPCDataSerialization extends TestCase {
|
||||
ClassLoader _ccl;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
_ccl = Thread.currentThread().getContextClassLoader();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
Thread.currentThread().setContextClassLoader(_ccl);
|
||||
}
|
||||
|
||||
public void test() throws Exception {
|
||||
// Generate a new class. This will create a new class, and load it with a new classloader.
|
||||
Class<?> cls = generateClass();
|
||||
ClassLoader newLoader = cls.getClassLoader();
|
||||
Thread.currentThread().setContextClassLoader(newLoader);
|
||||
|
||||
// Create moc objects
|
||||
MetaDataRepository repo = new DummyMetaDataRepository();
|
||||
ClassMetaData cmd = new DummyClassMetaData(cls, repo);
|
||||
|
||||
OpenJPAId oid = new IntId(cls, 7);
|
||||
PCDataImpl pcdi = new PCDataImpl(oid, cmd);
|
||||
|
||||
// Write the object out using the newly created classloader
|
||||
byte[] bytes = writeObject(pcdi);
|
||||
|
||||
// Switch contextclassloader back to the original and try to deserialize
|
||||
Thread.currentThread().setContextClassLoader(_ccl);
|
||||
|
||||
pcdi = (PCDataImpl) readObject(bytes);
|
||||
assertNotNull(pcdi);
|
||||
try {
|
||||
// This will throw a wrapped ClassNotFoundException because the domain class isn't available.
|
||||
pcdi.getType();
|
||||
fail("Should have thrown an exception.");
|
||||
} catch (RuntimeException cnfe) {
|
||||
// expected
|
||||
}
|
||||
// Write object without the class
|
||||
bytes = writeObject(pcdi);
|
||||
|
||||
// Switch to loader that has the new class and make sure we find it again.
|
||||
Thread.currentThread().setContextClassLoader(newLoader);
|
||||
pcdi = (PCDataImpl) readObject(bytes);
|
||||
assertNotNull(pcdi);
|
||||
assertEquals(cls, pcdi.getType());
|
||||
|
||||
}
|
||||
|
||||
private byte[] writeObject(Object o) throws Exception {
|
||||
ByteArrayOutputStream baos = null;
|
||||
ObjectOutputStream oos = null;
|
||||
try {
|
||||
baos = new ByteArrayOutputStream();
|
||||
oos = new ObjectOutputStream(baos);
|
||||
oos.writeObject(o);
|
||||
|
||||
return baos.toByteArray();
|
||||
} finally {
|
||||
if (oos != null) {
|
||||
oos.close();
|
||||
}
|
||||
if (baos != null) {
|
||||
baos.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Object readObject(byte[] bytes) throws Exception {
|
||||
ByteArrayInputStream bais = null;
|
||||
ObjectInputStream ois = null;
|
||||
try {
|
||||
bais = new ByteArrayInputStream(bytes);
|
||||
ois = new ObjectInputStream(bais);
|
||||
return ois.readObject();
|
||||
} finally {
|
||||
if (ois != null) {
|
||||
ois.close();
|
||||
}
|
||||
if (bais != null) {
|
||||
bais.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Class<?> generateClass() {
|
||||
DynamicStorageGenerator gen = new DynamicStorageGenerator();
|
||||
int[] types =
|
||||
new int[] { JavaTypes.BOOLEAN, JavaTypes.BYTE, JavaTypes.CHAR, JavaTypes.INT, JavaTypes.SHORT,
|
||||
JavaTypes.LONG, JavaTypes.FLOAT, JavaTypes.DOUBLE, JavaTypes.STRING, JavaTypes.OBJECT };
|
||||
DynamicStorage storage = gen.generateStorage(types, "org.apache.openjpa.enhance.Test");
|
||||
storage = storage.newInstance();
|
||||
|
||||
return storage.getClass();
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
class DummyClassMetaData extends ClassMetaData {
|
||||
public DummyClassMetaData(Class<?> cls, MetaDataRepository repo) {
|
||||
super(cls, repo);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
class DummyMetaDataRepository extends MetaDataRepository implements InvocationHandler {
|
||||
OpenJPAConfiguration _conf;
|
||||
|
||||
public DummyMetaDataRepository() {
|
||||
_conf =
|
||||
(OpenJPAConfiguration) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
|
||||
new Class[] { OpenJPAConfiguration.class }, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OpenJPAConfiguration getConfiguration() {
|
||||
return _conf;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue