Author: nico
Date: 2010-04-03 16:38:43 +0200 (Sat, 03 Apr 2010)
New Revision: 41754

Modified:
   mmbase/branches/MMBase-1_9/applications/editwizard/src/main/config/caches.xml
   
mmbase/branches/MMBase-1_9/applications/editwizard/src/main/java/org/mmbase/applications/editwizard/Wizard.java
   
mmbase/branches/MMBase-1_9/core/src/main/java/org/mmbase/module/core/MMObjectNode.java
   
mmbase/branches/MMBase-1_9/core/src/main/java/org/mmbase/util/magicfile/MagicXMLReader.java
   mmbase/trunk/applications/editwizard/src/main/config/caches.xml
   
mmbase/trunk/applications/editwizard/src/main/java/org/mmbase/applications/editwizard/Wizard.java
   mmbase/trunk/core/src/main/java/org/mmbase/module/core/MMObjectNode.java
   
mmbase/trunk/utils/src/main/java/org/mmbase/util/magicfile/MagicXMLReader.java
Log:
MMB-1948 Reduce memory footprint of collections and cached xmlfragements

Modified: 
mmbase/branches/MMBase-1_9/applications/editwizard/src/main/config/caches.xml
===================================================================
--- 
mmbase/branches/MMBase-1_9/applications/editwizard/src/main/config/caches.xml   
    2010-04-03 14:16:48 UTC (rev 41753)
+++ 
mmbase/branches/MMBase-1_9/applications/editwizard/src/main/config/caches.xml   
    2010-04-03 14:38:43 UTC (rev 41754)
@@ -4,10 +4,6 @@
 
   <!-- other caches ... -->
 
-  <cache name="Editwizard nodes">
-    <status>active</status>
-    <size>100</size>
-  </cache>
   <cache name="Editwizard schemas">
     <status>active</status>
     <size>100</size>

Modified: 
mmbase/branches/MMBase-1_9/applications/editwizard/src/main/java/org/mmbase/applications/editwizard/Wizard.java
===================================================================
--- 
mmbase/branches/MMBase-1_9/applications/editwizard/src/main/java/org/mmbase/applications/editwizard/Wizard.java
     2010-04-03 14:16:48 UTC (rev 41753)
+++ 
mmbase/branches/MMBase-1_9/applications/editwizard/src/main/java/org/mmbase/applications/editwizard/Wizard.java
     2010-04-03 14:38:43 UTC (rev 41754)
@@ -67,15 +67,14 @@
 
     // File -> Document (resolved includes/shortcuts)
     private static WizardSchemaCache wizardSchemaCache;
-    private static NodeCache nodeCache; // it's absurd to name this NodeCache
 
     static {
         wizardSchemaCache = new WizardSchemaCache();
         wizardSchemaCache.putCache();
-        nodeCache = new NodeCache();
-        nodeCache.putCache();
     }
 
+    private Map<String, Node> nodePermissionCache = new HashMap<String, 
Node>();
+
     /**
      * The cloud used to connect to MMBase
      */
@@ -304,7 +303,7 @@
      * @throws WizardException if the object cannot be retrieved
      */
     protected boolean checkNode(String objectNumber, String operation) throws 
WizardException {
-        Node node = nodeCache.get(objectNumber);
+        Node node = nodePermissionCache.get(objectNumber);
 
         if (node == null) {
             NodeList nodes = Utils.selectNodeList(data, ".//*...@number='" + 
objectNumber + "']");
@@ -323,7 +322,7 @@
                 node = databaseConnector.getDataNode(null, objectNumber, null);
             }
 
-            nodeCache.put(objectNumber, node);
+            nodePermissionCache.put(objectNumber, node);
             log.debug("Node loaded: " + node);
         } else {
             log.debug("Node found in cache: " + node);
@@ -2958,24 +2957,6 @@
     }
 
     /**
-     * Caches objectNumber to Node.
-     * @since MMBase-1.6.4
-     */
-    static class NodeCache extends Cache<String, Node> {
-        NodeCache() {
-            super(100);
-        }
-
-        public String getName() {
-            return "Editwizard nodes";
-        }
-
-        public String getDescription() {
-            return "objectNumber -> DOM Node";
-        }
-    }
-
-    /**
      * Caches File to  Editwizard schema Document.
      * @since MMBase-1.6.4
      */

Modified: 
mmbase/branches/MMBase-1_9/core/src/main/java/org/mmbase/module/core/MMObjectNode.java
===================================================================
--- 
mmbase/branches/MMBase-1_9/core/src/main/java/org/mmbase/module/core/MMObjectNode.java
      2010-04-03 14:16:48 UTC (rev 41753)
+++ 
mmbase/branches/MMBase-1_9/core/src/main/java/org/mmbase/module/core/MMObjectNode.java
      2010-04-03 14:38:43 UTC (rev 41754)
@@ -61,8 +61,9 @@
      * it can be used to optimise cacheing
      * @since MMBase-1.8
      */
