Author: struberg
Date: Mon Mar 14 17:07:38 2016
New Revision: 1734966
URL: http://svn.apache.org/viewvc?rev=1734966&view=rev
Log:
OPENJPA-2632 fallback to TCCL for select new if class cannot be found
That might happen if the entities are loaded within a shared ear lib
but the actual "select new" is performed from another ClassLoader (e.g. WAR)
Contributed by Reinhard Sandtner (apacheId: rsandtner). Txs for the patch!
Modified:
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java
Modified:
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java?rev=1734966&r1=1734965&r2=1734966&view=diff
==============================================================================
---
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java
(original)
+++
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java
Mon Mar 14 17:07:38 2016
@@ -220,6 +220,13 @@ public interface OpenJPAConfiguration
"openjpa.option.PostLoadOnMerge";
/**
+ * Option to enable TCCL if the result class for select new is not found
+ * in the entities classloader
+ */
+ public static final String OPTION_USE_TCCL_IN_SELECT_NEW =
+ "openjpa.option.UseTCCLinSelectNew";
+
+ /**
* Return the set of option strings supported by this runtime. This set
* is mutable.
*/
@@ -1949,5 +1956,32 @@ public interface OpenJPAConfiguration
* @since 2.2.0
*/
public void setOptimizeIdCopy(Boolean optimizeIds);
+
+ /**
+ * Indicates if the {@link Thread#contextClassLoader} should be used
+ * as fallback if the result class for {@code select new} is not found
+ * by the classloader of the entity.
+ *
+ * @since 2.4.2
+ */
+ public boolean getUseTCCLinSelectNew();
+
+ /**
+ * Indicates if the {@link Thread#contextClassLoader} should be used
+ * as fallback if the result class for {@code select new} is not found
+ * by the classloader of the entity.
+ *
+ * @since 2.4.2
+ */
+ public void setUseTCCLinSelectNew(boolean useTcclForSelectNew);
+
+ /**
+ * Indicates if the {@link Thread#contextClassLoader} should be used
+ * as fallback if the result class for {@code select new} is not found
+ * by the classloader of the entity.
+ *
+ * @since 2.4.2
+ */
+ public void setUseTCCLinSelectNew(Boolean useTcclForSelectNew);
}
Modified:
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java?rev=1734966&r1=1734965&r2=1734966&view=diff
==============================================================================
---
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java
(original)
+++
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java
Mon Mar 14 17:07:38 2016
@@ -177,6 +177,7 @@ public class OpenJPAConfigurationImpl
public PluginListValue instrumentationProviders;
public BooleanValue postLoadOnMerge;
public BooleanValue optimizeIdCopy;
+ public BooleanValue useTcclForSelectNew;
// custom values
public BrokerFactoryValue brokerFactoryPlugin;
@@ -604,6 +605,10 @@ public class OpenJPAConfigurationImpl
aliases = new String[] { "default", AuditLogger.class.getName(), };
auditorPlugin.setAliases(aliases);
auditorPlugin.setInstantiatingGetter("getAuditorInstance");
+
+ useTcclForSelectNew = addBoolean("UseTCCLinSelectNew");
+ useTcclForSelectNew.setDefault("false");
+ useTcclForSelectNew.set(false);
// initialize supported options that some runtimes may not support
supportedOptions.add(OPTION_NONTRANS_READ);
@@ -622,6 +627,7 @@ public class OpenJPAConfigurationImpl
supportedOptions.add(OPTION_VALUE_INCREMENT);
supportedOptions.add(OPTION_DATASTORE_CONNECTION);
supportedOptions.add(OPTION_POSTLOAD_ON_MERGE);
+ supportedOptions.add(OPTION_USE_TCCL_IN_SELECT_NEW);
if (derivations)
ProductDerivations.beforeConfigurationLoad(this);
@@ -1873,5 +1879,22 @@ public class OpenJPAConfigurationImpl
setOptimizeIdCopy(optimizeId.booleanValue());
}
}
+
+ @Override
+ public boolean getUseTCCLinSelectNew() {
+ return useTcclForSelectNew.get();
+ }
+
+ @Override
+ public void setUseTCCLinSelectNew(boolean useTcclForSelectNew) {
+ this.useTcclForSelectNew.set(useTcclForSelectNew);
+ }
+
+ @Override
+ public void setUseTCCLinSelectNew(Boolean useTcclForSelectNew) {
+ if (useTcclForSelectNew != null) {
+ setUseTCCLinSelectNew(useTcclForSelectNew.booleanValue());
+ }
+ }
}
Modified:
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java?rev=1734966&r1=1734965&r2=1734966&view=diff
==============================================================================
---
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java
(original)
+++
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java
Mon Mar 14 17:07:38 2016
@@ -22,6 +22,7 @@ import java.io.PrintStream;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.math.BigDecimal;
+import java.security.AccessController;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.ArrayList;
@@ -56,6 +57,7 @@ import org.apache.openjpa.kernel.exps.Re
import org.apache.openjpa.kernel.exps.Subquery;
import org.apache.openjpa.kernel.exps.Value;
import org.apache.openjpa.lib.log.Log;
+import org.apache.openjpa.lib.util.J2DoPrivHelper;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.lib.util.OrderedMap;
import org.apache.openjpa.lib.util.Localizer.Message;
@@ -410,6 +412,22 @@ public class JPQLExpressionBuilder
String baseName = left(node).getChild(n-1).text;
constructor = resolver.classForName(baseName, null);
}
+
+ if (constructor == null &&
resolver.getConfiguration().getUseTCCLinSelectNew()) {
+ try {
+ if (System.getSecurityManager() != null) {
+ constructor = AccessController.doPrivileged(
+
J2DoPrivHelper.getForNameAction(resultClassName, false,
+
AccessController.doPrivileged(J2DoPrivHelper.getContextClassLoaderAction())));
+ }
+ else {
+ constructor =
Thread.currentThread().getContextClassLoader().loadClass(resultClassName);
+ }
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+
if (constructor == null)
throw parseException(EX_USER, "no-constructor",
new Object[]{ resultClassName }, null);
@@ -1612,7 +1630,7 @@ public class JPQLExpressionBuilder
* determines whether the first argument is used as-is or converted to
* an Integer as parameter key.
*
- * @param the text as it appears in the parsed node
+ * @param id the text as it appears in the parsed node
* @param positional if true the first argument is converted to an integer
* @param isCollectionValued true for collection-valued parameters
*/