OPENJPA-1912: Generate externalizable methods correctly for super and subclasses - back ported to 2.1.x Mark Struberg's trunk changes.

git-svn-id: https://svn.apache.org/repos/asf/openjpa/branches/2.1.x@1483996 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Heath Thomann 2013-05-17 21:23:43 +00:00
parent f05c3de7c8
commit 5f824a2c5f
6 changed files with 287 additions and 8 deletions

View File

@ -4041,7 +4041,10 @@ public class PCEnhancer {
Code code = meth.getCode(true);
// super.readExternal (in);
Class sup = _meta.getDescribedType().getSuperclass();
// not sure if this works: this is depending on the order of the enhancement!
// if the subclass gets enhanced first, then the superclass misses
// the Externalizable at this point!
Class<?> sup = _meta.getDescribedType().getSuperclass();
if (!parentDetachable && Externalizable.class.isAssignableFrom(sup)) {
loadManagedInstance(code, false);
code.aload().setParam(0);
@ -4074,12 +4077,44 @@ public class PCEnhancer {
void.class, new Class[]{ StateManager.class });
}
addReadExternalFields();
// readExternalFields(in.readObject ());
loadManagedInstance(code, false);
code.aload().setParam(0);
code.invokevirtual().setMethod("readExternalFields",
void.class, inargs);
code.vreturn();
code.calculateMaxStack();
code.calculateMaxLocals();
}
private void addReadExternalFields() throws NoSuchMethodException {
Class<?>[] inargs = new Class[]{ ObjectInput.class };
BCMethod meth = _pc.declareMethod("readExternalFields", void.class, inargs);
meth.setAccessFlags(Constants.ACCESS_PROTECTED);
Exceptions exceps = meth.getExceptions(true);
exceps.addException(IOException.class);
exceps.addException(ClassNotFoundException.class);
Code code = meth.getCode(true);
Class<?> sup = _meta.getPCSuperclass();
if (sup != null) {
//add a call to super.readExternalFields()
loadManagedInstance(code, false);
code.aload().setParam(0);
code.invokespecial().setMethod(sup, "readExternalFields", void.class, inargs);
}
// read managed fields
FieldMetaData[] fmds = _meta.getFields();
for (int i = 0; i < fmds.length; i++)
if (!fmds[i].isTransient())
FieldMetaData[] fmds = _meta.getDeclaredFields();
for (int i = 0; i < fmds.length; i++) {
if (!fmds[i].isTransient()) {
readExternal(code, fmds[i].getName(),
fmds[i].getDeclaredType(), fmds[i]);
}
}
code.vreturn();
code.calculateMaxStack();
@ -4231,12 +4266,44 @@ public class PCEnhancer {
if (go2 != null)
go2.setTarget(code.nop());
// write managed fields
FieldMetaData[] fmds = _meta.getFields();
for (int i = 0; i < fmds.length; i++)
if (!fmds[i].isTransient())
addWriteExternalFields();
loadManagedInstance(code, false);
code.aload().setParam(0);
code.invokevirtual().setMethod("writeExternalFields",
void.class, outargs);
// return
code.vreturn();
code.calculateMaxStack();
code.calculateMaxLocals();
}
private void addWriteExternalFields()
throws NoSuchMethodException {
Class<?>[] outargs = new Class[]{ ObjectOutput.class };
BCMethod meth = _pc.declareMethod("writeExternalFields", void.class, outargs);
meth.setAccessFlags(Constants.ACCESS_PROTECTED);
Exceptions exceps = meth.getExceptions(true);
exceps.addException(IOException.class);
Code code = meth.getCode(true);
Class<?> sup = _meta.getPCSuperclass();
if (sup != null) {
// add a call to super.readExternalFields()
loadManagedInstance(code, false);
code.aload().setParam(0);
code.invokespecial().setMethod(sup, "writeExternalFields", void.class, outargs);
}
FieldMetaData[] fmds = _meta.getDeclaredFields();
for (int i = 0; i < fmds.length; i++) {
if (!fmds[i].isTransient()) {
writeExternal(code, fmds[i].getName(),
fmds[i].getDeclaredType(), fmds[i]);
}
}
// return
code.vreturn();

View File

@ -79,6 +79,8 @@
<exclude name="**/proxy/entities/*.class" />
<exclude name="**/xml/*.class" />
<exclude name="**/Unenhanced*.class" />
<exclude name="org/apache/openjpa/enhance/EnhancedSuperClass.class"/>
<exclude name="org/apache/openjpa/enhance/EnhancedSubClass.class"/>
<exclude name="**/AbstractUnenhanced*.class" />
<exclude name="**/unenhanced/*.class" />
<exclude name="**/persistence/property/AccessModsEntity.class"/>
@ -119,6 +121,16 @@
<include name="**/proxy/entities/*.class"/>
</fileset>
<config log="${openjpa.Log}" />
</openjpac>
<!-- Enhance with DetachedStateField=true option -->
<openjpac>
<config propertiesFile="${project.build.testOutputDirectory}/org/apache/openjpa/enhance/persistence1.xml" />
<classpath refid="cp" />
<fileset dir="${project.build.testOutputDirectory}">
<include name="org/apache/openjpa/enhance/EnhancedSuperClass.class"/>
<include name="org/apache/openjpa/enhance/EnhancedSubClass.class"/>
</fileset>
<config log="${openjpa.Log}" />
</openjpac>
<!-- Enhance delimited identifiers XML-based entities separately -->
<openjpac>

View File

@ -0,0 +1,41 @@
/*
* 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.enhance;
import javax.persistence.Entity;
import java.io.Serializable;
/**
* @see TestClassHierarchyEnhancement
*/
@Entity
public class EnhancedSubClass extends EnhancedSuperClass implements Serializable {
private static final long serialVersionUID = 2311337663046757789L;
private String valueInSubclass;
public String getValueInSubclass() {
return valueInSubclass;
}
public void setValueInSubclass(String valueInSubclass) {
this.valueInSubclass = valueInSubclass;
}
}

View File

@ -0,0 +1,57 @@
/*
* 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.enhance;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import java.io.Serializable;
/**
* @see TestClassHierarchyEnhancement
*/
@Entity
public class EnhancedSuperClass implements Serializable {
private static final long serialVersionUID = -4276267285828916940L;
@Id
@GeneratedValue
private Long id;
private String valueInSuperclass;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getValueInSuperclass() {
return valueInSuperclass;
}
public void setValueInSuperclass(String valueInSuperclass) {
this.valueInSuperclass = valueInSuperclass;
}
}

View File

@ -0,0 +1,65 @@
/*
* 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.enhance;
import org.apache.openjpa.persistence.test.SingleEMFTestCase;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
* This unit test checks the enhancement of a superclass/subclass
* constellation.
*/
public class TestClassHierarchyEnhancement extends SingleEMFTestCase {
/**
* This tests OPENJPA-1912.
*/
public void testSerialize() throws Exception {
// we don't even need an EntityManager for that ;)
EnhancedSubClass entity = new EnhancedSubClass();
entity.setValueInSubclass("sub");
entity.setValueInSuperclass("super");
byte[] serializedForm = serializeObject(entity);
EnhancedSubClass newEntity = (EnhancedSubClass) deSerializeObject(serializedForm);
}
private byte[] serializeObject(Object o) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(o);
return baos.toByteArray();
}
private Object deSerializeObject(byte[] serial)
throws IOException, ClassNotFoundException {
ByteArrayInputStream bais = new ByteArrayInputStream(serial);
ObjectInputStream ois = new ObjectInputStream(bais);
return ois.readObject();
}
}

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="1.0"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="enhancertest-pu">
<class>org.apache.openjpa.enhance.EnhancedSuperClass</class>
<class>org.apache.openjpa.enhance.EnhancedSubClass</class>
<properties>
<property name="openjpa.DynamicEnhancementAgent" value="false"/>
<property name="openjpa.DetachState" value="loaded(DetachedStateField=true)"/>
<property name="openjpa.jdbc.SynchronizeMappings"
value="buildSchema(ForeignKeys=true)"/>
</properties>
</persistence-unit>
</persistence>