mirror of https://github.com/apache/openjpa.git
OPENJPA-2911 move ApplicationIdTool from Serp to ASM
This commit is contained in:
parent
f19ba018e2
commit
39c838a56f
|
@ -110,5 +110,5 @@ public class ApplicationIdToolTask
|
||||||
: Files.getFile(dirName, getClassLoader());
|
: Files.getFile(dirName, getClassLoader());
|
||||||
ApplicationIdTool.run((OpenJPAConfiguration) getConfiguration(), files,
|
ApplicationIdTool.run((OpenJPAConfiguration) getConfiguration(), files,
|
||||||
flags, getClassLoader ());
|
flags, getClassLoader ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,12 +57,12 @@ import org.apache.openjpa.meta.JavaTypes;
|
||||||
import org.apache.openjpa.meta.MetaDataFactory;
|
import org.apache.openjpa.meta.MetaDataFactory;
|
||||||
import org.apache.openjpa.meta.MetaDataModes;
|
import org.apache.openjpa.meta.MetaDataModes;
|
||||||
import org.apache.openjpa.meta.MetaDataRepository;
|
import org.apache.openjpa.meta.MetaDataRepository;
|
||||||
|
import org.apache.openjpa.util.GeneratedClasses;
|
||||||
import org.apache.openjpa.util.InvalidStateException;
|
import org.apache.openjpa.util.InvalidStateException;
|
||||||
import org.apache.openjpa.util.UserException;
|
import org.apache.openjpa.util.UserException;
|
||||||
|
import org.apache.xbean.asm9.ClassWriter;
|
||||||
import serp.bytecode.BCClass;
|
import org.apache.xbean.asm9.Opcodes;
|
||||||
import serp.bytecode.BCClassLoader;
|
import org.apache.xbean.asm9.Type;
|
||||||
import serp.bytecode.Project;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a class appropriate for use as an application identity class.
|
* Generates a class appropriate for use as an application identity class.
|
||||||
|
@ -116,8 +116,7 @@ public class ApplicationIdTool {
|
||||||
* Constructs a new tool instance capable of generating an
|
* Constructs a new tool instance capable of generating an
|
||||||
* object id class for <code>meta</code>.
|
* object id class for <code>meta</code>.
|
||||||
*/
|
*/
|
||||||
public ApplicationIdTool(OpenJPAConfiguration conf, Class type,
|
public ApplicationIdTool(OpenJPAConfiguration conf, Class type, ClassMetaData meta) {
|
||||||
ClassMetaData meta) {
|
|
||||||
_log = conf.getLog(OpenJPAConfiguration.LOG_ENHANCE);
|
_log = conf.getLog(OpenJPAConfiguration.LOG_ENHANCE);
|
||||||
|
|
||||||
_type = type;
|
_type = type;
|
||||||
|
@ -828,8 +827,8 @@ public class ApplicationIdTool {
|
||||||
append(name).closeParen().closeParen();
|
append(name).closeParen().closeParen();
|
||||||
} else if (type == char[].class) {
|
} else if (type == char[].class) {
|
||||||
// ((name == null && other.name == null)
|
// ((name == null && other.name == null)
|
||||||
// || (name != null && String.valueOf (name).
|
// || (name != null && String.valueOf (name).
|
||||||
// equals (String.valueOf (other.name))))
|
// equals (String.valueOf (other.name))))
|
||||||
code.append("(").openParen(false).append(name).
|
code.append("(").openParen(false).append(name).
|
||||||
append(" == null && other.").append(name).
|
append(" == null && other.").append(name).
|
||||||
append(" == null").closeParen().endl();
|
append(" == null").closeParen().endl();
|
||||||
|
@ -843,7 +842,7 @@ public class ApplicationIdTool {
|
||||||
closeParen().append(")");
|
closeParen().append(")");
|
||||||
} else {
|
} else {
|
||||||
// ((name == null && other.name == null)
|
// ((name == null && other.name == null)
|
||||||
// || (name != null && name.equals (other.name)))
|
// || (name != null && name.equals (other.name)))
|
||||||
code.append("(").openParen(false).append(name).
|
code.append("(").openParen(false).append(name).
|
||||||
append(" == null && other.").append(name).
|
append(" == null && other.").append(name).
|
||||||
append(" == null").closeParen().endl();
|
append(" == null").closeParen().endl();
|
||||||
|
@ -1375,14 +1374,12 @@ public class ApplicationIdTool {
|
||||||
ApplicationIdTool tool;
|
ApplicationIdTool tool;
|
||||||
Class cls;
|
Class cls;
|
||||||
ClassMetaData meta;
|
ClassMetaData meta;
|
||||||
BCClassLoader bc = AccessController
|
|
||||||
.doPrivileged(J2DoPrivHelper.newBCClassLoaderAction(new Project()));
|
|
||||||
for (Object aClass : classes) {
|
for (Object aClass : classes) {
|
||||||
cls = (Class) aClass;
|
cls = (Class) aClass;
|
||||||
log.info(_loc.get("appid-running", cls));
|
log.info(_loc.get("appid-running", cls));
|
||||||
|
|
||||||
meta = repos.getMetaData(cls, null, false);
|
meta = repos.getMetaData(cls, null, false);
|
||||||
setObjectIdType(meta, flags, bc);
|
setObjectIdType(meta, flags);
|
||||||
|
|
||||||
tool = new ApplicationIdTool(conf, cls, meta);
|
tool = new ApplicationIdTool(conf, cls, meta);
|
||||||
tool.setDirectory(flags.directory);
|
tool.setDirectory(flags.directory);
|
||||||
|
@ -1396,15 +1393,13 @@ public class ApplicationIdTool {
|
||||||
else
|
else
|
||||||
log.info(_loc.get("appid-norun"));
|
log.info(_loc.get("appid-norun"));
|
||||||
}
|
}
|
||||||
bc.getProject().clear();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the object id type of the given metadata.
|
* Set the object id type of the given metadata.
|
||||||
*/
|
*/
|
||||||
private static void setObjectIdType(ClassMetaData meta, Flags flags,
|
private static void setObjectIdType(ClassMetaData meta, Flags flags)
|
||||||
BCClassLoader bc)
|
|
||||||
throws ClassNotFoundException {
|
throws ClassNotFoundException {
|
||||||
if (meta == null || (meta.getObjectIdType() != null
|
if (meta == null || (meta.getObjectIdType() != null
|
||||||
&& (!meta.isOpenJPAIdentity() || flags.name == null))
|
&& (!meta.isOpenJPAIdentity() || flags.name == null))
|
||||||
|
@ -1413,18 +1408,19 @@ public class ApplicationIdTool {
|
||||||
|
|
||||||
Class desc = meta.getDescribedType();
|
Class desc = meta.getDescribedType();
|
||||||
Class cls = null;
|
Class cls = null;
|
||||||
if (flags.name != null)
|
if (flags.name != null) {
|
||||||
cls = loadClass(desc, flags.name, bc);
|
cls = loadClass(desc, flags.name);
|
||||||
else if (flags.suffix != null)
|
}
|
||||||
cls = loadClass(desc, desc.getName() + flags.suffix, bc);
|
else if (flags.suffix != null) {
|
||||||
|
cls = loadClass(desc, desc.getName() + flags.suffix);
|
||||||
|
}
|
||||||
meta.setObjectIdType(cls, false);
|
meta.setObjectIdType(cls, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load the given class name even if it does not exist.
|
* Load the given class name even if it does not exist.
|
||||||
*/
|
*/
|
||||||
private static Class loadClass(Class context, String name,
|
private static Class loadClass(Class context, String name)
|
||||||
BCClassLoader bc)
|
|
||||||
throws ClassNotFoundException {
|
throws ClassNotFoundException {
|
||||||
if (name.indexOf('.') == -1 && context.getName().indexOf('.') != -1)
|
if (name.indexOf('.') == -1 && context.getName().indexOf('.') != -1)
|
||||||
name = ClassUtil.getPackageName(context) + "." + name;
|
name = ClassUtil.getPackageName(context) + "." + name;
|
||||||
|
@ -1441,9 +1437,16 @@ public class ApplicationIdTool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// create class
|
// create class
|
||||||
|
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
|
||||||
|
cw.visit(Opcodes.V11, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, name.replace(".", "/"),
|
||||||
|
null, Type.getInternalName(Object.class), null);
|
||||||
|
|
||||||
|
return GeneratedClasses.loadAsmClass(name, cw.toByteArray(), context, context.getClassLoader());
|
||||||
|
/*X TODO DELETE
|
||||||
BCClass oid = bc.getProject().loadClass(name, null);
|
BCClass oid = bc.getProject().loadClass(name, null);
|
||||||
oid.addDefaultConstructor();
|
oid.addDefaultConstructor();
|
||||||
return Class.forName(name, false, bc);
|
return Class.forName(name, false, bc);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1479,11 +1482,11 @@ public class ApplicationIdTool {
|
||||||
* object id classes.
|
* object id classes.
|
||||||
*/
|
*/
|
||||||
public interface ObjectIdLoader
|
public interface ObjectIdLoader
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Turn on the loading of all identity classes, even if they don't
|
* Turn on the loading of all identity classes, even if they don't
|
||||||
* exist.
|
* exist.
|
||||||
*/
|
*/
|
||||||
void setLoadObjectIds ();
|
void setLoadObjectIds ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,6 +87,7 @@
|
||||||
<exclude name="**/unenhanced/*.class" />
|
<exclude name="**/unenhanced/*.class" />
|
||||||
<exclude name="**/persistence/property/AccessModsEntity.class"/>
|
<exclude name="**/persistence/property/AccessModsEntity.class"/>
|
||||||
<exclude name="org/apache/openjpa/enhance/ids/*.class"/>
|
<exclude name="org/apache/openjpa/enhance/ids/*.class"/>
|
||||||
|
<exclude name="org/apache/openjpa/idtool/RecordsPerYear.class"/>
|
||||||
</fileset>
|
</fileset>
|
||||||
<openjpac>
|
<openjpac>
|
||||||
<classpath refid="cp" />
|
<classpath refid="cp" />
|
||||||
|
|
|
@ -149,7 +149,8 @@ public class TestEnhancementWithMultiplePUs
|
||||||
// not attempt to enhance.
|
// not attempt to enhance.
|
||||||
opts.setProperty("MetaDataRepository",
|
opts.setProperty("MetaDataRepository",
|
||||||
"org.apache.openjpa.enhance.RestrictedMetaDataRepository(excludedTypes=" +
|
"org.apache.openjpa.enhance.RestrictedMetaDataRepository(excludedTypes=" +
|
||||||
"org.apache.openjpa.persistence.jdbc.annotations.UnenhancedMixedAccess)");
|
"\"org.apache.openjpa.persistence.jdbc.annotations.UnenhancedMixedAccess," +
|
||||||
|
"org.apache.openjpa.idtool.RecordsPerYear\")");
|
||||||
opts.put(PCEnhancer.class.getName() + "#bytecodeWriter", writer);
|
opts.put(PCEnhancer.class.getName() + "#bytecodeWriter", writer);
|
||||||
PCEnhancer.run(null, opts);
|
PCEnhancer.run(null, opts);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* 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.idtool;
|
||||||
|
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entity for testing the {@link org.apache.openjpa.enhance.ApplicationIdTool}.
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
public class RecordsPerYear {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private String user;
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private int year;
|
||||||
|
|
||||||
|
private long counter;
|
||||||
|
|
||||||
|
public String getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUser(String user) {
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getYear() {
|
||||||
|
return year;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setYear(int year) {
|
||||||
|
this.year = year;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getCounter() {
|
||||||
|
return counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCounter(long counter) {
|
||||||
|
this.counter = counter;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.idtool;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
|
||||||
|
import org.apache.openjpa.enhance.ApplicationIdTool;
|
||||||
|
import org.apache.openjpa.persistence.jdbc.common.apps.AutoIncrementPC3;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for the ApplicationIdTool from openjpa-kernel.
|
||||||
|
* We cannot test it over in the openjpa-kernel package as
|
||||||
|
* we'd not be able to also test JPA features.
|
||||||
|
*/
|
||||||
|
public class TestApplicationIdTool {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testApplicationIdTool_wIdClassAnnotation() throws Exception{
|
||||||
|
String entityJavaFile = "./src/test/java/" + AutoIncrementPC3.class.getName().replace(".", "/") + ".java";
|
||||||
|
final String outputDir = "./target/idtooltest/";
|
||||||
|
ApplicationIdTool.main(new String[]{"-s","Id", entityJavaFile, "-d", outputDir});
|
||||||
|
|
||||||
|
String idJavaFile = outputDir + AutoIncrementPC3.class.getName().replace(".", "/") + "Id.java";
|
||||||
|
|
||||||
|
assertTrue(new File(idJavaFile).exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testApplicationIdTool_freshClass() throws Exception{
|
||||||
|
String entityJavaFile = "./src/test/java/" + RecordsPerYear.class.getName().replace(".", "/") + ".java";
|
||||||
|
final String outputDir = "./target/idtooltest/";
|
||||||
|
ApplicationIdTool.main(new String[]{"-s","Id", entityJavaFile, "-d", outputDir});
|
||||||
|
|
||||||
|
String idJavaFile = outputDir + RecordsPerYear.class.getName().replace(".", "/") + "Id.java";
|
||||||
|
|
||||||
|
final File generatedIdFile = new File(idJavaFile);
|
||||||
|
assertTrue(generatedIdFile.exists());
|
||||||
|
assertContains(generatedIdFile, "public class RecordsPerYearId");
|
||||||
|
assertContains(generatedIdFile, "public RecordsPerYearId(String str)");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertContains(File file, String find) throws IOException {
|
||||||
|
final byte[] bytes = Files.readAllBytes(file.toPath());
|
||||||
|
assertTrue(new String(bytes).contains(find));
|
||||||
|
}
|
||||||
|
}
|
|
@ -41,70 +41,71 @@ import jakarta.persistence.Table;
|
||||||
@Table(name="AUTOINCPC3")
|
@Table(name="AUTOINCPC3")
|
||||||
public class AutoIncrementPC3
|
public class AutoIncrementPC3
|
||||||
{
|
{
|
||||||
@Id
|
@Id
|
||||||
private long id = 0;
|
private long id = 0;
|
||||||
|
|
||||||
private Set setField = new HashSet ();
|
private Set setField = new HashSet ();
|
||||||
|
|
||||||
@Column(name="strngfld", length=50)
|
@Column(name="strngfld", length=50)
|
||||||
private String stringField = null;
|
private String stringField = null;
|
||||||
|
|
||||||
@OneToOne(cascade={CascadeType.PERSIST, CascadeType.REMOVE})
|
@OneToOne(cascade={CascadeType.PERSIST, CascadeType.REMOVE})
|
||||||
private AutoIncrementPC3 oneOne = null;
|
private AutoIncrementPC3 oneOne = null;
|
||||||
|
|
||||||
public AutoIncrementPC3()
|
public AutoIncrementPC3()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public AutoIncrementPC3(int id)
|
public AutoIncrementPC3(int id)
|
||||||
{
|
{
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public long getId ()
|
public long getId ()
|
||||||
{
|
{
|
||||||
return this.id;
|
return this.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setId (long id)
|
public void setId (long id)
|
||||||
{
|
{
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Set getSetField ()
|
public Set getSetField ()
|
||||||
{
|
{
|
||||||
return this.setField;
|
return this.setField;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setSetField (Set setField)
|
public void setSetField (Set setField)
|
||||||
{
|
{
|
||||||
this.setField = setField;
|
this.setField = setField;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public String getStringField ()
|
public String getStringField ()
|
||||||
{
|
{
|
||||||
return this.stringField;
|
return this.stringField;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setStringField (String stringField)
|
public void setStringField (String stringField)
|
||||||
{
|
{
|
||||||
this.stringField = stringField;
|
this.stringField = stringField;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public AutoIncrementPC3 getOneOne ()
|
public AutoIncrementPC3 getOneOne ()
|
||||||
{
|
{
|
||||||
return this.oneOne;
|
return this.oneOne;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setOneOne (AutoIncrementPC3 oneOne)
|
public void setOneOne (AutoIncrementPC3 oneOne)
|
||||||
{
|
{
|
||||||
this.oneOne = oneOne;
|
this.oneOne = oneOne;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue