Index: test/edu/ucsb/nceas/MCTestCase.java
===================================================================
--- test/edu/ucsb/nceas/MCTestCase.java	(revision 5285)
+++ test/edu/ucsb/nceas/MCTestCase.java	(revision 5286)
@@ -59,6 +59,7 @@
 import edu.ucsb.nceas.metacat.client.MetacatInaccessibleException;
 import edu.ucsb.nceas.metacat.properties.PropertyService;
 import edu.ucsb.nceas.metacat.shared.ServiceException;
+import edu.ucsb.nceas.metacat.util.DocumentUtil;
 import edu.ucsb.nceas.metacat.util.RequestUtil;
 import edu.ucsb.nceas.utilities.IOUtil;
 import edu.ucsb.nceas.utilities.PropertyNotFoundException;
@@ -515,31 +516,13 @@
 		} catch (InterruptedException ie) {
 			debug("Could not sleep: " + ie.getMessage());
 		}
-		
-		StringBuffer docid = new StringBuffer(prefix);
-		docid.append(".");
 
-		// Create a calendar to get the date formatted properly
-		String[] ids = TimeZone.getAvailableIDs(-8 * 60 * 60 * 1000);
-		SimpleTimeZone pdt = new SimpleTimeZone(-8 * 60 * 60 * 1000, ids[0]);
-		pdt.setStartRule(Calendar.APRIL, 1, Calendar.SUNDAY, 2 * 60 * 60 * 1000);
-		pdt.setEndRule(Calendar.OCTOBER, -1, Calendar.SUNDAY, 2 * 60 * 60 * 1000);
-		Calendar calendar = new GregorianCalendar(pdt);
-		Date trialTime = new Date();
-		calendar.setTime(trialTime);
-		docid.append(calendar.get(Calendar.YEAR));
-		docid.append(calendar.get(Calendar.DAY_OF_YEAR));
-		docid.append(calendar.get(Calendar.HOUR_OF_DAY));
-		docid.append(calendar.get(Calendar.MINUTE));
-		docid.append(calendar.get(Calendar.SECOND));
-
-		return docid.toString();
+		return DocumentUtil.generateDocumentId(prefix, 0);
 	}
 	
 	/**
 	 * Insert a document into metacat. The expected result is passed as result
 	 */
-
 	protected String insertDocumentId(String docid, String docText, boolean result,
 			boolean expectKarmaException) {
 		debug("insertDocumentId() - docid=" + docid + " expectedResult=" + result
Index: test/edu/ucsb/nceas/metacattest/restservice/MetacatRestClientTest.java
===================================================================
--- test/edu/ucsb/nceas/metacattest/restservice/MetacatRestClientTest.java	(revision 5285)
+++ test/edu/ucsb/nceas/metacattest/restservice/MetacatRestClientTest.java	(revision 5286)
@@ -25,6 +25,11 @@
 import java.io.IOException;
 import java.io.Reader;
 import java.io.StringReader;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.SimpleTimeZone;
+import java.util.TimeZone;
 import java.util.Vector;
 
 import junit.framework.Test;
@@ -204,9 +209,7 @@
         debug("-------------------------------------------------------"); 
         try {
             IdentifierManager im = IdentifierManager.getInstance();
-            String docid = insertTestDocument();
-            String guid = "test:"+docid;
-            im.createMapping(guid, docid);
+            String guid = insertTestDocument();
             Reader r =  m.getObject(guid, null);            
             String doc = IOUtil.getAsString(r, true);
             doc = doc +"\n";
@@ -358,7 +361,7 @@
                     accessBlock, null, null,
                     null, null);
             String docid = generateDocumentId();
-            
+            debug("Generated id: " + docid);
     		StringReader sr = new StringReader(emldoc);	
     		m.login(username,password);
 
@@ -368,6 +371,8 @@
     		debug("response:\n"+response);
             assertTrue(response.indexOf("success") != -1);
     		
+            Thread.sleep(5000);
+
     		sr = new StringReader(emldoc);
     		debug("\nNow update the document...");
     		response = m.putObject(docid + ".2",sr,false);    	 
@@ -375,7 +380,7 @@
             assertTrue(response.indexOf("success") != -1);
     		sr.close();
     		
-    		Thread.sleep(10000);
+    		Thread.sleep(5000);
     		
     		debug("\nFinally delete the document...");
     		response = m.deleteObject(docid + ".2");  
@@ -499,7 +504,7 @@
           }
     }
     
