OPENJPA-2911 move ApplicationIdTool from Serp to ASM
diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/ant/ApplicationIdToolTask.java b/openjpa-kernel/src/main/java/org/apache/openjpa/ant/ApplicationIdToolTask.java
index df19c35..634f0d8 100755
--- a/openjpa-kernel/src/main/java/org/apache/openjpa/ant/ApplicationIdToolTask.java
+++ b/openjpa-kernel/src/main/java/org/apache/openjpa/ant/ApplicationIdToolTask.java
@@ -110,5 +110,5 @@
             : Files.getFile(dirName, getClassLoader());
         ApplicationIdTool.run((OpenJPAConfiguration) getConfiguration(), files,
             flags, getClassLoader ());
-	}
+    }
 }
diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/ApplicationIdTool.java b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/ApplicationIdTool.java
index 922b558..680991c 100644
--- a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/ApplicationIdTool.java
+++ b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/ApplicationIdTool.java
@@ -57,12 +57,12 @@
 import org.apache.openjpa.meta.MetaDataFactory;
 import org.apache.openjpa.meta.MetaDataModes;
 import org.apache.openjpa.meta.MetaDataRepository;
+import org.apache.openjpa.util.GeneratedClasses;
 import org.apache.openjpa.util.InvalidStateException;
 import org.apache.openjpa.util.UserException;
-
-import serp.bytecode.BCClass;
-import serp.bytecode.BCClassLoader;
-import serp.bytecode.Project;
+import org.apache.xbean.asm9.ClassWriter;
+import org.apache.xbean.asm9.Opcodes;
+import org.apache.xbean.asm9.Type;
 
 /**
  * Generates a class appropriate for use as an application identity class.
@@ -116,8 +116,7 @@
      * Constructs a new tool instance capable of generating an
      * object id class for <code>meta</code>.
      */
-    public ApplicationIdTool(OpenJPAConfiguration conf, Class type,
-        ClassMetaData meta) {
+    public ApplicationIdTool(OpenJPAConfiguration conf, Class type, ClassMetaData meta) {
         _log = conf.getLog(OpenJPAConfiguration.LOG_ENHANCE);
 
         _type = type;
@@ -828,8 +827,8 @@
                     append(name).closeParen().closeParen();
             } else if (type == char[].class) {
                 // ((name == null && other.name == null)
-                //	|| (name != null && String.valueOf (name).
-                //	equals (String.valueOf (other.name))))
+                //    || (name != null && String.valueOf (name).
+                //    equals (String.valueOf (other.name))))
                 code.append("(").openParen(false).append(name).
                     append(" == null && other.").append(name).
                     append(" == null").closeParen().endl();
@@ -843,7 +842,7 @@
                     closeParen().append(")");
             } else {
                 // ((name == null && other.name == null)
-                //	|| (name != null && name.equals (other.name)))
+                //    || (name != null && name.equals (other.name)))
                 code.append("(").openParen(false).append(name).
                     append(" == null && other.").append(name).
                     append(" == null").closeParen().endl();
@@ -1375,14 +1374,12 @@
         ApplicationIdTool tool;
         Class cls;
         ClassMetaData meta;
-        BCClassLoader bc = AccessController
-            .doPrivileged(J2DoPrivHelper.newBCClassLoaderAction(new Project()));
         for (Object aClass : classes) {
             cls = (Class) aClass;
             log.info(_loc.get("appid-running", cls));
 
             meta = repos.getMetaData(cls, null, false);
-            setObjectIdType(meta, flags, bc);
+            setObjectIdType(meta, flags);
 
             tool = new ApplicationIdTool(conf, cls, meta);
             tool.setDirectory(flags.directory);
@@ -1396,15 +1393,13 @@
             else
                 log.info(_loc.get("appid-norun"));
         }
-        bc.getProject().clear();
         return true;
     }
 
     /**
      * Set the object id type of the given metadata.
      */
-    private static void setObjectIdType(ClassMetaData meta, Flags flags,
-        BCClassLoader bc)
+    private static void setObjectIdType(ClassMetaData meta, Flags flags)
         throws ClassNotFoundException {
         if (meta == null || (meta.getObjectIdType() != null
             && (!meta.isOpenJPAIdentity() || flags.name == null))
@@ -1413,18 +1408,19 @@
 
         Class desc = meta.getDescribedType();
         Class cls = null;
-        if (flags.name != null)
-            cls = loadClass(desc, flags.name, bc);
-        else if (flags.suffix != null)
-            cls = loadClass(desc, desc.getName() + flags.suffix, bc);
+        if (flags.name != null) {
+            cls = loadClass(desc, flags.name);
+        }
+        else if (flags.suffix != null) {
+            cls = loadClass(desc, desc.getName() + flags.suffix);
+        }
         meta.setObjectIdType(cls, false);
     }
 
     /**
      * Load the given class name even if it does not exist.
      */
-    private static Class loadClass(Class context, String name,
-        BCClassLoader bc)
+    private static Class loadClass(Class context, String name)
         throws ClassNotFoundException {
         if (name.indexOf('.') == -1 && context.getName().indexOf('.') != -1)
             name = ClassUtil.getPackageName(context) + "." + name;
@@ -1441,9 +1437,16 @@
         }
 
         // 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);
         oid.addDefaultConstructor();
         return Class.forName(name, false, bc);
+*/
     }
 
     /**
@@ -1479,11 +1482,11 @@
      * object id classes.
      */
     public interface ObjectIdLoader
-	{
-		/**
+    {
+        /**
          * Turn on the loading of all identity classes, even if they don't
          * exist.
-	 	 */
-		void setLoadObjectIds ();
-	}
+          */
+        void setLoadObjectIds ();
+    }
 }
