Index: src/edu/ucsb/nceas/metacat/dataone/CrudService.java
===================================================================
--- src/edu/ucsb/nceas/metacat/dataone/CrudService.java	(revision 5328)
+++ src/edu/ucsb/nceas/metacat/dataone/CrudService.java	(revision 5329)
@@ -22,6 +22,7 @@
  */
 package edu.ucsb.nceas.metacat.dataone;
 
+import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
@@ -28,6 +29,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.io.PrintWriter;
 import java.sql.SQLException;
 import java.util.Date;
 import java.util.Enumeration;
@@ -57,6 +59,10 @@
 import org.dataone.service.types.Identifier;
 import org.dataone.service.types.LogRecordSet;
 import org.dataone.service.types.SystemMetadata;
+import org.jibx.runtime.BindingDirectory;
+import org.jibx.runtime.IBindingFactory;
+import org.jibx.runtime.IMarshallingContext;
+import org.jibx.runtime.JiBXException;
 
 import com.gc.iotools.stream.is.InputStreamFromOutputStream;
 
@@ -71,6 +77,7 @@
 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.DocumentUtil;
 import edu.ucsb.nceas.metacat.util.SessionData;
 import edu.ucsb.nceas.utilities.ParseLSIDException;
 import edu.ucsb.nceas.utilities.PropertyNotFoundException;
@@ -180,16 +187,17 @@
 
         logMetacat.debug("Starting CrudService.create()...");
         
-        // TODO: authenticate & get user info
-        String username = "GARBAGETOBEREPLACED";
-        String[] groups = null;
+        // authenticate & get user info
+        SessionData sessionData = getSessionData(token);
+        String username = sessionData.getUserName();
+        String[] groups = sessionData.getGroupNames();
 
         // verify that guid == SystemMetadata.getIdentifier()
         logMetacat.debug("Comparing guid|sysmeta_guid: " + guid.getValue() + "|" + sysmeta.getIdentifier().getValue());
-//        if (!guid.getIdentifier().equals(sysmeta.getIdentifier().getIdentifier())) {
-//            throw new InvalidSystemMetadata(1180, 
-//                "GUID in method call does not match GUID in system metadata.");
-//        }
+        if (!guid.getValue().equals(sysmeta.getIdentifier().getValue())) {
+            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
@@ -203,82 +211,85 @@
         logMetacat.debug("Generating a guid/localId mapping");
         String localId = im.generateLocalId(guid.getValue(), 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
+        // Check if we are handling metadata or data
+        boolean isScienceMetadata = isScienceMetadata(sysmeta);
         
-        // TODO: CASE METADATA:
-        // Setup and call handleInsertOrUpdate()
+        if (isScienceMetadata) {
+            // 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)) {
+        } else {
+            // TODO: DEFAULT CASE: DATA (needs to be checked and completed)
+            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");
+                    // 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 dataDirectory = new File(datafilepath);
+                        dataDirectory.mkdirs();
 
-                    File newFile = writeStreamToFile(dataDirectory, localId, object);
+                        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!");
-                    //                        }
+                        // 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());
+                        //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());
                     }
 
-                    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());
             }
-        } 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());
+            
+            // Insert the system metadata into the object store
+            insertSystemMetadata(sysmeta, sessionData);
         }
         
         logMetacat.debug("Returning from CrudService.create()");
@@ -345,51 +356,6 @@
         } catch (McdbDocNotFoundException e) {
             throw new NotFound(1020, e.getMessage());
         }
-        
-/*    
- *      Alternative approach that uses Piped streams, but requires thread handling
- *      which makes exception handling difficult (because exceptions fall off the
- *      calling thread, terminating the thread.
- *      
-        // Look up the localId for this global identifier
-        IdentifierManager im = IdentifierManager.getInstance();
-        try {
-            final String localId = im.getLocalId(guid.getIdentifier());
-
-            // Now use that localId to read the object and return it
-            params.put("docid", new String[] { localId });        
-            final PipedInputStream in = new PipedInputStream();
-            new Thread(
-                    new Runnable() {
-                        public void run() {
-                            try {
-                                PipedOutputStream out = new PipedOutputStream(in);
-                                handler.readFromMetacat(request.getRemoteAddr(), null, 
-                                        out, localId, "xml",
-                                        username, groupNames, true, params);
-                            } catch (PropertyNotFoundException e) {
-                                throw new ServiceFailure(1030, e.getMessage());
-                            } catch (ClassNotFoundException e) {
-                                throw new ServiceFailure(1030, e.getMessage());
-                            } catch (IOException e) {
-                                throw new ServiceFailure(1030, e.getMessage());
-                            } catch (SQLException e) {
-                                throw new ServiceFailure(1030, e.getMessage());
-                            } catch (McdbException e) {
-                                throw new ServiceFailure(1030, e.getMessage());
-                            } catch (ParseLSIDException e) {
-                                throw new NotFound(1020, e.getMessage());
-                            } catch (InsufficientKarmaException e) {
-                                throw new NotAuthorized(1000, "Not authorized for get().");
-                            }
-                        }
-                    }
-            ).start();
-            return in;
-        } catch (McdbDocNotFoundException e) {
-            throw new NotFound(1020, e.getMessage());
-        }        
-*/
     }
 
     public Checksum getChecksum(AuthToken token, Identifier guid)
