Index: src/edu/ucsb/nceas/metacat/restservice/ResourceHandler.java
===================================================================
--- src/edu/ucsb/nceas/metacat/restservice/ResourceHandler.java	(revision 5331)
+++ src/edu/ucsb/nceas/metacat/restservice/ResourceHandler.java	(revision 5332)
@@ -22,6 +22,7 @@
  */
 package edu.ucsb.nceas.metacat.restservice;
 
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -54,6 +55,7 @@
 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.IUnmarshallingContext;
 import org.jibx.runtime.JiBXException;
 
@@ -190,6 +192,7 @@
      * API Resources
      */
     private static final String RESOURCE_OBJECTS = "object";
+    private static final String RESOURCE_META = "/meta";
     private static final String RESOURCE_SESSION = "session";
     private static final String RESOURCE_IDENTIFIER = "identifier";
 
@@ -299,9 +302,21 @@
                     logMetacat.debug("D1 Rest: Starting resource processing...");
                     loadSessionData();
 
+                    boolean isSysmetaRequest = false;
                     String objectId = request.getPathInfo();
-                    if (objectId != null && objectId.length() > 1)
+                    if (objectId != null && objectId.length() > 1) {
                         objectId = request.getPathInfo().substring(1); //trim the slash
+                        
+                        // Check if this is a request for SystemMetadata
+                        // TODO: Note that this REST uri means that GUIDs can not contain the RESOURCE_META string
+                        int start = objectId.indexOf(RESOURCE_META);
+                        if (start >= 0) {
+                            logMetacat.debug("Pruning meta at start value: " + start);
+                            objectId = objectId.substring(0, start);
+                            logMetacat.debug("New objectId for meta is: " + objectId);
+                            isSysmetaRequest = true;
+                        }
+                    }
                     logMetacat.debug("Processing objectId: " + objectId);
                     logMetacat.debug("verb:" + httpVerb);
 