diff --git a/openjpa-persistence-jdbc/src/main/ant/enhancer.xml b/openjpa-persistence-jdbc/src/main/ant/enhancer.xml
index 6168491..8fed766 100644
--- a/openjpa-persistence-jdbc/src/main/ant/enhancer.xml
+++ b/openjpa-persistence-jdbc/src/main/ant/enhancer.xml
@@ -87,6 +87,7 @@
             <exclude name="**/unenhanced/*.class" />
             <exclude name="**/persistence/property/AccessModsEntity.class"/>
             <exclude name="org/apache/openjpa/enhance/ids/*.class"/>
+            <exclude name="org/apache/openjpa/idtool/RecordsPerYear.class"/>
         </fileset>
         <openjpac>
             <classpath refid="cp" />
diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/TestEnhancementWithMultiplePUs.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/TestEnhancementWithMultiplePUs.java
index adb9fdb..a6c63ac 100644
--- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/TestEnhancementWithMultiplePUs.java
+++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/TestEnhancementWithMultiplePUs.java
@@ -149,7 +149,8 @@
         // not attempt to enhance.
         opts.setProperty("MetaDataRepository",
             "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);
         PCEnhancer.run(null, opts);
 
diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/idtool/RecordsPerYear.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/idtool/RecordsPerYear.java
new file mode 100644
index 0000000..0cbeb5c
--- /dev/null
+++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/idtool/RecordsPerYear.java
@@ -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;
+    }
+}
diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/idtool/TestApplicationIdTool.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/idtool/TestApplicationIdTool.java
new file mode 100644
index 0000000..62af291
--- /dev/null
+++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/idtool/TestApplicationIdTool.java
@@ -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));
+    }
+}
diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/common/apps/AutoIncrementPC3.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/common/apps/AutoIncrementPC3.java
index 7de213c..05751ec 100644
--- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/common/apps/AutoIncrementPC3.java
+++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/common/apps/AutoIncrementPC3.java
@@ -41,70 +41,71 @@
 @Table(name="AUTOINCPC3")
 public class AutoIncrementPC3
 {
-	@Id
-	private long				id			= 0;
+    @Id
+    private long				id			= 0;
+
     private Set                 setField    = new HashSet ();
 
-	@Column(name="strngfld", length=50)
-	private String				stringField	= null;
+    @Column(name="strngfld", length=50)
+    private String				stringField	= null;
 
-	@OneToOne(cascade={CascadeType.PERSIST, CascadeType.REMOVE})
-	private AutoIncrementPC3	oneOne		= null;
+    @OneToOne(cascade={CascadeType.PERSIST, CascadeType.REMOVE})
+    private AutoIncrementPC3	oneOne		= null;
 
-	public AutoIncrementPC3()
-	{
-	}
+    public AutoIncrementPC3()
+    {
+    }
 
-	public AutoIncrementPC3(int id)
-	{
-		this.id = id;
-	}
+    public AutoIncrementPC3(int id)
+    {
+        this.id = id;
+    }
 
 
-	public long getId ()
-	{
-		return this.id;
-	}
+    public long getId ()
+    {
+        return this.id;
+    }
 
 
-	public void setId (long id)
-	{
-		this.id = id;
-	}
+    public void setId (long id)
+    {
+        this.id = id;
+    }
 
 
-	public Set getSetField ()
-	{
-		return this.setField;
-	}
+    public Set getSetField ()
+    {
+        return this.setField;
+    }
 
 
-	public void setSetField (Set setField)
-	{
-		this.setField = setField;
-	}
+    public void setSetField (Set setField)
+    {
+        this.setField = setField;
+    }
 
 
-	public String getStringField ()
-	{
-		return this.stringField;
-	}
+    public String getStringField ()
+    {
+        return this.stringField;
+    }
 
 
-	public void setStringField (String stringField)
-	{
-		this.stringField = stringField;
-	}
+    public void setStringField (String stringField)
+    {
+        this.stringField = stringField;
+    }
 
 
-	public AutoIncrementPC3 getOneOne ()
-	{
-		return this.oneOne;
-	}
+    public AutoIncrementPC3 getOneOne ()
+    {
+        return this.oneOne;
+    }
 
 
-	public void setOneOne (AutoIncrementPC3 oneOne)
-	{
-		this.oneOne = oneOne;
-	}
+    public void setOneOne (AutoIncrementPC3 oneOne)
+    {
+        this.oneOne = oneOne;
+    }
 }