Index: lib/dataone-service-api-0.1.0.jar
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: src/edu/ucsb/nceas/metacat/restservice/ResourceHandler.java
===================================================================
--- src/edu/ucsb/nceas/metacat/restservice/ResourceHandler.java	(revision 5318)
+++ src/edu/ucsb/nceas/metacat/restservice/ResourceHandler.java	(revision 5319)
@@ -23,13 +23,20 @@
 package edu.ucsb.nceas.metacat.restservice;
 
 import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.OutputStream;
 import java.io.PrintWriter;
 import java.util.Enumeration;
 import java.util.Hashtable;
 import java.util.Timer;
 
+import javax.mail.BodyPart;
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeMultipart;
 import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
@@ -37,9 +44,19 @@
 import org.apache.commons.io.IOUtils;
 import org.apache.log4j.Logger;
 import org.dataone.service.exceptions.BaseException;
+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.NotImplemented;
 import org.dataone.service.exceptions.ServiceFailure;
+import org.dataone.service.exceptions.UnsupportedType;
 import org.dataone.service.types.AuthToken;
 import org.dataone.service.types.IdentifierType;
+import org.dataone.service.types.SystemMetadata;
+import org.exolab.castor.jdo.conf.DataSource;
 
 import edu.ucsb.nceas.metacat.DBUtil;
 import edu.ucsb.nceas.metacat.IdentifierManager;