@@ -414,13 +380,13 @@
             throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, 
             InvalidRequest, NotImplemented {
         
-        // Look up ID of system metadata based on guid
-            // Initially from document, later from entry in table?
+        // TODO: Look up ID of system metadata based on guid
+            // TODO: Initially from document, later from entry in table?
         
-        // Read system metadata from disk and create SystemMetadata object
-            // Follows same implementation plan as get()
+        // TODO: Read system metadata from disk and create SystemMetadata object
+            // TODO: Follows same implementation plan as get()
         
-        // return it
+        // TODO: return it
         throw new NotImplemented(1000, "This method not yet implemented.");
     }
 
@@ -473,5 +439,93 @@
 //        logMetacat.debug("***********************************************");
         
         return newFile;
-    }   
+    }
+
+    /** 
+     * Determine if a given object should be treated as an XML science metadata
+     * object. 
+     * 
+     * TODO: This test should be externalized in a configuration dictionary rather than being hardcoded.
+     * 
+     * @param sysmeta the SystemMetadata describig the object
+     * @return true if the object should be treated as science metadata
+     */
+    private boolean isScienceMetadata(SystemMetadata sysmeta) {
+        boolean scimeta = false;
+        switch (sysmeta.getObjectFormat()) {
+            case EML_2_1_0: scimeta = true; break;
+            case EML_2_0_1: scimeta = true; break;
+            case EML_2_0_0: scimeta = true; break;
+            case FGDC_STD_001_1_1999: scimeta = true; break;
+            case FGDC_STD_001_1998: scimeta = true; break;
+            case NCML_2_2: scimeta = true; break;
+        }
+        
+        return scimeta;
+    }
+
+    private void insertSystemMetadata(SystemMetadata sysmeta, SessionData sessionData) 
+        throws ServiceFailure {
+        logMetacat.debug("Starting to insert SystemMetadata...");
+        IdentifierManager im = IdentifierManager.getInstance();
+    
+        // generate guid/localId pair for sysmeta
+        String sysMetaGuid = DocumentUtil.generateDocumentId(1);
+        sysmeta.setDateSysMetadataModified(new Date());
+
+        String xml = new String(serializeSystemMetadata(sysmeta).toByteArray());
+        insertDocument(xml, sysMetaGuid, sessionData);
+    }
+    
+    private void insertDocument(String xml, String guid, SessionData sessionData) 
+        throws ServiceFailure {
+        logMetacat.debug("Starting to insert xml document...");
+        IdentifierManager im = IdentifierManager.getInstance();
+
+        // generate guid/localId pair for sysmeta
+        String localId = im.generateLocalId(guid, 1);
+        logMetacat.debug("Metadata guid|localId: " + guid + "|" +
+                localId);
+
+        // TODO: insert system metadata to metacat (probably at end)
+        // TODO: can't pass in the out PrintWriter, as we don't want to write
+        // error info on this stream -- need to be able to return to process
+        // the real object.  So, need to:
+        // TODO: refactor handleInsertOrUpdateAction() to not output XML directly
+        // onto output stream, or alternatively, capture that and parse it to 
+        // generate the right exceptions
+        String[] action = new String[1];
+        action[0] = "insert";
+        params.put("action", action);
+        String[] docid = new String[1];
+        docid[0] = localId;
+        params.put("docid", docid);
+        String[] doctext = new String[1];
+        doctext[0] = xml;
+        logMetacat.debug(doctext[0]);
+        params.put("doctext", doctext);
+        ByteArrayOutputStream output = new ByteArrayOutputStream();
+        PrintWriter pw = new PrintWriter(output);
+        handler.handleInsertOrUpdateAction(request.getRemoteAddr(), response, 
+                pw, params, sessionData.getUserName(),
+                sessionData.getGroupNames());
+        logMetacat.debug(new String(output.toByteArray()));
+        logMetacat.debug("Finsihed inserting xml document.");
+    }
+    
+    private ByteArrayOutputStream serializeSystemMetadata(SystemMetadata sysmeta) 
+        throws ServiceFailure {
+        IBindingFactory bfact;
+        ByteArrayOutputStream sysmetaOut = null;
+        try {
+            bfact = BindingDirectory.getFactory(SystemMetadata.class);
+            IMarshallingContext mctx = bfact.createMarshallingContext();
+            sysmetaOut = new ByteArrayOutputStream();
+            mctx.marshalDocument(sysmeta, "UTF-8", null, sysmetaOut);
+        } catch (JiBXException e) {
+            throw new ServiceFailure(1190, "Failed to serialize and insert SystemMetadata: " + e.getMessage());
+        }
+        
+        return sysmetaOut;
+    }
 }
