starting to make openjpa-knight
diff --git a/arthur-impl/src/main/java/org/apache/geronimo/arthur/impl/nativeimage/generator/ConfigurationGenerator.java b/arthur-impl/src/main/java/org/apache/geronimo/arthur/impl/nativeimage/generator/ConfigurationGenerator.java
index 84796bc..b092e1d 100644
--- a/arthur-impl/src/main/java/org/apache/geronimo/arthur/impl/nativeimage/generator/ConfigurationGenerator.java
+++ b/arthur-impl/src/main/java/org/apache/geronimo/arthur/impl/nativeimage/generator/ConfigurationGenerator.java
@@ -186,31 +186,7 @@
final Iterator<ClassReflectionModel> modelIterator = classReflectionModels.iterator();
final ClassReflectionModel model = modelIterator.next();
while (modelIterator.hasNext()) {
- final ClassReflectionModel next = modelIterator.next();
- if (next.getAllDeclaredClasses()) {
- model.setAllDeclaredClasses(true);
- }
- if (next.getAllDeclaredFields()) {
- model.setAllDeclaredFields(true);
- }
- if (next.getAllDeclaredConstructors()) {
- model.setAllDeclaredConstructors(true);
- }
- if (next.getAllDeclaredMethods()) {
- model.setAllDeclaredMethods(true);
- }
- if (next.getAllPublicMethods()) {
- model.setAllPublicMethods(true);
- }
- if (next.getAllPublicFields()) {
- model.setAllPublicFields(true);
- }
- if (next.getAllPublicConstructors()) {
- model.setAllPublicConstructors(true);
- }
- if (next.getAllPublicClasses()) {
- model.setAllPublicClasses(true);
- }
+ model.merge(modelIterator.next());
}
return model;
}
diff --git a/arthur-impl/src/main/java/org/apache/geronimo/arthur/impl/nativeimage/generator/DefautContext.java b/arthur-impl/src/main/java/org/apache/geronimo/arthur/impl/nativeimage/generator/DefautContext.java
index 6cdbca0..fdbb9d9 100644
--- a/arthur-impl/src/main/java/org/apache/geronimo/arthur/impl/nativeimage/generator/DefautContext.java
+++ b/arthur-impl/src/main/java/org/apache/geronimo/arthur/impl/nativeimage/generator/DefautContext.java
@@ -85,8 +85,17 @@
@Override
public void register(final ClassReflectionModel classReflectionModel) {
- reflections.removeIf(it -> Objects.equals(classReflectionModel.getName(), it.getName()));
- reflections.add(classReflectionModel);
+ reflections.stream()
+ .filter(it -> Objects.equals(classReflectionModel.getName(), it.getName()))
+ .findFirst()
+ .map(it -> {
+ it.merge(classReflectionModel);
+ return it;
+ })
+ .orElseGet(() -> {
+ reflections.add(classReflectionModel);
+ return classReflectionModel;
+ });
modified = true;
}
@@ -98,9 +107,14 @@
@Override
public void register(final ResourceBundleModel resourceBundleModel) {
- bundles.removeIf(it -> Objects.equals(it.getName(), resourceBundleModel.getName()));
- bundles.add(resourceBundleModel);
- modified = true;
+ bundles.stream()
+ .filter(it -> Objects.equals(resourceBundleModel.getName(), it.getName()))
+ .findFirst()
+ .orElseGet(() -> {
+ modified = true;
+ bundles.add(resourceBundleModel);
+ return resourceBundleModel;
+ });
}
@Override
diff --git a/arthur-spi/src/main/java/org/apache/geronimo/arthur/spi/model/ClassReflectionModel.java b/arthur-spi/src/main/java/org/apache/geronimo/arthur/spi/model/ClassReflectionModel.java
index 7a064ac..81ff279 100644
--- a/arthur-spi/src/main/java/org/apache/geronimo/arthur/spi/model/ClassReflectionModel.java
+++ b/arthur-spi/src/main/java/org/apache/geronimo/arthur/spi/model/ClassReflectionModel.java
@@ -16,11 +16,15 @@
*/
package org.apache.geronimo.arthur.spi.model;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
import java.util.Collection;
-import lombok.Data;
-
@Data
+@NoArgsConstructor
+@AllArgsConstructor
public class ClassReflectionModel {
private String name;
private Boolean allDeclaredConstructors;
@@ -34,13 +38,60 @@
private Collection<FieldReflectionModel> fields;
private Collection<MethodReflectionModel> methods;
+ public ClassReflectionModel allPublic(final String name) {
+ return new ClassReflectionModel(name, null, true, null, true, null, null, null, true, null, null);
+ }
+
+ public ClassReflectionModel allPublicConstructors(final String name) {
+ return new ClassReflectionModel(name, null, true, null, null, null, null, null, null, null, null);
+ }
+
+ public ClassReflectionModel allDeclaredConstructors(final String name) {
+ return new ClassReflectionModel(name, null, null, true, null, null, null, null, null, null, null);
+ }
+
+ public ClassReflectionModel allDeclared(final String name) {
+ return new ClassReflectionModel(name, true, null, true, null, null, null, true, null, null, null);
+ }
+
+ public void merge(final ClassReflectionModel other) {
+ if (other.getAllDeclaredClasses() != null && other.getAllDeclaredClasses()) {
+ setAllDeclaredClasses(true);
+ }
+ if (other.getAllDeclaredFields() != null && other.getAllDeclaredFields()) {
+ setAllDeclaredFields(true);
+ }
+ if (other.getAllDeclaredConstructors() != null && other.getAllDeclaredConstructors()) {
+ setAllDeclaredConstructors(true);
+ }
+ if (other.getAllDeclaredMethods() != null && other.getAllDeclaredMethods()) {
+ setAllDeclaredMethods(true);
+ }
+ if (other.getAllPublicMethods() != null && other.getAllPublicMethods()) {
+ setAllPublicMethods(true);
+ }
+ if (other.getAllPublicFields() != null && other.getAllPublicFields()) {
+ setAllPublicFields(true);
+ }
+ if (other.getAllPublicConstructors() != null && other.getAllPublicConstructors()) {
+ setAllPublicConstructors(true);
+ }
+ if (other.getAllPublicClasses() != null && other.getAllPublicClasses()) {
+ setAllPublicClasses(true);
+ }
+ }
+
@Data
+ @NoArgsConstructor
+ @AllArgsConstructor
public static class FieldReflectionModel {
private String name;
private Boolean allowWrite;
}
@Data
+ @NoArgsConstructor
+ @AllArgsConstructor
public static class MethodReflectionModel {
private String name;
private Collection<Class<?>> parameterTypes;
diff --git a/arthur-spi/src/main/java/org/apache/geronimo/arthur/spi/model/DynamicProxyModel.java b/arthur-spi/src/main/java/org/apache/geronimo/arthur/spi/model/DynamicProxyModel.java
index 661a4f0..9c0c7d9 100644
--- a/arthur-spi/src/main/java/org/apache/geronimo/arthur/spi/model/DynamicProxyModel.java
+++ b/arthur-spi/src/main/java/org/apache/geronimo/arthur/spi/model/DynamicProxyModel.java
@@ -16,11 +16,15 @@
*/
package org.apache.geronimo.arthur.spi.model;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
import java.util.Collection;
-import lombok.Data;
-
@Data
+@NoArgsConstructor
+@AllArgsConstructor
public class DynamicProxyModel {
private Collection<String> classes;
}
diff --git a/arthur-spi/src/main/java/org/apache/geronimo/arthur/spi/model/ResourceBundleModel.java b/arthur-spi/src/main/java/org/apache/geronimo/arthur/spi/model/ResourceBundleModel.java
index 6c1c943..1a32723 100644
--- a/arthur-spi/src/main/java/org/apache/geronimo/arthur/spi/model/ResourceBundleModel.java
+++ b/arthur-spi/src/main/java/org/apache/geronimo/arthur/spi/model/ResourceBundleModel.java
@@ -16,9 +16,13 @@
*/
package org.apache.geronimo.arthur.spi.model;
+import lombok.AllArgsConstructor;
import lombok.Data;
+import lombok.NoArgsConstructor;
@Data
+@NoArgsConstructor
+@AllArgsConstructor
public class ResourceBundleModel {
private String name;
}
diff --git a/arthur-spi/src/main/java/org/apache/geronimo/arthur/spi/model/ResourceModel.java b/arthur-spi/src/main/java/org/apache/geronimo/arthur/spi/model/ResourceModel.java
index 549a4d1..8e9bd27 100644
--- a/arthur-spi/src/main/java/org/apache/geronimo/arthur/spi/model/ResourceModel.java
+++ b/arthur-spi/src/main/java/org/apache/geronimo/arthur/spi/model/ResourceModel.java
@@ -16,9 +16,13 @@
*/
package org.apache.geronimo.arthur.spi.model;
+import lombok.AllArgsConstructor;
import lombok.Data;
+import lombok.NoArgsConstructor;
@Data
+@NoArgsConstructor
+@AllArgsConstructor
public class ResourceModel {
private String pattern;
}
diff --git a/arthur-spi/src/main/java/org/apache/geronimo/arthur/spi/model/ResourcesModel.java b/arthur-spi/src/main/java/org/apache/geronimo/arthur/spi/model/ResourcesModel.java
index 73a137f..0ca3e50 100644
--- a/arthur-spi/src/main/java/org/apache/geronimo/arthur/spi/model/ResourcesModel.java
+++ b/arthur-spi/src/main/java/org/apache/geronimo/arthur/spi/model/ResourcesModel.java
@@ -16,11 +16,15 @@
*/
package org.apache.geronimo.arthur.spi.model;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
import java.util.Collection;
-import lombok.Data;
-
@Data
+@NoArgsConstructor
+@AllArgsConstructor
public class ResourcesModel {
private Collection<ResourceModel> resources;
private Collection<ResourceBundleModel> bundles;
diff --git a/documentation/src/content/knights.adoc b/documentation/src/content/knights.adoc
index 7e42e78..a787c72 100644
--- a/documentation/src/content/knights.adoc
+++ b/documentation/src/content/knights.adoc
@@ -25,6 +25,8 @@
- link:winegrower-knight.html[Winegrower]: Apache winegrower (Cloud OSGi runtime) support.
- link:openwebbeans-knight.html[OpenWebBeans]: Apache OpenWebBeans (CDI SE runtime) support.
- link:slf4j-knight.html[SLF4J]: SLF4J (JUL) integration.
+- derby-knight: Apache Derby integration.
+- openjpa-knight: Apache OpenJPA integration.
== Configure a Knight in Arthur Maven plugin
diff --git a/integration-test/src/test/java/org/apache/geronimo/arthur/integrationtests/MavenTest.java b/integration-test/src/test/java/org/apache/geronimo/arthur/integrationtests/MavenTest.java
index 8b7c780..9006729 100644
--- a/integration-test/src/test/java/org/apache/geronimo/arthur/integrationtests/MavenTest.java
+++ b/integration-test/src/test/java/org/apache/geronimo/arthur/integrationtests/MavenTest.java
@@ -55,6 +55,14 @@
void scr() {}
@Test
+ @Spec(expectedOutput = "" +
+ "[main] INFO org.apache.geronimo.arthur.integrationtests.OpenJPAMain -" +
+ " findbyid => root:id=10000,name=root_1,children=[child:id=10001,name=child_2, child:id=10000,name=child_1]\n" +
+ "[main] INFO org.apache.geronimo.arthur.integrationtests.OpenJPAMain -" +
+ " criteria builder => root:id=10000,name=root_1,children=[child:id=10001,name=child_2, child:id=10000,name=child_1]")
+ void openjpa() {}
+
+ @Test
@Spec(expectedOutput = "pong", forwardedExecutionSystemProperties = {
"MavenTest.jsch.port", "java.library.path", "javax.net.ssl.trustStore"
})
diff --git a/integration-test/src/test/resources/integration-tests/openjpa/pom.xml b/integration-test/src/test/resources/integration-tests/openjpa/pom.xml
new file mode 100644
index 0000000..028ec9e
--- /dev/null
+++ b/integration-test/src/test/resources/integration-tests/openjpa/pom.xml
@@ -0,0 +1,154 @@
+<?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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://maven.apache.org/POM/4.0.0
+ http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <!--parent>
+ <groupId>org.apache</groupId>
+ <artifactId>apache</artifactId>
+ <version>21</version>
+ </parent-->
+
+ <parent>
+ <artifactId>knights</artifactId>
+ <groupId>org.apache.geronimo.arthur.knights</groupId>
+ <version>1.0.3-SNAPSHOT</version>
+ </parent>
+ <properties>
+ <!-- main deps -->
+ <slf4j.version>1.7.28</slf4j.version>
+ <ziplock.version>8.0.0</ziplock.version>
+
+ <!-- knights -->
+ <jsch.version>0.1.55</jsch.version>
+ <graalvm.version>20.3.0</graalvm.version>
+ <winegrower.version>1.0.0</winegrower.version>
+
+ <!-- plugin versions/confs -->
+ <maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
+ <maven.compiler.source>8</maven.compiler.source>
+ <maven.compiler.target>8</maven.compiler.target>
+
+ <!-- jar vars -->
+ <geronimo-arthur.shortname>${project.artifactId}</geronimo-arthur.shortname>
+ <geronimo-arthur.Automatic-Module-Name>${project.groupId}.${geronimo-arthur.shortname}
+ </geronimo-arthur.Automatic-Module-Name>
+ <junit.version>5.7.0</junit.version>
+
+ <openjpa.version>3.1.2</openjpa.version>
+ <derby.version>10.14.2.0</derby.version>
+ </properties>
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.apache.geronimo.arthur.integrationtests</groupId>
+ <artifactId>openjpa</artifactId>
+ <!--<version>1.0.0-SNAPSHOT</version>-->
+ <name>Arthur :: Integration Tests :: OpenJPA</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.openjpa</groupId>
+ <artifactId>openjpa</artifactId>
+ <version>${openjpa.version}</version>
+ </dependency>
+ <dependency> <!-- for hikari -->
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>${slf4j.version}</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <version>${slf4j.version}</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-dbcp2</artifactId>
+ <version>2.8.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.derby</groupId>
+ <artifactId>derbytools</artifactId>
+ <version>${derby.version}</version>
+ <scope>system</scope>
+ <systemPath>/opt/rmannibucau/dev/derby-10.14/jars/sane/derbytools.jar</systemPath>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.derby</groupId>
+ <artifactId>derby</artifactId>
+ <version>${derby.version}</version>
+ <scope>system</scope>
+ <systemPath>/opt/rmannibucau/dev/derby-10.14/jars/sane/derby.jar</systemPath>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.openjpa</groupId>
+ <artifactId>openjpa-maven-plugin</artifactId>
+ <version>${openjpa.version}</version>
+ <executions>
+ <execution>
+ <id>enhancer</id>
+ <phase>compile</phase>
+ <goals>
+ <goal>enhance</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <includes>org/apache/geronimo/arthur/integrationtests/entities/*.class</includes>
+ <sqlAction>build</sqlAction>
+ <toolProperties>
+ <MappingDefaults>jpa(ForeignKeyDeleteAction=restrict,JoinForeignKeyDeleteAction=restrict)</MappingDefaults>
+ <MetaDataFactory>jpa</MetaDataFactory>
+ </toolProperties>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>${maven-compiler-plugin.version}</version>
+ <configuration>
+ <source>${maven.compiler.source}</source>
+ <target>${maven.compiler.target}</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.geronimo.arthur</groupId>
+ <artifactId>arthur-maven-plugin</artifactId>
+ <version>${project.version}</version>
+ <configuration>
+ <main>org.apache.geronimo.arthur.integrationtests.OpenJPAMain</main>
+ <graalExtensions>
+ <graalExtension>derby</graalExtension>
+ <graalExtension>openjpa</graalExtension>
+ </graalExtensions>
+ <!-- avoid to conflict with host cache since we mount the local m2 to speed up the execution -->
+ <graalCacheGav>org.apache.geronimo.arthur.cache:graal-integrationtests</graalCacheGav>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/integration-test/src/test/resources/integration-tests/openjpa/src/main/java/org/apache/geronimo/arthur/integrationtests/OpenJPAMain.java b/integration-test/src/test/resources/integration-tests/openjpa/src/main/java/org/apache/geronimo/arthur/integrationtests/OpenJPAMain.java
new file mode 100644
index 0000000..c33a1dc
--- /dev/null
+++ b/integration-test/src/test/resources/integration-tests/openjpa/src/main/java/org/apache/geronimo/arthur/integrationtests/OpenJPAMain.java
@@ -0,0 +1,222 @@
+/*
+ * 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.geronimo.arthur.integrationtests;
+
+import org.apache.commons.dbcp2.BasicDataSource;
+import org.apache.derby.jdbc.EmbeddedDriver;
+import org.apache.geronimo.arthur.integrationtests.entities.Child;
+import org.apache.geronimo.arthur.integrationtests.entities.Root;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.EntityTransaction;
+import javax.persistence.SharedCacheMode;
+import javax.persistence.ValidationMode;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.spi.ClassTransformer;
+import javax.persistence.spi.PersistenceProvider;
+import javax.persistence.spi.PersistenceUnitInfo;
+import javax.persistence.spi.PersistenceUnitTransactionType;
+import javax.sql.DataSource;
+import java.net.URL;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.ServiceLoader;
+import java.util.UUID;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.emptyList;
+
+public final class OpenJPAMain {
+ private OpenJPAMain() {
+ // noop
+ }
+
+ /**
+ * [main] INFO org.apache.geronimo.arthur.integrationtests.OpenJPAMain - findbyid => root:id=10000,name=root_1,children=[child:id=10001,name=child_2, child:id=10000,name=child_1]
+ * [main] INFO org.apache.geronimo.arthur.integrationtests.OpenJPAMain - criteria builder => root:id=10000,name=root_1,children=[child:id=10001,name=child_2, child:id=10000,name=child_1]
+ */
+ public static void main(final String... args) throws SQLException {
+ setIfMissing("org.slf4j.simpleLogger.logFile", "System.out");
+ setIfMissing("org.slf4j.simpleLogger.defaultLogLevel", "WARN");
+ setIfMissing("org.slf4j.simpleLogger.log.org.apache.geronimo.arthur.integrationtests", "INFO");
+ setIfMissing("derby.stream.error.file", "target/derby_" + UUID.randomUUID() + ".log");
+
+ final BasicDataSource dataSource = createDataSource();
+ final Map<String, Object> map = new HashMap<>();
+ final Properties properties = new Properties();
+ properties.setProperty("javax.persistence.schema-generation.database.action", "drop-and-create");
+ properties.setProperty("openjpa.Log", "DefaultLevel=WARN, Runtime=WARN, Tool=WARN");
+ properties.setProperty("openjpa.Sequence", "class-table(Table=SEQUENCES, Increment=20, InitialValue=10000)");
+ final EntityManagerFactory factory = ServiceLoader.load(PersistenceProvider.class).iterator().next()
+ // use no xml option for now
+ .createContainerEntityManagerFactory(newInfo(dataSource, properties), map);
+ final Logger logger = LoggerFactory.getLogger(OpenJPAMain.class);
+ try {
+ final long rootId = createGraph(factory.createEntityManager());
+
+ final EntityManager findByIdEm = factory.createEntityManager();
+ logger.info("findbyid => " + findByIdEm.find(Root.class, rootId).toString());
+ findByIdEm.close();
+
+ final EntityManager criteriaBuilderEm = factory.createEntityManager();
+ final CriteriaBuilder cb = criteriaBuilderEm.getCriteriaBuilder();
+ final CriteriaQuery<Root> query = cb.createQuery(Root.class);
+ final javax.persistence.criteria.Root<Root> from = query.from(Root.class);
+ final CriteriaQuery<Root> criteriaQuery = query.select(from).where(cb.equal(from.get("id"), rootId));
+ logger.info("criteria builder => " + criteriaBuilderEm.createQuery(criteriaQuery).getSingleResult());
+ criteriaBuilderEm.close();
+ } finally {
+ factory.close();
+ dataSource.close();
+ }
+ }
+
+ private static long createGraph(final EntityManager entityManager) {
+ final EntityTransaction transaction = entityManager.getTransaction();
+ transaction.begin();
+
+ final Root root = new Root();
+ root.setName("root_1");
+ entityManager.persist(root);
+
+ final Child child1 = new Child();
+ child1.setName("child_1");
+ child1.setRoot(root);
+ entityManager.persist(child1);
+
+ final Child child2 = new Child();
+ child2.setName("child_2");
+ child2.setRoot(root);
+ entityManager.persist(child2);
+
+ transaction.commit();
+ entityManager.close();
+ return root.getId();
+ }
+
+ private static BasicDataSource createDataSource() throws SQLException {
+ DriverManager.registerDriver(new EmbeddedDriver());
+ final BasicDataSource dataSource = new BasicDataSource();
+ dataSource.setDriverClassName("org.apache.derby.jdbc.EmbeddedDriver");
+ dataSource.setUrl("jdbc:derby:target/arthur_" + UUID.randomUUID().toString().replace('-', '_') + ";create=true");
+ dataSource.setUsername("sa");
+ dataSource.setPassword("");
+ dataSource.setMinIdle(1);
+ return dataSource;
+ }
+
+ private static PersistenceUnitInfo newInfo(final DataSource dataSource, final Properties properties) {
+ return new PersistenceUnitInfo() {
+ @Override
+ public String getPersistenceUnitName() {
+ return "arthur";
+ }
+
+ @Override
+ public String getPersistenceProviderClassName() {
+ return "org.apache.openjpa.persistence.PersistenceProviderImpl";
+ }
+
+ @Override
+ public PersistenceUnitTransactionType getTransactionType() {
+ return PersistenceUnitTransactionType.RESOURCE_LOCAL;
+ }
+
+ @Override
+ public DataSource getJtaDataSource() {
+ return dataSource;
+ }
+
+ @Override
+ public DataSource getNonJtaDataSource() {
+ return dataSource;
+ }
+
+ @Override
+ public List<String> getMappingFileNames() {
+ return emptyList();
+ }
+
+ @Override
+ public List<URL> getJarFileUrls() {
+ return emptyList();
+ }
+
+ @Override
+ public URL getPersistenceUnitRootUrl() {
+ return null;
+ }
+
+ @Override
+ public List<String> getManagedClassNames() {
+ return asList(Root.class.getName(), Child.class.getName());
+ }
+
+ @Override
+ public boolean excludeUnlistedClasses() {
+ return true;
+ }
+
+ @Override
+ public SharedCacheMode getSharedCacheMode() {
+ return SharedCacheMode.UNSPECIFIED;
+ }
+
+ @Override
+ public ValidationMode getValidationMode() {
+ return ValidationMode.AUTO;
+ }
+
+ @Override
+ public Properties getProperties() {
+ return properties;
+ }
+
+ @Override
+ public String getPersistenceXMLSchemaVersion() {
+ return "2.0";
+ }
+
+ @Override
+ public ClassLoader getClassLoader() {
+ return Thread.currentThread().getContextClassLoader();
+ }
+
+ @Override
+ public void addTransformer(final ClassTransformer transformer) {
+ // no-op
+ }
+
+ @Override
+ public ClassLoader getNewTempClassLoader() {
+ return getClassLoader();
+ }
+ };
+ }
+
+ private static void setIfMissing(final String key, final String value) {
+ System.setProperty(key, System.getProperty(key, value));
+ }
+}
diff --git a/integration-test/src/test/resources/integration-tests/openjpa/src/main/java/org/apache/geronimo/arthur/integrationtests/entities/Child.java b/integration-test/src/test/resources/integration-tests/openjpa/src/main/java/org/apache/geronimo/arthur/integrationtests/entities/Child.java
new file mode 100644
index 0000000..55f4254
--- /dev/null
+++ b/integration-test/src/test/resources/integration-tests/openjpa/src/main/java/org/apache/geronimo/arthur/integrationtests/entities/Child.java
@@ -0,0 +1,76 @@
+/*
+ * 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.geronimo.arthur.integrationtests.entities;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.ManyToOne;
+import java.util.Objects;
+
+@Entity
+public class Child {
+ @Id
+ @GeneratedValue
+ private long id;
+ private String name;
+
+ @ManyToOne
+ private Root root;
+
+ public long getId() {
+ return id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public Root getRoot() {
+ return root;
+ }
+
+ public void setRoot(final Root root) {
+ this.root = root;
+ }
+
+ @Override
+ public String toString() {
+ return "child:id=" + id + ",name=" + name;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ final Child child = Child.class.cast(o);
+ return id == child.id;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id);
+ }
+}
diff --git a/integration-test/src/test/resources/integration-tests/openjpa/src/main/java/org/apache/geronimo/arthur/integrationtests/entities/Root.java b/integration-test/src/test/resources/integration-tests/openjpa/src/main/java/org/apache/geronimo/arthur/integrationtests/entities/Root.java
new file mode 100644
index 0000000..4af11e6
--- /dev/null
+++ b/integration-test/src/test/resources/integration-tests/openjpa/src/main/java/org/apache/geronimo/arthur/integrationtests/entities/Root.java
@@ -0,0 +1,79 @@
+/*
+ * 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.geronimo.arthur.integrationtests.entities;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import javax.persistence.OrderBy;
+import java.util.List;
+import java.util.Objects;
+
+@Entity
+public class Root {
+ @Id
+ @GeneratedValue
+ private long id;
+ private String name;
+
+ @OrderBy("name DESC")
+ @OneToMany(mappedBy = "root")
+ private List<Child> children;
+
+ public long getId() {
+ return id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public List<Child> getChildren() {
+ return children;
+ }
+
+ public void setChildren(final List<Child> children) {
+ this.children = children;
+ }
+
+ @Override
+ public String toString() {
+ return "root:id=" + id + ",name=" + name + ",children=" + children;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ final Root child = Root.class.cast(o);
+ return id == child.id;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id);
+ }
+}
diff --git a/knights/derby-knight/pom.xml b/knights/derby-knight/pom.xml
new file mode 100644
index 0000000..d4233f8
--- /dev/null
+++ b/knights/derby-knight/pom.xml
@@ -0,0 +1,50 @@
+<?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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>knights</artifactId>
+ <groupId>org.apache.geronimo.arthur.knights</groupId>
+ <version>1.0.3-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>derby-knight</artifactId>
+ <name>Arthur :: Knights :: Derby</name>
+
+ <properties>
+ <geronimo-arthur.shortname>knight.derby</geronimo-arthur.shortname>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geronimo.arthur</groupId>
+ <artifactId>arthur-spi</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.geronimo.arthur</groupId>
+ <artifactId>arthur-impl</artifactId>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/knights/derby-knight/src/main/java/org/apache/geronimo/arthur/knight/derby/DerbyExtension.java b/knights/derby-knight/src/main/java/org/apache/geronimo/arthur/knight/derby/DerbyExtension.java
new file mode 100644
index 0000000..cc7b272
--- /dev/null
+++ b/knights/derby-knight/src/main/java/org/apache/geronimo/arthur/knight/derby/DerbyExtension.java
@@ -0,0 +1,402 @@
+/*
+ * 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.geronimo.arthur.knight.derby;
+
+import org.apache.geronimo.arthur.spi.ArthurExtension;
+import org.apache.geronimo.arthur.spi.model.ClassReflectionModel;
+import org.apache.geronimo.arthur.spi.model.ResourceModel;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.sql.Driver;
+import java.util.Objects;
+import java.util.Properties;
+import java.util.stream.Stream;
+
+import static java.util.Optional.ofNullable;
+
+public class DerbyExtension implements ArthurExtension {
+ @Override
+ public void execute(final Context context) {
+ registerProperties(context);
+ tryToRegisterSPI(context);
+ context.findImplementations(Driver.class)
+ .forEach(it -> registerClass(context, it.getName()));
+
+ // extraDBMSclasses.properties + StoredFormatIds + ClassName + RegisteredFormatIds
+ Stream.of(
+ "org.apache.derby.catalog.GetProcedureColumns",
+ "org.apache.derby.catalog.Java5SystemProcedures",
+ "org.apache.derby.catalog.SystemProcedures",
+ "org.apache.derby.catalog.TriggerNewTransitionRows",
+ "org.apache.derby.catalog.TriggerOldTransitionRows",
+ "org.apache.derby.catalog.UUID",
+ "org.apache.derby.catalog.types.AggregateAliasInfo",
+ "org.apache.derby.catalog.types.BitTypeIdImpl",
+ "org.apache.derby.catalog.types.BooleanTypeIdImpl",
+ "org.apache.derby.catalog.types.CharTypeIdImpl",
+ "org.apache.derby.catalog.types.ClassAliasInfo",
+ "org.apache.derby.catalog.types.DecimalTypeIdImpl",
+ "org.apache.derby.catalog.types.DefaultInfoImpl",
+ "org.apache.derby.catalog.types.DoubleTypeIdImpl",
+ "org.apache.derby.catalog.types.IndexDescriptorImpl",
+ "org.apache.derby.catalog.types.IntTypeIdImpl",
+ "org.apache.derby.catalog.types.LongintTypeIdImpl",
+ "org.apache.derby.catalog.types.LongvarbitTypeIdImpl",
+ "org.apache.derby.catalog.types.LongvarcharTypeIdImpl",
+ "org.apache.derby.catalog.types.MethodAliasInfo",
+ "org.apache.derby.catalog.types.NationalCharTypeIdImpl",
+ "org.apache.derby.catalog.types.NationalLongVarcharTypeIdImpl",
+ "org.apache.derby.catalog.types.NationalVarcharTypeIdImpl",
+ "org.apache.derby.catalog.types.RealTypeIdImpl",
+ "org.apache.derby.catalog.types.RefTypeIdImpl",
+ "org.apache.derby.catalog.types.ReferencedColumnsDescriptorImpl",
+ "org.apache.derby.catalog.types.RoutineAliasInfo",
+ "org.apache.derby.catalog.types.RowMultiSetImpl",
+ "org.apache.derby.catalog.types.SmallintTypeIdImpl",
+ "org.apache.derby.catalog.types.StatisticsImpl",
+ "org.apache.derby.catalog.types.SynonymAliasInfo",
+ "org.apache.derby.catalog.types.TinyintTypeIdImpl",
+ "org.apache.derby.catalog.types.TypeDescriptorImpl",
+ "org.apache.derby.catalog.types.TypesImplInstanceGetter",
+ "org.apache.derby.catalog.types.UDTAliasInfo",
+ "org.apache.derby.catalog.types.UserAggregateAliasInfo",
+ "org.apache.derby.catalog.types.UserDefinedTypeIdImpl",
+ "org.apache.derby.catalog.types.VarbitTypeIdImpl",
+ "org.apache.derby.catalog.types.VarcharTypeIdImpl",
+ "org.apache.derby.catalog.types.WorkUnitAliasInfo",
+ "org.apache.derby.diag.ContainedRoles",
+ "org.apache.derby.diag.ErrorLogReader",
+ "org.apache.derby.diag.ErrorMessages",
+ "org.apache.derby.diag.LockTable",
+ "org.apache.derby.diag.SpaceTable",
+ "org.apache.derby.diag.StatementCache",
+ "org.apache.derby.diag.StatementDuration",
+ "org.apache.derby.diag.TransactionTable",
+ "org.apache.derby.iapi.db.ConsistencyChecker",
+ "org.apache.derby.iapi.db.Factory",
+ "org.apache.derby.iapi.db.OptimizerTrace",
+ "org.apache.derby.iapi.db.PropertyInfo",
+ "org.apache.derby.iapi.error.StandardException",
+ "org.apache.derby.iapi.error.ThreadDump",
+ "org.apache.derby.iapi.services.cache.ClassSizeCatalogImpl",
+ "org.apache.derby.iapi.services.context.Context",
+ "org.apache.derby.iapi.services.diag.DiagnosticUtil",
+ "org.apache.derby.iapi.services.diag.DiagnosticableGeneric",
+ "org.apache.derby.iapi.services.io.FormatableArrayHolder",
+ "org.apache.derby.iapi.services.io.FormatableBitSet",
+ "org.apache.derby.iapi.services.io.FormatableHashtable",
+ "org.apache.derby.iapi.services.io.FormatableIntHolder",
+ "org.apache.derby.iapi.services.io.FormatableLongHolder",
+ "org.apache.derby.iapi.services.io.FormatableProperties",
+ "org.apache.derby.iapi.services.io.Storable",
+ "org.apache.derby.iapi.services.io.StoredFormatIds",
+ "org.apache.derby.iapi.services.loader.GeneratedByteCode",
+ "org.apache.derby.iapi.services.loader.GeneratedClass",
+ "org.apache.derby.iapi.services.loader.GeneratedMethod",
+ "org.apache.derby.iapi.sql.Activation",
+ "org.apache.derby.iapi.sql.LanguageFactory",
+ "org.apache.derby.iapi.sql.ParameterValueSet",
+ "org.apache.derby.iapi.sql.ParameterValueSetFactory",
+ "org.apache.derby.iapi.sql.ResultSet",
+ "org.apache.derby.iapi.sql.Row",
+ "org.apache.derby.iapi.sql.conn.Authorizer",
+ "org.apache.derby.iapi.sql.conn.LanguageConnectionContext",
+ "org.apache.derby.iapi.sql.dictionary.DataDictionary",
+ "org.apache.derby.iapi.sql.dictionary.IndexRowGenerator",
+ "org.apache.derby.iapi.sql.dictionary.TriggerDescriptor",
+ "org.apache.derby.iapi.sql.execute.ConstantAction",
+ "org.apache.derby.iapi.sql.execute.CursorResultSet",
+ "org.apache.derby.iapi.sql.execute.ExecIndexRow",
+ "org.apache.derby.iapi.sql.execute.ExecPreparedStatement",
+ "org.apache.derby.iapi.sql.execute.ExecRow",
+ "org.apache.derby.iapi.sql.execute.ExecRowBuilder",
+ "org.apache.derby.iapi.sql.execute.ExecutionFactory",
+ "org.apache.derby.iapi.sql.execute.NoPutResultSet",
+ "org.apache.derby.iapi.sql.execute.ResultSetFactory",
+ "org.apache.derby.iapi.sql.execute.RowFactory",
+ "org.apache.derby.iapi.sql.execute.RunTimeStatistics",
+ "org.apache.derby.iapi.store.access.Qualifier",
+ "org.apache.derby.iapi.types.BitDataValue",
+ "org.apache.derby.iapi.types.BitTypeId",
+ "org.apache.derby.iapi.types.BooleanDataValue",
+ "org.apache.derby.iapi.types.BooleanTypeId",
+ "org.apache.derby.iapi.types.CharTypeId",
+ "org.apache.derby.iapi.types.ConcatableDataValue",
+ "org.apache.derby.iapi.types.DTSClassInfo",
+ "org.apache.derby.iapi.types.DataTypeDescriptor",
+ "org.apache.derby.iapi.types.DataValueDescriptor",
+ "org.apache.derby.iapi.types.DataValueFactory",
+ "org.apache.derby.iapi.types.DateTimeDataValue",
+ "org.apache.derby.iapi.types.DateTypeId",
+ "org.apache.derby.iapi.types.DecimalTypeId",
+ "org.apache.derby.iapi.types.DoubleTypeId",
+ "org.apache.derby.iapi.types.IntTypeId",
+ "org.apache.derby.iapi.types.JSQLType",
+ "org.apache.derby.iapi.types.LongintTypeId",
+ "org.apache.derby.iapi.types.LongvarbitTypeId",
+ "org.apache.derby.iapi.types.LongvarcharTypeId",
+ "org.apache.derby.iapi.types.NationalCharTypeId",
+ "org.apache.derby.iapi.types.NationalLongvarcharTypeId",
+ "org.apache.derby.iapi.types.NationalVarcharTypeId",
+ "org.apache.derby.iapi.types.NumberDataValue",
+ "org.apache.derby.iapi.types.RealTypeId",
+ "org.apache.derby.iapi.types.RefDataValue",
+ "org.apache.derby.iapi.types.RefTypeId",
+ "org.apache.derby.iapi.types.RowLocation",
+ "org.apache.derby.iapi.types.SQLLongint",
+ "org.apache.derby.iapi.types.SmallintTypeId",
+ "org.apache.derby.iapi.types.StringDataValue",
+ "org.apache.derby.iapi.types.TimeTypeId",
+ "org.apache.derby.iapi.types.TimestampTypeId",
+ "org.apache.derby.iapi.types.TinyintTypeId",
+ "org.apache.derby.iapi.types.UserDataValue",
+ "org.apache.derby.iapi.types.UserDefinedTypeId",
+ "org.apache.derby.iapi.types.UserDefinedTypeIdV2",
+ "org.apache.derby.iapi.types.UserDefinedTypeIdV3",
+ "org.apache.derby.iapi.types.UserType",
+ "org.apache.derby.iapi.types.VarbitTypeId",
+ "org.apache.derby.iapi.types.VarcharTypeId",
+ "org.apache.derby.iapi.types.VariableSizeDataValue",
+ "org.apache.derby.iapi.types.XML (implementation of",
+ "org.apache.derby.iapi.types.XMLDataValue",
+ "org.apache.derby.iapi.types.XMLDataValue)",
+ "org.apache.derby.impl.io.CPFile",
+ "org.apache.derby.impl.io.DirStorageFactory",
+ "org.apache.derby.impl.io.InputStreamFile",
+ "org.apache.derby.impl.io.JarDBFile",
+ "org.apache.derby.impl.io.URLFile",
+ "org.apache.derby.impl.io.VFMemoryStorageFactory",
+ "org.apache.derby.impl.jdbc.LOBStoredProcedure",
+ "org.apache.derby.impl.jdbc.SQLExceptionFactory",
+ "org.apache.derby.impl.jdbc.authentication.JNDIAuthenticationSchemeBase",
+ "org.apache.derby.impl.jdbc.authentication.JNDIAuthenticationService",
+ "org.apache.derby.impl.jdbc.authentication.LDAPAuthenticationSchemeImpl",
+ "org.apache.derby.impl.services.monitor.BaseMonitor",
+ "org.apache.derby.impl.services.monitor.FileMonitor",
+ "org.apache.derby.impl.services.stream.RollingFileStream",
+ "org.apache.derby.impl.services.stream.RollingFileStreamProvider",
+ "org.apache.derby.impl.services.uuid.BasicUUID",
+ "org.apache.derby.impl.services.uuid.BasicUUIDGetter",
+ "org.apache.derby.impl.sql.CursorInfo",
+ "org.apache.derby.impl.sql.CursorTableReference",
+ "org.apache.derby.impl.sql.GenericColumnDescriptor",
+ "org.apache.derby.impl.sql.GenericResultDescription",
+ "org.apache.derby.impl.sql.GenericStorablePreparedStatement",
+ "org.apache.derby.impl.sql.GenericTypeDescriptor",
+ "org.apache.derby.impl.sql.GenericTypeId",
+ "org.apache.derby.impl.sql.catalog.AliasDescriptorFinder",
+ "org.apache.derby.impl.sql.catalog.ColumnDescriptorFinder",
+ "org.apache.derby.impl.sql.catalog.ConglomerateDescriptorFinder",
+ "org.apache.derby.impl.sql.catalog.ConstraintDescriptorFinder",
+ "org.apache.derby.impl.sql.catalog.CoreDDFinderClassInfo",
+ "org.apache.derby.impl.sql.catalog.DD_AristotleVersion",
+ "org.apache.derby.impl.sql.catalog.DD_BuffyVersion",
+ "org.apache.derby.impl.sql.catalog.DD_DB2J72",
+ "org.apache.derby.impl.sql.catalog.DD_IvanovaVersion",
+ "org.apache.derby.impl.sql.catalog.DD_MulanVersion",
+ "org.apache.derby.impl.sql.catalog.DD_PlatoVersion",
+ "org.apache.derby.impl.sql.catalog.DD_SocratesVersion",
+ "org.apache.derby.impl.sql.catalog.DD_Version",
+ "org.apache.derby.impl.sql.catalog.DD_XenaVersion",
+ "org.apache.derby.impl.sql.catalog.DataDictionaryDescriptorFinder",
+ "org.apache.derby.impl.sql.catalog.DefaultDescriptorFinder",
+ "org.apache.derby.impl.sql.catalog.FileInfoFinder",
+ "org.apache.derby.impl.sql.catalog.IndexRowGeneratorImpl",
+ "org.apache.derby.impl.sql.catalog.OIDImpl",
+ "org.apache.derby.impl.sql.catalog.ParameterDescriptorImpl",
+ "org.apache.derby.impl.sql.catalog.RowListImpl",
+ "org.apache.derby.impl.sql.catalog.SPSDescriptorFinder",
+ "org.apache.derby.impl.sql.catalog.SchemaDescriptorFinder",
+ "org.apache.derby.impl.sql.catalog.SequenceDescriptorFinder",
+ "org.apache.derby.impl.sql.catalog.TableDescriptorFinder",
+ "org.apache.derby.impl.sql.catalog.TriggerDescriptor",
+ "org.apache.derby.impl.sql.catalog.TriggerDescriptorFinder",
+ "org.apache.derby.impl.sql.catalog.ViewDescriptorFinder",
+ "org.apache.derby.impl.sql.compile.MaxMinAggregateDefinition",
+ "org.apache.derby.impl.sql.compile.OptTraceViewer",
+ "org.apache.derby.impl.sql.compile.OptimizerTracer",
+ "org.apache.derby.impl.sql.compile.SumAvgAggregateDefinition",
+ "org.apache.derby.impl.sql.depend.DepClassInfo",
+ "org.apache.derby.impl.sql.execute.AggregatorInfo",
+ "org.apache.derby.impl.sql.execute.AggregatorInfoList",
+ "org.apache.derby.impl.sql.execute.AvgAggregator",
+ "org.apache.derby.impl.sql.execute.BaseActivation",
+ "org.apache.derby.impl.sql.execute.BaseExpressionActivation",
+ "org.apache.derby.impl.sql.execute.ColumnInfo",
+ "org.apache.derby.impl.sql.execute.ConstantActionActivation",
+ "org.apache.derby.impl.sql.execute.ConstraintInfo",
+ "org.apache.derby.impl.sql.execute.CountAggregator",
+ "org.apache.derby.impl.sql.execute.CurrentDatetime",
+ "org.apache.derby.impl.sql.execute.CursorActivation",
+ "org.apache.derby.impl.sql.execute.DeleteConstantAction",
+ "org.apache.derby.impl.sql.execute.FKInfo",
+ "org.apache.derby.impl.sql.execute.IndexColumnOrder",
+ "org.apache.derby.impl.sql.execute.InsertConstantAction",
+ "org.apache.derby.impl.sql.execute.MatchingClauseConstantAction",
+ "org.apache.derby.impl.sql.execute.MaxMinAggregator",
+ "org.apache.derby.impl.sql.execute.MergeConstantAction",
+ "org.apache.derby.impl.sql.execute.OrderableAggregator",
+ "org.apache.derby.impl.sql.execute.SavepointConstantAction",
+ "org.apache.derby.impl.sql.execute.StdDevPAggregator",
+ "org.apache.derby.impl.sql.execute.StdDevSAggregator",
+ "org.apache.derby.impl.sql.execute.SumAggregator",
+ "org.apache.derby.impl.sql.execute.TransactionConstantAction",
+ "org.apache.derby.impl.sql.execute.TriggerInfo",
+ "org.apache.derby.impl.sql.execute.UpdatableVTIConstantAction",
+ "org.apache.derby.impl.sql.execute.UpdateConstantAction",
+ "org.apache.derby.impl.sql.execute.UserDefinedAggregator",
+ "org.apache.derby.impl.sql.execute.VarPAggregator",
+ "org.apache.derby.impl.sql.execute.VarSAggregator",
+ "org.apache.derby.impl.store.access.ConglomerateDirectory",
+ "org.apache.derby.impl.store.access.PC_XenaVersion",
+ "org.apache.derby.impl.store.access.PropertyConglomerate",
+ "org.apache.derby.impl.store.access.StorableFormatId",
+ "org.apache.derby.impl.store.access.btree.BranchControlRow",
+ "org.apache.derby.impl.store.access.btree.LeafControlRow",
+ "org.apache.derby.impl.store.access.btree.index.B2I",
+ "org.apache.derby.impl.store.access.btree.index.B2IStaticCompiledInfo",
+ "org.apache.derby.impl.store.access.btree.index.B2IUndo",
+ "org.apache.derby.impl.store.access.btree.index.B2I_10_3",
+ "org.apache.derby.impl.store.access.btree.index.B2I_v10_2",
+ "org.apache.derby.impl.store.access.heap.Heap",
+ "org.apache.derby.impl.store.access.heap.HeapClassInfo",
+ "org.apache.derby.impl.store.access.heap.Heap_v10_2",
+ "org.apache.derby.impl.store.raw.data.AllocPage",
+ "org.apache.derby.impl.store.raw.data.AllocPageOperation",
+ "org.apache.derby.impl.store.raw.data.ChainAllocPageOperation",
+ "org.apache.derby.impl.store.raw.data.CompressSpacePageOperation",
+ "org.apache.derby.impl.store.raw.data.CompressSpacePageOperation10_2",
+ "org.apache.derby.impl.store.raw.data.ContainerOperation",
+ "org.apache.derby.impl.store.raw.data.ContainerUndoOperation",
+ "org.apache.derby.impl.store.raw.data.CopyRowsOperation",
+ "org.apache.derby.impl.store.raw.data.DeleteOperation",
+ "org.apache.derby.impl.store.raw.data.EncryptContainerOperation",
+ "org.apache.derby.impl.store.raw.data.EncryptContainerUndoOperation",
+ "org.apache.derby.impl.store.raw.data.FileContainer",
+ "org.apache.derby.impl.store.raw.data.InitPageOperation",
+ "org.apache.derby.impl.store.raw.data.InsertOperation",
+ "org.apache.derby.impl.store.raw.data.InvalidatePageOperation",
+ "org.apache.derby.impl.store.raw.data.LogicalUndoOperation",
+ "org.apache.derby.impl.store.raw.data.PhysicalUndoOperation",
+ "org.apache.derby.impl.store.raw.data.PurgeOperation",
+ "org.apache.derby.impl.store.raw.data.RemoveFileOperation",
+ "org.apache.derby.impl.store.raw.data.SetReservedSpaceOperation",
+ "org.apache.derby.impl.store.raw.data.StoredPage",
+ "org.apache.derby.impl.store.raw.data.StreamFileContainer",
+ "org.apache.derby.impl.store.raw.data.UpdateFieldOperation",
+ "org.apache.derby.impl.store.raw.data.UpdateOperation",
+ "org.apache.derby.impl.store.raw.log.CheckpointOperation",
+ "org.apache.derby.impl.store.raw.log.ChecksumOperation",
+ "org.apache.derby.impl.store.raw.log.LogCounter",
+ "org.apache.derby.impl.store.raw.log.LogRecord",
+ "org.apache.derby.impl.store.raw.log.LogToFile",
+ "org.apache.derby.impl.store.raw.xact.BeginXact",
+ "org.apache.derby.impl.store.raw.xact.EndXact",
+ "org.apache.derby.impl.store.raw.xact.GlobalXactId",
+ "org.apache.derby.impl.store.raw.xact.TransactionTable",
+ "org.apache.derby.impl.store.raw.xact.TransactionTableEntry",
+ "org.apache.derby.impl.store.raw.xact.XAXactId",
+ "org.apache.derby.impl.store.raw.xact.XactId",
+ "org.apache.derby.jdbc.BasicEmbeddedConnectionPoolDataSource40",
+ "org.apache.derby.jdbc.BasicEmbeddedDataSource40",
+ "org.apache.derby.jdbc.BasicEmbeddedXADataSource40",
+ "org.apache.derby.jdbc.EmbeddedConnectionPoolDataSource",
+ "org.apache.derby.jdbc.EmbeddedConnectionPoolDataSource40",
+ "org.apache.derby.jdbc.EmbeddedDataSource",
+ "org.apache.derby.jdbc.EmbeddedDataSource40",
+ "org.apache.derby.jdbc.EmbeddedDriver",
+ "org.apache.derby.jdbc.EmbeddedXADataSource",
+ "org.apache.derby.jdbc.EmbeddedXADataSource40",
+ "org.apache.derby.mbeans.Management",
+ "org.apache.derby.osgi.EmbeddedActivator",
+ "org.apache.derby.shared.common.sanity.ThreadDump",
+ "org.apache.derby.tools.sysinfo",
+ "org.apache.derby.vti.ForeignTableVTI",
+ "org.apache.derby.vti.StringColumnVTI",
+ "org.apache.derby.vti.UpdatableVTITemplate",
+ "org.apache.derby.vti.VTICosting",
+ "org.apache.derby.vti.VTIMetaDataTemplate",
+ "org.apache.derby.vti.XmlVTI"
+ ).distinct().forEach(it -> {
+ try {
+ registerClass(context, context.loadClass(it).getName());
+ } catch (final IllegalStateException | NoClassDefFoundError ise) {
+ // no-op
+ }
+ });
+ context.register(new ClassReflectionModel("org.apache.derby.iapi.services.context.ContextManager", null, null, null, null, null, null, null, null, null, null));
+ Stream.of(
+ "org.apache.derby.iapi.services.monitor.Monitor",
+ "org.apache.derby.iapi.services.context.ContextService"
+ ).forEach(it -> {
+ try {
+ context.initializeAtRunTime(context.loadClass(it).getName());
+ } catch (final IllegalStateException ise) {
+ // no-op
+ }
+ });
+ }
+
+ private void registerClass(final Context context, final String name) {
+ final ClassReflectionModel model = new ClassReflectionModel();
+ model.setName(name);
+ model.setAllPublicConstructors(true);
+ model.setAllDeclaredConstructors(true);
+ context.register(model);
+ }
+
+ private void tryToRegisterSPI(final Context context) {
+ final ClassLoader loader = Thread.currentThread().getContextClassLoader();
+ ofNullable(loader.getResourceAsStream("org/apache/derby/modules.properties"))
+ .map(res -> {
+ final Properties properties = new Properties();
+ try (final InputStream s = res) {
+ properties.load(s);
+ } catch (final IOException e) {
+ throw new IllegalStateException(e);
+ }
+ return properties;
+ })
+ .ifPresent(props -> props.stringPropertyNames().stream()
+ .map(props::getProperty)
+ .flatMap(it -> Stream.of(it.split(",")))
+ .map(String::trim)
+ .filter(it -> !it.isEmpty())
+ .map(it -> {
+ try {
+ return context.loadClass(it);
+ } catch (final IllegalStateException ise) {
+ return null;
+ }
+ })
+ .filter(Objects::nonNull)
+ .flatMap(context::findHierarchy)
+ .forEach(it -> {
+ final ClassReflectionModel model = new ClassReflectionModel();
+ model.setName(it.getName());
+ model.setAllDeclaredConstructors(true);
+ context.register(model);
+ }));
+ }
+
+ private void registerProperties(final Context context) {
+ final ResourceModel resourceModel = new ResourceModel();
+ resourceModel.setPattern("org\\/apache\\/derby\\/.+\\.properties");
+ context.register(resourceModel);
+ }
+}
diff --git a/knights/derby-knight/src/main/resources/META-INF/services/org.apache.geronimo.arthur.spi.ArthurExtension b/knights/derby-knight/src/main/resources/META-INF/services/org.apache.geronimo.arthur.spi.ArthurExtension
new file mode 100644
index 0000000..386e3a5
--- /dev/null
+++ b/knights/derby-knight/src/main/resources/META-INF/services/org.apache.geronimo.arthur.spi.ArthurExtension
@@ -0,0 +1 @@
+org.apache.geronimo.arthur.knight.derby.DerbyExtension
diff --git a/knights/openjpa-knight/pom.xml b/knights/openjpa-knight/pom.xml
new file mode 100644
index 0000000..6b6dae8
--- /dev/null
+++ b/knights/openjpa-knight/pom.xml
@@ -0,0 +1,56 @@
+<?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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>knights</artifactId>
+ <groupId>org.apache.geronimo.arthur.knights</groupId>
+ <version>1.0.3-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>openjpa-knight</artifactId>
+ <name>Arthur :: Knights :: OpenJPA</name>
+
+ <properties>
+ <geronimo-arthur.shortname>knight.openjpa</geronimo-arthur.shortname>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geronimo.arthur</groupId>
+ <artifactId>arthur-spi</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.openjpa</groupId>
+ <artifactId>openjpa</artifactId>
+ <version>3.1.2</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.geronimo.arthur</groupId>
+ <artifactId>arthur-impl</artifactId>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/knights/openjpa-knight/src/main/java/org/apache/geronimo/arthur/knight/openjpa/OpenJPAExtension.java b/knights/openjpa-knight/src/main/java/org/apache/geronimo/arthur/knight/openjpa/OpenJPAExtension.java
new file mode 100644
index 0000000..b13d699
--- /dev/null
+++ b/knights/openjpa-knight/src/main/java/org/apache/geronimo/arthur/knight/openjpa/OpenJPAExtension.java
@@ -0,0 +1,315 @@
+/*
+ * 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.geronimo.arthur.knight.openjpa;
+
+import org.apache.geronimo.arthur.spi.ArthurExtension;
+import org.apache.geronimo.arthur.spi.model.ClassReflectionModel;
+import org.apache.geronimo.arthur.spi.model.ResourceBundleModel;
+import org.apache.geronimo.arthur.spi.model.ResourceModel;
+
+import javax.persistence.Embeddable;
+import javax.persistence.Entity;
+import javax.persistence.MappedSuperclass;
+import java.lang.reflect.Field;
+import java.util.Objects;
+import java.util.stream.Stream;
+
+public class OpenJPAExtension implements ArthurExtension {
+ @Override
+ public void execute(final Context context) {
+ registerJPAClasses(context);
+ registerSPI(context);
+ registerI18n(context);
+ registerDictionaryResources(context);
+ registerPrimitiveWrappers(context);
+ registerDBCP2IfPresent(context);
+ }
+
+ // see Options class (stringToObject method)
+ private void registerPrimitiveWrappers(final Context context) {
+ Stream.of(Boolean.class, Byte.class, Character.class, Double.class, Float.class, Integer.class, Long.class, Short.class)
+ .forEach(it -> context.register(new ClassReflectionModel(it.getName(), null, true, null, true /*valueOf*/, null, null, null, null, null, null)));
+ }
+
+ private void registerDictionaryResources(final Context context) {
+ context.register(new ResourceModel("org\\/apache\\/openjpa\\/jdbc\\/sql\\/sql-keywords\\.rsrc"));
+ context.register(new ResourceModel("org\\/apache\\/openjpa\\/jdbc\\/sql\\/sql-error-state-codes\\.xml"));
+ }
+
+ // todo: dbcp2-knight and inherit from it automatically?
+ private void registerDBCP2IfPresent(final Context context) {
+ try {
+ final Class<?> evictionPolicy = context.loadClass("org.apache.commons.pool2.impl.DefaultEvictionPolicy");
+
+ final ClassReflectionModel model = new ClassReflectionModel();
+ model.setName(evictionPolicy.getName());
+ model.setAllPublicConstructors(true);
+ context.register(model);
+
+ context.register(new ResourceBundleModel("org.apache.commons.dbcp2.LocalStrings"));
+
+ // dbcp2 depends on commons-logging in a hardcoded way (don't ask)
+ addCommonsLogging(context).forEach(it -> {
+ final ClassReflectionModel reflect = new ClassReflectionModel();
+ reflect.setName(it.getName());
+ reflect.setAllPublicConstructors(true);
+ reflect.setAllDeclaredConstructors(true);
+ context.register(reflect);
+ });
+ } catch (final NoClassDefFoundError | Exception e) {
+ // no-op
+ }
+ }
+
+ // todo: replace that by a ResourceFinder?
+ // does not move often so maybe overkill but pattern being stable
+ // (org/apache/openjpa/*/localizer.properties) we could
+ private void registerI18n(final Context context) {
+ final ClassLoader loader = Thread.currentThread().getContextClassLoader();
+ Stream.of(
+ "org/apache/openjpa/abstractstore/localizer.properties",
+ "org/apache/openjpa/ant/localizer.properties",
+ "org/apache/openjpa/conf/localizer.properties",
+ "org/apache/openjpa/datacache/localizer.properties",
+ "org/apache/openjpa/ee/localizer.properties",
+ "org/apache/openjpa/enhance/localizer.properties",
+ "org/apache/openjpa/enhance/stats/localizer.properties",
+ "org/apache/openjpa/event/kubernetes/localizer.properties",
+ "org/apache/openjpa/event/localizer.properties",
+ "org/apache/openjpa/instrumentation/jmx/localizer.properties",
+ "org/apache/openjpa/jdbc/ant/localizer.properties",
+ "org/apache/openjpa/jdbc/conf/localizer.properties",
+ "org/apache/openjpa/jdbc/kernel/exps/localizer.properties",
+ "org/apache/openjpa/jdbc/kernel/localizer.properties",
+ "org/apache/openjpa/jdbc/meta/localizer.properties",
+ "org/apache/openjpa/jdbc/meta/strats/localizer.properties",
+ "org/apache/openjpa/jdbc/schema/localizer.properties",
+ "org/apache/openjpa/jdbc/sql/localizer.properties",
+ "org/apache/openjpa/kernel/exps/localizer.properties",
+ "org/apache/openjpa/kernel/jpql/localizer.properties",
+ "org/apache/openjpa/kernel/localizer.properties",
+ "org/apache/openjpa/lib/ant/localizer.properties",
+ "org/apache/openjpa/lib/conf/localizer.properties",
+ "org/apache/openjpa/lib/graph/localizer.properties",
+ "org/apache/openjpa/lib/jdbc/localizer.properties",
+ "org/apache/openjpa/lib/log/localizer.properties",
+ "org/apache/openjpa/lib/meta/localizer.properties",
+ "org/apache/openjpa/lib/rop/localizer.properties",
+ "org/apache/openjpa/lib/util/localizer.properties",
+ "org/apache/openjpa/lib/xml/localizer.properties",
+ "org/apache/openjpa/meta/localizer.properties",
+ "org/apache/openjpa/persistence/criteria/localizer.properties",
+ "org/apache/openjpa/persistence/jdbc/localizer.properties",
+ "org/apache/openjpa/persistence/jest/localizer.properties",
+ "org/apache/openjpa/persistence/localizer.properties",
+ "org/apache/openjpa/persistence/meta/localizer.properties",
+ "org/apache/openjpa/persistence/util/localizer.properties",
+ "org/apache/openjpa/persistence/validation/localizer.properties",
+ "org/apache/openjpa/slice/jdbc/localizer.properties",
+ "org/apache/openjpa/slice/localizer.properties",
+ "org/apache/openjpa/slice/transaction/localizer.properties",
+ "org/apache/openjpa/util/localizer.properties"
+ ).filter(it -> loader.getResource(it) != null).forEach(it -> {
+ final ResourceBundleModel model = new ResourceBundleModel();
+ model.setName(it.replace('/', '.').substring(0, it.length() - ".properties".length()));
+ context.register(model);
+ });
+ }
+
+ private void registerSPI(final Context context) {
+ spiClasses(context)
+ .distinct()
+ .map(Class::getName)
+ .forEach(it -> {
+ final ClassReflectionModel model = new ClassReflectionModel();
+ model.setName(it);
+ model.setAllPublicConstructors(true);
+ model.setAllDeclaredConstructors(true);
+ model.setAllPublicMethods(true);
+ context.register(model);
+ });
+ }
+
+ // todo: cut more of that by a review of the reflection.arthur.json
+ // one option is to precompute it for a pure openjpa deployment and just add all user impl only
+ private Stream<? extends Class<?>> spiClasses(final Context context) {
+ return Stream.of(
+ "org.apache.openjpa.kernel.BrokerFactory",
+ "org.apache.openjpa.lib.log.LogFactory",
+ "org.apache.openjpa.lib.conf.Configurable",
+ "org.apache.openjpa.util.CacheMap",
+ "org.apache.openjpa.event.SingleJVMRemoteCommitProvider",
+ "org.apache.openjpa.event.SingleJVMRemoteCommitProvider",
+ "org.apache.openjpa.persistence.jdbc.PersistenceMappingFactory",
+ "org.apache.openjpa.jdbc.kernel.TableJDBCSeq",
+ "org.apache.openjpa.jdbc.kernel.ValueTableJDBCSeq",
+ "org.apache.openjpa.jdbc.kernel.ClassTableJDBCSeq",
+ "org.apache.openjpa.jdbc.kernel.NativeJDBCSeq",
+ "org.apache.openjpa.kernel.TimeSeededSeq",
+ "org.apache.openjpa.jdbc.kernel.TableJDBCSeq",
+ "org.apache.openjpa.jdbc.kernel.ClassTableJDBCSeq",
+ "org.apache.openjpa.kernel.TimeSeededSeq",
+ "org.apache.openjpa.persistence.EntityManagerFactoryImpl",
+ "org.apache.openjpa.jdbc.meta.MappingRepository",
+ "org.apache.openjpa.meta.MetaDataRepository",
+ "org.apache.openjpa.util.ClassResolverImpl",
+ "org.apache.openjpa.datacache.DataCacheManagerImpl",
+ "org.apache.openjpa.datacache.DefaultCacheDistributionPolicy",
+ "org.apache.openjpa.datacache.ConcurrentDataCache",
+ "org.apache.openjpa.datacache.ConcurrentQueryCache",
+ "org.apache.openjpa.kernel.NoneLockManager",
+ "org.apache.openjpa.kernel.VersionLockManager",
+ "org.apache.openjpa.kernel.InverseManager",
+ "org.apache.openjpa.kernel.InMemorySavepointManager",
+ "org.apache.openjpa.event.LogOrphanedKeyAction",
+ "org.apache.openjpa.event.ExceptionOrphanedKeyAction",
+ "org.apache.openjpa.event.NoneOrphanedKeyAction",
+ "org.apache.openjpa.ee.AutomaticManagedRuntime",
+ "org.apache.openjpa.ee.JNDIManagedRuntime",
+ "org.apache.openjpa.ee.InvocationManagedRuntime",
+ "org.apache.openjpa.util.ProxyManagerImpl",
+ "org.apache.openjpa.conf.DetachOptions$Loaded",
+ "org.apache.openjpa.conf.DetachOptions$FetchGroups",
+ "org.apache.openjpa.conf.DetachOptions$All",
+ "org.apache.openjpa.conf.Compatibility",
+ "org.apache.openjpa.conf.CallbackOptions",
+ "org.apache.openjpa.event.LifecycleEventManager",
+ "org.apache.openjpa.validation.ValidatingLifecycleEventManager",
+ "org.apache.openjpa.instrumentation.InstrumentationManagerImpl",
+ "org.apache.openjpa.audit.AuditLogger",
+ "org.apache.openjpa.jdbc.sql.DBDictionary",
+ "org.apache.openjpa.jdbc.kernel.AbstractUpdateManager",
+ "org.apache.openjpa.jdbc.schema.DriverDataSource",
+ "org.apache.openjpa.jdbc.schema.DynamicSchemaFactory",
+ "org.apache.openjpa.jdbc.schema.LazySchemaFactory",
+ "org.apache.openjpa.jdbc.schema.FileSchemaFactory",
+ "org.apache.openjpa.jdbc.schema.TableSchemaFactory",
+ "org.apache.openjpa.jdbc.sql.SQLFactoryImpl",
+ "org.apache.openjpa.jdbc.meta.MappingDefaultsImpl",
+ "org.apache.openjpa.jdbc.kernel.PreparedQueryCacheImpl",
+ "org.apache.openjpa.jdbc.kernel.FinderCacheImpl",
+ "org.apache.openjpa.jdbc.identifier.DBIdentifierUtilImpl",
+ "org.apache.openjpa.lib.log.LogFactoryImpl",
+ "org.apache.openjpa.lib.log.SLF4JLogFactory",
+ "org.apache.openjpa.lib.log.NoneLogFactory",
+ "org.apache.openjpa.slice.DistributionPolicy$Default",
+ "org.apache.openjpa.slice.ReplicationPolicy$Default",
+ "javax.persistence.spi.PersistenceProvider")
+ .distinct()
+ .map(it -> {
+ try {
+ return context.loadClass(it);
+ } catch (final IllegalStateException | NoClassDefFoundError ise) {
+ return null;
+ }
+ })
+ .filter(Objects::nonNull)
+ .flatMap(context::findHierarchy)
+ .distinct()
+ .flatMap(it -> Stream.concat(Stream.of(it), context.findImplementations(it).stream()))
+ .distinct()
+ .filter(it -> needsReflection(it.getName()))
+ .flatMap(it -> {
+ if (it.getName().startsWith("org.apache.commons.logging.impl.")) {
+ try {
+ context.loadClass("org.apache.commons.logging.impl.LogFactoryImpl").getConstructor().newInstance();
+ return Stream.concat(Stream.of(it), addCommonsLogging(context));
+ } catch (final NoClassDefFoundError | Exception e) {
+ return Stream.empty();
+ }
+ }
+ return Stream.of(it);
+ })
+ .filter(it -> {
+ if ("org.apache.openjpa.jdbc.sql.PostgresDictionary".equals(it.getName())) {
+ try {
+ context.loadClass("org.postgresql.largeobject.LargeObjectManager");
+ return true;
+ } catch (final NoClassDefFoundError | Exception e) {
+ return false;
+ }
+ }
+ return true;
+ });
+ }
+
+ // todo: extract it in a commons-logging-knight and inherit from it automatically?
+ private Stream<? extends Class<?>> addCommonsLogging(final Context context) {
+ return Stream.of(
+ "org.apache.commons.logging.LogFactory",
+ "org.apache.commons.logging.impl.LogFactoryImpl",
+ "org.apache.commons.logging.impl.Jdk14Logger")
+ .map(n -> {
+ try {
+ return context.loadClass(n);
+ } catch (final NoClassDefFoundError | Exception ex) {
+ return null;
+ }
+ })
+ .filter(Objects::nonNull);
+ }
+
+ private boolean needsReflection(final String name) {
+ return !name.equals("org.apache.openjpa.ee.OSGiManagedRuntime") &&
+ !name.startsWith("org.apache.openjpa.ee.WAS") &&
+ !name.startsWith("org.slf4j.") &&
+ !name.startsWith("org.apache.commons.") &&
+ !name.startsWith("java.") &&
+ !name.startsWith("javax.") &&
+ !name.startsWith("jakarta.") &&
+ !name.contains("$util") &&
+ !name.contains("$1") &&
+ !name.startsWith("org.apache.openjpa.lib.jdbc.LoggingConnectionDecorator$") &&
+ !(name.endsWith("Comparator") && name.contains("$"));
+ }
+
+ private void registerJPAClasses(final Context context) {
+ Stream.of(Entity.class, MappedSuperclass.class, Embeddable.class)
+ .flatMap(it -> context.findAnnotatedClasses(it).stream())
+ .flatMap(context::findHierarchy)
+ .distinct()
+ .flatMap(it -> {
+ final ClassReflectionModel entity = new ClassReflectionModel();
+ entity.setName(it.getName());
+ entity.setAllPublicConstructors(true);
+ entity.setAllPublicMethods(true);
+ entity.setAllDeclaredConstructors(true);
+ entity.setAllDeclaredFields(true);
+ entity.setAllDeclaredMethods(true);
+ return Stream.concat(Stream.of(entity), extractFieldTypesForReflection(it));
+ })
+ .distinct()
+ .forEach(context::register);
+ }
+
+ private Stream<ClassReflectionModel> extractFieldTypesForReflection(final Class<?> entity) {
+ try {
+ final Field pcFieldTypes = entity.getDeclaredField("pcFieldTypes");
+ pcFieldTypes.setAccessible(true);
+ final Object types = pcFieldTypes.get(null);
+ return Stream.of(Class[].class.cast(types))
+ .distinct() // todo: filter(it -> !it.isPrimitive())?
+ .map(type -> {
+ final ClassReflectionModel fieldType = new ClassReflectionModel();
+ fieldType.setName(type.getName());
+ return fieldType;
+ });
+ } catch (final Exception e) {
+ return Stream.empty();
+ }
+ }
+}
diff --git a/knights/openjpa-knight/src/main/resources/META-INF/services/org.apache.geronimo.arthur.spi.ArthurExtension b/knights/openjpa-knight/src/main/resources/META-INF/services/org.apache.geronimo.arthur.spi.ArthurExtension
new file mode 100644
index 0000000..9886174
--- /dev/null
+++ b/knights/openjpa-knight/src/main/resources/META-INF/services/org.apache.geronimo.arthur.spi.ArthurExtension
@@ -0,0 +1 @@
+org.apache.geronimo.arthur.knight.openjpa.OpenJPAExtension
diff --git a/knights/pom.xml b/knights/pom.xml
index 9d27f40..ab0d1b6 100644
--- a/knights/pom.xml
+++ b/knights/pom.xml
@@ -33,6 +33,8 @@
<module>winegrower-knight</module>
<module>openwebbeans-knight</module>
<module>slf4j-knight</module>
+ <module>openjpa-knight</module>
+ <module>derby-knight</module>
</modules>
<dependencies>