[Jython-checkins] jython: Comments and minor re-write of PyJavaType.handleMroError
jeff.allen
jython-checkins at python.org
Fri Apr 19 13:32:03 EDT 2019
https://hg.python.org/jython/rev/262428b2c51a
changeset: 8237:262428b2c51a
user: Jeff Allen <ja.py at farowl.co.uk>
date: Fri Apr 19 17:43:45 2019 +0100
summary:
Comments and minor re-write of PyJavaType.handleMroError
This is work in aid of bjo #2445, to make the logic clearer, without (I think)
changing it. It adds (but skips) a failing test that reproduces the continuing
problem with IBM classes related to MQ.
files:
Lib/test/test_java_integration.py | 11 +-
src/org/python/core/Py.java | 39 +-
src/org/python/core/PyJavaType.java | 141 +++++----
src/org/python/core/PyType.java | 140 +++++++--
tests/java/org/python/tests/mro/EclipseChallengeMRO.java | 29 +-
tests/java/org/python/tests/mro/IBMMQChallengeMRO.java | 93 ++++++
6 files changed, 309 insertions(+), 144 deletions(-)
diff --git a/Lib/test/test_java_integration.py b/Lib/test/test_java_integration.py
--- a/Lib/test/test_java_integration.py
+++ b/Lib/test/test_java_integration.py
@@ -45,6 +45,7 @@
from javatests.ProxyTests import NullToString, Person
from clamp import SerializableProxies
+from unittest.case import skip
@@ -575,9 +576,15 @@
self.assertEqual(set(m), set(["abc", "xyz"]))
self.assertEqual(m["abc"], 42)
- def test_diamond_lattice_inheritance(self):
+ def test_mro_eclipse(self):
# http://bugs.jython.org/issue2445
- from org.python.tests.mro import TortureMRO
+ from org.python.tests.mro import EclipseChallengeMRO
+
+ @unittest.skip("FIXME: see http://bugs.jython.org/issue2445")
+ def test_mro_ibmmq(self):
+ # http://bugs.jython.org/issue2445
+ from org.python.tests.mro import IBMMQChallengeMRO
+ t = IBMMQChallengeMRO.mq.jms.MQQueue
def roundtrip_serialization(obj):
diff --git a/src/org/python/core/Py.java b/src/org/python/core/Py.java
--- a/src/org/python/core/Py.java
+++ b/src/org/python/core/Py.java
@@ -69,8 +69,7 @@
/** A zero-length array of Strings to pass to functions that
don't have any keyword arguments **/
public final static String[] NoKeywords = new String[0];
- /** A zero-length array of PyObject's to pass to functions that
- expect zero-arguments **/
+ /** A zero-length array of PyObject's to pass to functions when we have no arguments **/
public final static PyObject[] EmptyObjects = new PyObject[0];
/** A frozenset with zero elements **/
public final static PyFrozenSet EmptyFrozenSet = new PyFrozenSet();
@@ -2566,29 +2565,29 @@
}
}
+ /**
+ * Turn any Python iterable into an array of its elements.
+ *
+ * @param iterable to evaluate
+ * @return array of elements from iterable
+ */
static PyObject[] make_array(PyObject iterable) {
// Special-case the common tuple and list cases, for efficiency
if (iterable instanceof PySequenceList) {
return ((PySequenceList) iterable).getArray();
+ } else {
+ int n = 10;
+ if (!(iterable instanceof PyGenerator)) {
+ try {
+ n = iterable.__len__(); // may be available, otherwise ...
+ } catch (PyException pye) { /* ... leave n at 0 */ }
+ }
+ List<PyObject> objs = new ArrayList<PyObject>(n);
+ for (PyObject item : iterable.asIterable()) {
+ objs.add(item);
+ }
+ return objs.toArray(Py.EmptyObjects);
}
-
- // Guess result size and allocate space. The typical make_array arg supports
- // __len__, with one exception being generators, so avoid the overhead of an
- // exception from __len__ in their case
- int n = 10;
- if (!(iterable instanceof PyGenerator)) {
- try {
- n = iterable.__len__();
- } catch (PyException pye) {
- // ok
- }
- }
-
- List<PyObject> objs = new ArrayList<PyObject>(n);
- for (PyObject item : iterable.asIterable()) {
- objs.add(item);
- }
- return objs.toArray(Py.EmptyObjects);
}
//------------------------constructor-section---------------------------
diff --git a/src/org/python/core/PyJavaType.java b/src/org/python/core/PyJavaType.java
--- a/src/org/python/core/PyJavaType.java
+++ b/src/org/python/core/PyJavaType.java
@@ -1,5 +1,8 @@
package org.python.core;
+import org.python.core.util.StringUtil;
+import org.python.util.Generic;
+
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -27,7 +30,9 @@
import java.util.Enumeration;
import java.util.EventListener;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
+import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -35,9 +40,6 @@
import java.util.Set;
import java.util.Stack;
-import org.python.core.util.StringUtil;
-import org.python.util.Generic;
-
public class PyJavaType extends PyType {
private final static Class<?>[] OO = {PyObject.class, PyObject.class};
@@ -218,76 +220,88 @@
postDelattr(name);
}
+ /**
+ * {@inheritDoc}
+ * <p>
+ * An override specifically for Java classes (that are not {@link PyObject}) has the possibility
+ * of completing the MRO in {@code mro}, by additional steps affecting the {@code mro} and
+ * {@code toMerge} passed in. This divergence from the Python rules is acceptable for Java.
+ */
@Override
void handleMroError(MROMergeState[] toMerge, List<PyObject> mro) {
+
if (underlying_class != null) {
- // If this descends from PyObject, don't do the Java mro cleanup
+ // This descends from PyObject (but is not exposed): don't attempt recovery.
super.handleMroError(toMerge, mro);
}
- Set<PyJavaType> inConflict = Generic.set();
- PyJavaType winner = null;
+
+ // Make a set of all the PyJavaTypes still in the lists to merge.
+ Set<PyJavaType> inConflict = new LinkedHashSet<>();
for (MROMergeState mergee : toMerge) {
for (int i = mergee.next; i < mergee.mro.length; i++) {
- if (mergee.mro[i] == PyObject.TYPE
- || mergee.mro[i] == PyType.fromClass(Object.class)) {
- continue;
+ PyObject m = mergee.mro[i];
+ if (m instanceof PyJavaType && m != Constant.OBJECT) {
+ inConflict.add((PyJavaType) m);
}
- if (winner == null) {
- /*
- * Pick an arbitrary class to be added to the mro next and break the conflict.
- * If method name conflicts were allowed between methods added to Java types, it
- * would go first, but that's prevented, so being a winner doesn't actually get
- * it anything.
- */
- winner = (PyJavaType) mergee.mro[i];
- }
- inConflict.add((PyJavaType) mergee.mro[i]);
}
}
- Set<String> allModified = Generic.set();
- PyJavaType[] conflictedAttributes = inConflict.toArray(new PyJavaType[inConflict.size()]);
- for (PyJavaType type : conflictedAttributes) {
- if (type.modified == null) {
- continue;
- }
- for (String method : type.modified) {
- if (!allModified.add(method)) {
- // Another type in conflict has this method, possibly fail
- PyList types = new PyList();
- Set<Class<?>> proxySet = Generic.set();
- for (PyJavaType othertype : conflictedAttributes) {
+ /*
+ * Collect the names of all the methods added to any of these types (with certain
+ * exclusions) that occur in more than one of these residual types. If a name is found in
+ * more than one of these types, raise an error.
+ */
+ Set<String> allModified = new HashSet<>();
+ for (PyJavaType type : inConflict) {
+ if (type.modified != null) {
+ // For every method name modified in type ...
+ for (String method : type.modified) {
+ if (!allModified.add(method)) {
/*
- * Ignore any pairings of types that are in a superclass/superinterface
- * relationship with each other. This problem is a false positive that
- * happens because of the automatic addition of methods so that Java classes
- * behave more like their corresponding Python types, such as adding sort or
- * remove. See http://bugs.jython.org/issue2445
+ * The method name was already in the set, so has appeared already. Work out
+ * which one that was by rescanning.
+ */// XXX Why didn't we keep a map?
+ List<PyJavaType> types = new ArrayList<>();
+ Set<Class<?>> proxySet = new HashSet<>();
+ Class<?> proxyType = type.getProxyType();
+ for (PyJavaType othertype : inConflict) {
+ /*
+ * Ignore any pairings of types that are in a superclass/superinterface
+ * relationship with each other. This problem is a false positive that
+ * happens because of the automatic addition of methods so that Java
+ * classes behave more like their corresponding Python types, such as
+ * adding sort or remove. See http://bugs.jython.org/issue2445
+ */
+ if (othertype.modified != null && othertype.modified.contains(method)) {
+ Class<?> otherProxyType = othertype.getProxyType();
+ if (otherProxyType.isAssignableFrom(proxyType)) {
+ continue;
+ } else if (proxyType.isAssignableFrom(otherProxyType)) {
+ continue;
+ } else {
+ types.add(othertype);
+ proxySet.add(otherProxyType);
+ }
+ }
+ }
+
+ /*
+ * Need to special case collections that implement both Iterable and Map.
+ * Ignore the conflict in having duplicate __iter__ added (see
+ * getCollectionProxies), while still allowing each path on the inheritance
+ * hierarchy to get an __iter__. Annoying but necessary logic. See
+ * http://bugs.jython.org/issue1878
*/
- if (othertype.modified != null && othertype.modified.contains(method)
- && !(othertype.getProxyType().isAssignableFrom(type.getProxyType())
- || type.getProxyType()
- .isAssignableFrom(othertype.getProxyType()))) {
- types.add(othertype);
- proxySet.add(othertype.getProxyType());
+ if (method.equals("__iter__")
+ && Generic.set(Iterable.class, Map.class).containsAll(proxySet)) {
+ continue;
}
- }
- /*
- * Need to special case collections that implement both Iterable and Map. Ignore
- * the conflict in having duplicate __iter__ added (see getCollectionProxies),
- * while still allowing each path on the inheritance hierarchy to get an
- * __iter__. Annoying but necessary logic. See http://bugs.jython.org/issue1878
- */
- if (method.equals("__iter__")
- && Generic.set(Iterable.class, Map.class).containsAll(proxySet)) {
- continue;
- }
- if (types.size() > 0) {
- throw Py.TypeError(String.format(
- "Supertypes that share a modified attribute "
- + "have an MRO conflict[attribute=%s, supertypes=%s, type=%s]",
- method, types, this.getName()));
+ String fmt = "Supertypes that share a modified attribute "
+ + "have an MRO conflict[attribute=%s, supertypes=%s, type=%s]";
+ if (types.size() > 0) {
+ throw Py.TypeError(String.format(fmt, method, types, this.getName()));
+ }
}
}
}
@@ -297,7 +311,7 @@
* We can keep trucking, there aren't any existing method name conflicts. Mark the conflicts
* in all the classes so further method additions can check for trouble.
*/
- for (PyJavaType type : conflictedAttributes) {
+ for (PyJavaType type : inConflict) {
for (PyJavaType otherType : inConflict) {
if (otherType != type) {
if (type.conflicted == null) {
@@ -308,11 +322,18 @@
}
}
- // Add our winner to the mro, clear the clog, and try to finish the rest
+ /*
+ * Emit the first conflicting type we encountered to the MRO, and remove it from the working
+ * lists. Forcing a step like this is ok for classes compiled from Java as the order of
+ * bases is not significant as long as hierarchy is preserved.
+ */
+ PyJavaType winner = inConflict.iterator().next();
mro.add(winner);
for (MROMergeState mergee : toMerge) {
mergee.removeFromUnmerged(winner);
}
+
+ // Restart the MRO generation algorithm from the current state.
computeMro(toMerge, mro);
}
diff --git a/src/org/python/core/PyType.java b/src/org/python/core/PyType.java
--- a/src/org/python/core/PyType.java
+++ b/src/org/python/core/PyType.java
@@ -1441,30 +1441,39 @@
return (tp_flags & Py.TPFLAGS_IS_ABSTRACT) != 0;
}
+ /**
+ * Set the {@link #mro} field from the Python {@code mro()} method which uses
+ * ({@link #computeMro()} by default. We must repeat this whenever the bases of this type
+ * change, which they may in general for classes defined in Python.
+ */
private void mro_internal() {
+
if (getType() == TYPE) {
- mro = computeMro();
+ mro = computeMro(); // Shortcut
+
} else {
+ // Use the mro() method, which may have been redefined to find the MRO as an array.
PyObject mroDescr = getType().lookup("mro");
if (mroDescr == null) {
throw Py.AttributeError("mro");
}
PyObject[] result = Py.make_array(mroDescr.__get__(null, getType()).__call__(this));
+ // Verify that Python types in the MRO have a "solid base" in common with this type.
PyType solid = solid_base(this);
+
for (PyObject cls : result) {
if (cls instanceof PyClass) {
continue;
- }
- if (!(cls instanceof PyType)) {
- throw Py.TypeError(String.format("mro() returned a non-class ('%.500s')",
- cls.getType().fastGetName()));
- }
- PyType t = (PyType) cls;
- if (!solid.isSubType(solid_base(t))) {
- throw Py.TypeError(String.format(
- "mro() returned base with unsuitable layout " + "('%.500s')",
- t.fastGetName()));
+ } else if (cls instanceof PyType) {
+ PyType t = (PyType) cls;
+ if (!solid.isSubType(solid_base(t))) {
+ String fmt = "mro() returned base with unsuitable layout ('%.500s')";
+ throw Py.TypeError(String.format(fmt, t.fastGetName()));
+ }
+ } else {
+ String fmt = "mro() returned a non-class ('%.500s')";
+ throw Py.TypeError(String.format(fmt, cls.getType().fastGetName()));
}
}
mro = result;
@@ -1605,14 +1614,20 @@
}
@ExposedMethod(defaults = "null", doc = BuiltinDocs.type_mro_doc)
- final PyList type_mro(PyObject o) {
- if (o == null) {
- return new PyList(computeMro());
- }
- return new PyList(((PyType) o).computeMro());
+ final PyList type_mro(PyObject X) {
+ // This is either X.mro (where X is a type object) or type.mro(X)
+ PyObject[] res = (X == null) ? computeMro() : ((PyType) X).computeMro();
+ return new PyList(res);
}
+ /**
+ * Examine the bases (which must contain no repetition) and the MROs of these bases and return
+ * the MRO of this class.
+ *
+ * @return the MRO of this class
+ */
PyObject[] computeMro() {
+ // First check that there are no duplicates amongst the bases of this class.
for (int i = 0; i < bases.length; i++) {
PyObject cur = bases[i];
for (int j = i + 1; j < bases.length; j++) {
@@ -1624,6 +1639,7 @@
}
}
+ // Build a table of the MROs of the bases as MROMergeState objects.
MROMergeState[] toMerge = new MROMergeState[bases.length + 1];
for (int i = 0; i < bases.length; i++) {
toMerge[i] = new MROMergeState();
@@ -1633,14 +1649,27 @@
toMerge[i].mro = classic_mro((PyClass) bases[i]);
}
}
+
+ // Append to this table the list of bases of this class
toMerge[bases.length] = new MROMergeState();
toMerge[bases.length].mro = bases;
+ // The head of the output MRO is the current class itself.
List<PyObject> mro = Generic.list();
mro.add(this);
+
+ // Now execute the core of the MRO generation algorithm.
return computeMro(toMerge, mro);
}
+ /**
+ * Core algorithm for computing the MRO for "new-style" (although it's been a while) Python
+ * classes.
+ *
+ * @param toMerge data structure representing the (partly processed) MROs of bases.
+ * @param mro partial MRO (initially only this class)
+ * @return the MRO of this class
+ */
PyObject[] computeMro(MROMergeState[] toMerge, List<PyObject> mro) {
boolean addedProxy = false;
Class<?> thisProxyAttr = this.getProxyType();
@@ -1693,12 +1722,17 @@
}
/**
- * Must either throw an exception, or bring the merges in <code>toMerge</code> to completion by
- * finishing filling in <code>mro</code>.
+ * This method is called when the {@link #computeMro(MROMergeState[], List)} reaches an impasse
+ * as far as its official algorithm is concerned, with the partial MRO and current state of the
+ * working lists at the point the problem is detected. The base implementation raises a Python
+ * {@code TypeError}, diagnosing the problem.
+ *
+ * @param toMerge partially processed algorithm state
+ * @param mro output MRO (incomplete)
*/
void handleMroError(MROMergeState[] toMerge, List<PyObject> mro) {
StringBuilder msg = new StringBuilder(
- "Cannot create a consistent method resolution\n" + "order (MRO) for bases ");
+ "Cannot create a consistent method resolution\norder (MRO) for bases ");
Set<PyObject> set = Generic.set();
for (MROMergeState mergee : toMerge) {
if (!mergee.isMerged()) {
@@ -1720,7 +1754,9 @@
}
/**
- * Finds the parent of type with an underlying_class or with slots sans a __dict__ slot.
+ * Finds the first super-type of the given {@code type} that is a "solid base" of the type, that
+ * is, the returned type has an {@link #underlying_class}, or it defines {@code __slots__} and
+ * no instance level dictionary ({@code __dict__} attribute).
*/
private static PyType solid_base(PyType type) {
do {
@@ -1732,39 +1768,49 @@
return PyObject.TYPE;
}
+ /**
+ * A "solid base" is a type that has an {@link #underlying_class}, or defines {@code __slots__}
+ * and no instance level dictionary (no {@code __dict__} attribute).
+ */
private static boolean isSolidBase(PyType type) {
return type.underlying_class != null || (type.ownSlots != 0 && !type.needs_userdict);
}
/**
- * Finds the base in bases with the most derived solid_base, ie the most base type
+ * Find the base selected from a {@link #bases} array that has the "most derived solid base".
+ * This will become the {@link #base} attribute of a class under construction, or in which the
+ * {@link #bases} tuple is being updated. On a successful return, the return value is one of the
+ * elements of the argument {@code bases} and the solid base of that return is a sub-type of the
+ * solid bases of all other (non-classic) elements of the argument.
*
* @throws Py.TypeError if the bases don't all derive from the same solid_base
* @throws Py.TypeError if at least one of the bases isn't a new-style class
*/
private static PyType best_base(PyObject[] bases) {
- PyType winner = null;
- PyType candidate = null;
- PyType best = null;
- for (PyObject base : bases) {
- if (base instanceof PyClass) {
+ PyType best = null; // The best base found so far
+ PyType bestSolid = null; // The solid base of the best base so far
+ for (PyObject b : bases) {
+ if (b instanceof PyType) {
+ PyType base = (PyType) b, solid = solid_base(base);
+ if (bestSolid == null) {
+ // First (non-classic) base we find becomes the best base so far
+ best = base;
+ bestSolid = solid;
+ } else if (bestSolid.isSubType(solid)) {
+ // Current best is still the best so far
+ } else if (solid.isSubType(bestSolid)) {
+ // base is better than the previous best since its solid base is more derived.
+ best = base;
+ bestSolid = solid;
+ } else {
+ throw Py.TypeError("multiple bases have instance lay-out conflict");
+ }
+ } else if (b instanceof PyClass) {
+ // Skip over classic bases
continue;
- }
- if (!(base instanceof PyType)) {
+ } else {
throw Py.TypeError("bases must be types");
}
- candidate = solid_base((PyType) base);
- if (winner == null) {
- winner = candidate;
- best = (PyType) base;
- } else if (winner.isSubType(candidate)) {
- ;
- } else if (candidate.isSubType(winner)) {
- winner = candidate;
- best = (PyType) base;
- } else {
- throw Py.TypeError("multiple bases have instance lay-out conflict");
- }
}
if (best == null) {
throw Py.TypeError("a new-style class can't have only classic bases");
@@ -2603,6 +2649,20 @@
}
mro = newMro.toArray(new PyObject[newMro.size()]);
}
+
+ @Override
+ public String toString() {
+ List<String> names = Generic.list();
+ for (int i = next; i < mro.length; i++) {
+ PyObject t = mro[i];
+ if (t instanceof PyType) {
+ names.add(((PyType) t).name);
+ } else {
+ names.add(t.toString());
+ }
+ }
+ return names.toString();
+ }
}
/**
diff --git a/tests/java/org/python/tests/mro/TortureMRO.java b/tests/java/org/python/tests/mro/EclipseChallengeMRO.java
rename from tests/java/org/python/tests/mro/TortureMRO.java
rename to tests/java/org/python/tests/mro/EclipseChallengeMRO.java
--- a/tests/java/org/python/tests/mro/TortureMRO.java
+++ b/tests/java/org/python/tests/mro/EclipseChallengeMRO.java
@@ -1,4 +1,4 @@
-// Copyright (c) Jython Developers.
+// Copyright (c)2019 Jython Developers.
// Licensed to the Python Software Foundation under a Contributor Agreement.
package org.python.tests.mro;
@@ -6,46 +6,31 @@
/**
* A class providing interface and abstract class relationships that approximate the structure of
* org.eclipse.emf.ecore.util.DelegatingFeatureMap, in order to exercise b.j.o issue 2445. The
- * complex inheritance (more complex than diamond inheritance) confused PyJavaType handling of the
- * MRO. This class is imported by
- * {@code test_java_integration.JavaMROTest.test_diamond_lattice_inheritance} as a test.
+ * complex inheritance confused PyJavaType handling of the MRO. This class is imported by
+ * {@code test_java_integration.JavaMROTest.test_mro_eclipse} as a test.
* <p>
- * An invocation at the prompt (for debugging use), and output before the fix, is:
- *
- * <pre>
- * PS > dist\bin\jython -S -c"from org.python.tests.mro import TortureMRO"
+ * An invocation at the prompt (for debugging use), and output before the fix, is: <pre>
+ * PS > dist\bin\jython -S -c"from org.python.tests.mro import EclipseChallengeMRO"
* Traceback (most recent call last):
* File "<string>", line 1, in <module>
* TypeError: Supertypes that share a modified attribute have an MRO
* conflict[attribute=sort, supertypes=[<type 'java.util.List'>,
- * <type 'java.util.AbstractList'>], type=TortureMRO$Target]
+ * <type 'java.util.AbstractList'>], type=EclipseChallengeMRO$Target]
* </pre>
*/
-public class TortureMRO {
+public class EclipseChallengeMRO {
interface Entry {} // Was FeatureMap.Entry
-
interface Thing {} // Was EStructuralFeature.Setting
-
interface EList<E> extends java.util.List<E> {}
-
interface IEList<E> extends EList<E> {}
-
interface FList extends EList<Entry> {} // Was FeatureMap
-
interface FIEListThing extends FList, IEList<Entry>, Thing {} // Was 2 FeatureMap.Internal
-
abstract static class AbstractEList<E> extends java.util.AbstractList<E> implements EList<E> {}
-
abstract static class DEList<E> extends AbstractEList<E> {}
-
interface NList<E> extends EList<E> {}
-
abstract static class DNListImpl<E> extends DEList<E> implements NList<E> {}
-
abstract static class DNIEListImpl<E> extends DNListImpl<E> implements IEList<E> {}
-
abstract static class DNIEListThing<E> extends DNIEListImpl<E> implements Thing {}
-
public abstract static class Target extends DNIEListThing<Entry> implements FIEListThing {}
}
diff --git a/tests/java/org/python/tests/mro/IBMMQChallengeMRO.java b/tests/java/org/python/tests/mro/IBMMQChallengeMRO.java
new file mode 100644
--- /dev/null
+++ b/tests/java/org/python/tests/mro/IBMMQChallengeMRO.java
@@ -0,0 +1,93 @@
+// Copyright (c)2019 Jython Developers.
+// Licensed to the Python Software Foundation under a Contributor Agreement.
+
+package org.python.tests.mro;
+
+import java.io.Serializable;
+import java.util.Map;
+
+/**
+ * A class providing interface and abstract class relationships that approximate the structure of
+ * com.ibm classes related to MQ, in order to exercise b.j.o issue 2445. The complex inheritance
+ * confused PyJavaType handling of the MRO. This class is imported by
+ * {@code test_java_integration.JavaMROTest.test_mro_ibmmq}.
+ * <p>
+ * An invocation at the prompt (for debugging use), and output before the fix, is: <pre>
+ * PS > dist\bin\jython -S -c "from org.python.tests.mro import IBMMQChallengeMRO; t=m.mq.jms.MQQueue"
+ * Traceback (most recent call last):
+ * File "<string>", line 1, in <module>
+ * TypeError: Supertypes that share a modified attribute have an MRO conflict
+ * [attribute=get,supertypes=[<type
+ * 'org.python.tests.mro.IBMMQChallengeMRO$msg$client$jms$internal$JmsPropertyContextImpl'>],
+ * type=IBMMQChallengeMRO$mq$jms$MQQueue]
+ * </pre>
+ */
+public class IBMMQChallengeMRO {
+
+ static class javax_jms { // represents javax.jms
+
+ public interface Queue extends Destination {}
+ public interface Destination {}
+ }
+
+ static class javax_naming { // represents javax.naming
+
+ public interface Referenceable {}
+ }
+
+ static class msg { // represents com.ibm.msg
+
+ static class client { // represents com.ibm.msg.client
+
+ static class jms { // represents com.ibm.msg.client.jms
+
+ public interface JmsDestination extends JmsPropertyContext, javax_jms.Destination {}
+ public interface JmsPropertyContext
+ extends JmsReadablePropertyContext, Map<String, Object> {}
+ public interface JmsReadablePropertyContext extends Serializable {}
+ public interface JmsQueue extends JmsDestination, javax_jms.Queue {}
+
+ static class admin { // represents com.ibm.msg.client.jms.admin
+
+ public static abstract/* ? */ class JmsJndiDestinationImpl
+ extends JmsDestinationImpl
+ implements JmsDestination, javax_naming.Referenceable, Serializable {}
+ public static abstract/* ? */ class JmsDestinationImpl
+ extends internal.JmsPropertyContextImpl implements JmsDestination {}
+ }
+
+ static class internal { // represents com.ibm.msg.client.jms.internal
+
+ public static abstract/* ? */ class JmsPropertyContextImpl
+ extends JmsReadablePropertyContextImpl implements JmsPropertyContext,
+ provider.ProviderPropertyContextCallback {}
+ public static abstract class JmsReadablePropertyContextImpl
+ implements JmsReadablePropertyContext {}
+ }
+ }
+
+ static class provider { // represents com.ibm.msg.client.provider
+
+ public interface ProviderPropertyContextCallback {}
+ }
+ }
+ }
+
+ static class jms { // represents com.ibm.jms
+
+ public interface JMSDestination extends javax_jms.Destination {}
+ }
+
+ public static class mq { // represents com.ibm.mq
+
+ public static class jms { // represents com.ibm.mq.jms
+
+ public abstract/* ? */ class MQDestination
+ extends msg.client.jms.admin.JmsJndiDestinationImpl implements
+ javax_jms.Destination, IBMMQChallengeMRO.jms.JMSDestination, Serializable {}
+ /** Target class in the test **/
+ public abstract/* ? */ class MQQueue extends MQDestination implements javax_jms.Queue,
+ msg.client.jms.JmsQueue, javax_naming.Referenceable, Serializable {}
+ }
+ }
+}
--
Repository URL: https://hg.python.org/jython
More information about the Jython-checkins
mailing list