brooklyn-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From aleds...@apache.org
Subject [1/4] incubator-brooklyn git commit: Add recursive sanitation and move to own class
Date Wed, 11 Mar 2015 12:28:54 GMT
Repository: incubator-brooklyn
Updated Branches:
  refs/heads/master fd22cc070 -> 0ff4216a8


Add recursive sanitation and move to own class

Deprecates the existing method in Entities and updates all references.


Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/2f99f251
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/2f99f251
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/2f99f251

Branch: refs/heads/master
Commit: 2f99f2515bf5a4cfd7d87210c207346dd67bff60
Parents: c6e09bf
Author: Robert Moss <robertgmoss@gmail.com>
Authored: Tue Mar 10 12:01:11 2015 +0000
Committer: Robert Moss <robertgmoss@gmail.com>
Committed: Tue Mar 10 12:01:11 2015 +0000

----------------------------------------------------------------------
 .../java/brooklyn/entity/basic/Entities.java    | 17 +++---
 .../brooklyn/entity/basic/EntityConfigMap.java  |  2 +-
 .../java/brooklyn/entity/basic/Sanitizer.java   | 59 ++++++++++++++++++++
 .../entity/rebind/dto/AbstractMemento.java      |  3 +-
 .../entity/rebind/dto/BasicEnricherMemento.java |  3 +-
 .../entity/rebind/dto/BasicEntityMemento.java   |  7 ++-
 .../entity/rebind/dto/BasicFeedMemento.java     |  3 +-
 .../entity/rebind/dto/BasicLocationMemento.java |  3 +-
 .../entity/rebind/dto/BasicPolicyMemento.java   |  3 +-
 .../brooklyn/policy/basic/ConfigMapImpl.java    |  3 +-
 .../jclouds/ComputeServiceRegistryImpl.java     | 13 +++--
 .../location/jclouds/JcloudsLocation.java       |  3 +-
 .../brooklyn/location/jclouds/JcloudsUtil.java  |  3 +-
 13 files changed, 97 insertions(+), 25 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/2f99f251/core/src/main/java/brooklyn/entity/basic/Entities.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/Entities.java b/core/src/main/java/brooklyn/entity/basic/Entities.java
index 5b88087..4224197 100644
--- a/core/src/main/java/brooklyn/entity/basic/Entities.java
+++ b/core/src/main/java/brooklyn/entity/basic/Entities.java
@@ -270,17 +270,20 @@ public class Entities {
                 (v instanceof CharSequence&& ((CharSequence)v).length() == 0);
     }
 
+    /**
+     * @deprecated since 0.7
+     */
+    @Deprecated
     public static Map<String,Object> sanitize(ConfigBag input) {
-        return sanitize(input.getAllConfig());
+        return Sanitizer.sanitize(input.getAllConfig());
     }
 
+    /**
+     * @deprecated since 0.7
+     */
+    @Deprecated
     public static <K> Map<K,Object> sanitize(Map<K,?> input) {
-        Map<K,Object> result = Maps.newLinkedHashMap();
-        for (Map.Entry<K,?> e: input.entrySet()) {
-            if (isSecret(""+e.getKey())) result.put(e.getKey(), "xxxxxxxx");
-            else result.put(e.getKey(), e.getValue());
-        }
-        return result;
+        return Sanitizer.sanitize(input);
     }
 
     public static void dumpInfo(Iterable<? extends Entity> entities) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/2f99f251/core/src/main/java/brooklyn/entity/basic/EntityConfigMap.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/EntityConfigMap.java b/core/src/main/java/brooklyn/entity/basic/EntityConfigMap.java