-    private Map<String, Object> oldValues = Collections.synchronizedMap(new 
HashMap<String, Object>());
-
+    private Map<String, Object> oldValues = null;
+    
+    
     /**
      * Holds the name - value pairs of this node (the node's fields).
      * Most nodes will have a 'number' and an 'otype' field, and fields which 
will differ by builder.
@@ -72,8 +73,9 @@
      * Note: To avoid synchronisation conflicts, we can't really change the 
type until the property is made private.
      */
     protected Map<String, Object> values = Collections.synchronizedMap(new 
HashMap<String, Object>());
-    private Map<String, Long> sizes = Collections.synchronizedMap(new 
HashMap<String, Long>());
+    private Map<String, Long> sizes = null;
 
+
     /**
      * Determines whether the node is being initialized (typically when it is 
loaded from the database).
      * Use {...@link #start} to start initializing, use {...@link #finish} to 
end.
@@ -94,8 +96,8 @@
      * Set which stores the keys of the fields that were changed
      * since the last commit.
      */
-    private Set<String> changed = Collections.synchronizedSet(new 
HashSet<String>());
-
+    private Set<String> changed = null;
+    
     /**
      * Pointer to the parent builder that is responsible for this node.
      * Note: this may on occasion (due to optimization) differ for the node's 
original builder.
@@ -172,8 +174,13 @@
         isNew  = node.isNew();
         newContext = node.newContext;
         values.putAll(node.getValues());
-        values.putAll(node.getOldValues());
-        sizes.putAll(node.sizes);
+        Map<String, Object> nodeOldValues = node.getOldValues();
+        if (nodeOldValues != null) {
+           values.putAll(nodeOldValues);
+        }
+        if (node.sizes != null) {
+           sizesMap().putAll(node.sizes);
+        }
     }
 
     /**
@@ -187,6 +194,27 @@
         values = map;
     }
 
+    private Map<String, Object> oldValuesMap() {
+        if (oldValues == null) {
+            oldValues = Collections.synchronizedMap(new HashMap<String, 
Object>());
+        }
+        return oldValues;
+    }
+
+    private Set<String> changedMap() {
+        if (changed == null) {
+            changed = Collections.synchronizedSet(new HashSet<String>());
+        }
+        return changed;
+    }
+
+    private Map<String, Long> sizesMap() {
+        if (sizes == null) {
+            sizes = Collections.synchronizedMap(new HashMap<String, Long>());
+        }
+        return sizes;
+    }
+    
     /**
      * Returns the actual builder of the node.
      * Note that it is possible that, due to optimization, a node is currently 
associated with
@@ -226,6 +254,9 @@
 
 
     private void fixValues(final Map<String, Object> map, MMObjectBuilder bul) 
{
+        if (map == null) {
+            return;
+        }
         synchronized(map) {
 
             Set<String> targetFields     = bul.getFieldNames();
@@ -254,7 +285,6 @@
             }
         }
     }
-
     /**
      * @since MMBase-1.9.1
      */
@@ -308,11 +338,14 @@
      * @return <code>true</code> if the commit was succesfull, 
<code>false</code> is it failed
      */
     public boolean commit() {
+        assert values.get("number") != null;
         boolean success = parent.commit(this);
         if (success) {
             isNew = false; // perhaps it is always already false (otherwise 
insert is called, I think), but no matter, now it certainly isn't new!
         } else {
-            values.putAll(oldValues);
+            if (oldValues != null) {
+                values.putAll(oldValues);
+            }
         }
         clearChanged();
         return success;