@@ -308,7 +323,11 @@
                     logMetacat.debug("objectId:" + objectId);
 
                     if (httpVerb == GET) {
-                        getObject(objectId);
+                        if (isSysmetaRequest) {
+                            getSystemMetadataObject(objectId);
+                        } else {
+                            getObject(objectId);
+                        }
                         status = true;
                     } else if (httpVerb == POST) {
                         putObject(objectId, FUNCTION_NAME_INSERT);
@@ -482,6 +501,39 @@
     }
 
     /**
+     * Implements REST version of DataONE CRUD API --> getSystemMetadata
+     * @param guid ID of data object to be read
+     */
+    private void getSystemMetadataObject(String guid) {
+        CrudService cs = new CrudService(servletContext, request, response);
+        AuthToken token = null;
+        OutputStream out = null;
+        try {
+            out = response.getOutputStream();
+            Identifier id = new Identifier();
+            id.setValue(guid);
+            SystemMetadata sysmeta = cs.getSystemMetadata(token, id);
+            logMetacat.debug("Got sysmeta for: " + sysmeta.getIdentifier().getValue());
+            
+            // Serialize and write it to the output stream
+            try {
+                IBindingFactory bfact = BindingDirectory.getFactory(SystemMetadata.class);
+                IMarshallingContext mctx = bfact.createMarshallingContext();
+                mctx.marshalDocument(sysmeta, "UTF-8", null, out);
+            } catch (JiBXException e) {
+                throw new ServiceFailure(1190, "Failed to serialize SystemMetadata: " + e.getMessage());
+            }
+        } catch (BaseException e) {
+                serializeException(e, out);
+        } catch (IOException e) {
+            ServiceFailure sf = new ServiceFailure(1030, e.getMessage());
+            serializeException(sf, out);
+        } finally {
+            IOUtils.closeQuietly(out);
+        }
+    }
+    
+    /**
      * Earthgrid API > Query Service > Query Function : translates ecogrid query document to metacat query 
      * then calls DBQuery > createResultDocument function and then again translate resultset to ecogrid resultset
      * 
Index: src/edu/ucsb/nceas/metacat/dataone/CrudService.java
===================================================================
--- src/edu/ucsb/nceas/metacat/dataone/CrudService.java	(revision 5331)
+++ src/edu/ucsb/nceas/metacat/dataone/CrudService.java	(revision 5332)
@@ -62,6 +62,7 @@
 import org.jibx.runtime.BindingDirectory;
 import org.jibx.runtime.IBindingFactory;
 import org.jibx.runtime.IMarshallingContext;
+import org.jibx.runtime.IUnmarshallingContext;
 import org.jibx.runtime.JiBXException;
 
 import com.gc.iotools.stream.is.InputStreamFromOutputStream;
@@ -271,14 +272,61 @@
             throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, 
             InvalidRequest, NotImplemented {
         
-        // TODO: Look up ID of system metadata based on guid
+        logMetacat.debug("CrudService.getSystemMetadata - for guid: " + guid.getValue());
+        
+        // Retrieve the session information from the AuthToken
+        // If the session is expired, then the user is 'public'
+        final SessionData sessionData = getSessionData(token);
+
+        // TODO: Check access control rules
+                
+        try {
+            IdentifierManager im = IdentifierManager.getInstance();
+            // This is a test id of an existing sysmeta document -- for temporary testing
+            String testGuid = "autogen.20101192441566.1";
+            // TODO: Look up ID of system metadata based on guid
             // TODO: Initially from document, later from entry in table?
-        
-        // TODO: Read system metadata from disk and create SystemMetadata object
-            // TODO: Follows same implementation plan as get()
-        
-        // TODO: return it
-        throw new NotImplemented(1000, "This method not yet implemented.");
+//            String localId = im.getLocalId(guid.getValue());
+            final String localId = im.getLocalId(testGuid);
+            
+            // Read system metadata from metacat's db
+            final InputStreamFromOutputStream<String> objectStream = 
+                new InputStreamFromOutputStream<String>() {
+                
+                @Override
+                public String produce(final OutputStream dataSink) throws Exception {
+                    try {
+                        handler.readFromMetacat(request.getRemoteAddr(), null, 
+                                dataSink, localId, "xml",
+                                sessionData.getUserName(), 
+                                sessionData.getGroupNames(), 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().");
+                    }
+
+                    return "Completed";
+                }
+            };
+            
+            // Deserialize the xml to create a SystemMetadata object
+            SystemMetadata sysmeta = deserializeSystemMetadata(objectStream);
+            return sysmeta;
+            
+        } catch (McdbDocNotFoundException e) {
+            throw new NotFound(1000, e.getMessage());
+        }                
     }
 
     public Identifier update(AuthToken token, Identifier guid, 
@@ -483,11 +531,15 @@
         handler.handleInsertOrUpdateAction(request.getRemoteAddr(), response, 
                 pw, params, sessionData.getUserName(),
                 sessionData.getGroupNames());
-        logMetacat.debug(new String(output.toByteArray()));
+        String outputS = new String(output.toByteArray());
+        logMetacat.debug("CrudService.insertDocument - Metacat returned: " + outputS);
+//        if (!(outputS.indexOf("<success>") > 0 && outputS.indexOf(localId) > 0)) {
+//            throw new ServiceFailure(1190, outputS);
+//        }
         logMetacat.debug("Finsished inserting xml document.");
     }
     
-    private ByteArrayOutputStream serializeSystemMetadata(SystemMetadata sysmeta) 
+    public static ByteArrayOutputStream serializeSystemMetadata(SystemMetadata sysmeta) 
         throws ServiceFailure {
         IBindingFactory bfact;
         ByteArrayOutputStream sysmetaOut = null;
@@ -502,4 +554,16 @@
         
         return sysmetaOut;
     }
+    
+    public static SystemMetadata deserializeSystemMetadata(InputStream xml) 
+        throws ServiceFailure {
+        try {
+            IBindingFactory bfact = BindingDirectory.getFactory(SystemMetadata.class);
+            IUnmarshallingContext uctx = bfact.createUnmarshallingContext();
+            SystemMetadata sysmeta = (SystemMetadata) uctx.unmarshalDocument(xml, null);
+            return sysmeta;
+        } catch (JiBXException e) {
+            throw new ServiceFailure(1190, "Failed to serialize and insert SystemMetadata: " + e.getMessage());
+        }    
+    }
 }
