Repository: ignite Updated Branches: refs/heads/ignite-2100 c19f3b942 -> 6e243d83f
IGNITE-2100: Finished main implementation part. Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/6e243d83 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/6e243d83 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/6e243d83 Branch: refs/heads/ignite-2100 Commit: 6e243d83f3a801f40fd97e7e976cf951052f3d0a Parents: c19f3b9 Author: vozerov-gridgain <[email protected]> Authored: Tue Dec 15 17:42:15 2015 +0300 Committer: vozerov-gridgain <[email protected]> Committed: Tue Dec 15 17:42:15 2015 +0300 ---------------------------------------------------------------------- .../internal/binary/BinaryClassDescriptor.java | 59 ++---- .../ignite/internal/binary/BinaryContext.java | 12 ++ .../ignite/internal/binary/BinaryUtils.java | 36 ++++ .../processors/query/GridQueryProcessor.java | 195 ++++++++++++++----- 4 files changed, 207 insertions(+), 95 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/6e243d83/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryClassDescriptor.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryClassDescriptor.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryClassDescriptor.java index d348942..ab1a858 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryClassDescriptor.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryClassDescriptor.java @@ -17,14 +17,23 @@ package org.apache.ignite.internal.binary; -import java.io.Externalizable; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; +import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.binary.BinaryIdMapper; +import org.apache.ignite.binary.BinaryObjectException; +import org.apache.ignite.binary.BinarySerializer; +import org.apache.ignite.binary.Binarylizable; +import org.apache.ignite.internal.processors.cache.CacheObjectImpl; +import org.apache.ignite.internal.util.GridUnsafe; +import org.apache.ignite.internal.util.typedef.internal.U; +import org.apache.ignite.marshaller.MarshallerExclusions; +import org.apache.ignite.marshaller.optimized.OptimizedMarshaller; +import org.jetbrains.annotations.Nullable; +import sun.misc.Unsafe; + import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.lang.reflect.Modifier; import java.math.BigDecimal; import java.sql.Timestamp; import java.util.ArrayList; @@ -35,18 +44,6 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.UUID; -import org.apache.ignite.IgniteCheckedException; -import org.apache.ignite.binary.BinaryIdMapper; -import org.apache.ignite.binary.BinaryObjectException; -import org.apache.ignite.binary.BinarySerializer; -import org.apache.ignite.binary.Binarylizable; -import org.apache.ignite.internal.processors.cache.CacheObjectImpl; -import org.apache.ignite.internal.util.GridUnsafe; -import org.apache.ignite.internal.util.typedef.internal.U; -import org.apache.ignite.marshaller.MarshallerExclusions; -import org.apache.ignite.marshaller.optimized.OptimizedMarshaller; -import org.jetbrains.annotations.Nullable; -import sun.misc.Unsafe; import static java.lang.reflect.Modifier.isStatic; import static java.lang.reflect.Modifier.isTransient; @@ -162,7 +159,7 @@ public class BinaryClassDescriptor { excluded = MarshallerExclusions.isExcluded(cls); - useOptMarshaller = !predefined && useDfltSerialization && initUseOptimizedMarshallerFlag(); + useOptMarshaller = !predefined && useDfltSerialization && BinaryUtils.requireOptimizedMarshaller(cls); if (excluded) mode = BinaryWriteMode.EXCLUSION; @@ -760,32 +757,4 @@ public class BinaryClassDescriptor { throw new BinaryObjectException("Failed to get constructor for class: " + cls.getName(), e); } } - - /** - * Determines whether to use {@link OptimizedMarshaller} for serialization or - * not. - * - * @return {@code true} if to use, {@code false} otherwise. - */ - @SuppressWarnings("unchecked") - private boolean initUseOptimizedMarshallerFlag() { - for (Class c = cls; c != null && !c.equals(Object.class); c = c.getSuperclass()) { - if (Externalizable.class.isAssignableFrom(c)) - return true; - - try { - Method writeObj = c.getDeclaredMethod("writeObject", ObjectOutputStream.class); - Method readObj = c.getDeclaredMethod("readObject", ObjectInputStream.class); - - if (!Modifier.isStatic(writeObj.getModifiers()) && !Modifier.isStatic(readObj.getModifiers()) && - writeObj.getReturnType() == void.class && readObj.getReturnType() == void.class) - return true; - } - catch (NoSuchMethodException ignored) { - // No-op. - } - } - - return false; - } } http://git-wip-us.apache.org/repos/asf/ignite/blob/6e243d83/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java index 73fc71d..3c6f722 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java @@ -241,6 +241,18 @@ public class BinaryContext implements Externalizable { } /** + * Whether binary marshalling is forced for class. + * + * @param cls Class. + * @return {@code True} if forced. + */ + public boolean forceBinaryMarshalling(Class cls) { + int typeId = typeId(cls.getName()); + + return nonDfltSerializationFlags.contains(typeId); + } + + /** * @return Ignite configuration. */ public IgniteConfiguration configuration(){ http://git-wip-us.apache.org/repos/asf/ignite/blob/6e243d83/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java index c999657..2a7415a 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java @@ -33,7 +33,12 @@ import org.jetbrains.annotations.Nullable; import org.jsr166.ConcurrentHashMap8; import java.io.ByteArrayInputStream; +import java.io.Externalizable; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.lang.reflect.Array; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.math.BigDecimal; import java.math.BigInteger; import java.sql.Timestamp; @@ -54,6 +59,8 @@ import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentSkipListSet; +import org.apache.ignite.marshaller.optimized.OptimizedMarshaller; + import static java.nio.charset.StandardCharsets.UTF_8; /** @@ -1835,6 +1842,35 @@ public class BinaryUtils { } /** + * Determines whether to use {@link OptimizedMarshaller} for serialization or + * not. + * + * @param cls Class. + * @return {@code true} if to use, {@code false} otherwise. + */ + @SuppressWarnings("unchecked") + public static boolean requireOptimizedMarshaller(Class cls) { + for (Class c = cls; c != null && !c.equals(Object.class); c = c.getSuperclass()) { + if (Externalizable.class.isAssignableFrom(c)) + return true; + + try { + Method writeObj = c.getDeclaredMethod("writeObject", ObjectOutputStream.class); + Method readObj = c.getDeclaredMethod("readObject", ObjectInputStream.class); + + if (!Modifier.isStatic(writeObj.getModifiers()) && !Modifier.isStatic(readObj.getModifiers()) && + writeObj.getReturnType() == void.class && readObj.getReturnType() == void.class) + return true; + } + catch (NoSuchMethodException ignored) { + // No-op. + } + } + + return false; + } + + /** * Enum type. */ private static class EnumType { http://git-wip-us.apache.org/repos/asf/ignite/blob/6e243d83/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java index 0412b4c..4d6e66b 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java @@ -17,35 +17,13 @@ package org.apache.ignite.internal.processors.query; -import java.lang.reflect.AccessibleObject; -import java.lang.reflect.Field; -import java.lang.reflect.Member; -import java.lang.reflect.Method; -import java.math.BigDecimal; -import java.sql.Time; -import java.sql.Timestamp; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; -import java.util.UUID; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.ExecutorService; -import javax.cache.Cache; -import javax.cache.CacheException; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.IgniteException; import org.apache.ignite.IgniteLogger; import org.apache.ignite.binary.BinaryField; +import org.apache.ignite.binary.BinaryObject; import org.apache.ignite.binary.BinaryType; +import org.apache.ignite.binary.Binarylizable; import org.apache.ignite.cache.CacheTypeMetadata; import org.apache.ignite.cache.QueryEntity; import org.apache.ignite.cache.QueryIndex; @@ -55,15 +33,17 @@ import org.apache.ignite.cache.query.SqlFieldsQuery; import org.apache.ignite.cache.query.SqlQuery; import org.apache.ignite.configuration.CacheConfiguration; import org.apache.ignite.events.CacheQueryExecutedEvent; -import org.apache.ignite.binary.BinaryObject; import org.apache.ignite.internal.GridKernalContext; import org.apache.ignite.internal.IgniteInternalFuture; +import org.apache.ignite.internal.binary.BinaryMarshaller; +import org.apache.ignite.internal.binary.BinaryUtils; import org.apache.ignite.internal.processors.GridProcessorAdapter; import org.apache.ignite.internal.processors.cache.CacheEntryImpl; import org.apache.ignite.internal.processors.cache.CacheObject; import org.apache.ignite.internal.processors.cache.CacheObjectContext; import org.apache.ignite.internal.processors.cache.GridCacheContext; import org.apache.ignite.internal.processors.cache.QueryCursorImpl; +import org.apache.ignite.internal.processors.cache.binary.CacheObjectBinaryProcessorImpl; import org.apache.ignite.internal.processors.cache.query.CacheQueryFuture; import org.apache.ignite.internal.processors.cache.query.CacheQueryType; import org.apache.ignite.internal.processors.cache.query.GridCacheTwoStepQuery; @@ -87,6 +67,31 @@ import org.apache.ignite.spi.indexing.IndexingQueryFilter; import org.jetbrains.annotations.Nullable; import org.jsr166.ConcurrentHashMap8; +import javax.cache.Cache; +import javax.cache.CacheException; +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.math.BigDecimal; +import java.sql.Time; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; +import java.util.UUID; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; + import static org.apache.ignite.events.EventType.EVT_CACHE_QUERY_EXECUTED; import static org.apache.ignite.internal.IgniteComponentType.INDEXING; import static org.apache.ignite.internal.processors.query.GridQueryIndexType.FULLTEXT; @@ -193,6 +198,12 @@ public class GridQueryProcessor extends GridProcessorAdapter { idx.registerCache(ccfg); try { + List<Class<?>> extClasses = null; + + boolean binaryEnabled = ctx.cacheObjects().isBinaryEnabled(ccfg); + + CacheObjectContext coCtx = binaryEnabled ? ctx.cacheObjects().contextForCache(ccfg) : null; + if (!F.isEmpty(ccfg.getQueryEntities())) { for (QueryEntity qryEntity : ccfg.getQueryEntities()) { if (F.isEmpty(qryEntity.getValueType())) @@ -205,11 +216,17 @@ public class GridQueryProcessor extends GridProcessorAdapter { Class<?> keyCls = U.classForName(qryEntity.getKeyType(), Object.class); Class<?> valCls = U.classForName(qryEntity.getValueType(), null); + // If local node has the classes and they are externalizable, we must use reflection properties. + boolean binaryKeyAsOptimized = binaryAsOptimized(keyCls); + boolean binaryValAsOptimized = binaryAsOptimized(valCls); + + boolean binaryKeyOrValAsOptimized = binaryKeyAsOptimized || binaryValAsOptimized; + String simpleValType = valCls == null ? typeName(qryEntity.getValueType()) : typeName(valCls); desc.name(simpleValType); - if (ctx.cacheObjects().isBinaryEnabled(ccfg)) { + if (binaryEnabled && !binaryKeyOrValAsOptimized) { // Safe to check null. if (SQL_TYPES.contains(valCls)) desc.valueClass(valCls); @@ -234,10 +251,21 @@ public class GridQueryProcessor extends GridProcessorAdapter { desc.keyClass(keyCls); } + if (binaryEnabled && binaryKeyOrValAsOptimized) { + if (extClasses == null) + extClasses = new ArrayList<>(); + + if (binaryKeyAsOptimized) + extClasses.add(keyCls); + + if (binaryValAsOptimized) + extClasses.add(valCls); + } + TypeId typeId; TypeId altTypeId = null; - if (valCls == null || ctx.cacheObjects().isBinaryEnabled(ccfg)) { + if (valCls == null || (binaryEnabled && !binaryKeyOrValAsOptimized)) { processBinaryMeta(qryEntity, desc); typeId = new TypeId(ccfg.getName(), ctx.cacheObjects().typeId(qryEntity.getValueType())); @@ -246,7 +274,7 @@ public class GridQueryProcessor extends GridProcessorAdapter { altTypeId = new TypeId(ccfg.getName(), valCls); } else { - processClassMeta(qryEntity, desc); + processClassMeta(qryEntity, desc, coCtx); typeId = new TypeId(ccfg.getName(), valCls); altTypeId = new TypeId(ccfg.getName(), ctx.cacheObjects().typeId(qryEntity.getValueType())); @@ -279,9 +307,15 @@ public class GridQueryProcessor extends GridProcessorAdapter { Class<?> keyCls = U.classForName(meta.getKeyType(), Object.class); Class<?> valCls = U.classForName(meta.getValueType(), null); + // If local node has the classes and they are externalizable, we must use reflection properties. + boolean binaryKeyAsOptimized = binaryAsOptimized(keyCls); + boolean binaryValAsOptimized= binaryAsOptimized(valCls); + + boolean binaryKeyOrValAsOptimized = binaryKeyAsOptimized || binaryValAsOptimized; + desc.name(meta.getSimpleValueType()); - if (ctx.cacheObjects().isBinaryEnabled(ccfg)) { + if (binaryEnabled && !binaryKeyOrValAsOptimized) { // Safe to check null. if (SQL_TYPES.contains(valCls)) desc.valueClass(valCls); @@ -298,10 +332,21 @@ public class GridQueryProcessor extends GridProcessorAdapter { desc.keyClass(keyCls); } + if (binaryEnabled && binaryKeyOrValAsOptimized) { + if (extClasses == null) + extClasses = new ArrayList<>(); + + if (binaryKeyAsOptimized) + extClasses.add(keyCls); + + if (binaryValAsOptimized) + extClasses.add(valCls); + } + TypeId typeId; TypeId altTypeId = null; - if (valCls == null || ctx.cacheObjects().isBinaryEnabled(ccfg)) { + if (valCls == null || (binaryEnabled && !binaryKeyOrValAsOptimized)) { processBinaryMeta(meta, desc); typeId = new TypeId(ccfg.getName(), ctx.cacheObjects().typeId(meta.getValueType())); @@ -310,7 +355,7 @@ public class GridQueryProcessor extends GridProcessorAdapter { altTypeId = new TypeId(ccfg.getName(), valCls); } else { - processClassMeta(meta, desc); + processClassMeta(meta, desc, coCtx); typeId = new TypeId(ccfg.getName(), valCls); altTypeId = new TypeId(ccfg.getName(), ctx.cacheObjects().typeId(meta.getValueType())); @@ -327,6 +372,13 @@ public class GridQueryProcessor extends GridProcessorAdapter { } // Indexed types must be translated to CacheTypeMetadata in CacheConfiguration. + + if (extClasses != null) { + U.quietAndWarn(log, "Externalizable classes are specified in query configuration while " + + "BinaryMarshaller is used. Values of the following types will be deserialized in order to build " + + "indexes (use Serializable or " + Binarylizable.class.getSimpleName() +" implementation to " + + "allow fields extraction without deserialization): " + extClasses); + } } catch (IgniteCheckedException | RuntimeException e) { idx.unregisterCache(ccfg); @@ -336,6 +388,24 @@ public class GridQueryProcessor extends GridProcessorAdapter { } /** + * Check whether class will be deserialized anyways. + * + * @param cls Class. + * @return {@code True} if will be deserialized. + */ + private boolean binaryAsOptimized(Class cls) { + if (BinaryUtils.requireOptimizedMarshaller(cls)) { + if (ctx.config().getMarshaller() instanceof BinaryMarshaller) { + CacheObjectBinaryProcessorImpl proc0 = (CacheObjectBinaryProcessorImpl)ctx.cacheObjects(); + + return !proc0.binaryContext().forceBinaryMarshalling(cls); + } + } + + return false; + } + + /** * @param ccfg Cache configuration. * @param desc Type descriptor. * @throws IgniteCheckedException If failed. @@ -1185,9 +1255,10 @@ public class GridQueryProcessor extends GridProcessorAdapter { * * @param meta Type metadata. * @param d Type descriptor. + * @param coCtx Cache object context. * @throws IgniteCheckedException If failed. */ - private void processClassMeta(CacheTypeMetadata meta, TypeDescriptor d) + private void processClassMeta(CacheTypeMetadata meta, TypeDescriptor d, CacheObjectContext coCtx) throws IgniteCheckedException { Map<String,String> aliases = meta.getAliases(); @@ -1201,13 +1272,13 @@ public class GridQueryProcessor extends GridProcessorAdapter { assert valCls != null; for (Map.Entry<String, Class<?>> entry : meta.getAscendingFields().entrySet()) - addToIndex(d, keyCls, valCls, entry.getKey(), entry.getValue(), 0, IndexType.ASC, null, aliases); + addToIndex(d, keyCls, valCls, entry.getKey(), entry.getValue(), 0, IndexType.ASC, null, aliases, coCtx); for (Map.Entry<String, Class<?>> entry : meta.getDescendingFields().entrySet()) - addToIndex(d, keyCls, valCls, entry.getKey(), entry.getValue(), 0, IndexType.DESC, null, aliases); + addToIndex(d, keyCls, valCls, entry.getKey(), entry.getValue(), 0, IndexType.DESC, null, aliases, coCtx); for (String txtField : meta.getTextFields()) - addToIndex(d, keyCls, valCls, txtField, String.class, 0, IndexType.TEXT, null, aliases); + addToIndex(d, keyCls, valCls, txtField, String.class, 0, IndexType.TEXT, null, aliases, coCtx); Map<String, LinkedHashMap<String, IgniteBiTuple<Class<?>, Boolean>>> grps = meta.getGroups(); @@ -1226,7 +1297,7 @@ public class GridQueryProcessor extends GridProcessorAdapter { descending = false; addToIndex(d, keyCls, valCls, idxField.getKey(), idxField.getValue().get1(), order, - descending ? IndexType.DESC : IndexType.ASC, idxName, aliases); + descending ? IndexType.DESC : IndexType.ASC, idxName, aliases, coCtx); order++; } @@ -1239,7 +1310,8 @@ public class GridQueryProcessor extends GridProcessorAdapter { valCls, entry.getKey(), entry.getValue(), - aliases); + aliases, + coCtx); d.addProperty(prop, false); } @@ -1266,7 +1338,8 @@ public class GridQueryProcessor extends GridProcessorAdapter { int idxOrder, IndexType idxType, String idxName, - Map<String,String> aliases + Map<String,String> aliases, + CacheObjectContext coCtx ) throws IgniteCheckedException { String propName; Class<?> propCls; @@ -1281,7 +1354,8 @@ public class GridQueryProcessor extends GridProcessorAdapter { valCls, pathStr, resType, - aliases); + aliases, + coCtx); d.addProperty(prop, false); @@ -1410,7 +1484,11 @@ public class GridQueryProcessor extends GridProcessorAdapter { * @param d Type descriptor. * @throws IgniteCheckedException If failed. */ - private void processClassMeta(QueryEntity qryEntity, TypeDescriptor d) throws IgniteCheckedException { + private void processClassMeta( + QueryEntity qryEntity, + TypeDescriptor d, + CacheObjectContext coCtx + ) throws IgniteCheckedException { Map<String,String> aliases = qryEntity.getAliases(); if (aliases == null) @@ -1422,7 +1500,8 @@ public class GridQueryProcessor extends GridProcessorAdapter { d.valueClass(), entry.getKey(), U.classForName(entry.getValue(), Object.class), - aliases); + aliases, + coCtx); d.addProperty(prop, false); @@ -1524,16 +1603,17 @@ public class GridQueryProcessor extends GridProcessorAdapter { * @throws IgniteCheckedException If failed. */ private static ClassProperty buildClassProperty(Class<?> keyCls, Class<?> valCls, String pathStr, Class<?> resType, - Map<String,String> aliases) throws IgniteCheckedException { + Map<String,String> aliases, CacheObjectContext coCtx) throws IgniteCheckedException { ClassProperty res = buildClassProperty( true, keyCls, pathStr, resType, - aliases); + aliases, + coCtx); if (res == null) // We check key before value consistently with BinaryProperty. - res = buildClassProperty(false, valCls, pathStr, resType, aliases); + res = buildClassProperty(false, valCls, pathStr, resType, aliases, coCtx); if (res == null) throw new IgniteCheckedException("Failed to initialize property '" + pathStr + "' for " + @@ -1552,7 +1632,7 @@ public class GridQueryProcessor extends GridProcessorAdapter { * @return Property instance corresponding to the given path. */ static ClassProperty buildClassProperty(boolean key, Class<?> cls, String pathStr, Class<?> resType, - Map<String,String> aliases) { + Map<String,String> aliases, CacheObjectContext coCtx) { String[] path = pathStr.split("\\."); ClassProperty res = null; @@ -1576,7 +1656,7 @@ public class GridQueryProcessor extends GridProcessorAdapter { ClassProperty tmp = null; try { - tmp = new ClassProperty(cls.getMethod(bld.toString()), key, alias); + tmp = new ClassProperty(cls.getMethod(bld.toString()), key, alias, coCtx); } catch (NoSuchMethodException ignore) { // No-op. @@ -1584,7 +1664,7 @@ public class GridQueryProcessor extends GridProcessorAdapter { if (tmp == null) { try { - tmp = new ClassProperty(cls.getDeclaredField(prop), key, alias); + tmp = new ClassProperty(cls.getDeclaredField(prop), key, alias, coCtx); } catch (NoSuchFieldException ignored) { // No-op. @@ -1593,7 +1673,7 @@ public class GridQueryProcessor extends GridProcessorAdapter { if (tmp == null) { try { - tmp = new ClassProperty(cls.getMethod(prop), key, alias); + tmp = new ClassProperty(cls.getMethod(prop), key, alias, coCtx); } catch (NoSuchMethodException ignored) { // No-op. @@ -1733,12 +1813,15 @@ public class GridQueryProcessor extends GridProcessorAdapter { /** */ private boolean key; + /** */ + private CacheObjectContext coCtx; + /** * Constructor. * * @param member Element. */ - ClassProperty(Member member, boolean key, String name) { + ClassProperty(Member member, boolean key, String name, @Nullable CacheObjectContext coCtx) { this.member = member; this.key = key; @@ -1749,11 +1832,13 @@ public class GridQueryProcessor extends GridProcessorAdapter { ((AccessibleObject) member).setAccessible(true); field = member instanceof Field; + + this.coCtx = coCtx; } /** {@inheritDoc} */ @Override public Object value(Object key, Object val) throws IgniteCheckedException { - Object x = this.key ? key : val; + Object x = unwrap(this.key ? key : val); if (parent != null) x = parent.value(key, val); @@ -1778,6 +1863,16 @@ public class GridQueryProcessor extends GridProcessorAdapter { } } + /** + * Unwraps cache object, if needed. + * + * @param o Object to unwrap. + * @return Unwrapped object. + */ + private Object unwrap(Object o) { + return coCtx == null ? o : o instanceof CacheObject ? ((CacheObject)o).value(coCtx, false) : o; + } + /** {@inheritDoc} */ @Override public String name() { return name;