index c4efe7c..3b3b2a2 100644
--- a/core/src/main/java/brooklyn/entity/basic/EntityConfigMap.java
+++ b/core/src/main/java/brooklyn/entity/basic/EntityConfigMap.java
@@ -331,7 +331,7 @@ public class EntityConfigMap implements ConfigMap {
 
     @Override
     public String toString() {
-        return super.toString()+"[own="+Entities.sanitize(ownConfig)+"; inherited="+Entities.sanitize(inheritedConfig)+"]";
+        return super.toString()+"[own="+Sanitizer.sanitize(ownConfig)+"; inherited="+Sanitizer.sanitize(inheritedConfig)+"]";
     }
     
     public Map<String,Object> asMapWithStringKeys() {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/2f99f251/core/src/main/java/brooklyn/entity/basic/Sanitizer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/Sanitizer.java b/core/src/main/java/brooklyn/entity/basic/Sanitizer.java
new file mode 100644
index 0000000..15dd63e
--- /dev/null
+++ b/core/src/main/java/brooklyn/entity/basic/Sanitizer.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.entity.basic;
+
+import java.util.Map;
+import java.util.Set;
+
+import brooklyn.util.config.ConfigBag;
+
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
+public final class Sanitizer {
+
+    private Sanitizer() {
+    } // not instantiable
+
+    public static Map<String, Object> sanitize(ConfigBag input) {
+        return sanitize(input.getAllConfig());
+    }
+
+    public static <K> Map<K, Object> sanitize(Map<K, ?> input) {
+        return sanitize(input, Sets.newHashSet());
+    }
+
+    public static <K> Map<K, Object> sanitize(Map<K, ?> input, Set<Object>
visited) {
+        Map<K, Object> result = Maps.newLinkedHashMap();
+        for (Map.Entry<K, ?> e : input.entrySet()) {
+            if (Entities.isSecret("" + e.getKey()))
+                result.put(e.getKey(), "xxxxxxxx");
+            else if (e.getValue() instanceof Map) {
+                if (visited.contains(e.getValue())) {
+                    continue;
+                }
+                visited.add(e.getValue());
+                result.put(e.getKey(), sanitize((Map<?, ?>) e.getValue(), visited));
+            } else {
+                result.put(e.getKey(), e.getValue());
+            }
+        }
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/2f99f251/core/src/main/java/brooklyn/entity/rebind/dto/AbstractMemento.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/dto/AbstractMemento.java b/core/src/main/java/brooklyn/entity/rebind/dto/AbstractMemento.java
index 5603e65..db12e17 100644
--- a/core/src/main/java/brooklyn/entity/rebind/dto/AbstractMemento.java
+++ b/core/src/main/java/brooklyn/entity/rebind/dto/AbstractMemento.java
@@ -26,6 +26,7 @@ import java.util.Set;
 
 import brooklyn.BrooklynVersion;
 import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.Sanitizer;
 import brooklyn.mementos.Memento;
 
 import com.google.common.base.Objects;
@@ -198,7 +199,7 @@ public abstract class AbstractMemento implements Memento, Serializable
{
     
     protected ToStringHelper newVerboseStringHelper() {
         return Objects.toStringHelper(this).add("id", getId()).add("type", getType())
-                .add("displayName", getDisplayName()).add("customFields", Entities.sanitize(getCustomFields()));
+                .add("displayName", getDisplayName()).add("customFields", Sanitizer.sanitize(getCustomFields()));
     }
     
     protected <T> List<T> fromPersistedList(List<T> l) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/2f99f251/core/src/main/java/brooklyn/entity/rebind/dto/BasicEnricherMemento.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/dto/BasicEnricherMemento.java b/core/src/main/java/brooklyn/entity/rebind/dto/BasicEnricherMemento.java
index 6a735e0..703a62c 100644
--- a/core/src/main/java/brooklyn/entity/rebind/dto/BasicEnricherMemento.java
+++ b/core/src/main/java/brooklyn/entity/rebind/dto/BasicEnricherMemento.java
@@ -22,6 +22,7 @@ import java.io.Serializable;
 import java.util.Map;
 
 import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.Sanitizer;
 import brooklyn.mementos.EnricherMemento;
 
 import com.google.common.base.Objects.ToStringHelper;
@@ -87,6 +88,6 @@ public class BasicEnricherMemento extends AbstractMemento implements EnricherMem
 
     @Override
     protected ToStringHelper newVerboseStringHelper() {
-        return super.newVerboseStringHelper().add("config", Entities.sanitize(getConfig()));
+        return super.newVerboseStringHelper().add("config", Sanitizer.sanitize(getConfig()));
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/2f99f251/core/src/main/java/brooklyn/entity/rebind/dto/BasicEntityMemento.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/dto/BasicEntityMemento.java b/core/src/main/java/brooklyn/entity/rebind/dto/BasicEntityMemento.java
index 2d36ee8..787c850 100644
--- a/core/src/main/java/brooklyn/entity/rebind/dto/BasicEntityMemento.java
+++ b/core/src/main/java/brooklyn/entity/rebind/dto/BasicEntityMemento.java
@@ -35,6 +35,7 @@ import brooklyn.entity.Entity;
 import brooklyn.entity.basic.AbstractEntity;
 import brooklyn.entity.basic.ConfigKeys;
 import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.Sanitizer;
 import brooklyn.entity.rebind.RebindSupport;
 import brooklyn.event.AttributeSensor;
 import brooklyn.event.Sensor;
@@ -315,9 +316,9 @@ public class BasicEntityMemento extends AbstractTreeNodeMemento implements
Entit
     protected ToStringHelper newVerboseStringHelper() {
         return super.newVerboseStringHelper()
                 .add("members", getMembers())
-                .add("config", Entities.sanitize(getConfig()))
-                .add("configUnmatched", Entities.sanitize(getConfigUnmatched()))
-                .add("attributes", Entities.sanitize(getAttributes()))
+                .add("config", Sanitizer.sanitize(getConfig()))
+                .add("configUnmatched", Sanitizer.sanitize(getConfigUnmatched()))
+                .add("attributes", Sanitizer.sanitize(getAttributes()))
                 .add("policies", getPolicies())
                 .add("enrichers", getEnrichers())
                 .add("tags", getTags())

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/2f99f251/core/src/main/java/brooklyn/entity/rebind/dto/BasicFeedMemento.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/dto/BasicFeedMemento.java b/core/src/main/java/brooklyn/entity/rebind/dto/BasicFeedMemento.java
index 8c9e0b9..a17a53e 100644
--- a/core/src/main/java/brooklyn/entity/rebind/dto/BasicFeedMemento.java
+++ b/core/src/main/java/brooklyn/entity/rebind/dto/BasicFeedMemento.java
@@ -22,6 +22,7 @@ import java.io.Serializable;
 import java.util.Map;
 
 import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.Sanitizer;
 import brooklyn.mementos.FeedMemento;
 
 import com.google.common.base.Objects.ToStringHelper;
@@ -87,6 +88,6 @@ public class BasicFeedMemento extends AbstractMemento implements FeedMemento,
Se
 
     @Override
     protected ToStringHelper newVerboseStringHelper() {
-        return super.newVerboseStringHelper().add("config", Entities.sanitize(getConfig()));
+        return super.newVerboseStringHelper().add("config", Sanitizer.sanitize(getConfig()));
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/2f99f251/core/src/main/java/brooklyn/entity/rebind/dto/BasicLocationMemento.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/dto/BasicLocationMemento.java b/core/src/main/java/brooklyn/entity/rebind/dto/BasicLocationMemento.java
index 12c958c..a584902 100644
--- a/core/src/main/java/brooklyn/entity/rebind/dto/BasicLocationMemento.java
+++ b/core/src/main/java/brooklyn/entity/rebind/dto/BasicLocationMemento.java
@@ -23,6 +23,7 @@ import java.util.Map;
 import java.util.Set;
 
 import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.Sanitizer;
 import brooklyn.mementos.LocationMemento;
 import brooklyn.mementos.TreeNode;
 import brooklyn.util.config.ConfigBag;
@@ -100,7 +101,7 @@ public class BasicLocationMemento extends AbstractTreeNodeMemento implements
Loc
     @Override
     protected ToStringHelper newVerboseStringHelper() {
         return super.newVerboseStringHelper()
-                .add("config", Entities.sanitize(getLocationConfig()))
+                .add("config", Sanitizer.sanitize(getLocationConfig()))
                 .add("locationConfigDescription", getLocationConfigDescription());
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/2f99f251/core/src/main/java/brooklyn/entity/rebind/dto/BasicPolicyMemento.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/dto/BasicPolicyMemento.java b/core/src/main/java/brooklyn/entity/rebind/dto/BasicPolicyMemento.java
index d2c1ece..ce520d2 100644
--- a/core/src/main/java/brooklyn/entity/rebind/dto/BasicPolicyMemento.java
+++ b/core/src/main/java/brooklyn/entity/rebind/dto/BasicPolicyMemento.java
@@ -22,6 +22,7 @@ import java.io.Serializable;
 import java.util.Map;
 
 import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.Sanitizer;
 import brooklyn.mementos.PolicyMemento;
 
 import com.google.common.base.Objects.ToStringHelper;
@@ -87,6 +88,6 @@ public class BasicPolicyMemento extends AbstractMemento implements PolicyMemento
     
     @Override
     protected ToStringHelper newVerboseStringHelper() {
-        return super.newVerboseStringHelper().add("config", Entities.sanitize(getConfig()));
+        return super.newVerboseStringHelper().add("config", Sanitizer.sanitize(getConfig()));
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/2f99f251/core/src/main/java/brooklyn/policy/basic/ConfigMapImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/policy/basic/ConfigMapImpl.java b/core/src/main/java/brooklyn/policy/basic/ConfigMapImpl.java
index 9d62dda..22ce249 100644
--- a/core/src/main/java/brooklyn/policy/basic/ConfigMapImpl.java
+++ b/core/src/main/java/brooklyn/policy/basic/ConfigMapImpl.java
@@ -35,6 +35,7 @@ import brooklyn.entity.basic.ConfigMapViewWithStringKeys;
 import brooklyn.entity.basic.Entities;
 import brooklyn.entity.basic.EntityInternal;
 import brooklyn.entity.basic.EntityLocal;
+import brooklyn.entity.basic.Sanitizer;
 import brooklyn.event.basic.StructuredConfigKey;
 import brooklyn.management.ExecutionContext;
 import brooklyn.util.flags.TypeCoercions;
@@ -178,7 +179,7 @@ public class ConfigMapImpl implements brooklyn.config.ConfigMap {
 
     @Override
     public String toString() {
-        return super.toString()+"[own="+Entities.sanitize(ownConfig)+"]";
+        return super.toString()+"[own="+Sanitizer.sanitize(ownConfig)+"]";
     }
     
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/2f99f251/locations/jclouds/src/main/java/brooklyn/location/jclouds/ComputeServiceRegistryImpl.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/brooklyn/location/jclouds/ComputeServiceRegistryImpl.java
b/locations/jclouds/src/main/java/brooklyn/location/jclouds/ComputeServiceRegistryImpl.java
index a284ea3..48ac86f 100644
--- a/locations/jclouds/src/main/java/brooklyn/location/jclouds/ComputeServiceRegistryImpl.java
+++ b/locations/jclouds/src/main/java/brooklyn/location/jclouds/ComputeServiceRegistryImpl.java
@@ -38,6 +38,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.Sanitizer;
 import brooklyn.util.collections.MutableMap;
 import brooklyn.util.config.ConfigBag;
 
@@ -101,7 +102,7 @@ public class ComputeServiceRegistryImpl implements ComputeServiceRegistry,
Jclou
         // FIXME Deprecated mechanism, should have a ConfigKey for overrides
         Map<String, Object> extra = Maps.filterKeys(conf.getAllConfig(), Predicates.containsPattern("^jclouds\\."));
         if (extra.size() > 0) {
-            LOG.warn("Jclouds using deprecated property overrides: "+Entities.sanitize(extra));
+            LOG.warn("Jclouds using deprecated property overrides: "+Sanitizer.sanitize(extra));
         }
         properties.putAll(extra);
 
@@ -121,10 +122,10 @@ public class ComputeServiceRegistryImpl implements ComputeServiceRegistry,
Jclou
         if (allowReuse) {
             ComputeService result = cachedComputeServices.get(cacheKey);
             if (result!=null) {
-                LOG.trace("jclouds ComputeService cache hit for compute service, for "+Entities.sanitize(properties));
+                LOG.trace("jclouds ComputeService cache hit for compute service, for "+Sanitizer.sanitize(properties));
                 return result;
             }
-            LOG.debug("jclouds ComputeService cache miss for compute service, creating, for
"+Entities.sanitize(properties));
+            LOG.debug("jclouds ComputeService cache miss for compute service, creating, for
"+Sanitizer.sanitize(properties));
         }
 
         Iterable<Module> modules = getCommonModules();
@@ -144,12 +145,12 @@ public class ComputeServiceRegistryImpl implements ComputeServiceRegistry,
Jclou
             synchronized (cachedComputeServices) {
                 ComputeService result = cachedComputeServices.get(cacheKey);
                 if (result != null) {
-                    LOG.debug("jclouds ComputeService cache recovery for compute service,
for "+Entities.sanitize(cacheKey));
+                    LOG.debug("jclouds ComputeService cache recovery for compute service,
for "+Sanitizer.sanitize(cacheKey));
                     //keep the old one, discard the new one
                     computeService.getContext().close();
                     return result;
                 }
-                LOG.debug("jclouds ComputeService created "+computeService+", adding to cache,
for "+Entities.sanitize(properties));
+                LOG.debug("jclouds ComputeService created "+computeService+", adding to cache,
for "+Sanitizer.sanitize(properties));
                 cachedComputeServices.put(cacheKey, computeService);
             }
         }
@@ -166,7 +167,7 @@ public class ComputeServiceRegistryImpl implements ComputeServiceRegistry,
Jclou
      
     protected String getDeprecatedProperty(ConfigBag conf, String key) {
         if (conf.containsKey(key)) {
-            LOG.warn("Jclouds using deprecated brooklyn-jclouds property "+key+": "+Entities.sanitize(conf.getAllConfig()));
+            LOG.warn("Jclouds using deprecated brooklyn-jclouds property "+key+": "+Sanitizer.sanitize(conf.getAllConfig()));
             return (String) conf.getStringKey(key);
         } else {
             return null;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/2f99f251/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java
b/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java
index ab30c01..7329c8d 100644
--- a/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java
+++ b/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java
@@ -92,6 +92,7 @@ import brooklyn.config.ConfigKey;
 import brooklyn.config.ConfigKey.HasConfigKey;
 import brooklyn.config.ConfigUtils;
 import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.Sanitizer;
 import brooklyn.entity.rebind.persister.LocationWithObjectStore;
 import brooklyn.entity.rebind.persister.PersistenceObjectStore;
 import brooklyn.entity.rebind.persister.jclouds.JcloudsBlobStoreBasedObjectStore;
@@ -1677,7 +1678,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation
im
                     new Object[] {
                             getUser(setup), 
                             address, 
-                            Entities.sanitize(sshConfig),
+                            Sanitizer.sanitize(sshConfig),
                             sshHostAndPort,
                             setup.getDescription(), 
                             node

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/2f99f251/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsUtil.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsUtil.java b/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsUtil.java
index f617877..4a304cb 100644
--- a/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsUtil.java
+++ b/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsUtil.java
@@ -66,6 +66,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.Sanitizer;
 import brooklyn.location.jclouds.config.AlwaysRetryOnRenew;
 import brooklyn.util.collections.MutableList;
 import brooklyn.util.config.ConfigBag;
@@ -301,7 +302,7 @@ public class JcloudsUtil implements JcloudsLocationConfig {
     @Deprecated
     protected static String getDeprecatedProperty(ConfigBag conf, String key) {
         if (conf.containsKey(key)) {
-            LOG.warn("Jclouds using deprecated brooklyn-jclouds property "+key+": "+Entities.sanitize(conf.getAllConfig()));
+            LOG.warn("Jclouds using deprecated brooklyn-jclouds property "+key+": "+Sanitizer.sanitize(conf.getAllConfig()));
             return (String) conf.getStringKey(key);
         } else {
             return null;


Mime
View raw message