@@ -324,7 +357,9 @@
      * @since MMBase-1.8
      */
     public void cancel() {
-        values.putAll(oldValues);
+        if (oldValues != null) {
+            values.putAll(oldValues);
+        }
         clearChanged();
     }
     /**
@@ -373,6 +408,7 @@
      * @since MMBase-1.7
      */
     public boolean commit(UserContext user) {
+        assert values.get("number") != null;
         boolean success = parent.safeCommit(this);
         if (success) {
             MMBaseCop mmbaseCop = parent.getMMBase().getMMBaseCop();
@@ -495,23 +531,25 @@
     String defaultToString() {
         StringBuilder result = new StringBuilder();
         try {
-            Set<Map.Entry<String, Object>> entrySet = values.entrySet();
             synchronized(values) {
-                Iterator<Map.Entry<String, Object>> i = entrySet.iterator();
-                while (i.hasNext()) {
-                    Map.Entry<String, Object> entry = i.next();
+                for (Map.Entry<String, Object> entry : values.entrySet()) {
                     String key = entry.getKey();
-                    String value = "" + entry.getValue();  // XXX:should be 
retrieveValue ?
-                    if (result.length() == 0) {
-                        
result.append(key).append("='").append(value).append("'");
+                    if (result.length() > 0) {
+                        result.append(", ");
+                    }
+                    result.append(key);
+                    Object value = entry.getValue();
+                    if (value == null) {
+                        result.append(" is null");
                     } else {
-                        
result.append(",").append(key).append("='").append(value).append("'");
+                        
result.append("='").append(value.toString()).append("'");
                     }
                 }
             }
         } catch(Throwable e) {
             result.append(values); // simpler version...
         }
+        result.append(' ');
         result.append(super.toString());
         if (oldBuilder != null) {
             result.append(" (to be converted from " + 
oldBuilder.getTableName() + " to " + builder.getTableName() + ")");
@@ -539,7 +577,7 @@
             } else {
                 log.warn("Tried to use non-existing field '" + fieldName + "' 
of node '" + getNumber() + "' from " + getBuilder().getTableName());
                 if (log.isDebugEnabled()) {
-                    log.debug("Stacktrace", new Exception());
+                    log.debug(new Exception());
                 } else {
                     log.warn(Logging.applicationStacktrace());
 
@@ -586,6 +624,9 @@
         if (fieldValue != null && (fieldValue instanceof InputStream && (! 
(fieldValue instanceof Serializable)))) {
             fieldValue = new SerializableInputStream((InputStream) fieldValue, 
getSize(fieldName));
         }
+        if (fieldValue instanceof Node) {
+            fieldValue = Integer.valueOf(((Node) fieldValue).getNumber());
+        }
         fieldValue = checkSerializable(fieldName, fieldValue);
         if (checkFieldExistance(fieldName)) {
             values.put(fieldName, fieldValue);
@@ -602,9 +643,9 @@
      * @since MMBase-1.8
      */
     private void storeOldValue(String fieldName, Object object) {
-        if (! oldValues.containsKey(fieldName)) {
+        if (! oldValuesMap().containsKey(fieldName)) {
             object = checkSerializable(fieldName,  object);
-            oldValues.put(fieldName, object);
+            oldValuesMap().put(fieldName, object);
         }
     }
 
@@ -658,81 +699,83 @@
      *  @return <code>true</code> When the field was changed, false otherwise.
      */
     public boolean setValue(final String fieldName, Object fieldValue) {
-        // check the value also when the parent thing is null
-        Object originalValue = values.get(fieldName);
+        synchronized(values) {
+            // check the value also when the parent thing is null
+            Object originalValue = values.get(fieldName);
 
-        if (fieldValue != VALUE_SHORTED) {
-            // make sure this value remains not in the blob-cache.
-            BlobCache blobs = parent.getBlobCache(fieldName);
-            blobs.remove(blobs.getKey(getNumber(), fieldName));
-        }
+            if (fieldValue != VALUE_SHORTED) {
+                // make sure this value remains not in the blob-cache.
+                BlobCache blobs = parent.getBlobCache(fieldName);
+                blobs.remove(blobs.getKey(getNumber(), fieldName));
+            }
 
-        if (fieldValue instanceof DynamicDate) {
-            // 'dynamic' values can of course not be stored in database, and 
that is not the intentention too, so
-            // store a static version
-            fieldValue = new Date(((Date) fieldValue).getTime());
-        }
+            if (fieldValue instanceof DynamicDate) {
+                // 'dynamic' values can of course not be stored in database, 
and that is not the intentention too, so
+                // store a static version
+                fieldValue = new Date(((Date) fieldValue).getTime());
+            }
 
-        if (log.isDebugEnabled()) {
-            String string;
-            if (fieldValue instanceof byte[]) {
-                string = "byte array of size " + ((byte[])fieldValue).length;
-            } else {
-                string = Casting.toString(fieldValue);
-                if (string.length() > 200) string = string.substring(0, 200);
+            if (log.isDebugEnabled()) {
+                String string;
+                if (fieldValue instanceof byte[]) {
+                    string = "byte array of size " + 
((byte[])fieldValue).length;
+                } else {
+                    string = Casting.toString(fieldValue);
+                    if (string.length() > 200) string = string.substring(0, 
200);
+                }
+                log.debug("Setting " + fieldName + " to " +  string);
             }
-            log.debug("Setting " + fieldName + " to " +  string);
-        }
 
-        boolean changed =
-            (! values.containsKey(fieldName)) ||
-            (originalValue == null ? fieldValue != null : ! 
Casting.equals(originalValue, fieldValue));
-        if (! changed) return false;
+            boolean changed =
+                (! values.containsKey(fieldName)) ||
+                (originalValue == null ? fieldValue != null : ! 
Casting.equals(originalValue, fieldValue));
+            if (! changed) return false;
 
-        if (log.isDebugEnabled()) {
-            log.debug("" + fieldName + ":" + originalValue + " --> " + 
fieldValue);
-        }
+            if (log.isDebugEnabled()) {
+                log.debug("" + fieldName + ":" + originalValue + " --> " + 
fieldValue);
+            }
 
-        //store the old value
-        storeOldValue(fieldName, originalValue);
+            //store the old value
+            storeOldValue(fieldName, originalValue);
 
-        // put the key/value in the value hashtable
-        storeValue(fieldName, fieldValue);
-        if (fieldValue instanceof byte[]) {
-            setSize(fieldName, ((byte[]) fieldValue).length);
-            log.debug("Setting length to " + ((byte[]) fieldValue).length);
-        } else if (fieldValue instanceof 
org.apache.commons.fileupload.FileItem) {
-            org.apache.commons.fileupload.FileItem fi = 
(org.apache.commons.fileupload.FileItem) fieldValue;
-            setSize(fieldName, fi.getSize());
-        } else if (fieldValue instanceof SerializableInputStream) {
-            SerializableInputStream si = (SerializableInputStream) fieldValue;
-            log.debug("Setting '" + fieldName + "' to " + si + " " + 
si.getSize());
-            setSize(fieldName, si.getSize());
-        }
+            // put the key/value in the value hashtable
+            storeValue(fieldName, fieldValue);
+            if (fieldValue instanceof byte[]) {
+                setSize(fieldName, ((byte[]) fieldValue).length);
+                log.debug("Setting length to " + ((byte[]) fieldValue).length);
+            } else if (fieldValue instanceof 
org.apache.commons.fileupload.FileItem) {
+                org.apache.commons.fileupload.FileItem fi = 
(org.apache.commons.fileupload.FileItem) fieldValue;
+                setSize(fieldName, fi.getSize());
+            } else if (fieldValue instanceof SerializableInputStream) {
+                SerializableInputStream si = (SerializableInputStream) 
fieldValue;
+                log.debug("Setting '" + fieldName + "' to " + si + " " + 
si.getSize());
+                setSize(fieldName, si.getSize());
+            }
 
-        // process the changed value (?)
-        if (parent != null) {
-            if(!parent.setValue(this, fieldName, originalValue)) {
-                log.debug("setValue of parent returned false, no update 
needed...");
-                return false;
+            // process the changed value (?)
+            if (parent != null) {
+                if(!parent.setValue(this, fieldName, originalValue)) {
+                    log.debug("setValue of parent returned false, no update 
needed...");
+                    return false;
+                }
+            } else {
+                log.error("parent was null for node with number" + 
getNumber());
             }
-        } else {
-            log.error("parent was null for node with number" + getNumber());
-        }
-        setUpdate(fieldName);
+            setUpdate(fieldName);
 
-        if (fieldValue instanceof SerializableInputStream) {
-            // in case this is alled from a transaction, it must be possible 
to do it again on
-            // actual commit
-            try {
-                SerializableInputStream si = (SerializableInputStream) 
fieldValue;
-                si.reset();
-            } catch (IOException ioe) {
-                log.error(ioe);
+            if (fieldValue instanceof SerializableInputStream) {
+                // in case this is alled from a transaction, it must be 
possible to do it again on
+                // actual commit
+                try {
+                    SerializableInputStream si = (SerializableInputStream) 
fieldValue;
+                    si.reset();
+                } catch (IOException ioe) {
+                    log.error(ioe);
+                }
             }
+            log.debug("" + sequence + getChanged());
+            return true;
         }
-        log.debug("" + sequence + getChanged());
-        return true;
     }
 
     /**
@@ -742,7 +785,7 @@
      * @since MMBase-1.8
      */
     public void setSize(String fieldName, long size) {
-        sizes.put(fieldName, size);
+        sizesMap().put(fieldName, size);
     }
     /**
      * Returns the size (in byte) of the given field. This is mainly targeted 
at fields of the type
@@ -752,8 +795,12 @@
      * @since MMBase-1.8
      */
     public long getSize(String fieldName) {
-        Long l = sizes.get(fieldName);
-        if (l != null)  return l;
+        if (sizes != null) {
+            Long l = sizes.get(fieldName);
+            if (l != null)  {
+                return l;
+            }
+        }
         Object value = values.get(fieldName);
         // Value is null so it does not occupy any space.
         if (value == null) {
@@ -777,7 +824,7 @@
         // on the next commit
         if (! initializing) {
             log.trace("Marking '" + fieldName + "' as changed in " + sequence);
-            changed.add(fieldName);
+            changedMap().add(fieldName);
         }
         // is it a memory only field ? then send a fieldchange
         if (state == Field.STATE_VIRTUAL) {
@@ -1012,7 +1059,7 @@
         if (value == null) {
             checkFieldExistance(fieldName);
             log.debug("NULL on " + fieldName + " " + this, new Exception());
-            return new ByteArrayInputStream(new byte[0]);
+            return new SerializableInputStream(new byte[0]);
         } else {
             if (log.isTraceEnabled()) {
                 log.trace("Found " + value);
@@ -1053,13 +1100,17 @@
                 }
             } else {
                 v = (byte[]) blobs.get(key);
-                log.debug("Found in " + v.length + " bytes in blob cache for 
field " + fieldName );
-                assert v.length == getSize(fieldName);
+                log.debug("Found in " + v.length + " bytes in blob cache for 
field " + fieldName + " (expected  " + getSize(fieldName) + " )");
+                //assert v.length == getSize(fieldName) : ("" + fieldName + 
":" + v.length + " " + sizes);
+                if (v.length != getSize(fieldName)) {
+                    log.warn("Found incorrect size in " + sizes + "(" + 
fieldName + " should be " + v.length + "). Correcting now.");
+                    setSize(fieldName, v.length);
+                }
             }
-            return v == null ? null : new ByteArrayInputStream(v);
+            return v == null ? null : new SerializableInputStream(v);
         } else {
             if (value instanceof byte[]) {
-                return new ByteArrayInputStream((byte[]) value);
+                return new SerializableInputStream((byte[]) value);
             } else {
                 // probably not a byte-array field, do something.
                 // this behavior is undefined!, don't depend on it.
@@ -1261,7 +1312,7 @@
      * @return An unmodifiable Set containing Strings.
      */
     public Set<String> getChanged() {
-        return Collections.unmodifiableSet(changed);
+        return Collections.unmodifiableSet(changedMap());
     }
 
     /**
@@ -1269,7 +1320,7 @@
      * @return <code>true</code> if changes have been made, <code>false</code> 
otherwise
      */
     public boolean isChanged() {
-        return oldBuilder != null || newContext != null || changed.size() > 0;
+        return oldBuilder != null || newContext != null || (changed != null && 
changed.size() > 0);
     }
 
     /**
@@ -1281,8 +1332,12 @@
     public boolean clearChanged() {
         oldBuilder = null;
         newContext = null;
-        changed.clear();
-        oldValues.clear();
+        if (changed != null) {
+            changed.clear();
+        }
+        if (oldValues != null) {
+            oldValues.clear();
+        }
         return true;
     }
 
@@ -1310,7 +1365,7 @@
      * @since MMBase-1.8
      */
     public Map<String, Object> getOldValues() {
-        return Collections.unmodifiableMap(oldValues);
+        return Collections.unmodifiableMap(oldValuesMap());
     }
 
     /**

Modified: 
mmbase/branches/MMBase-1_9/core/src/main/java/org/mmbase/util/magicfile/MagicXMLReader.java
===================================================================
--- 
mmbase/branches/MMBase-1_9/core/src/main/java/org/mmbase/util/magicfile/MagicXMLReader.java
 2010-04-03 14:16:48 UTC (rev 41753)
+++ 
mmbase/branches/MMBase-1_9/core/src/main/java/org/mmbase/util/magicfile/MagicXMLReader.java
 2010-04-03 14:38:43 UTC (rev 41754)
@@ -19,49 +19,55 @@
 
     private static Logger log = 
Logging.getLoggerInstance(MagicXMLReader.class);
 
-    private static MagicXMLReader reader = null;
+    private static DetectorProvider provider;
+
     protected static final String MAGICXMLFILE = "magic.xml";
     // Name of the XML magic file - should reside in top config dir
 
-    private static void setReader(String config) throws 
IllegalArgumentException {
-        try {
-            InputSource is = 
ResourceLoader.getConfigurationRoot().getInputSource(config);
-            if (is != null) {
-                reader = new MagicXMLReader(is);
-            }
-        } catch (IOException ie) {
-            log.warn(ie);
-        }
-    }
+    private static void loadDetectorProvider(String config) throws 
IllegalArgumentException {
+       try {
+           InputSource is = 
ResourceLoader.getConfigurationRoot().getInputSource(config);
+           if (is != null) {
+              MagicXMLReader reader = new MagicXMLReader(is);
+               if (reader != null) {
+                   log.info("Magic XML file is: " + reader.getSystemId());
+                    final List<Detector> detectors = new 
ArrayList<Detector>(reader.getDetectors());
+                    DetectorProvider dp = new DetectorProvider() {
+                       public List<Detector> getDetectors() {
+                          return detectors;
+                       }
+                    };
+                    provider = dp;
+               }
+           }
+       } catch (IOException ie) {
+           log.warn(ie);
+       }
+   }
 
-    /**
-     * Gets the one MagicXMLReader (there can only be one).
-     * @return MagicXMLReader if mmbase was staterd or null if mmbase was not 
started
-     */
+   /**
+    * Gets the one MagicXMLReader (there can only be one).
+    * @return MagicXMLReader if mmbase was staterd or null if mmbase was not 
started
+    */
 
-    public synchronized static MagicXMLReader getInstance() {
-        if (reader == null) { // can only occur once.
+   public synchronized static DetectorProvider getInstance() {
+       if (provider == null) { // can only occur once.
 
-            setReader(MAGICXMLFILE);
+           loadDetectorProvider(MAGICXMLFILE);
 
-            if (reader != null) {
-                log.info("Magic XML file is: " + reader.getSystemId());
-            }
+           ResourceWatcher watcher = new ResourceWatcher() {
+                   public void onChange(String file) {
+                       // reader is replaced on every change of magic.xml
+                       loadDetectorProvider(file);
+                   }
+               };
+           watcher.start();
+           watcher.add(MAGICXMLFILE);
 
-            ResourceWatcher watcher = new ResourceWatcher() {
-                    public void onChange(String file) {
-                        // reader is replaced on every change of magic.xml
-                        setReader(file);
-                    }
-                };
-            watcher.start();
-            watcher.add(MAGICXMLFILE);
-
-        }
-        return reader;
-    }
-    private List<Detector> detectors = null;
-
+       }
+       return provider;
+   }
+   
     private MagicXMLReader(InputSource is) {
         super(is, MagicXMLReader.class);
     }
@@ -82,25 +88,22 @@
     /**
      * Returns all 'Detectors'.
      */
-    public List<Detector> getDetectors()  {
-        if (detectors == null) {
-            detectors = new CopyOnWriteArrayList<Detector>();
-            Element e = getElementByPath("magic.detectorlist");
-            if (e == null) {
-                log.fatal("Could not find magic/detectorlist in magic.xml");
-                // aargh!
-                return detectors;
+    public List<Detector> getDetectors() {
+        List<Detector> detectors = new CopyOnWriteArrayList<Detector>();
+        Element e = getElementByPath("magic.detectorlist");
+        if (e == null) {
+            log.fatal("Could not find magic/detectorlist in magic.xml");
+            // aargh!
+            return detectors;
+        }
+        for (Element element : getChildElements(e)) {
+            try {
+                Detector d = getOneDetector(element);
+                detectors.add(d);
+            } catch (Exception ex) {
+                log.error(ex.getClass() + " " + ex.getMessage() + ": " + 
XMLWriter.write(element));
             }
-            for (Element element : getChildElements(e)) {
-                try {
-                    Detector d = getOneDetector(element);
-                    detectors.add(d);
-                } catch (Exception ex) {
-                    log.error(ex.getClass() + " " + ex.getMessage() + ": " + 
XMLWriter.write(element));
-                }
-            }
         }
-
         return detectors;
     }
 

Modified: mmbase/trunk/applications/editwizard/src/main/config/caches.xml
===================================================================
--- mmbase/trunk/applications/editwizard/src/main/config/caches.xml     
2010-04-03 14:16:48 UTC (rev 41753)
+++ mmbase/trunk/applications/editwizard/src/main/config/caches.xml     
2010-04-03 14:38:43 UTC (rev 41754)
@@ -4,10 +4,6 @@
 
   <!-- other caches ... -->
 
-  <cache name="Editwizard nodes">
-    <status>active</status>
-    <size>100</size>
-  </cache>
   <cache name="Editwizard schemas">
     <status>active</status>
     <size>100</size>

Modified: 
mmbase/trunk/applications/editwizard/src/main/java/org/mmbase/applications/editwizard/Wizard.java
===================================================================
--- 
mmbase/trunk/applications/editwizard/src/main/java/org/mmbase/applications/editwizard/Wizard.java
   2010-04-03 14:16:48 UTC (rev 41753)
+++ 
mmbase/trunk/applications/editwizard/src/main/java/org/mmbase/applications/editwizard/Wizard.java
   2010-04-03 14:38:43 UTC (rev 41754)
@@ -67,15 +67,14 @@
 
     // File -> Document (resolved includes/shortcuts)
     private static WizardSchemaCache wizardSchemaCache;
-    private static NodeCache nodeCache; // it's absurd to name this NodeCache
 
     static {
         wizardSchemaCache = new WizardSchemaCache();
         wizardSchemaCache.putCache();
-        nodeCache = new NodeCache();
-        nodeCache.putCache();
     }
 
+    private Map<String, Node> nodePermissionCache = new HashMap<String, 
Node>();
+
     /**
      * The cloud used to connect to MMBase
      */
@@ -304,7 +303,7 @@
      * @throws WizardException if the object cannot be retrieved
      */
     protected boolean checkNode(String objectNumber, String operation) throws 
WizardException {
-        Node node = nodeCache.get(objectNumber);
+        Node node = nodePermissionCache.get(objectNumber);
 
         if (node == null) {
             NodeList nodes = Utils.selectNodeList(data, ".//*...@number='" + 
objectNumber + "']");
@@ -323,7 +322,7 @@
                 node = databaseConnector.getDataNode(null, objectNumber, null);
             }
 
-            nodeCache.put(objectNumber, node);
+            nodePermissionCache.put(objectNumber, node);
             log.debug("Node loaded: " + node);
         } else {
             log.debug("Node found in cache: " + node);
@@ -2958,24 +2957,6 @@
     }
 
     /**
-     * Caches objectNumber to Node.
-     * @since MMBase-1.6.4
-     */
-    static class NodeCache extends Cache<String, Node> {
-        NodeCache() {
-            super(100);
-        }
-
-        public String getName() {
-            return "Editwizard nodes";
-        }
-
-        public String getDescription() {
-            return "objectNumber -> DOM Node";
-        }
-    }
-
-    /**
      * Caches File to  Editwizard schema Document.
      * @since MMBase-1.6.4
      */

Modified: 
mmbase/trunk/core/src/main/java/org/mmbase/module/core/MMObjectNode.java
===================================================================
--- mmbase/trunk/core/src/main/java/org/mmbase/module/core/MMObjectNode.java    
2010-04-03 14:16:48 UTC (rev 41753)
+++ mmbase/trunk/core/src/main/java/org/mmbase/module/core/MMObjectNode.java    
2010-04-03 14:38:43 UTC (rev 41754)
@@ -61,8 +61,9 @@
      * it can be used to optimise cacheing
      * @since MMBase-1.8
      */
-    private Map<String, Object> oldValues = Collections.synchronizedMap(new 
HashMap<String, Object>());
-
+    private Map<String, Object> oldValues = null;
+    
+    
     /**
      * Holds the name - value pairs of this node (the node's fields).
      * Most nodes will have a 'number' and an 'otype' field, and fields which 
will differ by builder.
@@ -72,8 +73,9 @@
      * Note: To avoid synchronisation conflicts, we can't really change the 
type until the property is made private.
      */
     protected Map<String, Object> values = Collections.synchronizedMap(new 
HashMap<String, Object>());
-    private Map<String, Long> sizes = Collections.synchronizedMap(new 
HashMap<String, Long>());
+    private Map<String, Long> sizes = null;
 
+
     /**
      * Determines whether the node is being initialized (typically when it is 
loaded from the database).
      * Use {...@link #start} to start initializing, use {...@link #finish} to 
end.
@@ -94,8 +96,8 @@
      * Set which stores the keys of the fields that were changed
      * since the last commit.
      */
-    private Set<String> changed = Collections.synchronizedSet(new 
HashSet<String>());
-
+    private Set<String> changed = null;
+    
     /**
      * Pointer to the parent builder that is responsible for this node.
      * Note: this may on occasion (due to optimization) differ for the node's 
original builder.
@@ -172,8 +174,13 @@
         isNew  = node.isNew();
         newContext = node.newContext;
         values.putAll(node.getValues());
-        values.putAll(node.getOldValues());
-        sizes.putAll(node.sizes);
+        Map<String, Object> nodeOldValues = node.getOldValues();
+        if (nodeOldValues != null) {
+           values.putAll(nodeOldValues);
+        }
+        if (node.sizes != null) {
+           sizesMap().putAll(node.sizes);
+        }
     }
 
     /**
@@ -187,6 +194,27 @@
         values = map;
     }
 
+    private Map<String, Object> oldValuesMap() {
+        if (oldValues == null) {
+            oldValues = Collections.synchronizedMap(new HashMap<String, 
Object>());
+        }
+        return oldValues;
+    }
+
+    private Set<String> changedMap() {
+        if (changed == null) {
+            changed = Collections.synchronizedSet(new HashSet<String>());
+        }
+        return changed;
+    }
+
+    private Map<String, Long> sizesMap() {
+        if (sizes == null) {
+            sizes = Collections.synchronizedMap(new HashMap<String, Long>());
+        }
+        return sizes;
+    }
+    
     /**
      * Returns the actual builder of the node.
      * Note that it is possible that, due to optimization, a node is currently 
associated with
@@ -226,6 +254,9 @@
 
 
     private void fixValues(final Map<String, Object> map, MMObjectBuilder bul) 
{
+        if (map == null) {
+            return;
+        }
         synchronized(map) {
 
             Set<String> targetFields     = bul.getFieldNames();
@@ -312,7 +343,9 @@
         if (success) {
             isNew = false; // perhaps it is always already false (otherwise 
insert is called, I think), but no matter, now it certainly isn't new!
         } else {
-            values.putAll(oldValues);
+            if (oldValues != null) {
+                values.putAll(oldValues);
+            }
         }
         clearChanged();
         return success;
@@ -324,7 +357,9 @@
      * @since MMBase-1.8
      */
     public void cancel() {
-        values.putAll(oldValues);
+        if (oldValues != null) {
+            values.putAll(oldValues);
+        }
         clearChanged();
     }
     /**
@@ -608,9 +643,9 @@
      * @since MMBase-1.8
      */
     private void storeOldValue(String fieldName, Object object) {
-        if (! oldValues.containsKey(fieldName)) {
+        if (! oldValuesMap().containsKey(fieldName)) {
             object = checkSerializable(fieldName,  object);
-            oldValues.put(fieldName, object);
+            oldValuesMap().put(fieldName, object);
         }
     }
 
@@ -750,7 +785,7 @@
      * @since MMBase-1.8
      */
     public void setSize(String fieldName, long size) {
-        sizes.put(fieldName, size);
+        sizesMap().put(fieldName, size);
     }
     /**
      * Returns the size (in byte) of the given field. This is mainly targeted 
at fields of the type
@@ -760,9 +795,11 @@
      * @since MMBase-1.8
      */
     public long getSize(String fieldName) {
-        Long l = sizes.get(fieldName);
-        if (l != null)  {
-            return l;
+        if (sizes != null) {
+            Long l = sizes.get(fieldName);
+            if (l != null)  {
+                return l;
+            }
         }
         Object value = values.get(fieldName);
         // Value is null so it does not occupy any space.
@@ -787,7 +824,7 @@
         // on the next commit
         if (! initializing) {
             log.trace("Marking '" + fieldName + "' as changed in " + sequence);
-            changed.add(fieldName);
+            changedMap().add(fieldName);
         }
         // is it a memory only field ? then send a fieldchange
         if (state == Field.STATE_VIRTUAL) {
@@ -1275,7 +1312,7 @@
      * @return An unmodifiable Set containing Strings.
      */
     public Set<String> getChanged() {
-        return Collections.unmodifiableSet(changed);
+        return Collections.unmodifiableSet(changedMap());
     }
 
     /**
@@ -1283,7 +1320,7 @@
      * @return <code>true</code> if changes have been made, <code>false</code> 
otherwise
      */
     public boolean isChanged() {
-        return oldBuilder != null || newContext != null || changed.size() > 0;
+        return oldBuilder != null || newContext != null || (changed != null && 
changed.size() > 0);
     }
 
     /**
@@ -1295,8 +1332,12 @@
     public boolean clearChanged() {
         oldBuilder = null;
         newContext = null;
-        changed.clear();
-        oldValues.clear();
+        if (changed != null) {
+            changed.clear();
+        }
+        if (oldValues != null) {
+            oldValues.clear();
+        }
         return true;
     }
 
@@ -1324,7 +1365,7 @@
      * @since MMBase-1.8
      */
     public Map<String, Object> getOldValues() {
-        return Collections.unmodifiableMap(oldValues);
+        return Collections.unmodifiableMap(oldValuesMap());
     }
 
     /**

Modified: 
mmbase/trunk/utils/src/main/java/org/mmbase/util/magicfile/MagicXMLReader.java
===================================================================
--- 
mmbase/trunk/utils/src/main/java/org/mmbase/util/magicfile/MagicXMLReader.java  
    2010-04-03 14:16:48 UTC (rev 41753)
+++ 
mmbase/trunk/utils/src/main/java/org/mmbase/util/magicfile/MagicXMLReader.java  
    2010-04-03 14:38:43 UTC (rev 41754)
@@ -19,15 +19,26 @@
 
     private static Logger log = 
Logging.getLoggerInstance(MagicXMLReader.class);
 
-    private static MagicXMLReader reader = null;
+    private static DetectorProvider provider;
+
     protected static final String MAGICXMLFILE = "magic.xml";
     // Name of the XML magic file - should reside in top config dir
 
-    private static void setReader(String config) throws 
IllegalArgumentException {
+    private static void loadDetectorProvider(String config) throws 
IllegalArgumentException {
         try {
             InputSource is = 
ResourceLoader.getConfigurationRoot().getInputSource(config);
             if (is != null) {
-                reader = new MagicXMLReader(is);
+              MagicXMLReader reader = new MagicXMLReader(is);
+               if (reader != null) {
+                   log.info("Magic XML file is: " + reader.getSystemId());
+                    final List<Detector> detectors = new 
ArrayList<Detector>(reader.getDetectors());
+                    DetectorProvider dp = new DetectorProvider() {
+                       public List<Detector> getDetectors() {
+                          return detectors;
+                       }
+                    };
+                    provider = dp;
+               }
             }
         } catch (IOException ie) {
             log.warn(ie);
@@ -39,29 +50,24 @@
      * @return MagicXMLReader if mmbase was staterd or null if mmbase was not 
started
      */
 
-    public synchronized static MagicXMLReader getInstance() {
-        if (reader == null) { // can only occur once.
+   public synchronized static DetectorProvider getInstance() {
+       if (provider == null) { // can only occur once.
 
-            setReader(MAGICXMLFILE);
+           loadDetectorProvider(MAGICXMLFILE);
 
-            if (reader != null) {
-                log.info("Magic XML file is: " + reader.getSystemId());
-            }
+           ResourceWatcher watcher = new ResourceWatcher() {
+                   public void onChange(String file) {
+                       // reader is replaced on every change of magic.xml
+                       loadDetectorProvider(file);
+                   }
+               };
+           watcher.start();
+           watcher.add(MAGICXMLFILE);
 
-            ResourceWatcher watcher = new ResourceWatcher() {
-                    public void onChange(String file) {
-                        // reader is replaced on every change of magic.xml
-                        setReader(file);
-                    }
-                };
-            watcher.start();
-            watcher.add(MAGICXMLFILE);
-
-        }
-        return reader;
+       }
+       return provider;
     }
-    private List<Detector> detectors = null;
-
+   
     private MagicXMLReader(InputSource is) {
         super(is, MagicXMLReader.class);
     }
@@ -83,24 +89,21 @@
      * Returns all 'Detectors'.
      */
     public List<Detector> getDetectors()  {
-        if (detectors == null) {
-            detectors = new CopyOnWriteArrayList<Detector>();
-            Element e = getElementByPath("magic.detectorlist");
-            if (e == null) {
-                log.fatal("Could not find magic/detectorlist in magic.xml");
-                // aargh!
-                return detectors;
+        List<Detector> detectors = new CopyOnWriteArrayList<Detector>();
+        Element e = getElementByPath("magic.detectorlist");
+        if (e == null) {
+            log.fatal("Could not find magic/detectorlist in magic.xml");
+            // aargh!
+            return detectors;
+        }
+        for (Element element : getChildElements(e)) {
+            try {
+                Detector d = getOneDetector(element);
+                detectors.add(d);
+            } catch (Exception ex) {
+                log.error(ex.getClass() + " " + ex.getMessage() + ": " + 
XMLWriter.write(element));
             }
-            for (Element element : getChildElements(e)) {
-                try {
-                    Detector d = getOneDetector(element);
-                    detectors.add(d);
-                } catch (Exception ex) {
-                    log.error(ex.getClass() + " " + ex.getMessage() + ": " + 
XMLWriter.write(element));
-                }
-            }
         }
-
         return detectors;
     }
 

_______________________________________________
Cvs mailing list
[email protected]
http://lists.mmbase.org/mailman/listinfo/cvs

Reply via email to