diff options
5 files changed, 114 insertions, 137 deletions
diff --git a/container-search/src/main/java/com/yahoo/search/query/properties/CloneHelper.java b/container-search/src/main/java/com/yahoo/search/query/properties/CloneHelper.java new file mode 100644 index 00000000000..e0dec5e2d6c --- /dev/null +++ b/container-search/src/main/java/com/yahoo/search/query/properties/CloneHelper.java @@ -0,0 +1,16 @@ +package com.yahoo.search.query.properties; + +import com.yahoo.search.result.Hit; + +/** + * Created by balder on 13/02/2017. + */ +public class CloneHelper extends com.yahoo.processing.request.CloneHelper { + @Override + protected Object objectClone(Object object) { + if (object instanceof Hit) { + return ((Hit)object).clone(); + } + return super.objectClone(object); + } +} diff --git a/container-search/src/main/java/com/yahoo/search/query/properties/PropertyMap.java b/container-search/src/main/java/com/yahoo/search/query/properties/PropertyMap.java index 820c4fc8ea3..934f1cacf32 100644 --- a/container-search/src/main/java/com/yahoo/search/query/properties/PropertyMap.java +++ b/container-search/src/main/java/com/yahoo/search/query/properties/PropertyMap.java @@ -1,17 +1,8 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.search.query.properties; - -import com.yahoo.processing.request.CompoundName; +import com.yahoo.processing.request.*; import com.yahoo.search.query.Properties; -import com.yahoo.search.result.Hit; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.Map; +import java.util.*; import java.util.logging.Logger; /** @@ -29,7 +20,7 @@ import java.util.logging.Logger; */ public class PropertyMap extends Properties { - private static Logger log=Logger.getLogger(PropertyMap.class.getName()); + private final static CloneHelper cloneHelper = new CloneHelper(); /** The properties of this */ private Map<CompoundName, Object> properties = new LinkedHashMap<>(); @@ -64,7 +55,7 @@ public class PropertyMap extends Properties { PropertyMap clone = (PropertyMap)super.clone(); clone.properties = new HashMap<>(); for (Map.Entry<CompoundName, Object> entry : this.properties.entrySet()) { - Object cloneValue = clone(entry.getValue()); + Object cloneValue = cloneHelper.clone(entry.getValue()); if (cloneValue == null) cloneValue = entry.getValue(); // Shallow copy objects which does not support cloning clone.properties.put(entry.getKey(), cloneValue); @@ -72,50 +63,6 @@ public class PropertyMap extends Properties { return clone; } - /** Clones this object if it is clonable, and the clone is public. Returns null if not */ - public static Object clone(Object object) { - if (object==null) return null; - if (! ( object instanceof Cloneable) ) return null; - if (object instanceof Object[]) - return arrayClone((Object[])object); - else - return objectClone(object); - } - - private static Object arrayClone(Object[] object) { - Object[] arrayClone= Arrays.copyOf(object, object.length); - // deep clone - for (int i=0; i<arrayClone.length; i++) { - Object elementClone=clone(arrayClone[i]); - if (elementClone!=null) - arrayClone[i]=elementClone; - } - return arrayClone; - } - - private static Object objectClone(Object object) { - if (object instanceof Hit) { - return ((Hit) object).clone(); - } else if (object instanceof LinkedList) { - return ((LinkedList) object).clone(); - } - try { - Method cloneMethod=object.getClass().getMethod("clone"); - return cloneMethod.invoke(object); - } - catch (NoSuchMethodException e) { - log.warning("'" + object + "' is Cloneable, but has no clone method - will use the same instance in all requests"); - return null; - } - catch (IllegalAccessException e) { - log.warning("'" + object + "' is Cloneable, but clone method cannot be accessed - will use the same instance in all requests"); - return null; - } - catch (InvocationTargetException e) { - throw new RuntimeException("Exception cloning '" + object + "'",e); - } - } - @Override public Map<String, Object> listProperties(CompoundName path, Map<String, String> context, com.yahoo.processing.request.Properties substitution) { Map<String, Object> map = super.listProperties(path, context, substitution); diff --git a/processing/src/main/java/com/yahoo/processing/request/CloneHelper.java b/processing/src/main/java/com/yahoo/processing/request/CloneHelper.java new file mode 100644 index 00000000000..9bc1c89135c --- /dev/null +++ b/processing/src/main/java/com/yahoo/processing/request/CloneHelper.java @@ -0,0 +1,85 @@ +package com.yahoo.processing.request; + +import com.yahoo.collections.MethodCache; +import com.yahoo.component.provider.FreezableClass; +import com.yahoo.processing.request.properties.PublicCloneable; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.*; +import java.util.logging.Logger; + +/** + * @author : baldersheim + */ +public class CloneHelper { + private static Logger log = Logger.getLogger(CloneHelper.class.getName()); + private static final MethodCache cloneMethodCache = new MethodCache("clone"); + /** + * Clones this object if it is clonable, and the clone is public. Returns null if not + */ + public final Object clone(Object object) { + if (object == null) return null; + if (!(object instanceof Cloneable)) return null; + if (object instanceof Object[]) + return arrayClone((Object[]) object); + else + return objectClone(object); + } + + private final Object arrayClone(Object[] object) { + Object[] arrayClone = Arrays.copyOf(object, object.length); + // deep clone + for (int i = 0; i < arrayClone.length; i++) { + Object elementClone = clone(arrayClone[i]); + if (elementClone != null) + arrayClone[i] = elementClone; + } + return arrayClone; + } + + protected Object objectClone(Object object) { + // Fastpath for our own commonly used classes + if (object instanceof FreezableClass) { + // List common superclass of 'com.yahoo.search.result.Hit' + return ((FreezableClass) object).clone(); + } + else if (object instanceof PublicCloneable) { + return ((PublicCloneable)object).clone(); + } + else if (object instanceof LinkedList) { // TODO: Why? Somebody's infatuation with LinkedList knows no limits + return ((LinkedList) object).clone(); + } + else if (object instanceof ArrayList) { // TODO: Why? Likewise + return ((ArrayList) object).clone(); + } + + try { + Method cloneMethod = cloneMethodCache.get(object); + if (cloneMethod == null) { + log.warning("'" + object + "' is Cloneable, but has no clone method - will use the same instance in all requests"); + return null; + } + return cloneMethod.invoke(object); + } catch (IllegalAccessException e) { + log.warning("'" + object + "' is Cloneable, but clone method cannot be accessed - will use the same instance in all requests"); + return null; + } catch (InvocationTargetException e) { + throw new RuntimeException("Exception cloning '" + object + "'", e); + } + } + /** + * Clones a map by deep cloning each value which is cloneable and shallow copying all other values. + */ + public Map<CompoundName, Object> cloneMap(Map<CompoundName, Object> map) { + Map<CompoundName, Object> cloneMap = new HashMap<>(); + for (Map.Entry<CompoundName, Object> entry : map.entrySet()) { + Object cloneValue = clone(entry.getValue()); + if (cloneValue == null) + cloneValue = entry.getValue(); // Shallow copy objects which does not support cloning + cloneMap.put(entry.getKey(), cloneValue); + } + return cloneMap; + } + +} diff --git a/processing/src/main/java/com/yahoo/processing/request/Properties.java b/processing/src/main/java/com/yahoo/processing/request/Properties.java index 2c603b6c7a0..00be00f9794 100644 --- a/processing/src/main/java/com/yahoo/processing/request/Properties.java +++ b/processing/src/main/java/com/yahoo/processing/request/Properties.java @@ -1,9 +1,9 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.processing.request; -import java.util.Collections; -import java.util.HashMap; import java.util.Map; +import java.util.HashMap; +import java.util.Collections; /** * The properties of a request @@ -12,6 +12,7 @@ import java.util.Map; */ public class Properties implements Cloneable { + private final static CloneHelper cloneHelper = new CloneHelper(); private Properties chained = null; /** @@ -570,4 +571,10 @@ public class Properties implements Cloneable { } } + /** + * Clones a map by deep cloning each value which is cloneable and shallow copying all other values. + */ + public static Map<CompoundName, Object> cloneMap(Map<CompoundName, Object> map) { + return cloneHelper.cloneMap(map); + } } diff --git a/processing/src/main/java/com/yahoo/processing/request/properties/PropertyMap.java b/processing/src/main/java/com/yahoo/processing/request/properties/PropertyMap.java index 66e49cff51a..105de5f5347 100644 --- a/processing/src/main/java/com/yahoo/processing/request/properties/PropertyMap.java +++ b/processing/src/main/java/com/yahoo/processing/request/properties/PropertyMap.java @@ -1,19 +1,12 @@ // Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.processing.request.properties; -import com.yahoo.collections.MethodCache; -import com.yahoo.component.provider.FreezableClass; import com.yahoo.processing.request.CompoundName; import com.yahoo.processing.request.Properties; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.LinkedList; -import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.Arrays; -import java.util.logging.Logger; /** * A HashMap backing of Properties. @@ -30,9 +23,6 @@ import java.util.logging.Logger; */ public class PropertyMap extends Properties { - private static Logger log = Logger.getLogger(PropertyMap.class.getName()); - private static final MethodCache cloneMethodCache = new MethodCache("clone"); - /** * The properties of this */ @@ -69,74 +59,6 @@ public class PropertyMap extends Properties { return clone; } - /** - * Clones a map by deep cloning each value which is cloneable and shallow copying all other values. - */ - public static Map<CompoundName, Object> cloneMap(Map<CompoundName, Object> map) { - Map<CompoundName, Object> cloneMap = new HashMap<>(); - for (Map.Entry<CompoundName, Object> entry : map.entrySet()) { - Object cloneValue = clone(entry.getValue()); - if (cloneValue == null) - cloneValue = entry.getValue(); // Shallow copy objects which does not support cloning - cloneMap.put(entry.getKey(), cloneValue); - } - return cloneMap; - } - - /** - * Clones this object if it is clonable, and the clone is public. Returns null if not - */ - public static Object clone(Object object) { - if (object == null) return null; - if (!(object instanceof Cloneable)) return null; - if (object instanceof Object[]) - return arrayClone((Object[]) object); - else - return objectClone(object); - } - - private static Object arrayClone(Object[] object) { - Object[] arrayClone = Arrays.copyOf(object, object.length); - // deep clone - for (int i = 0; i < arrayClone.length; i++) { - Object elementClone = clone(arrayClone[i]); - if (elementClone != null) - arrayClone[i] = elementClone; - } - return arrayClone; - } - - private static Object objectClone(Object object) { - // Fastpath for our own commonly used classes - if (object instanceof FreezableClass) { - // List common superclass of 'com.yahoo.search.result.Hit' - return ((FreezableClass) object).clone(); - } - else if (object instanceof PublicCloneable) { - return ((PublicCloneable)object).clone(); - } - else if (object instanceof LinkedList) { // TODO: Why? Somebody's infatuation with LinkedList knows no limits - return ((LinkedList) object).clone(); - } - else if (object instanceof ArrayList) { // TODO: Why? Likewise - return ((ArrayList) object).clone(); - } - - try { - Method cloneMethod = cloneMethodCache.get(object); - if (cloneMethod == null) { - log.warning("'" + object + "' is Cloneable, but has no clone method - will use the same instance in all requests"); - return null; - } - return cloneMethod.invoke(object); - } catch (IllegalAccessException e) { - log.warning("'" + object + "' is Cloneable, but clone method cannot be accessed - will use the same instance in all requests"); - return null; - } catch (InvocationTargetException e) { - throw new RuntimeException("Exception cloning '" + object + "'", e); - } - } - @Override public Map<String, Object> listProperties(CompoundName path, Map<String, String> context, Properties substitution) { Map<String, Object> map = super.listProperties(path, context, substitution); |