Index: src/edu/ucsb/nceas/metacat/dataone/MNodeService.java
===================================================================
--- src/edu/ucsb/nceas/metacat/dataone/MNodeService.java	(revision 6240)
+++ src/edu/ucsb/nceas/metacat/dataone/MNodeService.java	(revision 6241)
@@ -66,6 +66,8 @@
 import edu.ucsb.nceas.metacat.EventLog;
 import edu.ucsb.nceas.metacat.IdentifierManager;
 import edu.ucsb.nceas.metacat.McdbDocNotFoundException;
+import edu.ucsb.nceas.metacat.properties.PropertyService;
+import edu.ucsb.nceas.utilities.PropertyNotFoundException;
 
 /**
  * Represents Metacat's implementation of the DataONE Member Node 
@@ -83,12 +85,33 @@
   private Logger logMetacat = null;
 
   /**
-   * singleton accessor
+   * Singleton accessor to get an instance of MNodeService.
+   * 
+   * @return instance - the instance of MNodeService
    */
-  public static MNodeService getInstance() 
-  {
+  public static MNodeService getInstance() {
     if (instance == null) {
-      instance = new MNodeService();
+    	String metacatUrl = "";
+      String server;
+      String port;
+      String context;
+      String serviceName;
+      
+      try {
+	      server = PropertyService.getProperty("server.name");
+	      port = PropertyService.getProperty("server.httpPort");
+	      context = PropertyService.getProperty("application.context");
+	      serviceName = PropertyService.getProperty("dataone.serviceName");
+      
+      } catch (PropertyNotFoundException e) {
+        throw new RuntimeException("Error getting the servlet url in MNodeService: " + 
+        	e.getMessage());
+        
+      }
+      metacatUrl = "http://" + server + ":" + port + "/" + context + "/" + serviceName;
+
+      instance = new MNodeService(metacatUrl);
+      
     }
     
     return instance;
@@ -96,46 +119,17 @@
   
   /**
    * Constructor, private for singleton access
+   * 
+   * @param metacatUrl - the URL of the metacat service, including the context
+   *                     and serviceName (/d1)
    */
-  private MNodeService() {
-  	super();
+  private MNodeService(String metacatUrl) {
+  	super(metacatUrl);
     logMetacat = Logger.getLogger(MNodeService.class);
         
   }
     
 	/**
-	 * Adds a new object to the Member Node, where the object is either a data 
-	 * object or a science metadata object. This method is called by clients 
-	 * to create new data objects on Member Nodes
-	 * 
-	 * @param session - the Session object containing the credentials for the Subject
-	 * @param pid - The object identifier to be created
-	 * @param object - the object bytes
-	 * @param sysmeta - the system metadata that describes the object  
-	 * 
-	 * @return pid - the object identifier created
-	 * 
-	 * @throws InvalidToken
-	 * @throws ServiceFailure
-	 * @throws NotAuthorized
-	 * @throws IdentifierNotUnique
-	 * @throws UnsupportedType
-	 * @throws InsufficientResources
-	 * @throws InvalidSystemMetadata
-	 * @throws NotImplemented
-	 * @throws InvalidRequest
-	 */
-  @Override
-	public Identifier create(Session session, Identifier pid, InputStream object,
-	  SystemMetadata sysmeta) 
-    throws InvalidToken, ServiceFailure, NotAuthorized, IdentifierNotUnique, 
-    UnsupportedType, InsufficientResources, InvalidSystemMetadata, 
-    NotImplemented, InvalidRequest {
-
-		return null;
-	}
-
-	/**
 	 * Deletes an object from the Member Node, where the object is either a 
 	 * data object or a science metadata object.
 	 * 
Index: src/edu/ucsb/nceas/metacat/dataone/CNodeService.java
===================================================================
--- src/edu/ucsb/nceas/metacat/dataone/CNodeService.java	(revision 6240)
+++ src/edu/ucsb/nceas/metacat/dataone/CNodeService.java	(revision 6241)
@@ -66,7 +66,9 @@
 import edu.ucsb.nceas.metacat.EventLog;
 import edu.ucsb.nceas.metacat.IdentifierManager;
 import edu.ucsb.nceas.metacat.McdbDocNotFoundException;
+import edu.ucsb.nceas.metacat.properties.PropertyService;
 import edu.ucsb.nceas.metacat.replication.ForceReplicationSystemMetadataHandler;
+import edu.ucsb.nceas.utilities.PropertyNotFoundException;
 
 /**
  * Represents Metacat's implementation of the DataONE Coordinating Node 
@@ -87,20 +89,42 @@
   /**
    * singleton accessor
    */
-  public static CNodeService getInstance() 
-  {
+  public static CNodeService getInstance() { 
     if (instance == null) {
-      instance = new CNodeService();
+    	String metacatUrl = "";
+      String server;
+      String port;
+      String context;
+      String serviceName;
+      
+      try {
+        server = PropertyService.getProperty("server.name");
+        port = PropertyService.getProperty("server.httpPort");
+        context = PropertyService.getProperty("application.context");
+        serviceName = PropertyService.getProperty("dataone.serviceName");
+      
+      } catch (PropertyNotFoundException e) {
+        throw new RuntimeException("Error getting the servlet url in MNodeService: " + 
+        	e.getMessage());
+        
+      }
+      metacatUrl = "http://" + server + ":" + port + "/" + context + "/" + serviceName;
+    
+      instance = new CNodeService(metacatUrl);
+      
     }
-    
+  
     return instance;
   }
   
   /**
    * Constructor, private for singleton access
+   * 
+   * @param metacatUrl - the URL of the metacat service, including the context
+   *                     and serviceName (/d1)
    */
-  private CNodeService() {
-  	super();
+  private CNodeService(String metacatUrl) {
+  	super(metacatUrl);
     logMetacat = Logger.getLogger(CNodeService.class);
         
   }
Index: src/edu/ucsb/nceas/metacat/dataone/D1NodeService.java
===================================================================
--- src/edu/ucsb/nceas/metacat/dataone/D1NodeService.java	(revision 6240)
+++ src/edu/ucsb/nceas/metacat/dataone/D1NodeService.java	(revision 6241)
@@ -29,6 +29,7 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.OutputStream;
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.Calendar;
@@ -42,13 +43,19 @@
 
 import javax.servlet.http.HttpServletRequest;
 
+import org.apache.commons.io.IOUtils;
 import org.apache.log4j.Logger;
+import org.dataone.client.ObjectFormatCache;
+import org.dataone.service.exceptions.IdentifierNotUnique;
+import org.dataone.service.exceptions.InsufficientResources;
 import org.dataone.service.exceptions.InvalidRequest;
+import org.dataone.service.exceptions.InvalidSystemMetadata;
 import org.dataone.service.exceptions.InvalidToken;
 import org.dataone.service.exceptions.NotAuthorized;
 import org.dataone.service.exceptions.NotFound;
 import org.dataone.service.exceptions.NotImplemented;
 import org.dataone.service.exceptions.ServiceFailure;
+import org.dataone.service.exceptions.UnsupportedType;
 import org.dataone.service.types.AccessPolicy;
 import org.dataone.service.types.AccessRule;
 import org.dataone.service.types.Event;
@@ -57,6 +64,7 @@
 import org.dataone.service.types.Log;
 import org.dataone.service.types.LogEntry;
 import org.dataone.service.types.NodeReference;
+import org.dataone.service.types.ObjectFormat;
 import org.dataone.service.types.Permission;
 import org.dataone.service.types.Person;
 import org.dataone.service.types.Session;
@@ -63,6 +71,8 @@
 import org.dataone.service.types.Subject;
 import org.dataone.service.types.SystemMetadata;
 
+import edu.ucsb.nceas.metacat.AccessionNumberException;
+import edu.ucsb.nceas.metacat.DocumentImpl;
 import edu.ucsb.nceas.metacat.EventLog;
 import edu.ucsb.nceas.metacat.IdentifierManager;
 import edu.ucsb.nceas.metacat.McdbDocNotFoundException;
@@ -70,6 +80,8 @@
 import edu.ucsb.nceas.metacat.MetacatHandler;
 import edu.ucsb.nceas.metacat.client.InsufficientKarmaException;
 import edu.ucsb.nceas.metacat.properties.PropertyService;
+import edu.ucsb.nceas.metacat.replication.ForceReplicationHandler;
+import edu.ucsb.nceas.metacat.util.SessionData;
 import edu.ucsb.nceas.utilities.ParseLSIDException;
 import edu.ucsb.nceas.utilities.PropertyNotFoundException;
 
@@ -77,6 +89,9 @@
   
   private static Logger logMetacat = Logger.getLogger(D1NodeService.class);
 
+  /* the metacat URL as a string (including ending /d1 service)*/
+  private String metacatUrl;
+  
   /* reference to the metacat handler */
   private MetacatHandler handler;
   
@@ -83,8 +98,136 @@
   /* parameters set in the incoming request */
   private Hashtable<String, String[]> params;
 
-  /* Methods common to CNCore and MNCore APIs */
+  /**
+   * Constructor - used to set the metacatUrl from a subclass extending D1NodeService
+   * 
+   * @param metacatUrl - the URL of the metacat service, including the ending /d1
+   */
+  public D1NodeService(String metacatUrl) {
+    this.metacatUrl = metacatUrl;
+    
+  }
+  
+  /**
+   * Adds a new object to the Node, where the object is either a data 
+   * object or a science metadata object. This method is called by clients 
+   * to create new data objects on Member Nodes or internally for Coordinating
+   * Nodes
+   * 
+   * @param session - the Session object containing the credentials for the Subject
+   * @param pid - The object identifier to be created
+   * @param object - the object bytes
+   * @param sysmeta - the system metadata that describes the object  
+   * 
+   * @return pid - the object identifier created
+   * 
+   * @throws InvalidToken
+   * @throws ServiceFailure
+   * @throws NotAuthorized
+   * @throws IdentifierNotUnique
+   * @throws UnsupportedType
+   * @throws InsufficientResources
+   * @throws InvalidSystemMetadata
+   * @throws NotImplemented
+   * @throws InvalidRequest
+   */
+  public Identifier create(Session session, Identifier pid, InputStream object,
+    SystemMetadata sysmeta) 
+    throws InvalidToken, ServiceFailure, NotAuthorized, IdentifierNotUnique, 
+    UnsupportedType, InsufficientResources, InvalidSystemMetadata, 
+    NotImplemented, InvalidRequest {
 
+    Identifier resultPid = null;
+    String localId = null;
+    Subject subject = session.getSubject();
+    boolean allowed = false;
+    
+    // be sure the user is authenticated for create()
+    if (subject.getValue() == null || 
+        subject.getValue().toLowerCase().equals("public") ) {
+      throw new NotAuthorized("1100", "The provided identity does not have " +
+        "permission to WRITE to the Member Node.");
+      
+    }
+    
+    // verify that pid == SystemMetadata.getIdentifier()
+    logMetacat.debug("Comparing pid|sysmeta_pid: " + 
+      pid.getValue() + "|" + sysmeta.getIdentifier().getValue());
+    if (!pid.getValue().equals(sysmeta.getIdentifier().getValue())) {
+        throw new InvalidSystemMetadata("1180", 
+            "The supplied system metadata is invalid. " +
+            "The identifier " + pid.getValue() + " does not match identifier" +
+            "in the system metadata identified by " +
+            sysmeta.getIdentifier().getValue() + ".");
+        
+    }
+
+    logMetacat.debug("Checking if identifier exists...");
+    // Check that the identifier does not already exist
+    IdentifierManager im = IdentifierManager.getInstance();
+    if (im.identifierExists(pid.getValue())) {
+        throw new IdentifierNotUnique("1120", 
+          "The requested identifier " + pid.getValue() +
+          " is already used by another object and" +
+          "therefore can not be used for this object. Clients should choose" +
+          "a new identifier that is unique and retry the operation or " +
+          "use CN_crud.reserveIdentifier() to reserve one.");
+        
+    }
+
+    // check for permission
+    try {
+      allowed = isAuthorized(session, pid, Permission.WRITE);
+            
+    } catch (NotFound e) {
+      // The identifier doesn't exist, writing should be fine.
+      allowed = true;
+      
+    }
+    
+    // we have the go ahead
+    if ( allowed ) {
+      
+      // Science metadata (XML) or science data object?
+      // TODO: there are cases where certain object formats are science metadata
+      // but are not XML (netCDF ...).  Handle this.
+      if ( isScienceMetadata(sysmeta) ) {
+        
+        // CASE METADATA:
+      	String objectAsXML = "";
+        try {
+	        objectAsXML = IOUtils.toString(object, "UTF-8");
+	        localId = insertOrUpdateDocument(objectAsXML, pid, session, "insert");
+	        //localId = im.getLocalId(pid.getValue());
+
+        } catch (IOException e) {
+        	String msg = "The Node is unable to create the object. " +
+          "There was a problem converting the object to XML";
+        	logMetacat.info(msg);
+          throw new ServiceFailure("1190", msg + ": " + e.getMessage());
+
+        }
+                    
+      }
+        
+
+    } else {
+        
+      // DEFAULT CASE: DATA (needs to be checked and completed)
+      //localId = insertDataObject(object, pid, session);
+        
+    }
+
+    // setting the resulting identifier failed
+    if (resultPid == null ) {
+      throw new ServiceFailure("1190", "The Node is unable to create the object. " +
+        "The resulting identifier was null.");
+      
+    }
+    
+    return resultPid;
+  }
+
   /**
    * Return the log records associated with a given event between the start and 
    * end dates listed given a particular Subject listed in the Session
@@ -165,7 +308,7 @@
       le.setEntryId(entryid);
       Identifier identifier = new Identifier();
       try {
-        logMetacat.debug("converting docid '" + docid + "' to a guid.");
+        logMetacat.debug("converting docid '" + docid + "' to a pid.");
         if (docid == null || docid.trim().equals("") || docid.trim().equals("null")) {
           continue;
         }
@@ -172,13 +315,13 @@
         docid = docid.substring(0, docid.lastIndexOf("."));
         identifier.setValue(im.getGUID(docid, im.getLatestRevForLocalId(docid)));
       } catch (Exception ex) { 
-        // try to get the guid, if that doesn't
+        // try to get the pid, if that doesn't
         // work, just use the local id
         // throw new ServiceFailure("1030",
-        // "Error getting guid for localId " +
+        // "Error getting pid for localId " +
         // docid + ": " + ex.getMessage());\
 
-        // skip it if the guid can't be found
+        // skip it if the pid can't be found
         continue;
       }
 
@@ -216,11 +359,7 @@
     logMetacat.info("getLogRecords");
     return log;
   }
-  
-  /* End methods common to CNCore and MNCore APIs */
-
-  /* Methods common to CNRead and MNRead APIs */
-  
+    
   /**
    * Return the object identified by the given object identifier
    * 
@@ -394,11 +533,7 @@
     
     return systemMetadata;
   }
-  
-  /* End methods common to CNRead and MNRead APIs */
-
-  /* Methods common to CNAuthorization and MNAuthorization APIs */
-  
+   
   /**
    * Set access for a given object using the object identifier and a Subject
    * under a given Session.
@@ -425,18 +560,18 @@
     // get the subject
     Subject subject = session.getSubject();
     // get the system metadata
-    String guid = pid.getValue();
+    String pidStr = pid.getValue();
     
     // are we allowed to do this?
     if (!isAuthorized(session, pid, Permission.CHANGE_PERMISSION)) {
-      throw new NotAuthorized("4420", "not allowed by " + subject.getValue() + " on " + guid);  
+      throw new NotAuthorized("4420", "not allowed by " + subject.getValue() + " on " + pidStr);  
     }
     
     SystemMetadata systemMetadata = null;
     try {
-      systemMetadata = IdentifierManager.getInstance().getSystemMetadata(guid);
+      systemMetadata = IdentifierManager.getInstance().getSystemMetadata(pidStr);
     } catch (McdbDocNotFoundException e) {
-      throw new NotFound("4400", "No record found for: " + guid);
+      throw new NotFound("4400", "No record found for: " + pid);
     }
         
     // set the access policy
@@ -487,12 +622,12 @@
     }
     
     // get the system metadata
-    String guid = pid.getValue();
+    String pidStr = pid.getValue();
     SystemMetadata systemMetadata = null;
     try {
-      systemMetadata = IdentifierManager.getInstance().getSystemMetadata(guid);
+      systemMetadata = IdentifierManager.getInstance().getSystemMetadata(pidStr);
     } catch (McdbDocNotFoundException e) {
-      throw new NotFound("1800", "No record found for: " + guid);
+      throw new NotFound("1800", "No record found for: " + pid);
     }
     List<AccessRule> allows = systemMetadata.getAccessPolicy().getAllowList();
     for (AccessRule accessRule: allows) {
@@ -508,12 +643,11 @@
     
     // TODO: throw or return?
     if (!allowed) {
-      throw new NotAuthorized("1820", permission + "not allowed on " + guid);
+      throw new NotAuthorized("1820", permission + "not allowed on " + pid);
     }
     return allowed;
+    
   }
-
-  /* End methods common to CNAuthorization and MNAuthorization APIs */
   
   /**
    * parse a logEntry and get the relevant field from it
@@ -550,5 +684,283 @@
     }
   }
   
+  /** 
+   * Determine if a given object should be treated as an XML science metadata
+   * object. 
+   * 
+   * @param sysmeta - the SystemMetadata describing the object
+   * @return true if the object should be treated as science metadata
+   */
+  private boolean isScienceMetadata(SystemMetadata sysmeta) {
+    
+    ObjectFormat objectFormat = null;
+    boolean isScienceMetadata = false;
+    
+    try {
+      objectFormat = ObjectFormatCache.getInstance().getFormat(sysmeta.getObjectFormat().getFmtid());
+      isScienceMetadata = objectFormat.isScienceMetadata();
+      
+    } catch (InvalidRequest e) {
+       logMetacat.debug("There was a problem determining if the object identified by" + 
+         sysmeta.getIdentifier().getValue() + 
+         " is science metadata: " + e.getMessage());
+       
+    } catch (ServiceFailure e) {
+      logMetacat.debug("There was a problem determining if the object identified by" + 
+          sysmeta.getIdentifier().getValue() + 
+          " is science metadata: " + e.getMessage());
+    
+    } catch (NotFound e) {
+      logMetacat.debug("There was a problem determining if the object identified by" + 
+          sysmeta.getIdentifier().getValue() + 
+          " is science metadata: " + e.getMessage());
+    
+    } catch (InsufficientResources e) {
+      logMetacat.debug("There was a problem determining if the object identified by" + 
+          sysmeta.getIdentifier().getValue() + 
+          " is science metadata: " + e.getMessage());
+    
+    } catch (NotImplemented e) {
+      logMetacat.debug("There was a problem determining if the object identified by" + 
+          sysmeta.getIdentifier().getValue() + 
+          " is science metadata: " + e.getMessage());
+    
+    }
+    
+    return isScienceMetadata;
 
-}
+  }
+  
+  /**
+   * Insert or update an XML document into Metacat
+   * 
+   * @param xml - the XML document to insert or update
+   * @param pid - the identifier to be used for the resulting object
+   * 
+   * @return localId - the resulting docid of the document created or updated
+   * 
+   */
+  protected String insertOrUpdateDocument(String xml, Identifier pid, 
+    Session session, String insertOrUpdate) 
+    throws ServiceFailure {
+    
+  	logMetacat.debug("Starting to insert xml document...");
+    IdentifierManager im = IdentifierManager.getInstance();
+
+    // generate pid/localId pair for sysmeta
+    String localId = null;
+    
+    if(insertOrUpdate.equals("insert")) {
+      localId = im.generateLocalId(pid.getValue(), 1);
+      
+    } else {
+      //localid should already exist in the identifier table, so just find it
+      try {
+        logMetacat.debug("Updating pid " + pid.getValue());
+        logMetacat.debug("looking in identifier table for pid " + pid.getValue());
+        
+        localId = im.getLocalId(pid.getValue());
+        
+        logMetacat.debug("localId: " + localId);
+        //increment the revision
+        String docid = localId.substring(0, localId.lastIndexOf("."));
+        String revS = localId.substring(localId.lastIndexOf(".") + 1, localId.length());
+        int rev = new Integer(revS).intValue();
+        rev++;
+        docid = docid + "." + rev;
+        localId = docid;
+        logMetacat.debug("incremented localId: " + localId);
+      
+      } catch(McdbDocNotFoundException e) {
+        throw new ServiceFailure("1030", "D1NodeService.insertOrUpdateDocument(): " +
+            "pid " + pid.getValue() + 
+            " should have been in the identifier table, but it wasn't: " + 
+            e.getMessage());
+      
+      }
+      
+    }
+
+    String[] action = new String[1];
+    action[0] = insertOrUpdate;
+    params.put("action", action);
+    String[] docid = new String[1];
+    docid[0] = localId;
+    params.put("docid", docid);
+    String[] doctext = new String[1];
+    doctext[0] = xml;
+    params.put("doctext", doctext);
+    
+    String username = "public";
+    String[] groupnames = null;
+    if( session != null ) {
+      username = session.getSubject().getValue();
+      List<Group> groupList = session.getSubjectList().getGroupList();
+      for ( int i = 0; i > groupList.size(); i++ ) {
+      	groupnames[i] = groupList.get(i).getGroupName();
+      	
+      }
+    }
+    
+    // do the insert or update action
+    String result = handler.handleInsertOrUpdateAction(metacatUrl, null, 
+                        null, params, username, groupnames);
+    
+    if(result.indexOf("<error>") != -1) {
+    	String detailCode = "";
+    	if ( insertOrUpdate.equals("insert") ) {
+    		detailCode = "1190";
+    		
+    	} else if ( insertOrUpdate.equals("update") ) {
+    		detailCode = "1310";
+    		
+    	}
+        throw new ServiceFailure(detailCode, 
+          "Error inserting or updating document: " + result);
+    }
+    logMetacat.debug("Finsished inserting xml document with id " + localId);
+    
+    return localId;
+  }
+  
+  /**
+   * Insert a data document
+   * 
+   * @param object
+   * @param pid
+   * @param sessionData
+   * @throws ServiceFailure
+   * @returns localId of the data object inserted
+   */
+  private String insertDataObject(InputStream object, Identifier pid, 
+          Session session) throws ServiceFailure {
+      
+    String username = "public";
+    String[] groupnames = null;
+    if( session != null ) {
+      username = session.getSubject().getValue();
+      List<Group> groupList = session.getSubjectList().getGroupList();
+      for ( int i = 0; i > groupList.size(); i++ ) {
+      	groupnames[i] = groupList.get(i).getGroupName();
+      	
+      }
+      
+    }
+  
+    // generate pid/localId pair for object
+    logMetacat.debug("Generating a pid/localId mapping");
+    IdentifierManager im = IdentifierManager.getInstance();
+    String localId = im.generateLocalId(pid.getValue(), 1);
+  
+    try {
+      logMetacat.debug("Case DATA: starting to write to disk.");
+      if (DocumentImpl.getDataFileLockGrant(localId)) {
+  
+        // Save the data file to disk using "localId" as the name
+        try {
+          String datafilepath = PropertyService.getProperty("application.datafilepath");
+  
+          File dataDirectory = new File(datafilepath);
+          dataDirectory.mkdirs();
+  
+          File newFile = writeStreamToFile(dataDirectory, localId, object);
+  
+          // TODO: Check that the file size matches SystemMetadata
+          // long size = newFile.length();
+          // if (size == 0) {
+          //     throw new IOException("Uploaded file is 0 bytes!");
+          // }
+  
+          // Register the file in the database (which generates an exception
+          // if the localId is not acceptable or other untoward things happen
+          try {
+            logMetacat.debug("Registering document...");
+            DocumentImpl.registerDocument(localId, "BIN", localId,
+                    username, groupnames);
+            logMetacat.debug("Registration step completed.");
+            
+          } catch (SQLException e) {
+            //newFile.delete();
+            logMetacat.debug("SQLE: " + e.getMessage());
+            e.printStackTrace(System.out);
+            throw new ServiceFailure("1190", "Registration failed: " + 
+            		e.getMessage());
+            
+          } catch (AccessionNumberException e) {
+            //newFile.delete();
+            logMetacat.debug("ANE: " + e.getMessage());
+            e.printStackTrace(System.out);
+            throw new ServiceFailure("1190", "Registration failed: " + 
+            	e.getMessage());
+            
+          } catch (Exception e) {
+            //newFile.delete();
+            logMetacat.debug("Exception: " + e.getMessage());
+            e.printStackTrace(System.out);
+            throw new ServiceFailure("1190", "Registration failed: " + 
+            	e.getMessage());
+          }
+  
+          logMetacat.debug("Logging the creation event.");
+          EventLog.getInstance().log(metacatUrl, username, localId, "create");
+  
+          // Schedule replication for this data file
+          logMetacat.debug("Scheduling replication.");
+          ForceReplicationHandler frh = new ForceReplicationHandler(
+            localId, "create", false, null);
+  
+        } catch (PropertyNotFoundException e) {
+          throw new ServiceFailure("1190", "Could not lock file for writing:" + 
+          	e.getMessage());
+          
+        }
+      }
+      return localId;
+    } catch (Exception e) {
+        // Could not get a lock on the document, so we can not update the file now
+        throw new ServiceFailure("1190", "Failed to lock file: " + e.getMessage());
+    }
+    
+  }
+  /**
+   * Write a stream to a file
+   * 
+   * @param dir - the directory to write to
+   * @param fileName - the file name to write to
+   * @param data - the object bytes as an input stream
+   * 
+   * @return newFile - the new file created
+   * 
+   * @throws ServiceFailure
+   */
+  private File writeStreamToFile(File dir, String fileName, InputStream data) 
+    throws ServiceFailure {
+    
+    File newFile = new File(dir, fileName);
+    logMetacat.debug("Filename for write is: " + newFile.getAbsolutePath());
+
+    try {
+        if (newFile.createNewFile()) {
+          // write data stream to desired file
+          OutputStream os = new FileOutputStream(newFile);
+          long length = IOUtils.copyLarge(data, os);
+          os.flush();
+          os.close();
+        } else {
+          logMetacat.debug("File creation failed, or file already exists.");
+          throw new ServiceFailure("1190", "File already exists: " + fileName);
+        }
+    } catch (FileNotFoundException e) {
+      logMetacat.debug("FNF: " + e.getMessage());
+      throw new ServiceFailure("1190", "File not found: " + fileName + " " 
+                + e.getMessage());
+    } catch (IOException e) {
+      logMetacat.debug("IOE: " + e.getMessage());
+      throw new ServiceFailure("1190", "File was not written: " + fileName 
+                + " " + e.getMessage());
+    }
+
+    return newFile;
+  }
+  
+}