-    /** Insert a test document, returning the docid that was used. */
+    /** Insert a test document, returning the identifier that was used. */
     private String insertTestDocument()
     {
         String accessBlock = getAccessBlock("public", true, true,
@@ -508,12 +513,13 @@
                 null, "http://fake.example.com/somedata", null,
                 accessBlock, null, null,
                 null, null);
-        String docid = generateDocumentId() + ".1";
+        //String docid = generateDocumentId() + ".1";
+        String guid = "testid:" + generateTimeString();
         StringReader sr = new StringReader(emldoc);        
         String response;
         try {
             m.login(username,password);
-            response = m.putObject(docid,sr,true);
+            response = m.putObject(guid, sr, true);
             debug("response:\n"+response);
             assertTrue(response.indexOf("success") != -1);
         } catch (InsufficientKarmaException e) {
@@ -527,6 +533,29 @@
         } catch (MetacatAuthException e) {
             fail(e.getMessage());
         }
-        return docid;
+        return guid;
     }
+    
+    /** Generate a timestamp for use in IDs. */
+    private String generateTimeString()
+    {
+        StringBuffer guid = new StringBuffer();
+
+        // Create a calendar to get the date formatted properly
+        String[] ids = TimeZone.getAvailableIDs(-8 * 60 * 60 * 1000);
+        SimpleTimeZone pdt = new SimpleTimeZone(-8 * 60 * 60 * 1000, ids[0]);
+        pdt.setStartRule(Calendar.APRIL, 1, Calendar.SUNDAY, 2 * 60 * 60 * 1000);
+        pdt.setEndRule(Calendar.OCTOBER, -1, Calendar.SUNDAY, 2 * 60 * 60 * 1000);
+        Calendar calendar = new GregorianCalendar(pdt);
+        Date trialTime = new Date();
+        calendar.setTime(trialTime);
+        guid.append(calendar.get(Calendar.YEAR));
+        guid.append(calendar.get(Calendar.DAY_OF_YEAR));
+        guid.append(calendar.get(Calendar.HOUR_OF_DAY));
+        guid.append(calendar.get(Calendar.MINUTE));
+        guid.append(calendar.get(Calendar.SECOND));
+        guid.append(calendar.get(Calendar.MILLISECOND));
+
+        return guid.toString();
+    }
 }
Index: src/edu/ucsb/nceas/metacat/restservice/ResourceHandler.java
===================================================================
--- src/edu/ucsb/nceas/metacat/restservice/ResourceHandler.java	(revision 5285)
+++ src/edu/ucsb/nceas/metacat/restservice/ResourceHandler.java	(revision 5286)
@@ -227,13 +227,15 @@
     private void loadSessionData() {
         SessionData sessionData = RequestUtil.getSessionData(request);
 
+        // TODO: validate the session before allowing these values to be set
         username = sessionData.getUserName();
         password = sessionData.getPassword();
         groupNames = sessionData.getGroupNames();
         sessionId = sessionData.getId();
 
-        if (username == null)
+        if (username == null) {
             username = "public";
+        }
     }
 
     /**
@@ -344,11 +346,22 @@
 
     /**
      *  Earthgrid API > Identifier Service > isRegistered Function : calls MetacatHandler > handleIdIsRegisteredAction
-     * @param identifierId
+     * @param guid
      * @throws IOException
      */
