[jboss-svn-commits] JBL Code SVN: r25679 - in labs/jbossrules/trunk/drools-repository/src: main/java/org/drools/repository/events and 3 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Tue Mar 17 01:00:39 EDT 2009


Author: michael.neale at jboss.com
Date: 2009-03-17 01:00:38 -0400 (Tue, 17 Mar 2009)
New Revision: 25679

Added:
   labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/events/LoadEvent.java
   labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/events/SaveEvent.java
   labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/events/StorageEventManager.java
   labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/utils/
   labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/utils/ByteArrayOutputStream.java
   labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/utils/IOUtils.java
   labs/jbossrules/trunk/drools-repository/src/test/java/org/drools/repository/events/
   labs/jbossrules/trunk/drools-repository/src/test/java/org/drools/repository/events/MockLoadEvent.java
   labs/jbossrules/trunk/drools-repository/src/test/java/org/drools/repository/events/MockSaveEvent.java
   labs/jbossrules/trunk/drools-repository/src/test/java/org/drools/repository/events/StorageEventManagerTest.java
Removed:
   labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/events/AssetChange.java
   labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/events/AssetCreate.java
   labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/events/AssetDelete.java
   labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/events/AssetMove.java
   labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/events/AssetUpdate.java
   labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/events/ChangeSet.java
Modified:
   labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/AssetItem.java
   labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/PackageItem.java
   labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/RulesRepository.java
   labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/VersionableItem.java
   labs/jbossrules/trunk/drools-repository/src/test/java/org/drools/repository/PackageItemTest.java
Log:
GUVNOR-164 content event callbacks

Modified: labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/AssetItem.java
===================================================================
--- labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/AssetItem.java	2009-03-17 03:40:32 UTC (rev 25678)
+++ labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/AssetItem.java	2009-03-17 05:00:38 UTC (rev 25679)
@@ -1,8 +1,6 @@
 package org.drools.repository;
 
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.io.ByteArrayOutputStream;
+import java.io.*;
 import java.util.Calendar;
 import java.util.Iterator;
 
@@ -12,6 +10,8 @@
 import javax.jcr.RepositoryException;
 
 import org.apache.log4j.Logger;