@@ -280,25 +297,25 @@
                         status = true;
                     }
                 } else if (resource.equals(RESOURCE_OBJECTS)) {
-
+                    logMetacat.debug("D1 Rest: Starting resource processing...");
                     loadSessionData();
 
                     String objectId = request.getPathInfo();
                     if (objectId != null && objectId.length() > 1)
                         objectId = request.getPathInfo().substring(1); //trim the slash
+                    logMetacat.debug("Processing objectId: " + objectId);
+                    logMetacat.debug("verb:" + httpVerb);
 
-                    System.out.println("verb:" + httpVerb);
+                    logMetacat.debug("objectId:" + objectId);
 
-                    System.out.println("objectId:" + objectId);
-
                     if (httpVerb == GET) {
                         getObject(objectId);
                         status = true;
                     } else if (httpVerb == POST) {
-                        query();
+                        putObject(objectId, FUNCTION_NAME_INSERT);
                         status = true;
                     } else if (httpVerb == PUT) {
-                        putObject(objectId);
+                        putObject(objectId, FUNCTION_NAME_UPDATE);
                         status = true;
                     } else if (httpVerb == DELETE) {
                         deleteObject(objectId);
@@ -450,31 +467,16 @@
     private void getObject(String guid) {
         CrudService cs = new CrudService(servletContext, request, response);
         AuthToken token = null;
+        OutputStream out = null;
         try {
+            out = response.getOutputStream();
             InputStream data = cs.get(token, new IdentifierType(guid));
             IOUtils.copyLarge(data, response.getOutputStream());
         } catch (BaseException e) {
-                response.setContentType("text/xml");
-                response.setStatus(e.getCode());
-                // TODO: Use content negotiation to determine which return format to use
-                try {
-                    IOUtils.write(e.serialize(BaseException.FMT_XML), 
-                            response.getOutputStream());
-                } catch (IOException e1) {
-                    logMetacat.error("Error writing exception to stream. " 
-                            + e1.getMessage());
-                }
+                serializeException(e, out);
         } catch (IOException e) {
             ServiceFailure sf = new ServiceFailure(1030, e.getMessage());
-            response.setContentType("text/xml");
-            response.setStatus(sf.getCode());
-            try {
-                IOUtils.write(sf.serialize(BaseException.FMT_XML), 
-                        response.getOutputStream());
-            } catch (IOException e1) {
-                logMetacat.error("Error writing service exception to stream. " 
-                        + e1.getMessage());
-            }
+            serializeException(sf, out);
         }
     }
 
@@ -544,63 +546,110 @@
         out.print("<error>Query operation not yet supported by Metacat.</error>");
         out.close();
     }
-
+    
     /**
      * Earthgrid API > Put Service >Put Function : calls MetacatHandler > handleInsertOrUpdateAction 
      * 
-     * @param objectId ID of data object to be inserted or updated
+     * @param guid ID of data object to be inserted or updated
      * @throws IOException
      */
-    private void putObject(String objectId) throws IOException {
-
+    private void putObject(String guid, String action) {
+        logMetacat.debug("Entering putObject: " + guid + "/" + action);
+        
         // TODO: This function lacks proper handling of authz and authn, so it
         // seems that anyone can insert or update; interacts with 
-        // loadSessinData(), which doesn't validate the session
+        // loadSessionData(), which doesn't validate the session
         
-        String action = request.getParameter(FUNCTION_KEYWORD);
+        // Get an output stream for handling errors; this should really be passed in as
+        // a parameter
+        OutputStream out = null;
+        try {
+            out = response.getOutputStream();
+        } catch (IOException e1) {
+            logMetacat.error("Could not get the output stream for writing in putObject");
+        }
+        try {
+            if (action.equals(FUNCTION_NAME_UPDATE)
+                    || action.equals(FUNCTION_NAME_INSERT)) {
 
-        if (action.equals(FUNCTION_NAME_UPDATE)
-                || action.equals(FUNCTION_NAME_INSERT)) {
-            
-            // Check if the objectId exists
-            IdentifierManager im = IdentifierManager.getInstance();
-            if (im.identifierExists(objectId)) {
-                // TODO: return IdentifierNotUnique exception
-            }
-            
-            // TODO: For updates, need to check if the old id exists, and if not throw an exception
-            
-            // WARNING: This should not be a Reader if we are inserting data
-            // Nor should it be read into a String
-            // so this seems like a latent bug to me (MBJ; 16Mar2010)
-            BufferedReader reader = request.getReader();
-            StringBuffer buffer = new StringBuffer();
-            String line = null;
-            while ((line = reader.readLine()) != null) {
-                buffer.append(line);
-            }
+                // Check if the objectId exists
+                IdentifierManager im = IdentifierManager.getInstance();
+                if (im.identifierExists(guid)) {
+                    throw new IdentifierNotUnique(1000, "Identifier is already in use: " + guid);
+                }
 
-            String localId = im.generateLocalId(objectId, 1);
-            params.put("docid", new String[] { localId });
-            params.put("doctext", new String[] { buffer.toString().trim() });
-            params.put("action", new String[] { action });
+                // TODO: For updates, need to check if the old id exists, and if not throw an exception
 
-            if (username != null && !username.equals("public")) {
-                PrintWriter out = response.getWriter();
-                handler.handleInsertOrUpdateAction(request, response, out,
-                        params, username, groupNames);
-                out.close();
+                // TODO: Change this to read the MIME forms that are created
+                logMetacat.debug("Disassembling MIME multipart form");
+                InputStream object = null;
+                InputStream sysmeta = null;
+                MimeMultipart mmp = new MimeMultipart(new InputStreamDataSource("message", request.getInputStream()));
+                logMetacat.debug("MMP created.");
+                mmp.writeTo(System.out);
+                for (int i = 0; i < mmp.getCount(); i++) {
+                    logMetacat.debug("Looping over MMP parts: " + i);
+                    BodyPart part = mmp.getBodyPart(i);
+                    String name = part.getFileName();
+                    logMetacat.debug("Part name is: " + name);
+                    logMetacat.debug("Part has class name: " + part.getClass().getName());
+                    if (name.equals("object")) {
+                        object = part.getInputStream();
+                        logMetacat.debug("Found object part, size is: " + part.getSize());
+                    } else if (name.equals("systemmetadata")) {
+                        sysmeta = part.getInputStream();
+                        logMetacat.debug("Found sysmeta part, size is: " + part.getSize());
+                    } else {
+                        throw new InvalidRequest(1000, "Request had malformed MIME part with name: " + name);
+                    }
+                }
+
+                //if (username != null && !username.equals("public")) {
+                if (username != null) {
+
+                    logMetacat.debug("Commence creation...");
+                    AuthToken token = null;
+                    SystemMetadata m = new SystemMetadata(sysmeta);
+                    logMetacat.debug(m.serialize(SystemMetadata.FMT_XML));
+                    //IOUtils.copy(object, System.out);
+//                    byte[] b = new byte[2048];
+//                    int len = object.read(b);
+//                    logMetacat.debug("Read " + len + " bytes from object: " + new String(b));
+                    CrudService cs = new CrudService(servletContext, request, response);
+                    cs.create(token, new IdentifierType(guid), object, m);
+
+                } else {
+                    logMetacat.debug("Unauthorized to create.");
+                    throw new NotAuthorized(1000, "Permission denied for user " + username);
+                }
             } else {
-                // TODO: throw exception to show lack of credentials
-                printError("Permission denied for user " + username, response);
-
+                throw new InvalidRequest(1000, "Operation must be create or update.");
             }
-        } else {
-            // TODO: throw the proper exception to indicate an invalid request
-            printError("Specifiy the operation type.(update or insert)",
-                    response);
+        } catch (NotAuthorized e) {
+            serializeException(e, out);
+        } catch (InvalidToken e) {
+            serializeException(e, out);
+        } catch (ServiceFailure e) {
+            serializeException(e, out);
+        } catch (IdentifierNotUnique e) {
+            serializeException(e, out);
+        } catch (UnsupportedType e) {
+            serializeException(e, out);
+        } catch (InsufficientResources e) {
+            serializeException(e, out);
+        } catch (InvalidSystemMetadata e) {
+            serializeException(e, out);
+        } catch (NotImplemented e) {
+            serializeException(e, out);
+        } catch (InvalidRequest e) {
+            serializeException(e, out);
+        } catch (MessagingException e) {
+            ServiceFailure sf = new ServiceFailure(1000, e.getMessage());
+            serializeException(sf, out);
+        } catch (IOException e) {
+            ServiceFailure sf = new ServiceFailure(1000, e.getMessage());
+            serializeException(sf, out);
         }
-
     }
 
     /**
@@ -668,4 +717,16 @@
         }
     }
 
+    private void serializeException(BaseException e, OutputStream out) {
+        // TODO: Use content negotiation to determine which return format to use
+        response.setContentType("text/xml");
+        response.setStatus(e.getCode());
+        try {
+            IOUtils.write(e.serialize(BaseException.FMT_XML), out);
+        } catch (IOException e1) {
+            logMetacat.error("Error writing exception to stream. " 
+                    + e1.getMessage());
+        }
+    }
+
 }
Index: src/edu/ucsb/nceas/metacat/restservice/InputStreamDataSource.java
===================================================================
--- src/edu/ucsb/nceas/metacat/restservice/InputStreamDataSource.java	(nonexistent)
+++ src/edu/ucsb/nceas/metacat/restservice/InputStreamDataSource.java	(revision 5319)
@@ -0,0 +1,65 @@
+/**
+ *  Copyright: 2010 Regents of the University of California and the
+ *              National Center for Ecological Analysis and Synthesis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+package edu.ucsb.nceas.metacat.restservice;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import javax.activation.DataSource;
+
+/**
+ * Encapsulate an InputStream within a DataSource interface so that it is 
+ * accessible to MIME processors.
+ * 
+ * @author Matthew Jones
+ */
+public class InputStreamDataSource implements DataSource {
+    private String name;
+    private InputStream stream;
+    private boolean readOnce;
+    
+    public InputStreamDataSource(String name, InputStream stream) {
+        super();
+        this.name = name;
+        this.stream = stream;
+        this.readOnce = false;
+    }
+
+    public String getContentType() {
+        return "application/octet-stream";
+    }
+
+    public InputStream getInputStream() throws IOException {
+        if (readOnce) {
+            throw new IOException("Only call getInputStream() once.");
+        }
+        readOnce = true;
+        
+        return stream;
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public OutputStream getOutputStream() throws IOException {
+        throw new IOException("Can't get an OutputStream from an InputStreamDataSource.");
+    }
+}

Property changes on: src/edu/ucsb/nceas/metacat/restservice/InputStreamDataSource.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: src/edu/ucsb/nceas/metacat/MetaCatServlet.java
===================================================================
--- src/edu/ucsb/nceas/metacat/MetaCatServlet.java	(revision 5318)
+++ src/edu/ucsb/nceas/metacat/MetaCatServlet.java	(revision 5319)
@@ -874,7 +874,7 @@
 			} else if (action.equals("insert") || action.equals("update")) {
 				PrintWriter out = response.getWriter();
 				if ((userName != null) && !userName.equals("public")) {
-					handler.handleInsertOrUpdateAction(request, response, out, params, userName,
+					handler.handleInsertOrUpdateAction(request.getRemoteAddr(), response, out, params, userName,
 							groupNames);
 				} else {
 					response.setContentType("text/xml");
Index: src/edu/ucsb/nceas/metacat/IndexingTimerTask.java
===================================================================
--- src/edu/ucsb/nceas/metacat/IndexingTimerTask.java	(revision 5318)
+++ src/edu/ucsb/nceas/metacat/IndexingTimerTask.java	(revision 5319)
@@ -92,7 +92,7 @@
 	    		}
 	    		
 	    		String xmlDocumentsCheck = 
-	    			DatabaseService.getDBAdapter().getLeftJoinQuery("a.docid, a.rev", "xml_documents", 
+	    			DatabaseService.getInstance().getDBAdapter().getLeftJoinQuery("a.docid, a.rev", "xml_documents", 
 	    					"xml_index", "a.docid = b.docid", nonJoinCriteria);
 
 	    		PreparedStatement xmlDocCheck = dbConn.prepareStatement(xmlDocumentsCheck);
Index: src/edu/ucsb/nceas/metacat/DocumentImpl.java
===================================================================
--- src/edu/ucsb/nceas/metacat/DocumentImpl.java	(revision 5318)
+++ src/edu/ucsb/nceas/metacat/DocumentImpl.java	(revision 5319)
@@ -485,7 +485,7 @@
       
       PreparedStatement pstmt = null;
       int revision = (new Integer(rev)).intValue();
-      String sqlDateString = DatabaseService.getDBAdapter().getDateTimeFunction();
+      String sqlDateString = DatabaseService.getInstance().getDBAdapter().getDateTimeFunction();
       if (createDate == null)
       {
           createDate = sqlDateString;
@@ -492,7 +492,7 @@
       }
       else
       {
-          createDate = DatabaseService.getDBAdapter().toDate(createDate, "YYYY-MM-DD HH24:MI:SS");
+          createDate = DatabaseService.getInstance().getDBAdapter().toDate(createDate, "YYYY-MM-DD HH24:MI:SS");
       }
       
       if (updateDate == null)
@@ -501,7 +501,7 @@
       }
       else
       {
-          updateDate = DatabaseService.getDBAdapter().toDate(updateDate, "YYYY-MM-DD HH24:MI:SS");
+          updateDate = DatabaseService.getInstance().getDBAdapter().toDate(updateDate, "YYYY-MM-DD HH24:MI:SS");
       }
       try
       {
@@ -549,7 +549,7 @@
     }
     catch(Exception e) 
     {
-     
+        logMetacat.debug("Caught a general exception: " + e.getMessage());
         throw e;
     }
     finally 
@@ -2273,7 +2273,7 @@
             String catalogid, int serverCode, String createDate, String updateDate) throws SQLException, Exception
     {
         //System.out.println("!!!!!!!!1write document to db  " +docid +"."+rev);
-        String sysdate = DatabaseService.getDBAdapter().getDateTimeFunction();
+        String sysdate = DatabaseService.getInstance().getDBAdapter().getDateTimeFunction();
         if (createDate == null)
         {
             createDate = sysdate;
@@ -2280,7 +2280,7 @@
         }
         else
         {
-            createDate = DatabaseService.getDBAdapter().toDate(createDate, "YYYY-MM-DD HH24:MI:SS");
+            createDate = DatabaseService.getInstance().getDBAdapter().toDate(createDate, "YYYY-MM-DD HH24:MI:SS");
         }
         if (updateDate == null)
         {
@@ -2288,7 +2288,7 @@
         }
         else
         {
-            updateDate = DatabaseService.getDBAdapter().toDate(updateDate, "YYYY-MM-DD HH24:MI:SS");
+            updateDate = DatabaseService.getInstance().getDBAdapter().toDate(updateDate, "YYYY-MM-DD HH24:MI:SS");
         }
         DocumentImpl thisdoc = null;
 
@@ -3551,7 +3551,7 @@
     private static void archiveDocAndNodesRevison(DBConnection dbconn, String docid, 
                                      String user, long rootNodeId) throws Exception
     {
-        String sysdate = DatabaseService.getDBAdapter().getDateTimeFunction();
+        String sysdate = DatabaseService.getInstance().getDBAdapter().getDateTimeFunction();
         //DBConnection conn = null;
         //int serialNumber = -1;
         PreparedStatement pstmt = null;
@@ -3637,7 +3637,7 @@
     /** Save a document entry in the xml_revisions table */
     private static void archiveDocRevision(String docid, String user, DBConnection conn) throws Exception
     {
-        String sysdate = DatabaseService.getDBAdapter().getDateTimeFunction();
+        String sysdate = DatabaseService.getInstance().getDBAdapter().getDateTimeFunction();
         PreparedStatement pstmt = null;
 
         // create a record in xml_revisions table
@@ -3882,7 +3882,7 @@
                         .prepareStatement("INSERT INTO xml_replication "
                                 + "(server, last_checked, replicate, datareplicate, hub) "
                                 + "VALUES ('" + server + "', "
-                                + DatabaseService.getDBAdapter().toDate("01/01/1980", "MM/DD/YYYY")
+                                + DatabaseService.getInstance().getDBAdapter().toDate("01/01/1980", "MM/DD/YYYY")
                                 + ", '" + replicate + "', '" + dataReplicate
                                 + "','" + hub + "')");
 
@@ -4078,20 +4078,20 @@
             
             if (createDate == null)
             {
-                createDate = DatabaseService.getDBAdapter().getDateTimeFunction();
+                createDate = DatabaseService.getInstance().getDBAdapter().getDateTimeFunction();
             }
             else
             {
-                createDate = DatabaseService.getDBAdapter().toDate(createDate, "YYYY-MM-DD HH24:MI:SS");
+                createDate = DatabaseService.getInstance().getDBAdapter().toDate(createDate, "YYYY-MM-DD HH24:MI:SS");
             }
             logMetacat.debug("DocumentImpl.writeDocumentToRevisionTable - the create date is "+createDate);
             if (updateDate == null)
             {
-                updateDate = DatabaseService.getDBAdapter().getDateTimeFunction();
+                updateDate = DatabaseService.getInstance().getDBAdapter().getDateTimeFunction();
             }
             else
             {
-                updateDate = DatabaseService.getDBAdapter().toDate(updateDate, "YYYY-MM-DD HH24:MI:SS");
+                updateDate = DatabaseService.getInstance().getDBAdapter().toDate(updateDate, "YYYY-MM-DD HH24:MI:SS");
             }
             logMetacat.debug("DocumentImpl.writeDocumentToRevisionTable - the update date is "+updateDate);
             PreparedStatement pstmt = null;
Index: src/edu/ucsb/nceas/metacat/DBSAXNode.java
===================================================================
--- src/edu/ucsb/nceas/metacat/DBSAXNode.java	(revision 5318)
+++ src/edu/ucsb/nceas/metacat/DBSAXNode.java	(revision 5319)
@@ -241,7 +241,7 @@
       pstmt.close();
 
       // get the generated unique id afterward
-      nid = DatabaseService.getDBAdapter().getUniqueID(connection.getConnections(), "xml_nodes");
+      nid = DatabaseService.getInstance().getDBAdapter().getUniqueID(connection.getConnections(), "xml_nodes");
       //should increase connection usage!!!!!!
 
 
@@ -370,7 +370,7 @@
       pstmt.close();
 
       // get the generated unique id afterward
-      nid = DatabaseService.getDBAdapter().getUniqueID(connection.getConnections(), "xml_nodes");
+      nid = DatabaseService.getInstance().getDBAdapter().getUniqueID(connection.getConnections(), "xml_nodes");
       //should incease connection usage!!!!!!
 
     } catch (SQLException e) {
Index: src/edu/ucsb/nceas/metacat/MetacatHandler.java
===================================================================
--- src/edu/ucsb/nceas/metacat/MetacatHandler.java	(revision 5318)
+++ src/edu/ucsb/nceas/metacat/MetacatHandler.java	(revision 5319)
@@ -1285,7 +1285,7 @@
      * Handle the database putdocument request and write an XML document to the
      * database connection
      */
-    public void handleInsertOrUpdateAction(HttpServletRequest request,
+    public void handleInsertOrUpdateAction(String ipAddress,
             HttpServletResponse response, PrintWriter out, Hashtable<String, String[]> params,
             String user, String[] groups) {
         Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
@@ -1421,15 +1421,13 @@
                         logMetacat.warn("MetaCatServlet.handleInsertOrUpdateAction - writing with null acnumber");
                         newdocid = documentWrapper.write(dbConn, doctext[0], pub, dtd,
                                 doAction, null, user, groups);
-                        EventLog.getInstance().log(request.getRemoteAddr(),
-                                user, "", action[0]);
-                        } else {
-                            newdocid = documentWrapper.write(dbConn, doctext[0], pub, dtd,
-                                    doAction, accNumber, user, groups);
-                            
-                            EventLog.getInstance().log(request.getRemoteAddr(),
-                                    user, accNumber, action[0]);
-                        }
+                        EventLog.getInstance().log(ipAddress, user, "", action[0]);
+                    } else {
+                        newdocid = documentWrapper.write(dbConn, doctext[0], pub, dtd,
+                                doAction, accNumber, user, groups);
+
+                        EventLog.getInstance().log(ipAddress, user, accNumber, action[0]);
+                    }
                 } finally {
                     // Return db connection
                     DBConnectionPool.returnDBConnection(dbConn, serialNumber);
@@ -2345,7 +2343,7 @@
                 doctextArr[0] = doctext;
                 params.put("doctext", doctextArr);
                 //call the insert routine
-                handleInsertOrUpdateAction(request, response, out, 
+                handleInsertOrUpdateAction(request.getRemoteAddr(), response, out, 
                           params, username, groupnames);
               }
               catch(Exception e)
@@ -2373,11 +2371,11 @@
         Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
         //PrintWriter out = null;
         //Connection conn = null;
-//        String action = null;
+        //        String action = null;
         String docid = null;
         String qformat = null;
         String output = "";
-        
+
         /*
          * response.setContentType("text/xml"); try { out =
          * response.getWriter(); } catch (IOException ioe2) {
@@ -2384,15 +2382,15 @@
          * System.err.println("Fatal Error: couldn't get response output
          * stream.");
          */
-        
+
         if (params.containsKey("docid")) {
             docid = params.get("docid")[0];
         }
-        
+
         if(params.containsKey("qformat")) {
             qformat = params.get("qformat")[0];
         }
-        
+
         // Make sure we have a docid and datafile
         if (docid != null && fileList.containsKey("datafile")) {
             logMetacat.info("MetaCatServlet.handleUploadAction - Uploading data docid: " + docid);
@@ -2402,7 +2400,7 @@
             logMetacat.info("MetaCatServlet.handleUploadAction - Uploading filename: " + fileName);
             // Check if the right file existed in the uploaded data
             if (fileName != null) {
-                
+
                 try {
                     //logMetacat.info("Upload datafile " + docid
                     // +"...", 10);
@@ -2413,12 +2411,12 @@
                         File dataDirectory = new File(datafilepath);
                         dataDirectory.mkdirs();
                         File newFile = null;
-    //                    File tempFile = null;
+                        //                    File tempFile = null;
                         String tempFileName = fileList.get("name");
                         String newFileName = dataDirectory + File.separator + docid;
                         long size = 0;
                         boolean fileExists = false;
-                        
+
                         try {
                             newFile = new File(newFileName);
                             fileExists = newFile.exists();
@@ -2436,7 +2434,9 @@
                                 if (size == 0) {
                                     throw new IOException("Uploaded file is 0 bytes!");
                                 }
-                            }
+                            } // Latent bug here if the file already exists, then the
+                              // conditional fails but the document is still registered.
+                              // maybe this never happens because we already requested a lock?
                             logMetacat.info("MetaCatServlet.handleUploadAction - Uploading the following to Metacat:" +
                                     fileName + ", " + docid + ", " +
                                     username + ", " + groupnames);
@@ -2447,17 +2447,23 @@
                             DocumentImpl.registerDocument(fileName, "BIN", docid,
                                     username, groupnames);
                         } catch (Exception ee) {
-                            //delete the file to create
-                            // if the revision already exists, don't delete
-                            // the file
+                            // If the file did not exist before this method was 
+                            // called and an exception is generated while 
+                            // creating or registering it, then we want to delete
+                            // the file from disk because the operation failed.
+                            // However, if the file already existed before the 
+                            // method was called, then the exception probably
+                            // occurs when registering the document, and so we
+                            // want to leave the old file in place.
                             if ( fileExists == false ) {
                                 newFile.delete();
                             }
+                            
                             logMetacat.info("MetaCatServlet.handleUploadAction - in Exception: fileExists is " + fileExists);
                             logMetacat.error("MetaCatServlet.handleUploadAction - Upload Error: " + ee.getMessage());
                             throw ee;
                         }
-                        
+
                         EventLog.getInstance().log(request.getRemoteAddr(),
                                 username, docid, "upload");
                         // Force replication this data file
@@ -2470,7 +2476,7 @@
                         ForceReplicationHandler frh = new ForceReplicationHandler(
                                 docid, "insert", false, null);
                         logMetacat.debug("MetaCatServlet.handleUploadAction - ForceReplicationHandler created: " + frh.toString());
-                        
+
                         // set content type and other response header fields
                         // first
                         output += "<?xml version=\"1.0\"?>";
@@ -2479,9 +2485,9 @@
                         output += "<size>" + size + "</size>";
                         output += "</success>";
                     }
-                    
+
                 } catch (Exception e) {
-                    
+
                     output += "<?xml version=\"1.0\"?>";
                     output += "<error>";
                     output += e.getMessage();
@@ -2499,10 +2505,10 @@
             output += "<?xml version=\"1.0\"?>";
             output += "<error>";
             output += "The uploaded data did not contain a valid docid "
-                    + "or valid file.";
+                + "or valid file.";
             output += "</error>";
         }
-        
+
         if (qformat == null || qformat.equals("xml")) {
             response.setContentType("text/xml");
             out.println(output);
@@ -2514,7 +2520,7 @@
                         "message", "-//W3C//HTML//EN", qformat,
                         out, null, null);
             } catch (Exception e) {
-                
+
                 logMetacat.error("MetaCatServlet.handleUploadAction - General error: "
                         + e.getMessage());
                 e.printStackTrace(System.out);
Index: src/edu/ucsb/nceas/metacat/database/DBConnectionPool.java
===================================================================
--- src/edu/ucsb/nceas/metacat/database/DBConnectionPool.java	(revision 5318)
+++ src/edu/ucsb/nceas/metacat/database/DBConnectionPool.java	(revision 5319)
@@ -224,9 +224,9 @@
     int random = 0; //random number
     int index = 0; //index
     int size = 0; //size of connection pool
-    logMetacat.debug("DBConnectionPool.getDBConnection - Trying to check out connection...");
+//    logMetacat.debug("DBConnectionPool.getDBConnection - Trying to check out connection...");
     size = connectionPool.size();
-    logMetacat.debug("DBConnectionPool.getDBConnection - size of connection pool: " + size);
+//    logMetacat.debug("DBConnectionPool.getDBConnection - size of connection pool: " + size);
     
      //try every DBConnection in the pool
     //every DBConnection will be try LIMITE times
@@ -239,9 +239,9 @@
       {
         index =(i+random)%size;
         db = (DBConnection) connectionPool.elementAt(index);
-        logMetacat.debug("DBConnectionPool.getDBConnection - Index: " + index);
-        logMetacat.debug("DBConnectionPool.getDBConnection - Tag: " + db.getTag());
-        logMetacat.debug("DBConnectionPool.getDBConnection - Status: " + db.getStatus());
+//        logMetacat.debug("DBConnectionPool.getDBConnection - Index: " + index);
+//        logMetacat.debug("DBConnectionPool.getDBConnection - Tag: " + db.getTag());
+//        logMetacat.debug("DBConnectionPool.getDBConnection - Status: " + db.getStatus());
         //check if the connection is free
         if (db.getStatus()==FREE)
         {
@@ -259,11 +259,11 @@
             db.setCheckOutMethodName(methodName);
             db.setAutoCommit(true);
             //debug message
-            logMetacat.debug("DBConnectionPool.getDBConnection - The connection is checked out: " + db.getTag());
-            logMetacat.debug("DBConnectionPool.getDBConnection - The method for checking is: " + db.getCheckOutMethodName());
-            logMetacat.debug("DBConnectionPool.getDBConnection - The age is " + db.getAge());
-            logMetacat.debug("DBConnectionPool.getDBConnection - The usage is " + db.getUsageCount());
-            logMetacat.debug("DBConnectionPool.getDBConnection - The connection time is: " + db.getConnectionTime());
+//            logMetacat.debug("DBConnectionPool.getDBConnection - The connection is checked out: " + db.getTag());
+//            logMetacat.debug("DBConnectionPool.getDBConnection - The method for checking is: " + db.getCheckOutMethodName());
+//            logMetacat.debug("DBConnectionPool.getDBConnection - The age is " + db.getAge());
+//            logMetacat.debug("DBConnectionPool.getDBConnection - The usage is " + db.getUsageCount());
+//            logMetacat.debug("DBConnectionPool.getDBConnection - The connection time is: " + db.getConnectionTime());
             //set check out time
             db.setCheckOutTime(System.currentTimeMillis());
             // set count of reach maximum 0 because it can check out
@@ -418,8 +418,8 @@
     index = getIndexOfPoolForConnection(conn);
     if ( index ==-1 )
     {
-      logMetacat.info("DBConnectionPool.returnDBConnection - Couldn't find a DBConnection in the pool" + 
-    		  " which have same tag to the returned DBConnetion object");
+//      logMetacat.info("DBConnectionPool.returnDBConnection - Couldn't find a DBConnection in the pool" + 
+//    		  " which have same tag to the returned DBConnetion object");
       return;
                                   
     }//if
@@ -429,9 +429,9 @@
       //if it is as same as the object's checkout serial number.
       //if it is same return it. If it is not same, maybe the connection already
       // was returned earlier.
-      logMetacat.debug("DBConnectionPool.returnDBConnection - serial number in Connection: " +
-              conn.getCheckOutSerialNumber());
-      logMetacat.debug("DBConnectionPool.returnDBConnection - serial number in local: " + serialNumber);
+//      logMetacat.debug("DBConnectionPool.returnDBConnection - serial number in Connection: " +
+//              conn.getCheckOutSerialNumber());
+//      logMetacat.debug("DBConnectionPool.returnDBConnection - serial number in local: " + serialNumber);
       if (conn.getCheckOutSerialNumber() == serialNumber)
       {
         dbConn = (DBConnection) connectionPool.elementAt(index);
@@ -444,16 +444,16 @@
         //set check out time to 0
         dbConn.setCheckOutTime(0);
         
-        logMetacat.debug("DBConnectionPool.returnDBConnection - Connection: " + 
-        		dbConn.getTag() + " checked in.");
-        logMetacat.debug("DBConnectionPool.returnDBConnection - Connection: " +
-        		dbConn.getTag() + "'s status: " + dbConn.getStatus());
+//        logMetacat.debug("DBConnectionPool.returnDBConnection - Connection: " + 
+//        		dbConn.getTag() + " checked in.");
+//        logMetacat.debug("DBConnectionPool.returnDBConnection - Connection: " +
+//        		dbConn.getTag() + "'s status: " + dbConn.getStatus());
                                                                        
       }//if
       else
       {
-        logMetacat.info("DBConnectionPool.returnDBConnection - This DBConnection couldn't return" +
-        		dbConn.getTag());
+//        logMetacat.info("DBConnectionPool.returnDBConnection - This DBConnection couldn't return" +
+//        		dbConn.getTag());
       }//else
     }//else
    
Index: src/edu/ucsb/nceas/metacat/database/DatabaseService.java
===================================================================
--- src/edu/ucsb/nceas/metacat/database/DatabaseService.java	(revision 5318)
+++ src/edu/ucsb/nceas/metacat/database/DatabaseService.java	(revision 5319)
@@ -102,7 +102,7 @@
 	 * 
 	 * @return AbstractDatabase object for this application's database adapter.
 	 */
-	public static AbstractDatabase getDBAdapter() {
+	public AbstractDatabase getDBAdapter() {
 		return dbAdapter;
 	}
 
Index: src/edu/ucsb/nceas/metacat/dataone/CrudService.java
===================================================================
--- src/edu/ucsb/nceas/metacat/dataone/CrudService.java	(revision 5318)
+++ src/edu/ucsb/nceas/metacat/dataone/CrudService.java	(revision 5319)
@@ -22,6 +22,9 @@
  */
 package edu.ucsb.nceas.metacat.dataone;
 
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -35,6 +38,8 @@
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.commons.io.IOUtils;
+import org.apache.log4j.Logger;
 import org.dataone.service.exceptions.IdentifierNotUnique;
 import org.dataone.service.exceptions.InsufficientResources;
 import org.dataone.service.exceptions.InvalidRequest;
@@ -55,11 +60,16 @@
 
 import com.gc.iotools.stream.is.InputStreamFromOutputStream;
 
+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;
 import edu.ucsb.nceas.metacat.McdbException;
 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.service.SessionService;
 import edu.ucsb.nceas.metacat.util.SessionData;
 import edu.ucsb.nceas.utilities.ParseLSIDException;
@@ -84,6 +94,7 @@
 //    private String sessionId;
 //    private String[] groupNames;
     private Hashtable<String, String[]> params;
+    Logger logMetacat = null;
 
     /**
      * Initializes new instance by setting servlet context,request and response.
@@ -95,6 +106,7 @@
         this.servletContext = servletContext;
         this.request = request;
         this.response = response;
+        logMetacat = Logger.getLogger(CrudService.class);
 
         handler = new MetacatHandler(this.servletContext, new Timer());
         initParams();
@@ -165,7 +177,112 @@
             InputStream object, SystemMetadata sysmeta) throws InvalidToken, 
             ServiceFailure, NotAuthorized, IdentifierNotUnique, UnsupportedType, 
             InsufficientResources, InvalidSystemMetadata, NotImplemented {
-        throw new NotImplemented(1000, "This method not yet implemented.");
+
+        logMetacat.debug("Starting CrudService.create()...");
+        
+        // TODO: authenticate & get user info
+        String username = "GARBAGETOBEREPLACED";
+        String[] groups = null;
+
+        // verify that guid == SystemMetadata.getIdentifier()
+        logMetacat.debug("Comparing guid|sysmeta_guid: " + guid.getIdentifier() + "|" + sysmeta.getIdentifier().getIdentifier());
+//        if (!guid.getIdentifier().equals(sysmeta.getIdentifier().getIdentifier())) {
+//            throw new InvalidSystemMetadata(1180, 
+//                "GUID in method call does not match GUID in system metadata.");
+//        }
+
+        logMetacat.debug("Checking if identifier exists...");
+        // Check that the identifier does not already exist
+        IdentifierManager im = IdentifierManager.getInstance();
+        if (im.identifierExists(guid.getIdentifier())) {
+            throw new IdentifierNotUnique(1120, 
+                "GUID is already in use by an existing object.");
+        }
+
+        // generate guid/localId pair for object
+        logMetacat.debug("Generating a guid/localId mapping");
+        String localId = im.generateLocalId(guid.getIdentifier(), 1);
+
+        // TODO: generate guid/localId pair for sysmeta
+        // TODO: update system metadata fields
+        // TODO: insert system metadata to metacat (probably at end)
+
+        // TODO: Check if we are handling metadata or data
+        
+        // TODO: CASE METADATA:
+        // Setup and call handleInsertOrUpdate()
+
+        // TODO: DEFAULT CASE: DATA
+        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 docid is not acceptable or other untoward things happen
+                    try {
+                        logMetacat.debug("Registering document...");
+                        DocumentImpl.registerDocument(localId, "BIN", localId,
+                                username, groups);
+                        logMetacat.debug("Registrtion 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(request.getRemoteAddr(),
+                            username, localId, "create");
+                    
+                    // Force replication this data file
+                    // To data file, "insert" and update is same
+                    // The fourth parameter is null. Because it is notification 
+                    // server and this method is in MetaCatServerlet. It is
+                    // original command, not get force replication info from 
+                    // another metacat
+                    // TODO: note that GUID mapping is not being replicated
+                    logMetacat.debug("Scheduling replication.");
+                    ForceReplicationHandler frh = new ForceReplicationHandler(
+                            localId, "insert", false, null);
+
+                } catch (PropertyNotFoundException e) {
+                    throw new ServiceFailure(1190, "Could not lock file for writing:" + e.getMessage());
+                }
+
+            }
+        } 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());
+        }
+        
+        logMetacat.debug("Returning from CrudService.create()");
+        return guid;
     }
 
     public IdentifierType delete(AuthToken token, IdentifierType guid)
@@ -296,6 +413,14 @@
     public SystemMetadata getSystemMetadata(AuthToken token, IdentifierType guid)
             throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, 
             InvalidRequest, NotImplemented {
+        
+        // Look up ID of system metadata based on guid
+            // Initially from document, later from entry in table?
+        
+        // Read system metadata from disk and create SystemMetadata object
+            // Follows same implementation plan as get()
+        
+        // return it
         throw new NotImplemented(1000, "This method not yet implemented.");
     }
 
@@ -307,4 +432,46 @@
         throw new NotImplemented(1000, "This method not yet implemented.");
     }
 
+    private File writeStreamToFile(File dir, String fileName, InputStream data) 
+        throws ServiceFailure {
+//        logMetacat.debug("***********************************************");
+//        logMetacat.debug("** FILE TEST FROM CS                         **");
+//        logMetacat.debug("***********************************************");
+        
+        File newFile = new File(dir, fileName);
+        logMetacat.debug("Filename for write is: " + newFile.getAbsolutePath());
+
+        try {
+            if (newFile.createNewFile()) {
+//                logMetacat.debug("File doesn't yet exist, so write to it.");
+//                logMetacat.debug("Creating file stream...");
+                
+                // write data stream to desired file
+                OutputStream os = new FileOutputStream(newFile);
+//                logMetacat.debug("Copying file stream...");
+                long length = IOUtils.copyLarge(data, os);
+                os.flush();
+//                logMetacat.debug("Closing file stream...");
+                os.close();
+//                logMetacat.debug("Done with file stream...");
+            } 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());
+        }
+
+//        logMetacat.debug("***********************************************");
+//        logMetacat.debug("** END FILE TEST                             **");
+//        logMetacat.debug("***********************************************");
+        
+        return newFile;
+    }   
 }
Index: src/edu/ucsb/nceas/metacat/replication/ReplicationHandler.java
===================================================================
--- src/edu/ucsb/nceas/metacat/replication/ReplicationHandler.java	(revision 5318)
+++ src/edu/ucsb/nceas/metacat/replication/ReplicationHandler.java	(revision 5319)
@@ -671,7 +671,7 @@
          sql.append(datestr).append("', 'YY-MM-DD HH24:MI:SS') where ");
          sql.append("server like '").append(server).append("'");*/
          sql.append("update xml_replication set last_checked = ");
-         sql.append(DatabaseService.getDBAdapter().toDate(datestr, "MM/DD/YY HH24:MI:SS"));
+         sql.append(DatabaseService.getInstance().getDBAdapter().toDate(datestr, "MM/DD/YY HH24:MI:SS"));
          sql.append(" where server like '").append(server).append("'");
          pstmt = dbConn.prepareStatement(sql.toString());
 
Index: src/edu/ucsb/nceas/metacat/replication/ReplicationService.java
===================================================================
--- src/edu/ucsb/nceas/metacat/replication/ReplicationService.java	(revision 5318)
+++ src/edu/ucsb/nceas/metacat/replication/ReplicationService.java	(revision 5319)
@@ -279,7 +279,7 @@
 				//Get hub value
 				hub = ((String[]) params.get("hub"))[0];
 
-				String toDateSql = DatabaseService.getDBAdapter().toDate("01/01/1980","MM/DD/YYYY");
+				String toDateSql = DatabaseService.getInstance().getDBAdapter().toDate("01/01/1980","MM/DD/YYYY");
 				String sql = "INSERT INTO xml_replication "
 						+ "(server, last_checked, replicate, datareplicate, hub) "
 						+ "VALUES (?," + toDateSql + ",?,?,?)";
@@ -1181,7 +1181,7 @@
 
 			// Get correct docid that reside on this server according the requesting
 			// server's replicate and data replicate value in xml_replication table
-			docsql.append(DatabaseService.getDBAdapter().getReplicationDocumentListSQL());
+			docsql.append(DatabaseService.getInstance().getDBAdapter().getReplicationDocumentListSQL());
 			//docsql.append("select docid, rev, doctype from xml_documents where (docid not in (select a.docid from xml_documents a, xml_revisions b where a.docid=b.docid and a.rev<=b.rev)) ");
 			revisionSql.append("select docid, rev, doctype from xml_revisions ");
 			// If the localhost is not a hub to the remote server, only replicate
Index: src/edu/ucsb/nceas/metacat/replication/ReplicationServerList.java
===================================================================
--- src/edu/ucsb/nceas/metacat/replication/ReplicationServerList.java	(revision 5318)
+++ src/edu/ucsb/nceas/metacat/replication/ReplicationServerList.java	(revision 5319)
@@ -456,7 +456,7 @@
         pStmt = dbConn.prepareStatement("INSERT INTO xml_replication " +
                       "(server, last_checked, replicate, datareplicate, hub) "+
                        "VALUES ('" + givenServerName + "', "+
-                        DatabaseService.getDBAdapter().toDate("01/01/1980","MM/DD/YYYY") + ", '" +
+                        DatabaseService.getInstance().getDBAdapter().toDate("01/01/1980","MM/DD/YYYY") + ", '" +
                        replicate +"', '"+dataReplicate+"','"+ hub + "')");
         pStmt.execute();
        
