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;

Reply via email to