+import org.drools.repository.events.StorageEventManager;
+import org.drools.repository.utils.IOUtils;
 
 /**
  * The RuleItem class is used to abstract away the details of the underlying JCR repository.
@@ -74,12 +74,20 @@
                null );
     }
 
+
+
+
     /**
      * returns the string contents of the rule node.
      * If this is a binary asset, this will return null (use getBinaryContent instead).
      */
     public String getContent() throws RulesRepositoryException {
         try {
+
+            if (StorageEventManager.hasLoadEvent()) {
+                return IOUtils.toString(StorageEventManager.getLoadEvent().loadContent(this));
+            }
+
             if ( isBinary() ) {
                 return new String( this.getBinaryContentAsBytes() );
             }
@@ -140,6 +148,9 @@
      */
     public InputStream getBinaryContentAttachment() {
         try {
+            if (StorageEventManager.hasLoadEvent()) {
+                return StorageEventManager.getLoadEvent().loadContent(this);
+            }
             Node ruleNode = getVersionContentNode();
             if ( ruleNode.hasProperty( CONTENT_PROPERTY_BINARY_NAME ) ) {
                 Property data = ruleNode.getProperty( CONTENT_PROPERTY_BINARY_NAME );
@@ -169,6 +180,9 @@
     public byte[] getBinaryContentAsBytes() {
         try {
             Node ruleNode = getVersionContentNode();
+            if (StorageEventManager.hasLoadEvent()) {
+                return IOUtils.toByteArray(StorageEventManager.getLoadEvent().loadContent(this));
+            }
             if (isBinary()) {
                     Property data = ruleNode.getProperty( CONTENT_PROPERTY_BINARY_NAME );
                     InputStream in = data.getStream();
@@ -477,6 +491,11 @@
      * to make it easy to roll back.
      */
     public void remove() {
+
+        if (StorageEventManager.hasSaveEvent()) {
+            StorageEventManager.getSaveEvent().onAssetDelete(this);
+        }
+
         checkIsUpdateable();
         if ( this.getDateExpired() != null ) {
             if ( Calendar.getInstance().before( this.getDateExpired() ) ) {

Modified: labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/PackageItem.java
===================================================================
--- labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/PackageItem.java	2009-03-17 03:40:32 UTC (rev 25678)
+++ labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/PackageItem.java	2009-03-17 05:00:38 UTC (rev 25679)
@@ -225,19 +225,8 @@
 
     }
 
-    /**
-     * Remove an asset by name
-     * After doing this, you will need to check in the package
-     * as removing an item effects the parent package.
-     */
-    public void removeAsset(String name) {
-        try {
-            this.node.getNode( ASSET_FOLDER_NAME + "/" + name ).remove();
-        } catch ( RepositoryException e ) {
-            throw new RulesRepositoryException( e );
-        }
-    }
 
+
     /**
      * This will permanently delete this package.
      */

Modified: labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/RulesRepository.java
===================================================================
--- labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/RulesRepository.java	2009-03-17 03:40:32 UTC (rev 25678)
+++ labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/RulesRepository.java	2009-03-17 05:00:38 UTC (rev 25679)
@@ -25,6 +25,7 @@
 
 import org.apache.log4j.Logger;
 import org.drools.repository.migration.MigrateDroolsPackage;
+import org.drools.repository.events.StorageEventManager;
 
 /**
  * RulesRepository is the class that defines the bahavior for the JBoss Rules
@@ -685,6 +686,10 @@
                                                 rulePackageNode );
             item.checkin( "Initial" );
 
+            if (StorageEventManager.hasSaveEvent()) {
+                StorageEventManager.getSaveEvent().onPackageCreate(item);
+            }
+
             return item;
         } catch ( ItemExistsException e ) {
             throw new RulesRepositoryException( "A package name must be unique.",

Modified: labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/VersionableItem.java
===================================================================
--- labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/VersionableItem.java	2009-03-17 03:40:32 UTC (rev 25678)
+++ labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/VersionableItem.java	2009-03-17 05:00:38 UTC (rev 25679)
@@ -1,5 +1,7 @@
 package org.drools.repository;
 
+import org.drools.repository.events.StorageEventManager;
+
 import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Iterator;
@@ -524,6 +526,13 @@
             this.node.setProperty( VERSION_NUMBER_PROPERTY_NAME,  nextVersion );
             this.node.getSession().save();
             this.node.checkin();
+
+            if (StorageEventManager.hasSaveEvent()) {
+                if (this instanceof AssetItem) {
+                    StorageEventManager.getSaveEvent().onAssetCheckin((AssetItem) this);
+                }
+            }
+
         } catch ( RepositoryException e ) {
             throw new RulesRepositoryException( "Unable to checkin.",
                                                 e );

Deleted: labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/events/AssetChange.java
===================================================================
--- labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/events/AssetChange.java	2009-03-17 03:40:32 UTC (rev 25678)
+++ labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/events/AssetChange.java	2009-03-17 05:00:38 UTC (rev 25679)
@@ -1,16 +0,0 @@
-package org.drools.repository.events;
-
-public class AssetChange {
-
-    private String changeComment;
-
-    public String getChangeComment() {
-        return changeComment;
-    }
-
-    public void setChangeComment(String changeComment) {
-        this.changeComment = changeComment;
-    }
-    
-    
-}

Deleted: labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/events/AssetCreate.java
===================================================================
--- labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/events/AssetCreate.java	2009-03-17 03:40:32 UTC (rev 25678)
+++ labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/events/AssetCreate.java	2009-03-17 05:00:38 UTC (rev 25679)
@@ -1,43 +0,0 @@
-package org.drools.repository.events;
-
-public class AssetCreate extends AssetChange {
-
-    private String content;
-    private String fileName;
-    private String format;
-    private String path;
-    
-    public String getContent() {
-        return content;
-    }
-    public String getFileName() {
-        return fileName;
-    }
-    
-    /** This is in effect the "file extension" as well as the format type. */
-    public String getFormat() {
-        return format;
-    }
-    
-    /** 
-     * The path is the directory path to the resource in "file" terms (not JCR terms). 
-     * Forward slash delimited.
-     */
-    public String getPath() {
-        return path;
-    }
-    
-    public AssetCreate(String content,
-                       String fileName,
-                       String format,
-                       String path) {
-       
-        this.content = content;
-        this.fileName = fileName;
-        this.format = format;
-        this.path = path;
-    }
-    
-    
-    
-}

Deleted: labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/events/AssetDelete.java
===================================================================
--- labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/events/AssetDelete.java	2009-03-17 03:40:32 UTC (rev 25678)
+++ labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/events/AssetDelete.java	2009-03-17 05:00:38 UTC (rev 25679)
@@ -1,32 +0,0 @@
-package org.drools.repository.events;
-
-public class AssetDelete extends AssetChange {
-
-    private String fileName;
-    private String format;
-    private String path;
-    
-    public String getFileName() {
-        return fileName;
-    }
-    
-    public String getFormat() {
-        return format;
-    }
-    public String getPath() {
-        return path;
-    }
-
-    public AssetDelete(String fileName,
-                       String format,
-                       String path) {
-        super();
-        this.fileName = fileName;
-        this.format = format;
-        this.path = path;
-    }
-
-    
-    
-    
-}

Deleted: labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/events/AssetMove.java
===================================================================
--- labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/events/AssetMove.java	2009-03-17 03:40:32 UTC (rev 25678)
+++ labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/events/AssetMove.java	2009-03-17 05:00:38 UTC (rev 25679)
@@ -1,41 +0,0 @@
-package org.drools.repository.events;
-
-public class AssetMove extends AssetChange {
-
-    private String oldFileName;
-    private String format;
-    private String oldPath;
-    private String newFileFormat;
-    private String newPath;
-    
-    public AssetMove(String oldFileName,
-                     String format,
-                     String oldPath,
-                     String newFileFormat,
-                     String newPath) {
-        super();
-        this.oldFileName = oldFileName;
-        this.format = format;
-        this.oldPath = oldPath;
-        this.newFileFormat = newFileFormat;
-        this.newPath = newPath;
-    }
-    
-    public String getFormat() {
-        return format;
-    }
-    public String getNewFileFormat() {
-        return newFileFormat;
-    }
-    public String getNewPath() {
-        return newPath;
-    }
-    public String getOldFileName() {
-        return oldFileName;
-    }
-    public String getOldPath() {
-        return oldPath;
-    }
-
-    
-}

Deleted: labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/events/AssetUpdate.java
===================================================================
--- labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/events/AssetUpdate.java	2009-03-17 03:40:32 UTC (rev 25678)
+++ labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/events/AssetUpdate.java	2009-03-17 05:00:38 UTC (rev 25679)
@@ -1,48 +0,0 @@
-package org.drools.repository.events;
-
-public class AssetUpdate extends AssetChange {
-
-    private String oldContent;
-    private String newContent;
-    private String fileName;
-    private String format;
-    private String path;
-    
-    public String getOldContent() {
-        return oldContent;
-    }
-    public String getFileName() {
-        return fileName;
-    }
-    public String getNewContent() {
-        return newContent;
-    }
-    
-    
-    /** This is in effect the "file extension" as well as the format type. */
-    public String getFormat() {
-        return format;
-    }
-    
-    /** 
-     * The path is the directory path to the resource in "file" terms (not JCR terms). 
-     * Forward slash delimited.
-     */
-    public String getPath() {
-        return path;
-    }
-    
-    public AssetUpdate(String oldContent,
-                       String newContent,
-                       String fileName,
-                       String format,
-                       String path) {
-       
-        this.oldContent = oldContent;
-        this.newContent = newContent;
-        this.fileName = fileName;
-        this.format = format;
-        this.path = path;
-    }    
-    
-}

Deleted: labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/events/ChangeSet.java
===================================================================
--- labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/events/ChangeSet.java	2009-03-17 03:40:32 UTC (rev 25678)
+++ labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/events/ChangeSet.java	2009-03-17 05:00:38 UTC (rev 25679)
@@ -1,24 +0,0 @@
-package org.drools.repository.events;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-
-
-public class ChangeSet {
-
-    private ArrayList assetChanges;
-    
-    public ChangeSet() {
-        assetChanges = new ArrayList();
-    }
-    
-    public void addChange(AssetChange change) {
-        this.assetChanges.add( change );
-    }
-    
-    public Iterator getChanges() {
-        return this.assetChanges.iterator();
-    }
-    
-    
-}

Added: labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/events/LoadEvent.java
===================================================================
--- labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/events/LoadEvent.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/events/LoadEvent.java	2009-03-17 05:00:38 UTC (rev 25679)
@@ -0,0 +1,22 @@
+package org.drools.repository.events;
+
+import org.drools.repository.AssetItem;
+
+import java.io.InputStream;
+
+/**
+ * This event handler is used to provide alternative asset content.
+ * When the asset payload (content) is fetched, it will call this, and it will use its input stream as the source
+ * of data rather then the JCR node.
+ *
+ * Use with care ! (it could slow things down).
+ *
+ * To install, create an instance of LoadEvent, make it available on the classpath and then set the system property
+ * 'loadEventListener' with the value of the full name of the class. 
+ *
+ * @author Michael Neale
+ */
+public interface LoadEvent {
+
+    public InputStream loadContent(AssetItem item);
+}

Added: labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/events/SaveEvent.java
===================================================================
--- labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/events/SaveEvent.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/events/SaveEvent.java	2009-03-17 05:00:38 UTC (rev 25679)
@@ -0,0 +1,33 @@
+package org.drools.repository.events;
+
+import org.drools.repository.AssetItem;
+import org.drools.repository.PackageItem;
+
+/**
+ * This will be called as content is saved to the repository - you can hook in and also store content in an external store.
+ * Content can be text or binary.
+ *
+ * To install an implementation of this, create an instance of SaveEvent, make it available on the classpath
+ * and set the system property 'guvnor.saveEventListener' with the full name of the class. 
+ *
+ * @author Michael Neale
+ */
+public interface SaveEvent {
+
+    /**
+     * When the content of the asset changes, or some meta data. This will also be called when it is new.
+     */
+    public void onAssetCheckin(AssetItem item);
+
+    /**
+     * When it is hard deleted. A soft delete is just a checkin with the archive flag set.
+     */
+    public void onAssetDelete(AssetItem item);
+
+
+    /**
+     * Called once, when a package is created.
+     */
+    public void onPackageCreate(PackageItem item);
+
+}

Added: labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/events/StorageEventManager.java
===================================================================
--- labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/events/StorageEventManager.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/events/StorageEventManager.java	2009-03-17 05:00:38 UTC (rev 25679)
@@ -0,0 +1,63 @@
+package org.drools.repository.events;
+
+import org.drools.repository.AssetItem;
+
+import java.io.InputStream;
+
+/**
+ * @author Michael Neale
+ */
+public class StorageEventManager {
+
+    static LoadEvent le = loadEvent();
+    static SaveEvent se = saveEvent();
+
+    static LoadEvent loadEvent() {
+        String leClassName = System.getProperty("guvnor.loadEventListener", "");
+        try {
+            if (!leClassName.equals("")) {
+                return (LoadEvent) Class.forName(leClassName).newInstance();
+            } else {
+                return null;
+            }
+        } catch (Exception e) {
+            System.err.println("Unable to initialise the load event listener: " + leClassName);
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    static SaveEvent saveEvent() {
+        String seClassName = System.getProperty("guvnor.saveEventListener", "");
+        try {
+            if (!seClassName.equals("")) {
+                return (SaveEvent) Class.forName(seClassName).newInstance();
+            } else {
+                return null;
+            }
+        } catch (Exception e) {
+            System.err.println("Unable to initialise the save event listener: " + seClassName);
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    public static boolean hasLoadEvent() {
+        return le != null;
+    }
+
+    public static boolean hasSaveEvent() {
+        return se != null;
+    }
+
+    public static LoadEvent getLoadEvent() {
+        return le;
+    }
+
+    public static SaveEvent getSaveEvent() {
+        return se;
+    }
+
+
+    
+}

Added: labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/utils/ByteArrayOutputStream.java
===================================================================
--- labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/utils/ByteArrayOutputStream.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/utils/ByteArrayOutputStream.java	2009-03-17 05:00:38 UTC (rev 25679)
@@ -0,0 +1,308 @@
+/*
+ * 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 org.drools.repository.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class implements an output stream in which the data is
+ * written into a byte array. The buffer automatically grows as data
+ * is written to it.
+ * <p>
+ * The data can be retrieved using <code>toByteArray()</code> and
+ * <code>toString()</code>.
+ * <p>
+ * Closing a <tt>ByteArrayOutputStream</tt> has no effect. The methods in
+ * this class can be called after the stream has been closed without
+ * generating an <tt>IOException</tt>.
+ * <p>
+ * This is an alternative implementation of the java.io.ByteArrayOutputStream
+ * class. The original implementation only allocates 32 bytes at the beginning.
+ * As this class is designed for heavy duty it starts at 1024 bytes. In contrast
+ * to the original it doesn't reallocate the whole memory block but allocates
+ * additional buffers. This way no buffers need to be garbage collected and
+ * the contents don't have to be copied to the new buffer. This class is
+ * designed to behave exactly like the original. The only exception is the
+ * deprecated toString(int) method that has been ignored.
+ *
+ * @author <a href="mailto:jeremias at apache.org">Jeremias Maerki</a>
+ * @author Holger Hoffstatte
+ * @version $Id: ByteArrayOutputStream.java 610010 2008-01-08 14:50:59Z niallp $
+ */
+public class ByteArrayOutputStream extends OutputStream {
+
+    /** A singleton empty byte array. */
+    private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
+
+    /** The list of buffers, which grows and never reduces. */
+    private List buffers = new ArrayList();
+    /** The index of the current buffer. */
+    private int currentBufferIndex;
+    /** The total count of bytes in all the filled buffers. */
+    private int filledBufferSum;
+    /** The current buffer. */
+    private byte[] currentBuffer;
+    /** The total count of bytes written. */
+    private int count;
+
+    /**
+     * Creates a new byte array output stream. The buffer capacity is
+     * initially 1024 bytes, though its size increases if necessary.
+     */
+    public ByteArrayOutputStream() {
+        this(1024);
+    }
+
+    /**
+     * Creates a new byte array output stream, with a buffer capacity of
+     * the specified size, in bytes.
+     *
+     * @param size  the initial size
+     * @throws IllegalArgumentException if size is negative
+     */
+    public ByteArrayOutputStream(int size) {
+        if (size < 0) {
+            throw new IllegalArgumentException(
+                "Negative initial size: " + size);
+        }
+        needNewBuffer(size);
+    }
+
+    /**
+     * Return the appropriate <code>byte[]</code> buffer
+     * specified by index.
+     *
+     * @param index  the index of the buffer required
+     * @return the buffer
+     */
+    private byte[] getBuffer(int index) {
+        return (byte[]) buffers.get(index);
+    }
+
+    /**
+     * Makes a new buffer available either by allocating
+     * a new one or re-cycling an existing one.
+     *
+     * @param newcount  the size of the buffer if one is created
+     */
+    private void needNewBuffer(int newcount) {
+        if (currentBufferIndex < buffers.size() - 1) {
+            //Recycling old buffer
+            filledBufferSum += currentBuffer.length;
+
+            currentBufferIndex++;
+            currentBuffer = getBuffer(currentBufferIndex);
+        } else {
+            //Creating new buffer
+            int newBufferSize;
+            if (currentBuffer == null) {
+                newBufferSize = newcount;
+                filledBufferSum = 0;
+            } else {
+                newBufferSize = Math.max(
+                    currentBuffer.length << 1,
+                    newcount - filledBufferSum);
+                filledBufferSum += currentBuffer.length;
+            }
+
+            currentBufferIndex++;
+            currentBuffer = new byte[newBufferSize];
+            buffers.add(currentBuffer);
+        }
+    }
+
+    /**
+     * Write the bytes to byte array.
+     * @param b the bytes to write
+     * @param off The start offset
+     * @param len The number of bytes to write
+     */
+    public void write(byte[] b, int off, int len) {
+        if ((off < 0)
+                || (off > b.length)
+                || (len < 0)
+                || ((off + len) > b.length)
+                || ((off + len) < 0)) {
+            throw new IndexOutOfBoundsException();
+        } else if (len == 0) {
+            return;
+        }
+        synchronized (this) {
+            int newcount = count + len;
+            int remaining = len;
+            int inBufferPos = count - filledBufferSum;
+            while (remaining > 0) {
+                int part = Math.min(remaining, currentBuffer.length - inBufferPos);
+                System.arraycopy(b, off + len - remaining, currentBuffer, inBufferPos, part);
+                remaining -= part;
+                if (remaining > 0) {
+                    needNewBuffer(newcount);
+                    inBufferPos = 0;
+                }
+            }
+            count = newcount;
+        }
+    }
+
+    /**
+     * Write a byte to byte array.
+     * @param b the byte to write
+     */
+    public synchronized void write(int b) {
+        int inBufferPos = count - filledBufferSum;
+        if (inBufferPos == currentBuffer.length) {
+            needNewBuffer(count + 1);
+            inBufferPos = 0;
+        }
+        currentBuffer[inBufferPos] = (byte) b;
+        count++;
+    }
+
+    /**
+     * Writes the entire contents of the specified input stream to this
+     * byte stream. Bytes from the input stream are read directly into the
+     * internal buffers of this streams.
+     *
+     * @param in the input stream to read from
+     * @return total number of bytes read from the input stream
+     *         (and written to this stream)
+     * @throws IOException if an I/O error occurs while reading the input stream
+     * @since Commons IO 1.4
+     */
+    public synchronized int write(InputStream in) throws IOException {
+        int readCount = 0;
+        int inBufferPos = count - filledBufferSum;
+        int n = in.read(currentBuffer, inBufferPos, currentBuffer.length - inBufferPos);
+        while (n != -1) {
+            readCount += n;
+            inBufferPos += n;
+            count += n;
+            if (inBufferPos == currentBuffer.length) {
+                needNewBuffer(currentBuffer.length);
+                inBufferPos = 0;
+            }
+            n = in.read(currentBuffer, inBufferPos, currentBuffer.length - inBufferPos);
+        }
+        return readCount;
+    }
+
+    /**
+     * Return the current size of the byte array.
+     * @return the current size of the byte array
+     */
+    public synchronized int size() {
+        return count;
+    }
+
+    /**
+     * Closing a <tt>ByteArrayOutputStream</tt> has no effect. The methods in
+     * this class can be called after the stream has been closed without
+     * generating an <tt>IOException</tt>.
+     *
+     * @throws IOException never (this method should not declare this exception
+     * but it has to now due to backwards compatability)
+     */
+    public void close() throws IOException {
+        //nop
+    }
+
+    /**
+     * @see java.io.ByteArrayOutputStream#reset()
+     */
+    public synchronized void reset() {
+        count = 0;
+        filledBufferSum = 0;
+        currentBufferIndex = 0;
+        currentBuffer = getBuffer(currentBufferIndex);
+    }
+
+    /**
+     * Writes the entire contents of this byte stream to the
+     * specified output stream.
+     *
+     * @param out  the output stream to write to
+     * @throws IOException if an I/O error occurs, such as if the stream is closed
+     * @see java.io.ByteArrayOutputStream#writeTo(OutputStream)
+     */
+    public synchronized void writeTo(OutputStream out) throws IOException {
+        int remaining = count;
+        for (int i = 0; i < buffers.size(); i++) {
+            byte[] buf = getBuffer(i);
+            int c = Math.min(buf.length, remaining);
+            out.write(buf, 0, c);
+            remaining -= c;
+            if (remaining == 0) {
+                break;
+            }
+        }
+    }
+
+    /**
+     * Gets the curent contents of this byte stream as a byte array.
+     * The result is independent of this stream.
+     *
+     * @return the current contents of this output stream, as a byte array
+     * @see java.io.ByteArrayOutputStream#toByteArray()
+     */
+    public synchronized byte[] toByteArray() {
+        int remaining = count;
+        if (remaining == 0) {
+            return EMPTY_BYTE_ARRAY;
+        }
+        byte newbuf[] = new byte[remaining];
+        int pos = 0;
+        for (int i = 0; i < buffers.size(); i++) {
+            byte[] buf = getBuffer(i);
+            int c = Math.min(buf.length, remaining);
+            System.arraycopy(buf, 0, newbuf, pos, c);
+            pos += c;
+            remaining -= c;
+            if (remaining == 0) {
+                break;
+            }
+        }
+        return newbuf;
+    }
+
+    /**
+     * Gets the curent contents of this byte stream as a string.
+     * @return the contents of the byte array as a String
+     * @see java.io.ByteArrayOutputStream#toString()
+     */
+    public String toString() {
+        return new String(toByteArray());
+    }
+
+    /**
+     * Gets the curent contents of this byte stream as a string
+     * using the specified encoding.
+     *
+     * @param enc  the name of the character encoding
+     * @return the string converted from the byte array
+     * @throws UnsupportedEncodingException if the encoding is not supported
+     * @see java.io.ByteArrayOutputStream#toString(String)
+     */
+    public String toString(String enc) throws UnsupportedEncodingException {
+        return new String(toByteArray(), enc);
+    }
+
+}

Added: labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/utils/IOUtils.java
===================================================================
--- labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/utils/IOUtils.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/utils/IOUtils.java	2009-03-17 05:00:38 UTC (rev 25679)
@@ -0,0 +1,1205 @@
+/*
+ * 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 org.drools.repository.utils;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.CharArrayWriter;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.io.Reader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+
+
+/**
+ * General IO stream manipulation utilities.
+ * <p>
+ * This class provides static utility methods for input/output operations.
+ * <ul>
+ * <li>closeQuietly - these methods close a stream ignoring nulls and exceptions
+ * <li>toXxx/read - these methods read data from a stream
+ * <li>write - these methods write data to a stream
+ * <li>copy - these methods copy all the data from one stream to another
+ * <li>contentEquals - these methods compare the content of two streams
+ * </ul>
+ * <p>
+ * The byte-to-char methods and char-to-byte methods involve a conversion step.
+ * Two methods are provided in each case, one that uses the platform default
+ * encoding and the other which allows you to specify an encoding. You are
+ * encouraged to always specify an encoding because relying on the platform
+ * default can lead to unexpected results, for example when moving from
+ * development to production.
+ * <p>
+ * All the methods in this class that read a stream are buffered internally.
+ * This means that there is no cause to use a <code>BufferedInputStream</code>
+ * or <code>BufferedReader</code>. The default buffer size of 4K has been shown
+ * to be efficient in tests.
+ * <p>
+ * Wherever possible, the methods in this class do <em>not</em> flush or close
+ * the stream. This is to avoid making non-portable assumptions about the
+ * streams' origin and further use. Thus the caller is still responsible for
+ * closing streams after use.
+ * <p>
+ * Origin of code: Excalibur.
+ *
+ * @author Peter Donald
+ * @author Jeff Turner
+ * @author Matthew Hawthorne
+ * @author Stephen Colebourne
+ * @author Gareth Davis
+ * @author Ian Springer
+ * @author Niall Pemberton
+ * @author Sandy McArthur
+ * @version $Id: IOUtils.java 481854 2006-12-03 18:30:07Z scolebourne $
+ */
+public class IOUtils {
+    // NOTE: This class is focussed on InputStream, OutputStream, Reader and
+    // Writer. Each method should take at least one of these as a parameter,
+    // or return one of them.
+
+    /**
+     * The Unix directory separator character.
+     */
+    public static final char DIR_SEPARATOR_UNIX = '/';
+    /**
+     * The Windows directory separator character.
+     */
+    public static final char DIR_SEPARATOR_WINDOWS = '\\';
+    /**
+     * The system directory separator character.
+     */
+    public static final char DIR_SEPARATOR = File.separatorChar;
+    /**
+     * The Unix line separator string.
+     */
+    public static final String LINE_SEPARATOR_UNIX = "\n";
+    /**
+     * The Windows line separator string.
+     */
+    public static final String LINE_SEPARATOR_WINDOWS = "\r\n";
+    /**
+     * The system line separator string.
+     */
+    public static final String LINE_SEPARATOR;
+    static {
+        // avoid security issues
+        StringWriter buf = new StringWriter(4);
+        PrintWriter out = new PrintWriter(buf);
+        out.println();
+        LINE_SEPARATOR = buf.toString();
+    }
+
+    /**
+     * The default buffer size to use.
+     */
+    private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
+
+    /**
+     * Instances should NOT be constructed in standard programming.
+     */
+    public IOUtils() {
+        super();
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Unconditionally close an <code>Reader</code>.
+     * <p>
+     * Equivalent to {@link Reader#close()}, except any exceptions will be ignored.
+     * This is typically used in finally blocks.
+     *
+     * @param input  the Reader to close, may be null or already closed
+     */
+    public static void closeQuietly(Reader input) {
+        try {
+            if (input != null) {
+                input.close();
+            }
+        } catch (IOException ioe) {
+            // ignore
+        }
+    }
+
+    /**
+     * Unconditionally close a <code>Writer</code>.
+     * <p>
+     * Equivalent to {@link Writer#close()}, except any exceptions will be ignored.
+     * This is typically used in finally blocks.
+     *
+     * @param output  the Writer to close, may be null or already closed
+     */
+    public static void closeQuietly(Writer output) {
+        try {
+            if (output != null) {
+                output.close();
+            }
+        } catch (IOException ioe) {
+            // ignore
+        }
+    }
+
+    /**
+     * Unconditionally close an <code>InputStream</code>.
+     * <p>
+     * Equivalent to {@link InputStream#close()}, except any exceptions will be ignored.
+     * This is typically used in finally blocks.
+     *
+     * @param input  the InputStream to close, may be null or already closed
+     */
+    public static void closeQuietly(InputStream input) {
+        try {
+            if (input != null) {
+                input.close();
+            }
+        } catch (IOException ioe) {
+            // ignore
+        }
+    }
+
+    /**
+     * Unconditionally close an <code>OutputStream</code>.
+     * <p>
+     * Equivalent to {@link OutputStream#close()}, except any exceptions will be ignored.
+     * This is typically used in finally blocks.
+     *
+     * @param output  the OutputStream to close, may be null or already closed
+     */
+    public static void closeQuietly(OutputStream output) {
+        try {
+            if (output != null) {
+                output.close();
+            }
+        } catch (IOException ioe) {
+            // ignore
+        }
+    }
+
+    // read toByteArray
+    //-----------------------------------------------------------------------
+    /**
+     * Get the contents of an <code>InputStream</code> as a <code>byte[]</code>.
+     * <p>
+     * This method buffers the input internally, so there is no need to use a
+     * <code>BufferedInputStream</code>.
+     *
+     * @param input  the <code>InputStream</code> to read from
+     * @return the requested byte array
+     * @throws NullPointerException if the input is null
+     * @throws IOException if an I/O error occurs
+     */
+    public static byte[] toByteArray(InputStream input) throws IOException {
+        ByteArrayOutputStream output = new ByteArrayOutputStream();
+        copy(input, output);
+        return output.toByteArray();
+    }
+
+    /**
+     * Get the contents of a <code>Reader</code> as a <code>byte[]</code>
+     * using the default character encoding of the platform.
+     * <p>
+     * This method buffers the input internally, so there is no need to use a
+     * <code>BufferedReader</code>.
+     *
+     * @param input  the <code>Reader</code> to read from
+     * @return the requested byte array
+     * @throws NullPointerException if the input is null
+     * @throws IOException if an I/O error occurs
+     */
+    public static byte[] toByteArray(Reader input) throws IOException {
+        ByteArrayOutputStream output = new ByteArrayOutputStream();
+        copy(input, output);
+        return output.toByteArray();
+    }
+
+    /**
+     * Get the contents of a <code>Reader</code> as a <code>byte[]</code>
+     * using the specified character encoding.
+     * <p>
+     * Character encoding names can be found at
+     * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
+     * <p>
+     * This method buffers the input internally, so there is no need to use a
+     * <code>BufferedReader</code>.
+     *
+     * @param input  the <code>Reader</code> to read from
+     * @param encoding  the encoding to use, null means platform default
+     * @return the requested byte array
+     * @throws NullPointerException if the input is null
+     * @throws IOException if an I/O error occurs
+     * @since Commons IO 1.1
+     */
+    public static byte[] toByteArray(Reader input, String encoding)
+            throws IOException {
+        ByteArrayOutputStream output = new ByteArrayOutputStream();
+        copy(input, output, encoding);
+        return output.toByteArray();
+    }
+
+    /**
+     * Get the contents of a <code>String</code> as a <code>byte[]</code>
+     * using the default character encoding of the platform.
+     * <p>
+     * This is the same as {@link String#getBytes()}.
+     *
+     * @param input  the <code>String</code> to convert
+     * @return the requested byte array
+     * @throws NullPointerException if the input is null
+     * @throws IOException if an I/O error occurs (never occurs)
+     * @deprecated Use {@link String#getBytes()}
+     */
+    public static byte[] toByteArray(String input) throws IOException {
+        return input.getBytes();
+    }
+
+    // read char[]
+    //-----------------------------------------------------------------------
+    /**
+     * Get the contents of an <code>InputStream</code> as a character array
+     * using the default character encoding of the platform.
+     * <p>
+     * This method buffers the input internally, so there is no need to use a
+     * <code>BufferedInputStream</code>.
+     *
+     * @param is  the <code>InputStream</code> to read from
+     * @return the requested character array
+     * @throws NullPointerException if the input is null
+     * @throws IOException if an I/O error occurs
+     * @since Commons IO 1.1
+     */
+    public static char[] toCharArray(InputStream is) throws IOException {
+        CharArrayWriter output = new CharArrayWriter();
+        copy(is, output);
+        return output.toCharArray();
+    }
+
+    /**
+     * Get the contents of an <code>InputStream</code> as a character array
+     * using the specified character encoding.
+     * <p>
+     * Character encoding names can be found at
+     * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
+     * <p>
+     * This method buffers the input internally, so there is no need to use a
+     * <code>BufferedInputStream</code>.
+     *
+     * @param is  the <code>InputStream</code> to read from
+     * @param encoding  the encoding to use, null means platform default
+     * @return the requested character array
+     * @throws NullPointerException if the input is null
+     * @throws IOException if an I/O error occurs
+     * @since Commons IO 1.1
+     */
+    public static char[] toCharArray(InputStream is, String encoding)
+            throws IOException {
+        CharArrayWriter output = new CharArrayWriter();
+        copy(is, output, encoding);
+        return output.toCharArray();
+    }
+
+    /**
+     * Get the contents of a <code>Reader</code> as a character array.
+     * <p>
+     * This method buffers the input internally, so there is no need to use a
+     * <code>BufferedReader</code>.
+     *
+     * @param input  the <code>Reader</code> to read from
+     * @return the requested character array
+     * @throws NullPointerException if the input is null
+     * @throws IOException if an I/O error occurs
+     * @since Commons IO 1.1
+     */
+    public static char[] toCharArray(Reader input) throws IOException {
+        CharArrayWriter sw = new CharArrayWriter();
+        copy(input, sw);
+        return sw.toCharArray();
+    }
+
+    // read toString
+    //-----------------------------------------------------------------------
+    /**
+     * Get the contents of an <code>InputStream</code> as a String
+     * using the default character encoding of the platform.
+     * <p>
+     * This method buffers the input internally, so there is no need to use a
+     * <code>BufferedInputStream</code>.
+     *
+     * @param input  the <code>InputStream</code> to read from
+     * @return the requested String
+     * @throws NullPointerException if the input is null
+     * @throws IOException if an I/O error occurs
+     */
+    public static String toString(InputStream input) throws IOException {
+        StringWriter sw = new StringWriter();
+        copy(input, sw);
+        return sw.toString();
+    }
+
+    /**
+     * Get the contents of an <code>InputStream</code> as a String
+     * using the specified character encoding.
+     * <p>
+     * Character encoding names can be found at
+     * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
+     * <p>
+     * This method buffers the input internally, so there is no need to use a
+     * <code>BufferedInputStream</code>.
+     *
+     * @param input  the <code>InputStream</code> to read from
+     * @param encoding  the encoding to use, null means platform default
+     * @return the requested String
+     * @throws NullPointerException if the input is null
+     * @throws IOException if an I/O error occurs
+     */
+    public static String toString(InputStream input, String encoding)
+            throws IOException {
+        StringWriter sw = new StringWriter();
+        copy(input, sw, encoding);
+        return sw.toString();
+    }
+
+    /**
+     * Get the contents of a <code>Reader</code> as a String.
+     * <p>
+     * This method buffers the input internally, so there is no need to use a
+     * <code>BufferedReader</code>.
+     *
+     * @param input  the <code>Reader</code> to read from
+     * @return the requested String
+     * @throws NullPointerException if the input is null
+     * @throws IOException if an I/O error occurs
+     */
+    public static String toString(Reader input) throws IOException {
+        StringWriter sw = new StringWriter();
+        copy(input, sw);
+        return sw.toString();
+    }
+
+    /**
+     * Get the contents of a <code>byte[]</code> as a String
+     * using the default character encoding of the platform.
+     *
+     * @param input the byte array to read from
+     * @return the requested String
+     * @throws NullPointerException if the input is null
+     * @throws IOException if an I/O error occurs (never occurs)
+     * @deprecated Use {@link String#String(byte[])}
+     */
+    public static String toString(byte[] input) throws IOException {
+        return new String(input);
+    }
+
+    /**
+     * Get the contents of a <code>byte[]</code> as a String
+     * using the specified character encoding.
+     * <p>
+     * Character encoding names can be found at
+     * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
+     *
+     * @param input the byte array to read from
+     * @param encoding  the encoding to use, null means platform default
+     * @return the requested String
+     * @throws NullPointerException if the input is null
+     * @throws IOException if an I/O error occurs (never occurs)
+     * @deprecated Use {@link String#String(byte[],String)}
+     */
+    public static String toString(byte[] input, String encoding)
+            throws IOException {
+        if (encoding == null) {
+            return new String(input);
+        } else {
+            return new String(input, encoding);
+        }
+    }
+
+    // readLines
+    //-----------------------------------------------------------------------
+    /**
+     * Get the contents of an <code>InputStream</code> as a list of Strings,
+     * one entry per line, using the default character encoding of the platform.
+     * <p>
+     * This method buffers the input internally, so there is no need to use a
+     * <code>BufferedInputStream</code>.
+     *
+     * @param input  the <code>InputStream</code> to read from, not null
+     * @return the list of Strings, never null
+     * @throws NullPointerException if the input is null
+     * @throws IOException if an I/O error occurs
+     * @since Commons IO 1.1
+     */
+    public static List readLines(InputStream input) throws IOException {
+        InputStreamReader reader = new InputStreamReader(input);
+        return readLines(reader);
+    }
+
+    /**
+     * Get the contents of an <code>InputStream</code> as a list of Strings,
+     * one entry per line, using the specified character encoding.
+     * <p>
+     * Character encoding names can be found at
+     * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
+     * <p>
+     * This method buffers the input internally, so there is no need to use a
+     * <code>BufferedInputStream</code>.
+     *
+     * @param input  the <code>InputStream</code> to read from, not null
+     * @param encoding  the encoding to use, null means platform default
+     * @return the list of Strings, never null
+     * @throws NullPointerException if the input is null
+     * @throws IOException if an I/O error occurs
+     * @since Commons IO 1.1
+     */
+    public static List readLines(InputStream input, String encoding) throws IOException {
+        if (encoding == null) {
+            return readLines(input);
+        } else {
+            InputStreamReader reader = new InputStreamReader(input, encoding);
+            return readLines(reader);
+        }
+    }
+
+    /**
+     * Get the contents of a <code>Reader</code> as a list of Strings,
+     * one entry per line.
+     * <p>
+     * This method buffers the input internally, so there is no need to use a
+     * <code>BufferedReader</code>.
+     *
+     * @param input  the <code>Reader</code> to read from, not null
+     * @return the list of Strings, never null
+     * @throws NullPointerException if the input is null
+     * @throws IOException if an I/O error occurs
+     * @since Commons IO 1.1
+     */
+    public static List readLines(Reader input) throws IOException {
+        BufferedReader reader = new BufferedReader(input);
+        List list = new ArrayList();
+        String line = reader.readLine();
+        while (line != null) {
+            list.add(line);
+            line = reader.readLine();
+        }
+        return list;
+    }
+
+
+
+
+
+    //-----------------------------------------------------------------------
+    /**
+     * Convert the specified string to an input stream, encoded as bytes
+     * using the default character encoding of the platform.
+     *
+     * @param input the string to convert
+     * @return an input stream
+     * @since Commons IO 1.1
+     */
+    public static InputStream toInputStream(String input) {
+        byte[] bytes = input.getBytes();
+        return new ByteArrayInputStream(bytes);
+    }
+
+    /**
+     * Convert the specified string to an input stream, encoded as bytes
+     * using the specified character encoding.
+     * <p>
+     * Character encoding names can be found at
+     * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
+     *
+     * @param input the string to convert
+     * @param encoding the encoding to use, null means platform default
+     * @throws IOException if the encoding is invalid
+     * @return an input stream
+     * @since Commons IO 1.1
+     */
+    public static InputStream toInputStream(String input, String encoding) throws IOException {
+        byte[] bytes = encoding != null ? input.getBytes(encoding) : input.getBytes();
+        return new ByteArrayInputStream(bytes);
+    }
+
+    // write byte[]
+    //-----------------------------------------------------------------------
+    /**
+     * Writes bytes from a <code>byte[]</code> to an <code>OutputStream</code>.
+     *
+     * @param data  the byte array to write, do not modify during output,
+     * null ignored
+     * @param output  the <code>OutputStream</code> to write to
+     * @throws NullPointerException if output is null
+     * @throws IOException if an I/O error occurs
+     * @since Commons IO 1.1
+     */
+    public static void write(byte[] data, OutputStream output)
+            throws IOException {
+        if (data != null) {
+            output.write(data);
+        }
+    }
+
+    /**
+     * Writes bytes from a <code>byte[]</code> to chars on a <code>Writer</code>
+     * using the default character encoding of the platform.
+     * <p>
+     * This method uses {@link String#String(byte[])}.
+     *
+     * @param data  the byte array to write, do not modify during output,
+     * null ignored
+     * @param output  the <code>Writer</code> to write to
+     * @throws NullPointerException if output is null
+     * @throws IOException if an I/O error occurs
+     * @since Commons IO 1.1
+     */
+    public static void write(byte[] data, Writer output) throws IOException {
+        if (data != null) {
+            output.write(new String(data));
+        }
+    }
+
+    /**
+     * Writes bytes from a <code>byte[]</code> to chars on a <code>Writer</code>
+     * using the specified character encoding.
+     * <p>
+     * Character encoding names can be found at
+     * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
+     * <p>
+     * This method uses {@link String#String(byte[], String)}.
+     *
+     * @param data  the byte array to write, do not modify during output,
+     * null ignored
+     * @param output  the <code>Writer</code> to write to
+     * @param encoding  the encoding to use, null means platform default
+     * @throws NullPointerException if output is null
+     * @throws IOException if an I/O error occurs
+     * @since Commons IO 1.1
+     */
+    public static void write(byte[] data, Writer output, String encoding)
+            throws IOException {
+        if (data != null) {
+            if (encoding == null) {
+                write(data, output);
+            } else {
+                output.write(new String(data, encoding));
+            }
+        }
+    }
+
+    // write char[]
+    //-----------------------------------------------------------------------
+    /**
+     * Writes chars from a <code>char[]</code> to a <code>Writer</code>
+     * using the default character encoding of the platform.
+     *
+     * @param data  the char array to write, do not modify during output,
+     * null ignored
+     * @param output  the <code>Writer</code> to write to
+     * @throws NullPointerException if output is null
+     * @throws IOException if an I/O error occurs
+     * @since Commons IO 1.1
+     */
+    public static void write(char[] data, Writer output) throws IOException {
+        if (data != null) {
+            output.write(data);
+        }
+    }
+
+    /**
+     * Writes chars from a <code>char[]</code> to bytes on an
+     * <code>OutputStream</code>.
+     * <p>
+     * This method uses {@link String#String(char[])} and
+     * {@link String#getBytes()}.
+     *
+     * @param data  the char array to write, do not modify during output,
+     * null ignored
+     * @param output  the <code>OutputStream</code> to write to
+     * @throws NullPointerException if output is null
+     * @throws IOException if an I/O error occurs
+     * @since Commons IO 1.1
+     */
+    public static void write(char[] data, OutputStream output)
+            throws IOException {
+        if (data != null) {
+            output.write(new String(data).getBytes());
+        }
+    }
+
+    /**
+     * Writes chars from a <code>char[]</code> to bytes on an
+     * <code>OutputStream</code> using the specified character encoding.
+     * <p>
+     * Character encoding names can be found at
+     * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
+     * <p>
+     * This method uses {@link String#String(char[])} and
+     * {@link String#getBytes(String)}.
+     *
+     * @param data  the char array to write, do not modify during output,
+     * null ignored
+     * @param output  the <code>OutputStream</code> to write to
+     * @param encoding  the encoding to use, null means platform default
+     * @throws NullPointerException if output is null
+     * @throws IOException if an I/O error occurs
+     * @since Commons IO 1.1
+     */
+    public static void write(char[] data, OutputStream output, String encoding)
+            throws IOException {
+        if (data != null) {
+            if (encoding == null) {
+                write(data, output);
+            } else {
+                output.write(new String(data).getBytes(encoding));
+            }
+        }
+    }
+
+    // write String
+    //-----------------------------------------------------------------------
+    /**
+     * Writes chars from a <code>String</code> to a <code>Writer</code>.
+     *
+     * @param data  the <code>String</code> to write, null ignored
+     * @param output  the <code>Writer</code> to write to
+     * @throws NullPointerException if output is null
+     * @throws IOException if an I/O error occurs
+     * @since Commons IO 1.1
+     */
+    public static void write(String data, Writer output) throws IOException {
+        if (data != null) {
+            output.write(data);
+        }
+    }
+
+    /**
+     * Writes chars from a <code>String</code> to bytes on an
+     * <code>OutputStream</code> using the default character encoding of the
+     * platform.
+     * <p>
+     * This method uses {@link String#getBytes()}.
+     *
+     * @param data  the <code>String</code> to write, null ignored
+     * @param output  the <code>OutputStream</code> to write to
+     * @throws NullPointerException if output is null
+     * @throws IOException if an I/O error occurs
+     * @since Commons IO 1.1
+     */
+    public static void write(String data, OutputStream output)
+            throws IOException {
+        if (data != null) {
+            output.write(data.getBytes());
+        }
+    }
+
+    /**
+     * Writes chars from a <code>String</code> to bytes on an
+     * <code>OutputStream</code> using the specified character encoding.
+     * <p>
+     * Character encoding names can be found at
+     * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
+     * <p>
+     * This method uses {@link String#getBytes(String)}.
+     *
+     * @param data  the <code>String</code> to write, null ignored
+     * @param output  the <code>OutputStream</code> to write to
+     * @param encoding  the encoding to use, null means platform default
+     * @throws NullPointerException if output is null
+     * @throws IOException if an I/O error occurs
+     * @since Commons IO 1.1
+     */
+    public static void write(String data, OutputStream output, String encoding)
+            throws IOException {
+        if (data != null) {
+            if (encoding == null) {
+                write(data, output);
+            } else {
+                output.write(data.getBytes(encoding));
+            }
+        }
+    }
+
+    // write StringBuffer
+    //-----------------------------------------------------------------------
+    /**
+     * Writes chars from a <code>StringBuffer</code> to a <code>Writer</code>.
+     *
+     * @param data  the <code>StringBuffer</code> to write, null ignored
+     * @param output  the <code>Writer</code> to write to
+     * @throws NullPointerException if output is null
+     * @throws IOException if an I/O error occurs
+     * @since Commons IO 1.1
+     */
+    public static void write(StringBuffer data, Writer output)
+            throws IOException {
+        if (data != null) {
+            output.write(data.toString());
+        }
+    }
+
+    /**
+     * Writes chars from a <code>StringBuffer</code> to bytes on an
+     * <code>OutputStream</code> using the default character encoding of the
+     * platform.
+     * <p>
+     * This method uses {@link String#getBytes()}.
+     *
+     * @param data  the <code>StringBuffer</code> to write, null ignored
+     * @param output  the <code>OutputStream</code> to write to
+     * @throws NullPointerException if output is null
+     * @throws IOException if an I/O error occurs
+     * @since Commons IO 1.1
+     */
+    public static void write(StringBuffer data, OutputStream output)
+            throws IOException {
+        if (data != null) {
+            output.write(data.toString().getBytes());
+        }
+    }
+
+    /**
+     * Writes chars from a <code>StringBuffer</code> to bytes on an
+     * <code>OutputStream</code> using the specified character encoding.
+     * <p>
+     * Character encoding names can be found at
+     * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
+     * <p>
+     * This method uses {@link String#getBytes(String)}.
+     *
+     * @param data  the <code>StringBuffer</code> to write, null ignored
+     * @param output  the <code>OutputStream</code> to write to
+     * @param encoding  the encoding to use, null means platform default
+     * @throws NullPointerException if output is null
+     * @throws IOException if an I/O error occurs
+     * @since Commons IO 1.1
+     */
+    public static void write(StringBuffer data, OutputStream output,
+            String encoding) throws IOException {
+        if (data != null) {
+            if (encoding == null) {
+                write(data, output);
+            } else {
+                output.write(data.toString().getBytes(encoding));
+            }
+        }
+    }
+
+    // writeLines
+    //-----------------------------------------------------------------------
+    /**
+     * Writes the <code>toString()</code> value of each item in a collection to
+     * an <code>OutputStream</code> line by line, using the default character
+     * encoding of the platform and the specified line ending.
+     *
+     * @param lines  the lines to write, null entries produce blank lines
+     * @param lineEnding  the line separator to use, null is system default
+     * @param output  the <code>OutputStream</code> to write to, not null, not closed
+     * @throws NullPointerException if the output is null
+     * @throws IOException if an I/O error occurs
+     * @since Commons IO 1.1
+     */
+    public static void writeLines(Collection lines, String lineEnding,
+            OutputStream output) throws IOException {
+        if (lines == null) {
+            return;
+        }
+        if (lineEnding == null) {
+            lineEnding = LINE_SEPARATOR;
+        }
+        for (Iterator it = lines.iterator(); it.hasNext(); ) {
+            Object line = it.next();
+            if (line != null) {
+                output.write(line.toString().getBytes());
+            }
+            output.write(lineEnding.getBytes());
+        }
+    }
+
+    /**
+     * Writes the <code>toString()</code> value of each item in a collection to
+     * an <code>OutputStream</code> line by line, using the specified character
+     * encoding and the specified line ending.
+     * <p>
+     * Character encoding names can be found at
+     * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
+     *
+     * @param lines  the lines to write, null entries produce blank lines
+     * @param lineEnding  the line separator to use, null is system default
+     * @param output  the <code>OutputStream</code> to write to, not null, not closed
+     * @param encoding  the encoding to use, null means platform default
+     * @throws NullPointerException if the output is null
+     * @throws IOException if an I/O error occurs
+     * @since Commons IO 1.1
+     */
+    public static void writeLines(Collection lines, String lineEnding,
+            OutputStream output, String encoding) throws IOException {
+        if (encoding == null) {
+            writeLines(lines, lineEnding, output);
+        } else {
+            if (lines == null) {
+                return;
+            }
+            if (lineEnding == null) {
+                lineEnding = LINE_SEPARATOR;
+            }
+            for (Iterator it = lines.iterator(); it.hasNext(); ) {
+                Object line = it.next();
+                if (line != null) {
+                    output.write(line.toString().getBytes(encoding));
+                }
+                output.write(lineEnding.getBytes(encoding));
+            }
+        }
+    }
+
+    /**
+     * Writes the <code>toString()</code> value of each item in a collection to
+     * a <code>Writer</code> line by line, using the specified line ending.
+     *
+     * @param lines  the lines to write, null entries produce blank lines
+     * @param lineEnding  the line separator to use, null is system default
+     * @param writer  the <code>Writer</code> to write to, not null, not closed
+     * @throws NullPointerException if the input is null
+     * @throws IOException if an I/O error occurs
+     * @since Commons IO 1.1
+     */
+    public static void writeLines(Collection lines, String lineEnding,
+            Writer writer) throws IOException {
+        if (lines == null) {
+            return;
+        }
+        if (lineEnding == null) {
+            lineEnding = LINE_SEPARATOR;
+        }
+        for (Iterator it = lines.iterator(); it.hasNext(); ) {
+            Object line = it.next();
+            if (line != null) {
+                writer.write(line.toString());
+            }
+            writer.write(lineEnding);
+        }
+    }
+
+    // copy from InputStream
+    //-----------------------------------------------------------------------
+    /**
+     * Copy bytes from an <code>InputStream</code> to an
+     * <code>OutputStream</code>.
+     * <p>
+     * This method buffers the input internally, so there is no need to use a
+     * <code>BufferedInputStream</code>.
+     * <p>
+     * Large streams (over 2GB) will return a bytes copied value of
+     * <code>-1</code> after the copy has completed since the correct
+     * number of bytes cannot be returned as an int. For large streams
+     * use the <code>copyLarge(InputStream, OutputStream)</code> method.
+     *
+     * @param input  the <code>InputStream</code> to read from
+     * @param output  the <code>OutputStream</code> to write to
+     * @return the number of bytes copied
+     * @throws NullPointerException if the input or output is null
+     * @throws IOException if an I/O error occurs
+     * @throws ArithmeticException if the byte count is too large
+     * @since Commons IO 1.1
+     */
+    public static int copy(InputStream input, OutputStream output) throws IOException {
+        long count = copyLarge(input, output);
+        if (count > Integer.MAX_VALUE) {
+            return -1;
+        }
+        return (int) count;
+    }
+
+    /**
+     * Copy bytes from a large (over 2GB) <code>InputStream</code> to an
+     * <code>OutputStream</code>.
+     * <p>
+     * This method buffers the input internally, so there is no need to use a
+     * <code>BufferedInputStream</code>.
+     *
+     * @param input  the <code>InputStream</code> to read from
+     * @param output  the <code>OutputStream</code> to write to
+     * @return the number of bytes copied
+     * @throws NullPointerException if the input or output is null
+     * @throws IOException if an I/O error occurs
+     * @since Commons IO 1.3
+     */
+    public static long copyLarge(InputStream input, OutputStream output)
+            throws IOException {
+        byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
+        long count = 0;
+        int n = 0;
+        while (-1 != (n = input.read(buffer))) {
+            output.write(buffer, 0, n);
+            count += n;
+        }
+        return count;
+    }
+
+    /**
+     * Copy bytes from an <code>InputStream</code> to chars on a
+     * <code>Writer</code> using the default character encoding of the platform.
+     * <p>
+     * This method buffers the input internally, so there is no need to use a
+     * <code>BufferedInputStream</code>.
+     * <p>
+     * This method uses {@link InputStreamReader}.
+     *
+     * @param input  the <code>InputStream</code> to read from
+     * @param output  the <code>Writer</code> to write to
+     * @throws NullPointerException if the input or output is null
+     * @throws IOException if an I/O error occurs
+     * @since Commons IO 1.1
+     */
+    public static void copy(InputStream input, Writer output)
+            throws IOException {
+        InputStreamReader in = new InputStreamReader(input);
+        copy(in, output);
+    }
+
+    /**
+     * Copy bytes from an <code>InputStream</code> to chars on a
+     * <code>Writer</code> using the specified character encoding.
+     * <p>
+     * This method buffers the input internally, so there is no need to use a
+     * <code>BufferedInputStream</code>.
+     * <p>
+     * Character encoding names can be found at
+     * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
+     * <p>
+     * This method uses {@link InputStreamReader}.
+     *
+     * @param input  the <code>InputStream</code> to read from
+     * @param output  the <code>Writer</code> to write to
+     * @param encoding  the encoding to use, null means platform default
+     * @throws NullPointerException if the input or output is null
+     * @throws IOException if an I/O error occurs
+     * @since Commons IO 1.1
+     */
+    public static void copy(InputStream input, Writer output, String encoding)
+            throws IOException {
+        if (encoding == null) {
+            copy(input, output);
+        } else {
+            InputStreamReader in = new InputStreamReader(input, encoding);
+            copy(in, output);
+        }
+    }
+
+    // copy from Reader
+    //-----------------------------------------------------------------------
+    /**
+     * Copy chars from a <code>Reader</code> to a <code>Writer</code>.
+     * <p>
+     * This method buffers the input internally, so there is no need to use a
+     * <code>BufferedReader</code>.
+     * <p>
+     * Large streams (over 2GB) will return a chars copied value of
+     * <code>-1</code> after the copy has completed since the correct
+     * number of chars cannot be returned as an int. For large streams
+     * use the <code>copyLarge(Reader, Writer)</code> method.
+     *
+     * @param input  the <code>Reader</code> to read from
+     * @param output  the <code>Writer</code> to write to
+     * @return the number of characters copied
+     * @throws NullPointerException if the input or output is null
+     * @throws IOException if an I/O error occurs
+     * @throws ArithmeticException if the character count is too large
+     * @since Commons IO 1.1
+     */
+    public static int copy(Reader input, Writer output) throws IOException {
+        long count = copyLarge(input, output);
+        if (count > Integer.MAX_VALUE) {
+            return -1;
+        }
+        return (int) count;
+    }
+
+    /**
+     * Copy chars from a large (over 2GB) <code>Reader</code> to a <code>Writer</code>.
+     * <p>
+     * This method buffers the input internally, so there is no need to use a
+     * <code>BufferedReader</code>.
+     *
+     * @param input  the <code>Reader</code> to read from
+     * @param output  the <code>Writer</code> to write to
+     * @return the number of characters copied
+     * @throws NullPointerException if the input or output is null
+     * @throws IOException if an I/O error occurs
+     * @since Commons IO 1.3
+     */
+    public static long copyLarge(Reader input, Writer output) throws IOException {
+        char[] buffer = new char[DEFAULT_BUFFER_SIZE];
+        long count = 0;
+        int n = 0;
+        while (-1 != (n = input.read(buffer))) {
+            output.write(buffer, 0, n);
+            count += n;
+        }
+        return count;
+    }
+
+    /**
+     * Copy chars from a <code>Reader</code> to bytes on an
+     * <code>OutputStream</code> using the default character encoding of the
+     * platform, and calling flush.
+     * <p>
+     * This method buffers the input internally, so there is no need to use a
+     * <code>BufferedReader</code>.
+     * <p>
+     * Due to the implementation of OutputStreamWriter, this method performs a
+     * flush.
+     * <p>
+     * This method uses {@link OutputStreamWriter}.
+     *
+     * @param input  the <code>Reader</code> to read from
+     * @param output  the <code>OutputStream</code> to write to
+     * @throws NullPointerException if the input or output is null
+     * @throws IOException if an I/O error occurs
+     * @since Commons IO 1.1
+     */
+    public static void copy(Reader input, OutputStream output)
+            throws IOException {
+        OutputStreamWriter out = new OutputStreamWriter(output);
+        copy(input, out);
+        // XXX Unless anyone is planning on rewriting OutputStreamWriter, we
+        // have to flush here.
+        out.flush();
+    }
+
+    /**
+     * Copy chars from a <code>Reader</code> to bytes on an
+     * <code>OutputStream</code> using the specified character encoding, and
+     * calling flush.
+     * <p>
+     * This method buffers the input internally, so there is no need to use a
+     * <code>BufferedReader</code>.
+     * <p>
+     * Character encoding names can be found at
+     * <a href="http://www.iana.org/assignments/character-sets">IANA</a>.
+     * <p>
+     * Due to the implementation of OutputStreamWriter, this method performs a
+     * flush.
+     * <p>
+     * This method uses {@link OutputStreamWriter}.
+     *
+     * @param input  the <code>Reader</code> to read from
+     * @param output  the <code>OutputStream</code> to write to
+     * @param encoding  the encoding to use, null means platform default
+     * @throws NullPointerException if the input or output is null
+     * @throws IOException if an I/O error occurs
+     * @since Commons IO 1.1
+     */
+    public static void copy(Reader input, OutputStream output, String encoding)
+            throws IOException {
+        if (encoding == null) {
+            copy(input, output);
+        } else {
+            OutputStreamWriter out = new OutputStreamWriter(output, encoding);
+            copy(input, out);
+            // XXX Unless anyone is planning on rewriting OutputStreamWriter,
+            // we have to flush here.
+            out.flush();
+        }
+    }
+
+    // content equals
+    //-----------------------------------------------------------------------
+    /**
+     * Compare the contents of two Streams to determine if they are equal or
+     * not.
+     * <p>
+     * This method buffers the input internally using
+     * <code>BufferedInputStream</code> if they are not already buffered.
+     *
+     * @param input1  the first stream
+     * @param input2  the second stream
+     * @return true if the content of the streams are equal or they both don't
+     * exist, false otherwise
+     * @throws NullPointerException if either input is null
+     * @throws IOException if an I/O error occurs
+     */
+    public static boolean contentEquals(InputStream input1, InputStream input2)
+            throws IOException {
+        if (!(input1 instanceof BufferedInputStream)) {
+            input1 = new BufferedInputStream(input1);
+        }
+        if (!(input2 instanceof BufferedInputStream)) {
+            input2 = new BufferedInputStream(input2);
+        }
+
+        int ch = input1.read();
+        while (-1 != ch) {
+            int ch2 = input2.read();
+            if (ch != ch2) {
+                return false;
+            }
+            ch = input1.read();
+        }
+
+        int ch2 = input2.read();
+        return (ch2 == -1);
+    }
+
+    /**
+     * Compare the contents of two Readers to determine if they are equal or
+     * not.
+     * <p>
+     * This method buffers the input internally using
+     * <code>BufferedReader</code> if they are not already buffered.
+     *
+     * @param input1  the first reader
+     * @param input2  the second reader
+     * @return true if the content of the readers are equal or they both don't
+     * exist, false otherwise
+     * @throws NullPointerException if either input is null
+     * @throws IOException if an I/O error occurs
+     * @since Commons IO 1.1
+     */
+    public static boolean contentEquals(Reader input1, Reader input2)
+            throws IOException {
+        if (!(input1 instanceof BufferedReader)) {
+            input1 = new BufferedReader(input1);
+        }
+        if (!(input2 instanceof BufferedReader)) {
+            input2 = new BufferedReader(input2);
+        }
+
+        int ch = input1.read();
+        while (-1 != ch) {
+            int ch2 = input2.read();
+            if (ch != ch2) {
+                return false;
+            }
+            ch = input1.read();
+        }
+
+        int ch2 = input2.read();
+        return (ch2 == -1);
+    }
+
+}
+

Modified: labs/jbossrules/trunk/drools-repository/src/test/java/org/drools/repository/PackageItemTest.java
===================================================================
--- labs/jbossrules/trunk/drools-repository/src/test/java/org/drools/repository/PackageItemTest.java	2009-03-17 03:40:32 UTC (rev 25678)
+++ labs/jbossrules/trunk/drools-repository/src/test/java/org/drools/repository/PackageItemTest.java	2009-03-17 05:00:38 UTC (rev 25679)
@@ -550,14 +550,14 @@
             AssetItem ruleItem2 = rulePackageItem1.addAsset("testRemoveRule2", "test lhs content");
 
             //remove the rule, make sure the other rule in the pacakge stays around
-            rulePackageItem1.removeAsset(ruleItem1.getName());
+            rulePackageItem1.loadAsset(ruleItem1.getName()).remove();
             rulePackageItem1.rulesRepository.save();
             rules = iteratorToList(rulePackageItem1.getAssets());
             assertEquals(1, rules.size());
             assertEquals("testRemoveRule2", ((AssetItem)rules.get(0)).getName());
 
             //remove the rule that is following the head revision, make sure the pacakge is now empty
-            rulePackageItem1.removeAsset(ruleItem2.getName());
+            rulePackageItem1.loadAsset(ruleItem2.getName()).remove();
             rules = iteratorToList(rulePackageItem1.getAssets());
             assertNotNull(rules);
             assertEquals(0, rules.size());

Added: labs/jbossrules/trunk/drools-repository/src/test/java/org/drools/repository/events/MockLoadEvent.java
===================================================================
--- labs/jbossrules/trunk/drools-repository/src/test/java/org/drools/repository/events/MockLoadEvent.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-repository/src/test/java/org/drools/repository/events/MockLoadEvent.java	2009-03-17 05:00:38 UTC (rev 25679)
@@ -0,0 +1,16 @@
+package org.drools.repository.events;
+
+import org.drools.repository.AssetItem;
+
+import java.io.InputStream;
+import java.io.ByteArrayInputStream;
+
+/**
+ * @author Michael Neale
+ */
+public class MockLoadEvent implements LoadEvent {
+
+            public InputStream loadContent(AssetItem item) {
+                return new ByteArrayInputStream("hey".getBytes());
+            }
+}

Added: labs/jbossrules/trunk/drools-repository/src/test/java/org/drools/repository/events/MockSaveEvent.java
===================================================================
--- labs/jbossrules/trunk/drools-repository/src/test/java/org/drools/repository/events/MockSaveEvent.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-repository/src/test/java/org/drools/repository/events/MockSaveEvent.java	2009-03-17 05:00:38 UTC (rev 25679)
@@ -0,0 +1,21 @@
+package org.drools.repository.events;
+
+import org.drools.repository.AssetItem;
+import org.drools.repository.PackageItem;
+
+/**
+ * @author Michael Neale
+ */
+public class MockSaveEvent implements SaveEvent {
+    public void onAssetCheckin(AssetItem item) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    public void onAssetDelete(AssetItem item) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    public void onPackageCreate(PackageItem item) {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+}

Added: labs/jbossrules/trunk/drools-repository/src/test/java/org/drools/repository/events/StorageEventManagerTest.java
===================================================================
--- labs/jbossrules/trunk/drools-repository/src/test/java/org/drools/repository/events/StorageEventManagerTest.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-repository/src/test/java/org/drools/repository/events/StorageEventManagerTest.java	2009-03-17 05:00:38 UTC (rev 25679)
@@ -0,0 +1,57 @@
+package org.drools.repository.events;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Michael Neale
+ */
+public class StorageEventManagerTest extends TestCase {
+
+    @Override
+    protected void tearDown() throws Exception {
+        StorageEventManager.le = null;
+        StorageEventManager.se = null;
+    }
+
+    public void testLoadEvent() {
+        System.setProperty("guvnor.loadEventListener", "org.drools.repository.events.MockLoadEvent");
+        LoadEvent le = StorageEventManager.loadEvent();
+        assertNotNull(le);
+        assertTrue(le instanceof MockLoadEvent);
+
+        System.setProperty("guvnor.loadEventListener", "");
+        assertNull(StorageEventManager.loadEvent());
+
+
+        StorageEventManager.le = le;
+        assertNotNull(StorageEventManager.getLoadEvent());
+        assertTrue(StorageEventManager.hasLoadEvent());
+
+        StorageEventManager.le = null;
+        assertFalse(StorageEventManager.hasLoadEvent());
+
+
+    }
+
+
+    public void testSaveEvent() {
+        System.setProperty("guvnor.saveEventListener", "org.drools.repository.events.MockSaveEvent");
+        SaveEvent le = StorageEventManager.saveEvent();
+        assertNotNull(le);
+        assertTrue(le instanceof MockSaveEvent);
+
+        System.setProperty("guvnor.saveEventListener", "");
+        assertNull(StorageEventManager.saveEvent());
+
+
+        StorageEventManager.se = le;
+        assertNotNull(StorageEventManager.getSaveEvent());
+        assertTrue(StorageEventManager.hasSaveEvent());
+
+        StorageEventManager.se = null;
+        assertFalse(StorageEventManager.hasSaveEvent());
+
+
+    }
+
+}




More information about the jboss-svn-commits mailing list