-    private void isRegistered(String identifierId) throws IOException {
-        params.put("docid", new String[] { identifierId });
+    private void isRegistered(String guid) throws IOException
+    {
+        
+        // Look up the localId for this guid
+        IdentifierManager im = IdentifierManager.getInstance();
+        String localId = "";
+        try {
+            localId = im.getLocalId(guid);
+        } catch (McdbDocNotFoundException e) {
+            // TODO: Need to return the proper DataONE exception
+        }
+        
+        params.put("docid", new String[] { localId });
         PrintWriter out = response.getWriter();
         handler.handleIdIsRegisteredAction(out, params, response);
         out.close();
@@ -366,25 +379,35 @@
 
     /**
      * Earthgrid API > Identifier Service > getNextRevision Function : calls MetacatHandler > handleGetRevisionAndDocTypeAction
-     * @param identifierId
+     * @param guid
      * @throws IOException
      */
-    private void getNextRevision(String identifierId) throws IOException {
-        params.put("docid", new String[] { identifierId });
+    private void getNextRevision(String guid) throws IOException 
+    {
+        params.put("docid", new String[] { guid });
         PrintWriter out = response.getWriter();
         //handler.handleGetRevisionAndDocTypeAction(out, params);
 
         try {
             // Make sure there is a docid
-            if (identifierId == null || identifierId.equals("")) {
+            if (guid == null || guid.equals("")) {
                 throw new Exception("User didn't specify docid!");
-            }//if
+            }
 
+            // Look up the localId for this guid
+            IdentifierManager im = IdentifierManager.getInstance();
+            String localId = "";
+            try {
+                localId = im.getLocalId(guid);
+            } catch (McdbDocNotFoundException e) {
+                // TODO: Need to return the proper DataONE exception
+            }
+           
             // Create a DBUtil object
             DBUtil dbutil = new DBUtil();
             // Get a rev and doctype
             String revAndDocType = dbutil
-                    .getCurrentRevisionAndDocTypeForGivenDocument(identifierId);
+                    .getCurrentRevisionAndDocTypeForGivenDocument(localId);
             int revision = Integer.parseInt(revAndDocType.split(";")[0]) + 1;
 
             out.println("<?xml version=\"1.0\"?>");
@@ -425,7 +448,7 @@
         try {
             localId = im.getLocalId(guid);
         } catch (McdbDocNotFoundException e) {
-            // Need to return the proper DataONE exception
+            // TODO: Need to return the proper DataONE exception
         }
         
         // Now use that localId to read the object and return it
@@ -454,7 +477,7 @@
     private void query() throws Exception {
         /*  This block commented out because of the EcoGrid circular dependency.
          *  For now, query will not be supported until the circularity can be
-         *  resolved, probably by movind the ecogrid query syntax transformers
+         *  resolved, probably by moving the ecogrid query syntax transformers
          *  directly into the Metacat codebase.  MBJ 2010-02-03
          
         try {
@@ -509,11 +532,23 @@
      */
     private void putObject(String objectId) throws IOException {
 
+        // 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
+        
         String action = request.getParameter(FUNCTION_KEYWORD);
 
         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)
@@ -524,7 +559,8 @@
                 buffer.append(line);
             }
 
-            params.put("docid", new String[] { objectId });
+            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 });
 
@@ -534,10 +570,12 @@
                         params, username, groupNames);
                 out.close();
             } else {
+                // TODO: throw exception to show lack of credentials
                 printError("Permission denied for user " + username, response);
 
             }
         } else {
+            // TODO: throw the proper exception to indicate an invalid request
             printError("Specifiy the operation type.(update or insert)",
                     response);
         }
Index: src/edu/ucsb/nceas/metacat/util/DocumentUtil.java
===================================================================
--- src/edu/ucsb/nceas/metacat/util/DocumentUtil.java	(revision 5285)
+++ src/edu/ucsb/nceas/metacat/util/DocumentUtil.java	(revision 5286)
@@ -28,8 +28,13 @@
 
 import java.io.PrintWriter;
 import java.sql.SQLException;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
 import java.util.Hashtable;
+import java.util.SimpleTimeZone;
 import java.util.Stack;
+import java.util.TimeZone;
 import java.util.Vector;
 
 import javax.servlet.http.HttpServletRequest;
@@ -60,14 +65,21 @@
     
     private static Logger logMetacat = Logger.getLogger(DocumentUtil.class);
     private static char separator = '.';
-
+    private static String prefix = "autogen";
+    
     static {
         try {
-        	separator = PropertyService.getProperty("document.accNumSeparator").charAt(0);
+        	separator = PropertyService.getProperty("document.accNumSeparator").charAt(0);    	
         } catch (PropertyNotFoundException pnfe) {
-        	logMetacat.error("DocumentUtil() - Could not retrieve account number separator. " 
+        	logMetacat.error("DocumentUtil() - Could not retrieve accession number separator. " 
         			+ "Separator set to '.' : " + pnfe.getMessage());
         }
+        try {
+            prefix = PropertyService.getProperty("document.accNumPrefix");      
+        } catch (PropertyNotFoundException pnfe) {
+            logMetacat.error("DocumentUtil() - Could not retrieve accession number prefix. " 
+                    + "Prefix set to " + prefix + ": " + pnfe.getMessage());
+        }
     }
 
     /**
@@ -486,5 +498,53 @@
     	
     	out.write(result);
     }
+    
+    /**
+     * Create a unique docid for use in inserts and updates using the default
+     * prefix from the document.accNumPrefix property. Does not include the 
+     * 'revision' part of the id if revision is '0', otherwise sets the 
+     * revision number to 'revision'.
+     * 
+     * @param idPrefix the prefix to be used to construct the scope portion of the docid
+     * @param revision the integer revision to use for this docid
+     * @return a String docid based on the current date and time
+     */
+    public static String generateDocumentId(int revision) {
+        return generateDocumentId(prefix, revision);
+    }
+    
+    /**
+     * Create a unique docid for use in inserts and updates using the prefix
+     * that is provided. Does not include the 'revision' part of the id if 
+     * revision is '0', otherwise sets the revision number to 'revision'.
+     * 
+     * @param idPrefix the prefix to be used to construct the scope portion of the docid
+     * @param revision the integer revision to use for this docid
+     * @return a String docid based on the current date and time
+     */
+    public static String generateDocumentId(String idPrefix, int revision)
+    {
+        StringBuffer docid = new StringBuffer(idPrefix);
+        docid.append(".");
 
+        // Create a calendar to get the date formatted properly
+        String[] ids = TimeZone.getAvailableIDs(-8 * 60 * 60 * 1000);
+        SimpleTimeZone pdt = new SimpleTimeZone(-8 * 60 * 60 * 1000, ids[0]);
+        pdt.setStartRule(Calendar.APRIL, 1, Calendar.SUNDAY, 2 * 60 * 60 * 1000);
+        pdt.setEndRule(Calendar.OCTOBER, -1, Calendar.SUNDAY, 2 * 60 * 60 * 1000);
+        Calendar calendar = new GregorianCalendar(pdt);
+        Date trialTime = new Date();
+        calendar.setTime(trialTime);
+        docid.append(calendar.get(Calendar.YEAR));
+        docid.append(calendar.get(Calendar.DAY_OF_YEAR));
+        docid.append(calendar.get(Calendar.HOUR_OF_DAY));
+        docid.append(calendar.get(Calendar.MINUTE));
+        docid.append(calendar.get(Calendar.SECOND));
+        docid.append(calendar.get(Calendar.MILLISECOND));
+
+        if (revision > 0) {
+            docid.append(".").append(revision);
+        }
+        return docid.toString();
+    }
 }
Index: src/edu/ucsb/nceas/metacat/IdentifierManager.java
===================================================================
--- src/edu/ucsb/nceas/metacat/IdentifierManager.java	(revision 5285)
+++ src/edu/ucsb/nceas/metacat/IdentifierManager.java	(revision 5286)
@@ -32,6 +32,7 @@
 
 import edu.ucsb.nceas.metacat.database.DBConnection;
 import edu.ucsb.nceas.metacat.database.DBConnectionPool;
+import edu.ucsb.nceas.metacat.util.DocumentUtil;
 
 /**
  * Manage the relationship between Metacat local identifiers (LocalIDs) that are
@@ -186,4 +187,49 @@
             DBConnectionPool.returnDBConnection(dbConn, serialNumber);
         }
     }
+
+    /**
+     * Given a global identifier (guid), create a suitable local identifier that
+     * follows Metacat's docid semantics and format (scope.id.rev), and create
+     * a mapping between these two identifiers.  This effectively reserves both
+     * the global and the local identifier, as they will now be present in the
+     * identifier mapping table.  If the incoming guid has the syntax of a
+     * Metacat docid (scope.id.rev), then simply use it.
+     * 
+     * @param guid the global string identifier
+     * @param rev the revision number to be used in the localId
+     * @return String containing the localId to be used for Metacat operations
+     */
+    public String generateLocalId(String guid, int rev) 
+    {
+        String localId = "";
+        boolean conformsToDocidFormat = false;
+        
+        // Check if the guid passed in is already in docid (scope.id.rev) format
+        try {
+            AccessionNumber acc = new AccessionNumber(guid, "NONE");
+            if (new Integer(acc.getRev()).intValue() > 0) {
+                conformsToDocidFormat = true;
+            }
+        } catch (NumberFormatException e) {
+            // No action needed, simply detecting invalid AccessionNumbers
+        } catch (AccessionNumberException e) {
+            // No action needed, simply detecting invalid AccessionNumbers
+        } catch (SQLException e) {
+            // No action needed, simply detecting invalid AccessionNumbers
+        }
+        
+        if (conformsToDocidFormat) {
+            // if it conforms, use it for both guid and localId
+            localId = guid;
+        } else {
+            // if not, then generate a new unique localId
+            localId = DocumentUtil.generateDocumentId(rev);
+        }
+        
+        // Register this new pair in the identifier mapping table
+        createMapping(guid, localId);
+        
+        return localId;
+    }
 }
