Index: src/edu/ucsb/nceas/metacat/restservice/CNRestServlet.java
===================================================================
--- src/edu/ucsb/nceas/metacat/restservice/CNRestServlet.java	(revision 8809)
+++ src/edu/ucsb/nceas/metacat/restservice/CNRestServlet.java	(nonexistent)
@@ -1,47 +0,0 @@
-/**
- *  '$RCSfile$'
- *  Copyright: 2000 Regents of the University of California and the
- *              National Center for Ecological Analysis and Synthesis
- *
- *   '$Author$'
- *     '$Date$'
- *
- * 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 javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-
-/**
- * Routes CN REST service requests to the appropriate handler
- *  
- */
-public class CNRestServlet extends D1RestServlet {
-    
-	/**
-	 * Provide a CNResourceHandler subclass of D1ResourceHandler
-	 */
-	@Override
-    protected D1ResourceHandler createHandler(HttpServletRequest request, HttpServletResponse response) 
-    	throws ServletException, IOException {
-        return new CNResourceHandler(getServletContext(), request, response);
-    }
-
-}

Property changes on: src/edu/ucsb/nceas/metacat/restservice/CNRestServlet.java
___________________________________________________________________
Deleted: svn:eol-style
## -1 +0,0 ##
-native
\ No newline at end of property
Deleted: svn:keywords
## -1 +0,0 ##
-Author Date Id Revision
\ No newline at end of property
Index: src/edu/ucsb/nceas/metacat/restservice/CNResourceHandler.java
===================================================================
--- src/edu/ucsb/nceas/metacat/restservice/CNResourceHandler.java	(revision 8809)
+++ src/edu/ucsb/nceas/metacat/restservice/CNResourceHandler.java	(nonexistent)
@@ -1,1702 +0,0 @@
-/**
- *  '$RCSfile$'
- *  Copyright: 2011 Regents of the University of California and the
- *              National Center for Ecological Analysis and Synthesis
- *
- *   '$Author$'
- *     '$Date$'
- *
- * 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.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Date;
-import java.util.Enumeration;
-import java.util.Map;
-
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.xml.parsers.ParserConfigurationException;
-
-import org.apache.commons.fileupload.FileUploadException;
-import org.apache.commons.io.IOUtils;
-import org.apache.log4j.Logger;
-import org.dataone.client.ObjectFormatCache;
-import org.dataone.client.formats.ObjectFormatInfo;
-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.NotFound;
-import org.dataone.service.exceptions.NotImplemented;
-import org.dataone.service.exceptions.ServiceFailure;
-import org.dataone.service.exceptions.UnsupportedType;
-import org.dataone.service.exceptions.VersionMismatch;
-import org.dataone.service.types.v1.AccessPolicy;
-import org.dataone.service.types.v1.Checksum;
-import org.dataone.service.types.v1.ChecksumAlgorithmList;
-import org.dataone.service.types.v1.DescribeResponse;
-import org.dataone.service.types.v1.Event;
-import org.dataone.service.types.v1.Identifier;
-import org.dataone.service.types.v1.Log;
-import org.dataone.service.types.v1.NodeReference;
-import org.dataone.service.types.v1.ObjectFormat;
-import org.dataone.service.types.v1.ObjectFormatIdentifier;
-import org.dataone.service.types.v1.ObjectFormatList;
-import org.dataone.service.types.v1.ObjectList;
-import org.dataone.service.types.v1.ObjectLocationList;
-import org.dataone.service.types.v1.Permission;
-import org.dataone.service.types.v1.Replica;
-import org.dataone.service.types.v1.ReplicationPolicy;
-import org.dataone.service.types.v1.ReplicationStatus;
-import org.dataone.service.types.v1.Subject;
-import org.dataone.service.types.v1.SystemMetadata;
-import org.dataone.service.util.Constants;
-import org.dataone.service.util.DateTimeMarshaller;
-import org.dataone.service.util.EncodingUtilities;
-import org.dataone.service.util.TypeMarshaller;
-import org.jibx.runtime.JiBXException;
-import org.xml.sax.SAXException;
-
-import edu.ucsb.nceas.metacat.dataone.CNodeService;
-import edu.ucsb.nceas.metacat.properties.PropertyService;
-import edu.ucsb.nceas.utilities.PropertyNotFoundException;
-
-/**
- * CN REST service implementation handler
- * 
- * ****************** CNCore -- DONE create() - POST /d1/cn/object/PID
- * listFormats() - GET /d1/cn/formats getFormat() - GET /d1/cn/formats/FMTID
- * getLogRecords - GET /d1/cn/log reserveIdentifier() - POST /d1/cn/reserve
- * listNodes() - Not implemented registerSystemMetadata() - POST /d1/meta/PID
- * 
- * CNRead -- DONE get() - GET /d1/cn/object/PID getSystemMetadata() - GET
- * /d1/cn/meta/PID resolve() - GET /d1/cn/resolve/PID assertRelation() - GET
- * /d1/cn/assertRelation/PID getChecksum() - GET /d1/cn/checksum search() - Not
- * implemented in Metacat
- * 
- * CNAuthorization setOwner() - PUT /d1/cn/owner/PID isAuthorized() - GET
- * /d1/cn/isAuthorized/PID setAccessPolicy() - POST /d1/cn/accessRules
- * 
- * CNIdentity - not implemented at all on Metacat
- * 
- * CNReplication setReplicationStatus() - PUT /replicaNotifications/PID
- * updateReplicationMetadata() - PUT /replicaMetadata/PID setReplicationPolicy()
- * - PUT /replicaPolicies/PID isNodeAuthorized() - GET
- * /replicaAuthorizations/PID
- * 
- * CNRegister -- not implemented at all in Metacat ******************
- * 
- * @author leinfelder
- * 
- */
-public class CNResourceHandler extends D1ResourceHandler {
-
-    /** CN-specific operations **/
-    protected static final String RESOURCE_RESERVE = "reserve";
-    protected static final String RESOURCE_FORMATS = "formats";
-    protected static final String RESOURCE_RESOLVE = "resolve";
-    protected static final String RESOURCE_OWNER = "owner";
-    protected static final String RESOURCE_REPLICATION_POLICY = "replicaPolicies";
-    protected static final String RESOURCE_REPLICATION_META = "replicaMetadata";
-    protected static final String RESOURCE_REPLICATION_AUTHORIZED = "replicaAuthorizations";
-    protected static final String RESOURCE_REPLICATION_NOTIFY = "replicaNotifications";
-
-    public CNResourceHandler(ServletContext servletContext,
-            HttpServletRequest request, HttpServletResponse response) {
-        super(servletContext, request, response);
-        logMetacat = Logger.getLogger(CNResourceHandler.class);
-    }
-
-    /**
-     * This function is called from REST API servlet and handles each request to
-     * the servlet
-     * 
-     * @param httpVerb
-     *            (GET, POST, PUT or DELETE)
-     */
-    @Override
-    public void handle(byte httpVerb) {
-        // prepare the handler
-        super.handle(httpVerb);
-
-        try {
-
-        	// only service requests if we have D1 configured
-        	if (!isD1Enabled()) {
-        		ServiceFailure se = new ServiceFailure("0000", "DataONE services are not enabled on this node");
-                serializeException(se, response.getOutputStream());
-                return;
-        	}
-        	
-            // get the resource
-            String resource = request.getPathInfo();
-            resource = resource.substring(resource.indexOf("/") + 1);
-
-            // for the rest of the resouce
-            String extra = null;
-
-            logMetacat.debug("handling verb " + httpVerb
-                    + " request with resource '" + resource + "'");
-            boolean status = false;
-
-            if (resource != null) {
-
-                if (resource.startsWith(RESOURCE_ACCESS_RULES)
-                        && httpVerb == PUT) {
-                    logMetacat.debug("Setting access policy");
-                    // after the command
-                    extra = parseTrailing(resource, RESOURCE_ACCESS_RULES);
-                    setAccess(extra);
-                    status = true;
-                    logMetacat.debug("done setting access");
-
-                } else if (resource.startsWith(RESOURCE_META)) {
-                    logMetacat.debug("Using resource: " + RESOURCE_META);
-
-                    // after the command
-                    extra = parseTrailing(resource, RESOURCE_META);
-
-                    // get
-                    if (httpVerb == GET) {
-                        getSystemMetadataObject(extra);
-                        status = true;
-                    }
-                    // post to register system metadata
-                    if (httpVerb == POST) {
-                        registerSystemMetadata();
-                        status = true;
-                    }
-
-                } else if (resource.startsWith(RESOURCE_RESERVE)) {
-                    // reserve the ID (in params)
-                    if (httpVerb == POST) {
-                        reserve();
-                        status = true;
-                    }
-                } else if (resource.startsWith(RESOURCE_RESOLVE)) {
-
-                    // after the command
-                    extra = parseTrailing(resource, RESOURCE_RESOLVE);
-
-                    // resolve the object location
-                    if (httpVerb == GET) {
-                        resolve(extra);
-                        status = true;
-                    }
-                } else if (resource.startsWith(RESOURCE_OWNER)) {
-
-                    // after the command
-                    extra = parseTrailing(resource, RESOURCE_OWNER);
-
-                    // set the owner
-                    if (httpVerb == PUT) {
-                        owner(extra);
-                        status = true;
-                    }
-                } else if (resource.startsWith(RESOURCE_IS_AUTHORIZED)) {
-
-                    // after the command
-                    extra = parseTrailing(resource, RESOURCE_IS_AUTHORIZED);
-
-                    // authorized?
-                    if (httpVerb == GET) {
-                        isAuthorized(extra);
-                        status = true;
-                    }
-                } else if (resource.startsWith(RESOURCE_OBJECTS)) {
-                    logMetacat.debug("Using resource 'object'");
-                    logMetacat
-                            .debug("D1 Rest: Starting resource processing...");
-
-                    // after the command
-                    extra = parseTrailing(resource, RESOURCE_OBJECTS);
-
-                    logMetacat.debug("objectId: " + extra);
-                    logMetacat.debug("verb:" + httpVerb);
-
-                    if (httpVerb == GET) {
-                        if (extra != null) {
-                            getObject(extra);
-                        } else {
-                            listObjects();
-                        }
-                        status = true;
-                    } else if (httpVerb == POST) {
-                        putObject(FUNCTION_NAME_INSERT);
-                        status = true;
-                    } else if (httpVerb == HEAD) {
-                        describeObject(extra);
-                        status = true;
-                    } else if (httpVerb == DELETE) {
-                        deleteObject(extra);
-                        status = true;
-                    } 
-
-                } else if (resource.startsWith(RESOURCE_FORMATS)) {
-                    logMetacat.debug("Using resource: " + RESOURCE_FORMATS);
-
-                    // after the command
-                    extra = parseTrailing(resource, RESOURCE_FORMATS);
-
-                    // handle each verb
-                    if (httpVerb == GET) {
-                        if (extra == null) {
-                            // list the formats collection
-                            listFormats();
-                        } else {
-                            // get the specified format
-                            getFormat(extra);
-                        }
-                        status = true;
-                    }
-
-                } else if (resource.startsWith(RESOURCE_LOG)) {
-                    logMetacat.debug("Using resource: " + RESOURCE_LOG);
-                    // handle log events
-                    if (httpVerb == GET) {
-                        getLog();
-                        status = true;
-                    }
-
-                } else if (resource.startsWith(Constants.RESOURCE_ARCHIVE)) {
-                    logMetacat.debug("Using resource " + Constants.RESOURCE_ARCHIVE);
-                    // handle archive events
-                    if (httpVerb == PUT) {
-                        extra = parseTrailing(resource, Constants.RESOURCE_ARCHIVE);
-                        archive(extra);
-                        status = true;
-                    }
-                } else if (resource.startsWith(Constants.RESOURCE_CHECKSUM)) {
-                    logMetacat.debug("Using resource: " + Constants.RESOURCE_CHECKSUM);
-
-                    // after the command
-                    extra = parseTrailing(resource, Constants.RESOURCE_CHECKSUM);
-
-                    // handle checksum requests
-                    if (httpVerb == GET) {
-
-                    	if (extra != null && extra.length() > 0) {
-	                        checksum(extra);
-	                        status = true;
-                    	} else {
-                    		listChecksumAlgorithms();
-                    		status = true;
-                    	}
-
-                    }
-
-                } else if (resource.startsWith(RESOURCE_REPLICATION_POLICY)
-                        && httpVerb == PUT) {
-
-                    logMetacat.debug("Using resource: "
-                            + RESOURCE_REPLICATION_POLICY);
-                    // get the trailing pid
-                    extra = parseTrailing(resource, RESOURCE_REPLICATION_POLICY);
-                    setReplicationPolicy(extra);
-                    status = true;
-
-                } else if (resource.startsWith(RESOURCE_REPLICATION_META)
-                        && httpVerb == PUT) {
-
-                    logMetacat.debug("Using resource: "
-                            + RESOURCE_REPLICATION_META);
-                    // get the trailing pid
-                    extra = parseTrailing(resource, RESOURCE_REPLICATION_META);
-                    updateReplicationMetadata(extra);
-                    status = true;
-
-                } else if (resource.startsWith(RESOURCE_REPLICATION_NOTIFY)
-                        && httpVerb == PUT) {
-
-                    logMetacat.debug("Using resource: "
-                            + RESOURCE_REPLICATION_NOTIFY);
-                    // get the trailing pid
-                    extra = parseTrailing(resource, RESOURCE_REPLICATION_NOTIFY);
-                    setReplicationStatus(extra);
-                    status = true;
-
-                } else if (resource.startsWith(RESOURCE_REPLICATION_AUTHORIZED)
-                        && httpVerb == GET) {
-
-                    logMetacat.debug("Using resource: "
-                            + RESOURCE_REPLICATION_AUTHORIZED);
-                    // get the trailing pid
-                    extra = parseTrailing(resource,
-                            RESOURCE_REPLICATION_AUTHORIZED);
-                    isNodeAuthorized(extra);
-                    status = true;
-
-                } else if (resource.startsWith(Constants.RESOURCE_MONITOR_PING)) {
-                    if (httpVerb == GET) {
-                    	// after the command
-                        extra = parseTrailing(resource, Constants.RESOURCE_MONITOR_PING);
-                        
-                        logMetacat.debug("processing ping request");
-                        Date result = CNodeService.getInstance(request).ping();
-                        // TODO: send to output	
-                        status = true;
-                    }
-                } else if (resource.startsWith(Constants.RESOURCE_META_OBSOLETEDBY)
-                        && httpVerb == PUT) {
-
-                    logMetacat.debug("Using resource: "
-                            + Constants.RESOURCE_META_OBSOLETEDBY);
-                    // get the trailing pid
-                    extra = parseTrailing(resource, Constants.RESOURCE_META_OBSOLETEDBY);
-                    setObsoletedBy(extra);
-                    status = true;
-                } else if (resource.startsWith(Constants.RESOURCE_REPLICATION_DELETE_REPLICA)
-                        && httpVerb == PUT) {
-
-                    logMetacat.debug("Using resource: "
-                            + Constants.RESOURCE_REPLICATION_DELETE_REPLICA);
-                    // get the trailing pid
-                    extra = parseTrailing(resource, Constants.RESOURCE_REPLICATION_DELETE_REPLICA);
-                    deleteReplica(extra);
-                    status = true;
-                }
-
-                if (!status) {
-                    throw new ServiceFailure("0000", "Unknown error, status = "
-                            + status);
-                }
-            } else {
-                throw new InvalidRequest("0000", "No resource matched for "
-                        + resource);
-            }
-        } catch (BaseException be) {
-            // report Exceptions as clearly and generically as possible
-            OutputStream out = null;
-            try {
-                out = response.getOutputStream();
-            } catch (IOException ioe) {
-                logMetacat.error("Could not get output stream from response",
-                        ioe);
-            }
-            serializeException(be, out);
-        } catch (Exception e) {
-            // report Exceptions as clearly and generically as possible
-            logMetacat.error(e.getClass() + ": " + e.getMessage(), e);
-            OutputStream out = null;
-            try {
-                out = response.getOutputStream();
-            } catch (IOException ioe) {
-                logMetacat.error("Could not get output stream from response",
-                        ioe);
-            }
-            ServiceFailure se = new ServiceFailure("0000", e.getMessage());
-            serializeException(se, out);
-        }
-    }
-
-    /**
-     * Get the checksum for the given guid
-     * 
-     * @param guid
-     * @throws NotImplemented
-     * @throws InvalidRequest
-     * @throws NotFound
-     * @throws NotAuthorized
-     * @throws ServiceFailure
-     * @throws InvalidToken
-     * @throws IOException
-     * @throws JiBXException
-     */
-    private void checksum(String guid) throws InvalidToken, ServiceFailure,
-            NotAuthorized, NotFound, InvalidRequest, NotImplemented,
-            JiBXException, IOException {
-        Identifier guidid = new Identifier();
-        guidid.setValue(guid);
-        logMetacat.debug("getting checksum for object " + guid);
-        Checksum c = CNodeService.getInstance(request).getChecksum(session,
-                guidid);
-        logMetacat.debug("got checksum " + c.getValue());
-        response.setStatus(200);
-        logMetacat.debug("serializing response");
-        TypeMarshaller.marshalTypeToOutputStream(c, response.getOutputStream());
-        logMetacat.debug("done serializing response.");
-
-    }
-
-    /**
-     * get the logs based on passed params. Available params are token,
-     * fromDate, toDate, event. See
-     * http://mule1.dataone.org/ArchitectureDocs/mn_api_crud
-     * .html#MN_crud.getLogRecords for more info
-     * 
-     * @throws NotImplemented
-     * @throws InvalidRequest
-     * @throws NotAuthorized
-     * @throws ServiceFailure
-     * @throws InvalidToken
-     * @throws IOException
-     * @throws JiBXException
-     */
-    private void getLog() throws InvalidToken, ServiceFailure, NotAuthorized,
-            InvalidRequest, NotImplemented, IOException, JiBXException {
-
-        Date fromDate = null;
-        Date toDate = null;
-        Event event = null;
-        Integer start = null;
-        Integer count = null;
-        String pidFilter = null;
-
-        try {
-            String fromDateS = params.get("fromDate")[0];
-            logMetacat.debug("param fromDateS: " + fromDateS);
-            fromDate = DateTimeMarshaller.deserializeDateToUTC(fromDateS);
-        } catch (Exception e) {
-            logMetacat.warn("Could not parse fromDate: " + e.getMessage());
-        }
-        try {
-            String toDateS = params.get("toDate")[0];
-            logMetacat.debug("param toDateS: " + toDateS);
-            toDate = DateTimeMarshaller.deserializeDateToUTC(toDateS);
-        } catch (Exception e) {
-            logMetacat.warn("Could not parse toDate: " + e.getMessage());
-        }
-        try {
-            String eventS = params.get("event")[0];
-            event = Event.convert(eventS);
-        } catch (Exception e) {
-            logMetacat.warn("Could not parse event: " + e.getMessage());
-        }
-        logMetacat.debug("fromDate: " + fromDate + " toDate: " + toDate);
-
-        try {
-            start = Integer.parseInt(params.get("start")[0]);
-        } catch (Exception e) {
-            logMetacat.warn("Could not parse start: " + e.getMessage());
-        }
-        try {
-            count = Integer.parseInt(params.get("count")[0]);
-        } catch (Exception e) {
-            logMetacat.warn("Could not parse count: " + e.getMessage());
-        }
-
-        try {
-            pidFilter = params.get("pidFilter")[0];
-        } catch (Exception e) {
-            logMetacat.warn("Could not parse pidFilter: " + e.getMessage());
-        }
-        
-        logMetacat.debug("calling getLogRecords");
-        Log log = CNodeService.getInstance(request).getLogRecords(session,
-                fromDate, toDate, event, pidFilter, start, count);
-
-        OutputStream out = response.getOutputStream();
-        response.setStatus(200);
-        response.setContentType("text/xml");
-
-        TypeMarshaller.marshalTypeToOutputStream(log, out);
-
-    }
-
-    /**
-     * Implements REST version of DataONE CRUD API --> get
-     * 
-     * @param guid
-     *            ID of data object to be read
-     * @throws NotImplemented
-     * @throws InvalidRequest
-     * @throws NotFound
-     * @throws NotAuthorized
-     * @throws ServiceFailure
-     * @throws InvalidToken
-     * @throws IOException
-     */
-    protected void getObject(String guid) throws InvalidToken, ServiceFailure,
-            NotAuthorized, NotFound, InvalidRequest, NotImplemented,
-            IOException {
-
-        Identifier id = new Identifier();
-        id.setValue(guid);
-
-        SystemMetadata sm = CNodeService.getInstance(request)
-                .getSystemMetadata(session, id);
-
-        // set the headers for the content
-        String mimeType = ObjectFormatInfo.instance().getMimeType(sm.getFormatId().getValue());
-        if (mimeType == null) {
-        	mimeType = "application/octet-stream";
-        }
-        String extension = ObjectFormatInfo.instance().getExtension(sm.getFormatId().getValue());
-        String filename = id.getValue();
-        if (extension != null) {
-        	filename = id.getValue() + extension;
-        }
-        response.setContentType(mimeType);
-        response.setHeader("Content-Disposition", "inline; filename=" + filename);
-
-        InputStream data = CNodeService.getInstance(request).get(session, id);
-
-        OutputStream out = response.getOutputStream();
-        response.setStatus(200);
-        IOUtils.copyLarge(data, out);
-
-    }
-
-    /**
-     * Implements REST version of DataONE CRUD API --> getSystemMetadata
-     * 
-     * @param guid
-     *            ID of data object to be read
-     * @throws NotImplemented
-     * @throws InvalidRequest
-     * @throws NotFound
-     * @throws NotAuthorized
-     * @throws ServiceFailure
-     * @throws InvalidToken
-     * @throws IOException
-     * @throws JiBXException
-     */
-    protected void getSystemMetadataObject(String guid) throws InvalidToken,
-            ServiceFailure, NotAuthorized, NotFound, InvalidRequest,
-            NotImplemented, IOException, JiBXException {
-
-        Identifier id = new Identifier();
-        id.setValue(guid);
-        SystemMetadata sysmeta = CNodeService.getInstance(request)
-                .getSystemMetadata(session, id);
-
-        response.setContentType("text/xml");
-        response.setStatus(200);
-        OutputStream out = response.getOutputStream();
-
-        // Serialize and write it to the output stream
-        TypeMarshaller.marshalTypeToOutputStream(sysmeta, out);
-    }
-
-    /**
-     * Earthgrid API > Put Service >Put Function : calls MetacatHandler >
-     * handleInsertOrUpdateAction
-     * 
-     * @param guid
-     *            - ID of data object to be inserted or updated. If action is
-     *            update, the pid is the existing pid. If insert, the pid is the
-     *            new one
-     * @throws InvalidRequest
-     * @throws ServiceFailure
-     * @throws IdentifierNotUnique
-     * @throws JiBXException
-     * @throws NotImplemented
-     * @throws InvalidSystemMetadata
-     * @throws InsufficientResources
-     * @throws UnsupportedType
-     * @throws NotAuthorized
-     * @throws InvalidToken
-     * @throws IOException
-     * @throws IllegalAccessException
-     * @throws InstantiationException
-     */
-    protected void putObject(String action) throws ServiceFailure,
-            InvalidRequest, IdentifierNotUnique, JiBXException, InvalidToken,
-            NotAuthorized, UnsupportedType, InsufficientResources,
-            InvalidSystemMetadata, NotImplemented, IOException,
-            InstantiationException, IllegalAccessException {
-    	
-        // Read the incoming data from its Mime Multipart encoding
-        Map<String, File> files = collectMultipartFiles();
-        
-	    // get the encoded pid string from the body and make the object
-        String pidString = multipartparams.get("pid").get(0);
-        Identifier pid = new Identifier();
-        pid.setValue(pidString);
-        
-        logMetacat.debug("putObject: " + pid.getValue() + "/" + action);
-        
-        InputStream object = null;
-        InputStream sysmeta = null;
-
-        File smFile = files.get("sysmeta");
-        sysmeta = new FileInputStream(smFile);
-        File objFile = files.get("object");
-        object = new FileInputStream(objFile);
-
-        if (action.equals(FUNCTION_NAME_INSERT)) { // handle inserts
-
-            logMetacat.debug("Commence creation...");
-            SystemMetadata smd = TypeMarshaller.unmarshalTypeFromStream(
-                    SystemMetadata.class, sysmeta);
-
-           
-            logMetacat.debug("creating object with pid " + pid.getValue());
-            Identifier rId = CNodeService.getInstance(request).create(session, pid, object, smd);
-
-            OutputStream out = response.getOutputStream();
-            response.setStatus(200);
-            response.setContentType("text/xml");
-
-            TypeMarshaller.marshalTypeToOutputStream(rId, out);
-
-        } else {
-            throw new InvalidRequest("1000", "Operation must be create.");
-        }
-    }
-
-    /**
-     * List the object formats registered with the system
-     * 
-     * @throws NotImplemented
-     * @throws InsufficientResources
-     * @throws NotFound
-     * @throws ServiceFailure
-     * @throws InvalidRequest
-     * @throws IOException
-     * @throws JiBXException
-     */
-    private void listFormats() throws InvalidRequest, ServiceFailure, NotFound,
-            InsufficientResources, NotImplemented, IOException, JiBXException {
-        logMetacat.debug("Entering listFormats()");
-
-        ObjectFormatList objectFormatList = CNodeService.getInstance(request)
-                .listFormats();
-        // get the response output stream
-        OutputStream out = response.getOutputStream();
-        response.setStatus(200);
-        response.setContentType("text/xml");
-
-        // style the object with a processing directive
-        String stylesheet = null;
-        try {
-            stylesheet = PropertyService.getProperty("dataone.types.xsl");
-        } catch (PropertyNotFoundException e) {
-            logMetacat.warn("Could not locate DataONE types XSLT: "
-                    + e.getMessage());
-        }
-
-        TypeMarshaller.marshalTypeToOutputStream(objectFormatList, out,
-                stylesheet);
-
-    }
-    
-    private void listChecksumAlgorithms() throws IOException, ServiceFailure,
-			NotImplemented, JiBXException {
-		logMetacat.debug("Entering listFormats()");
-
-		ChecksumAlgorithmList result = CNodeService.getInstance(request).listChecksumAlgorithms();
-
-		// get the response output stream
-		OutputStream out = response.getOutputStream();
-		response.setStatus(200);
-		response.setContentType("text/xml");
-
-		TypeMarshaller.marshalTypeToOutputStream(result, out);
-
-	}
-    
-    /**
-     * http://mule1.dataone.org/ArchitectureDocs-current/apis/CN_APIs.html#CNRead.describe
-     * @param pid
-     * @throws InvalidToken
-     * @throws ServiceFailure
-     * @throws NotAuthorized
-     * @throws NotFound
-     * @throws NotImplemented
-     * @throws InvalidRequest
-     */
-    private void describeObject(String pid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, InvalidRequest
-    {
-        response.setContentType("text/xml");
-        
-        Identifier id = new Identifier();
-        id.setValue(pid);
-        
-        DescribeResponse dr = null;
-        try {
-            dr = CNodeService.getInstance(request).describe(session, id);
-        } catch (BaseException e) {
-        	response.setStatus(e.getCode());
-        	response.addHeader("DataONE-Exception-Name", e.getClass().getName());
-            response.addHeader("DataONE-Exception-DetailCode", e.getDetail_code());
-            response.addHeader("DataONE-Exception-Description", e.getDescription());
-            response.addHeader("DataONE-Exception-PID", id.getValue());
-            return;
-		}
-        
-        response.setStatus(200);
-        //response.addHeader("pid", pid);
-        response.addHeader("DataONE-Checksum", dr.getDataONE_Checksum().getAlgorithm() + "," + dr.getDataONE_Checksum().getValue());
-        response.addHeader("Content-Length", dr.getContent_Length() + "");
-        response.addHeader("Last-Modified", DateTimeMarshaller.serializeDateToUTC(dr.getLast_Modified()));
-        response.addHeader("DataONE-ObjectFormat", dr.getDataONE_ObjectFormatIdentifier().getValue());
-        response.addHeader("DataONE-SerialVersion", dr.getSerialVersion().toString());
-
-    }
-    
-    /**
-     * Handle delete 
-     * @param pid ID of data object to be deleted
-     * @throws IOException
-     * @throws InvalidRequest 
-     * @throws NotImplemented 
-     * @throws NotFound 
-     * @throws NotAuthorized 
-     * @throws ServiceFailure 
-     * @throws InvalidToken 
-     * @throws JiBXException 
-     */
-    private void deleteObject(String pid) throws IOException, InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, InvalidRequest, JiBXException 
-    {
-
-        OutputStream out = response.getOutputStream();
-        response.setStatus(200);
-        response.setContentType("text/xml");
-
-        Identifier id = new Identifier();
-        id.setValue(pid);
-
-        logMetacat.debug("Calling delete for identifier " + pid);
-        CNodeService.getInstance(request).delete(session, id);
-        TypeMarshaller.marshalTypeToOutputStream(id, out);
-        
-    }
-    
-    /**
-     * Archives the given pid
-     * @param pid
-     * @throws InvalidToken
-     * @throws ServiceFailure
-     * @throws NotAuthorized
-     * @throws NotFound
-     * @throws NotImplemented
-     * @throws IOException
-     * @throws JiBXException
-     */
-    private void archive(String pid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, IOException, JiBXException {
-
-        OutputStream out = response.getOutputStream();
-        response.setStatus(200);
-        response.setContentType("text/xml");
-
-        Identifier id = new Identifier();
-        id.setValue(pid);
-
-        logMetacat.debug("Calling archive");
-        CNodeService.getInstance(request).archive(session, id);
-        
-        TypeMarshaller.marshalTypeToOutputStream(id, out);
-        
-    }
-
-    /**
-     * Return the requested object format
-     * 
-     * @param fmtidStr
-     *            the requested format identifier as a string
-     * @throws NotImplemented
-     * @throws InsufficientResources
-     * @throws NotFound
-     * @throws ServiceFailure
-     * @throws InvalidRequest
-     * @throws IOException
-     * @throws JiBXException
-     */
-    private void getFormat(String fmtidStr) throws InvalidRequest,
-            ServiceFailure, NotFound, InsufficientResources, NotImplemented,
-            IOException, JiBXException {
-        logMetacat.debug("Entering listFormats()");
-
-        ObjectFormatIdentifier fmtid = new ObjectFormatIdentifier();
-        fmtid.setValue(fmtidStr);
-
-        // get the specified object format
-        ObjectFormat objectFormat = CNodeService.getInstance(request)
-                .getFormat(fmtid);
-
-        OutputStream out = response.getOutputStream();
-        response.setStatus(200);
-        response.setContentType("text/xml");
-
-        TypeMarshaller.marshalTypeToOutputStream(objectFormat, out);
-
-    }
-
-    /**
-     * Reserve the given Identifier
-     * 
-     * @throws InvalidToken
-     * @throws ServiceFailure
-     * @throws NotAuthorized
-     * @throws IdentifierNotUnique
-     * @throws NotImplemented
-     * @throws InvalidRequest
-     */
-    private void reserve() 
-        throws InvalidToken, ServiceFailure, NotAuthorized, IdentifierNotUnique, 
-        NotImplemented, InvalidRequest {
-        Identifier pid = null;
-        String scope = null;
-        String format = null;
-
-        // Parse the params out of the multipart form data
-        logMetacat.debug("Parsing reserve parameters from the mime multipart entity");
-        try {
-            collectMultipartParams();
-            
-        } catch (FileUploadException e1) {
-            String msg = "FileUploadException: Couldn't parse the mime multipart information: " +
-            e1.getMessage();
-            logMetacat.debug(msg);
-            throw new ServiceFailure("4210", msg);
-
-        } catch (IOException e1) {
-            String msg = "IOException: Couldn't parse the mime multipart information: " +
-            e1.getMessage();
-            logMetacat.debug(msg);
-            throw new ServiceFailure("4210", msg);
-        
-        } catch (Exception e1) {
-            String msg = "Exception: Couldn't parse the mime multipart information: " +
-            e1.getMessage();
-            logMetacat.debug(msg);
-            throw new ServiceFailure("4210", msg);
-
-        }
-        
-        // gather the params
-        try {
-            String id = multipartparams.get("pid").get(0);
-            pid = new Identifier();
-            pid.setValue(id);
-            
-        } catch (NullPointerException e) {
-            String msg = "The 'pid' must be provided as a parameter and was not.";
-            logMetacat.error(msg);
-            throw new InvalidRequest("4200", msg);
- 
-        }
-        
-        // call the implementation
-        try {
-            Identifier resultPid = CNodeService.getInstance(request).reserveIdentifier(session, pid);
-            OutputStream out = response.getOutputStream();
-            response.setStatus(200);
-            response.setContentType("text/xml");
-            // send back the reserved pid
-            TypeMarshaller.marshalTypeToOutputStream(resultPid, out);
-            
-        } catch (IOException e) {
-            String msg = "Couldn't write the identifier to the response output stream: " +
-                e.getMessage();
-            logMetacat.debug(msg);
-            throw new ServiceFailure("4210", msg);
-        
-        } catch (JiBXException e) {
-            String msg = "Couldn't marshall the identifier to the response output stream: " +
-            e.getMessage();
-            logMetacat.debug(msg);
-            throw new ServiceFailure("4210", msg);
-            
-        }
-    }
-
-    /**
-     * 
-     * @param id
-     * @throws InvalidRequest
-     * @throws InvalidToken
-     * @throws ServiceFailure
-     * @throws NotAuthorized
-     * @throws NotFound
-     * @throws NotImplemented
-     * @throws IOException
-     * @throws JiBXException
-     */
-    private void resolve(String id) throws InvalidRequest, InvalidToken,
-            ServiceFailure, NotAuthorized, NotFound, NotImplemented,
-            IOException, JiBXException {
-        Identifier pid = new Identifier();
-        pid.setValue(id);
-        ObjectLocationList locationList = CNodeService.getInstance(request)
-                .resolve(session, pid);
-        OutputStream out = response.getOutputStream();
-        response.setStatus(200);
-        response.setContentType("text/xml");
-        TypeMarshaller.marshalTypeToOutputStream(locationList, out);
-
-    }
-
-    /**
-     * Set the owner of a resource
-     * 
-     * @param id
-     * @throws InvalidToken
-     * @throws ServiceFailure
-     * @throws NotFound
-     * @throws NotAuthorized
-     * @throws NotImplemented
-     * @throws InvalidRequest
-     * @throws IllegalAccessException
-     * @throws InstantiationException
-     * @throws VersionMismatch 
-     */
-    private void owner(String id) 
-        throws InvalidToken, ServiceFailure, NotFound, NotAuthorized, 
-        NotImplemented, InvalidRequest, InstantiationException, 
-        IllegalAccessException, VersionMismatch {
-
-        Identifier pid = new Identifier();
-        pid.setValue(id);
-
-        long serialVersion = 0L;
-        String serialVersionStr = null;
-        String userIdStr = null;
-        Subject userId = null;
-        
-        // Parse the params out of the multipart form data
-        // Read the incoming data from its Mime Multipart encoding
-        logMetacat.debug("Parsing rights holder parameters from the mime multipart entity");
-        try {
-            collectMultipartParams();
-            
-        } catch (FileUploadException e1) {
-            String msg = "FileUploadException: Couldn't parse the mime multipart information: " +
-            e1.getMessage();
-            logMetacat.debug(msg);
-            throw new ServiceFailure("4490", msg);
-
-        } catch (IOException e1) {
-            String msg = "IOException: Couldn't parse the mime multipart information: " +
-            e1.getMessage();
-            logMetacat.debug(msg);
-            throw new ServiceFailure("4490", msg);
-        
-        } catch (Exception e1) {
-            String msg = "Exception: Couldn't parse the mime multipart information: " +
-            e1.getMessage();
-            logMetacat.debug(msg);
-            throw new ServiceFailure("4490", msg);
-
-        }
-        
-        // get the serialVersion
-        try {
-            serialVersionStr = multipartparams.get("serialVersion").get(0);
-            serialVersion = new Long(serialVersionStr).longValue();
-            
-        } catch (NumberFormatException nfe) {
-            String msg = "The 'serialVersion' must be provided as a positive integer and was not.";
-            logMetacat.error(msg);
-            throw new InvalidRequest("4442", msg);
-                        
-        } catch (NullPointerException e) {
-            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
-            logMetacat.error(msg);
-            throw new InvalidRequest("4442", msg);
-            
-        }
-
-        // get the subject userId that will become the rights holder
-        try {
-            userIdStr = multipartparams.get("userId").get(0);
-            userId = new Subject();
-            userId.setValue(userIdStr);
-                                    
-        } catch (NullPointerException e) {
-            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
-            logMetacat.error(msg);
-            throw new InvalidRequest("4442", msg);
-            
-        }
-
-        // set the rights holder
-        Identifier retPid = CNodeService.getInstance(request).setRightsHolder(session, pid, userId, serialVersion);
-        
-        try {
-            OutputStream out = response.getOutputStream();
-            response.setStatus(200);
-            response.setContentType("text/xml");
-            TypeMarshaller.marshalTypeToOutputStream(retPid, out);
-            
-        } catch (IOException e) {
-            String msg = "Couldn't write the identifier to the response output stream: " +
-                e.getMessage();
-            logMetacat.debug(msg);
-            throw new ServiceFailure("4490", msg);
-        
-        } catch (JiBXException e) {
-            String msg = "Couldn't marshall the identifier to the response output stream: " +
-            e.getMessage();
-            logMetacat.debug(msg);
-            throw new ServiceFailure("4490", msg);
-            
-        }
-    }
-
-    /**
-     * Processes the authorization check for given id
-     * 
-     * @param id
-     * @return
-     * @throws ServiceFailure
-     * @throws InvalidToken
-     * @throws NotFound
-     * @throws NotAuthorized
-     * @throws NotImplemented
-     * @throws InvalidRequest
-     */
-    private boolean isAuthorized(String id) throws ServiceFailure,
-            InvalidToken, NotFound, NotAuthorized, NotImplemented,
-            InvalidRequest {
-        Identifier pid = new Identifier();
-        pid.setValue(id);
-        String permission = params.get("action")[0];
-        boolean result = CNodeService.getInstance(request).isAuthorized(
-                session, pid, Permission.convert(permission));
-        response.setStatus(200);
-        response.setContentType("text/xml");
-        return result;
-    }
-
-    /**
-     * Register System Metadata without data or metadata object
-     * 
-     * @param pid
-     *            identifier for System Metadata entry
-     * @throws JiBXException
-     * @throws FileUploadException
-     * @throws IOException
-     * @throws InvalidRequest
-     * @throws ServiceFailure
-     * @throws InvalidSystemMetadata
-     * @throws NotAuthorized
-     * @throws NotImplemented
-     * @throws IllegalAccessException
-     * @throws InstantiationException
-     */
-    protected void registerSystemMetadata()
-            throws ServiceFailure, InvalidRequest, IOException,
-            FileUploadException, JiBXException, NotImplemented, NotAuthorized,
-            InvalidSystemMetadata, InstantiationException,
-            IllegalAccessException {
-    	
-    	// Read the incoming data from its Mime Multipart encoding
-        Map<String, File> files = collectMultipartFiles();
-        
-    	// get the encoded pid string from the body and make the object
-        String pidString = multipartparams.get("pid").get(0);
-        Identifier pid = new Identifier();
-        pid.setValue(pidString);
-        
-        logMetacat.debug("registerSystemMetadata: " + pid);
-
-        // get the system metadata from the request
-        File smFile = files.get("sysmeta");
-        FileInputStream sysmeta = new FileInputStream(smFile);
-        SystemMetadata systemMetadata = TypeMarshaller.unmarshalTypeFromStream(SystemMetadata.class, sysmeta);
-
-        logMetacat.debug("registering system metadata with pid " + pid.getValue());
-        Identifier retGuid = CNodeService.getInstance(request).registerSystemMetadata(session, pid, systemMetadata);
-
-        OutputStream out = response.getOutputStream();
-        response.setStatus(200);
-        response.setContentType("text/xml");
-        
-        TypeMarshaller.marshalTypeToOutputStream(retGuid, out);
-
-    }
-
-    /**
-     * set the access perms on a document
-     * 
-     * @throws JiBXException
-     * @throws InvalidRequest
-     * @throws NotImplemented
-     * @throws NotAuthorized
-     * @throws NotFound
-     * @throws ServiceFailure
-     * @throws InvalidToken
-     * @throws IllegalAccessException
-     * @throws InstantiationException
-     * @throws IOException
-     * @throws SAXException
-     * @throws ParserConfigurationException
-     * @throws VersionMismatch 
-     */
-    protected void setAccess(String pid) throws JiBXException, InvalidToken,
-            ServiceFailure, NotFound, NotAuthorized, NotImplemented,
-            InvalidRequest, IOException, InstantiationException,
-            IllegalAccessException, ParserConfigurationException, SAXException, VersionMismatch {
-
-        long serialVersion = 0L;
-        String serialVersionStr = null;
-        AccessPolicy accessPolicy = collectAccessPolicy();
-
-        // get the serialVersion
-        try {
-            serialVersionStr = multipartparams.get("serialVersion").get(0);
-            serialVersion = new Long(serialVersionStr).longValue();
-
-        } catch (NumberFormatException nfe) {
-            String msg = "The 'serialVersion' must be provided as a positive integer and was not.";
-            logMetacat.error(msg);
-            throw new InvalidRequest("4402", msg);
-            
-        } catch (NullPointerException e) {
-            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
-            logMetacat.error(msg);
-            throw new InvalidRequest("4402", msg);
-
-        }
-
-        Identifier id = new Identifier();
-        id.setValue(pid);
-
-        CNodeService.getInstance(request).setAccessPolicy(session, id,
-                accessPolicy, serialVersion);
-
-    }
-
-    /**
-     * List the objects
-     * 
-     * @throws NotImplemented
-     * @throws InvalidRequest
-     * @throws NotAuthorized
-     * @throws ServiceFailure
-     * @throws InvalidToken
-     * @throws NotFound
-     * @throws IOException
-     * @throws JiBXException
-     * @throws Exception
-     */
-    private void listObjects() throws InvalidToken, ServiceFailure,
-            NotAuthorized, InvalidRequest, NotImplemented, NotFound,
-            IOException, JiBXException {
-
-        Date startTime = null;
-        Date endTime = null;
-        ObjectFormatIdentifier formatId = null;
-        boolean replicaStatus = true;
-        int start = 0;
-        int count = 1000;
-        Enumeration<String> paramlist = request.getParameterNames();
-        while (paramlist.hasMoreElements()) {
-            // parse the params and make the call
-            String name = paramlist.nextElement();
-            String[] values = request.getParameterValues(name);
-            String value = null;
-            if (values != null && values.length > 0) {
-            	value = values[0];
-            	value = EncodingUtilities.decodeString(value);
-            }
-
-            if (name.equals("fromDate") && value != null) {
-                try {
-                    startTime = DateTimeMarshaller.deserializeDateToUTC(value);
-                } catch (Exception e) {
-                    // if we can't parse it, just don't use the startTime param
-                    logMetacat.warn("Could not parse fromDate: " + value);
-                    startTime = null;
-                }
-            } else if (name.equals("toDate") && value != null) {
-                try {
-                    endTime = DateTimeMarshaller.deserializeDateToUTC(value);
-                } catch (Exception e) {
-                    // if we can't parse it, just don't use the endTime param
-                    logMetacat.warn("Could not parse toDate: " + value);
-                    endTime = null;
-                }
-            } else if (name.equals("formatId") && value != null) {
-            	formatId = new ObjectFormatIdentifier();
-            	formatId.setValue(value);
-            } else if (name.equals("replicaStatus") && value != null) {
-                replicaStatus = Boolean.parseBoolean(value);
-            } else if (name.equals("start") && value != null) {
-                start = Integer.valueOf(value);
-            } else if (name.equals("count") && value != null) {
-                count = Integer.valueOf(value);
-            }
-        }
-        // make the call
-        logMetacat.debug("session: " + session + " fromDate: " + startTime
-                + " toDate: " + endTime + " formatId: " + formatId
-                + " replicaStatus: " + replicaStatus + " start: " + start
-                + " count: " + count);        
-
-        // get the list
-        ObjectList ol = CNodeService.getInstance(request).listObjects(session,
-                startTime, endTime, formatId, replicaStatus, start, count);
-
-        // send it
-        OutputStream out = response.getOutputStream();
-        response.setStatus(200);
-        response.setContentType("text/xml");
-
-        // style the object with a processing directive
-        String stylesheet = null;
-        try {
-            stylesheet = PropertyService.getProperty("dataone.types.xsl");
-        } catch (PropertyNotFoundException e) {
-            logMetacat.warn("Could not locate DataONE types XSLT: "
-                    + e.getMessage());
-        }
-
-        // Serialize and write it to the output stream
-        TypeMarshaller.marshalTypeToOutputStream(ol, out, stylesheet);
-    }
-
-    /**
-     * Pass the request to get node replication authorization to CNodeService
-     * 
-     * @param pid
-     *            the identifier of the object to get authorization to replicate
-     * 
-     * @throws NotImplemented
-     * @throws NotAuthorized
-     * @throws InvalidToken
-     * @throws ServiceFailure
-     * @throws NotFound
-     * @throws InvalidRequest
-     */
-    public boolean isNodeAuthorized(String pid) throws NotImplemented,
-            NotAuthorized, InvalidToken, ServiceFailure, NotFound,
-            InvalidRequest {
-
-        boolean result = false;
-        Subject targetNodeSubject = new Subject();
-        String nodeSubject = null;
-        String replPermission = null;
-
-        // get the pid
-        Identifier identifier = new Identifier();
-        identifier.setValue(pid);
-
-        // get the target node subject
-        try {
-            nodeSubject = params.get("targetNodeSubject")[0];
-            targetNodeSubject.setValue(nodeSubject);
-
-        } catch (NullPointerException e) {
-            String msg = "The 'targetNodeSubject' must be provided as a parameter and was not.";
-            logMetacat.error(msg);
-            throw new InvalidRequest("4873", msg);
-
-        }
-
-        result = CNodeService.getInstance(request).isNodeAuthorized(session, targetNodeSubject, identifier);
-
-        response.setStatus(200);
-        response.setContentType("text/xml");
-        return result;
-
-    }
-
-    /**
-     * Pass the request to set the replication policy to CNodeService
-     * 
-     * @param pid
-     *            the identifier of the object to set the replication policy on
-     * 
-     * @throws NotImplemented
-     * @throws NotFound
-     * @throws NotAuthorized
-     * @throws ServiceFailure
-     * @throws InvalidRequest
-     * @throws InvalidToken
-     * @throws IOException
-     * @throws InstantiationException
-     * @throws IllegalAccessException
-     * @throws JiBXException
-     * @throws VersionMismatch 
-     */
-    public boolean setReplicationPolicy(String pid) throws NotImplemented,
-            NotFound, NotAuthorized, ServiceFailure, InvalidRequest,
-            InvalidToken, IOException, InstantiationException,
-            IllegalAccessException, JiBXException, VersionMismatch {
-
-        boolean result = false;
-        ReplicationPolicy policy = null;
-        long serialVersion = 0L;
-        String serialVersionStr = null;
-
-        Identifier identifier = new Identifier();
-        identifier.setValue(pid);
-
-        policy = collectReplicationPolicy();
-
-        // get the serialVersion
-        try {
-            serialVersionStr = multipartparams.get("serialVersion").get(0);
-            serialVersion = new Long(serialVersionStr).longValue();
-
-        } catch (NullPointerException e) {
-            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
-            logMetacat.error(msg);
-            throw new InvalidRequest("4883", msg);
-
-        }
-        result = CNodeService.getInstance(request).setReplicationPolicy(
-                session, identifier, policy, serialVersion);
-        response.setStatus(200);
-        response.setContentType("text/xml");
-        return result;
-
-    }
-    
-    /**
-     * Update the system metadata for a given pid, setting it to be obsoleted
-     * by the obsoletedByPid
-     *  
-     * @param pid
-     * @return
-     * @throws NotImplemented
-     * @throws NotFound
-     * @throws NotAuthorized
-     * @throws ServiceFailure
-     * @throws InvalidRequest
-     * @throws InvalidToken
-     * @throws InstantiationException
-     * @throws IllegalAccessException
-     * @throws VersionMismatch
-     */
-    public boolean setObsoletedBy(String pid) 
-        throws NotImplemented, NotFound, NotAuthorized, ServiceFailure, 
-        InvalidRequest, InvalidToken, InstantiationException, 
-        IllegalAccessException, VersionMismatch {
-
-        boolean result = false;
-        long serialVersion = 0L;
-        String serialVersionStr = null;
-
-        Identifier identifier = new Identifier();
-        identifier.setValue(pid);
-        String obsoletedByPidString = null;
-        Identifier obsoletedByPid = null;
-
-        // Parse the params out of the multipart form data
-        // Read the incoming data from its Mime Multipart encoding
-        logMetacat.debug("Parsing rights holder parameters from the mime multipart entity");
-        try {
-            collectMultipartParams();
-            
-        } catch (FileUploadException e1) {
-            String msg = "FileUploadException: Couldn't parse the mime multipart information: " +
-            e1.getMessage();
-            logMetacat.debug(msg);
-            throw new ServiceFailure("4941", msg);
-
-        } catch (IOException e1) {
-            String msg = "IOException: Couldn't parse the mime multipart information: " +
-            e1.getMessage();
-            logMetacat.debug(msg);
-            throw new ServiceFailure("4941", msg);
-        
-        } catch (Exception e1) {
-            String msg = "Exception: Couldn't parse the mime multipart information: " +
-            e1.getMessage();
-            logMetacat.debug(msg);
-            throw new ServiceFailure("4941", msg);
-
-        }
-
-        // get the obsoletedByPid
-        try {
-            obsoletedByPidString = multipartparams.get("obsoletedByPid").get(0);
-            obsoletedByPid = new Identifier();
-            obsoletedByPid.setValue(obsoletedByPidString);
-        } catch (NullPointerException e) {
-            String msg = "The 'obsoletedByPid' must be provided as a parameter and was not.";
-            logMetacat.error(msg);
-            throw new InvalidRequest("4883", msg);
-        }
-
-        // get the serialVersion
-        try {
-            serialVersionStr = multipartparams.get("serialVersion").get(0);
-            serialVersion = new Long(serialVersionStr).longValue();
-            
-        } catch (NumberFormatException nfe) {
-            String msg = "The 'serialVersion' must be provided as a positive integer and was not.";
-            logMetacat.error(msg);
-            throw new InvalidRequest("4942", msg);
-                        
-        } catch (NullPointerException e) {
-            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
-            logMetacat.error(msg);
-            throw new InvalidRequest("4942", msg);
-            
-        }
-        result = CNodeService.getInstance(request).setObsoletedBy(session,
-            identifier, obsoletedByPid, serialVersion);
-        response.setStatus(200);
-        response.setContentType("text/xml");
-        return result;
-
-    }
-    
-    /**
-     * Delete the replica entry with the given nodeId for the given pid
-     * 
-     * @param pid
-     * @return
-     * @throws NotImplemented
-     * @throws NotFound
-     * @throws NotAuthorized
-     * @throws ServiceFailure
-     * @throws InvalidRequest
-     * @throws InvalidToken
-     * @throws InstantiationException
-     * @throws IllegalAccessException
-     * @throws VersionMismatch
-     */
-    public boolean deleteReplica(String pid) 
-        throws NotImplemented, NotFound, NotAuthorized, ServiceFailure, 
-        InvalidRequest, InvalidToken, InstantiationException, 
-        IllegalAccessException, VersionMismatch {
-
-        boolean result = false;
-        long serialVersion = 0L;
-        String serialVersionStr = null;
-
-        Identifier identifier = new Identifier();
-        identifier.setValue(pid);
-
-        NodeReference nodeId = null;
-        
-        // Parse the params out of the multipart form data
-        // Read the incoming data from its Mime Multipart encoding
-        logMetacat.debug("Parsing delete replica parameters from the mime multipart entity");
-        try {
-            collectMultipartParams();
-            
-        } catch (FileUploadException e1) {
-            String msg = "FileUploadException: Couldn't parse the mime multipart information: " +
-            e1.getMessage();
-            logMetacat.debug(msg);
-            throw new ServiceFailure("4951", msg);
-
-        } catch (IOException e1) {
-            String msg = "IOException: Couldn't parse the mime multipart information: " +
-            e1.getMessage();
-            logMetacat.debug(msg);
-            throw new ServiceFailure("4951", msg);
-        
-        } catch (Exception e1) {
-            String msg = "Exception: Couldn't parse the mime multipart information: " +
-            e1.getMessage();
-            logMetacat.debug(msg);
-            throw new ServiceFailure("4951", msg);
-
-        }
-        
-        // get the nodeId param
-        try {
-            String nodeIdString = multipartparams.get("nodeId").get(0);
-            nodeId = new NodeReference();
-            nodeId.setValue(nodeIdString);
-            
-        } catch (NullPointerException e) {
-            String msg = "The 'nodeId' must be provided as a parameter and was not.";
-            logMetacat.error(msg);
-            throw new InvalidRequest("4952", msg);
-        }
-
-        // get the serialVersion
-        try {
-            serialVersionStr = multipartparams.get("serialVersion").get(0);
-            serialVersion = new Long(serialVersionStr).longValue();
-            
-        } catch (NumberFormatException nfe) {
-            String msg = "The 'serialVersion' must be provided as a positive integer and was not.";
-            logMetacat.error(msg);
-            throw new InvalidRequest("4952", msg);
-                        
-        } catch (NullPointerException e) {
-            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
-            logMetacat.error(msg);
-            throw new InvalidRequest("4952", msg);
-            
-        }
-        result = CNodeService.getInstance(request).deleteReplicationMetadata(
-                session, identifier, nodeId, serialVersion);
-        response.setStatus(200);
-        response.setContentType("text/xml");
-        return result;
-
-    }
-
-    /**
-     * Pass the request to set the replication status to CNodeService
-     * 
-     * @param pid
-     *            the identifier of the object to set the replication status on
-     * 
-     * @throws ServiceFailure
-     * @throws NotImplemented
-     * @throws InvalidToken
-     * @throws NotAuthorized
-     * @throws InvalidRequest
-     * @throws NotFound
-     * @throws JiBXException 
-     * @throws IllegalAccessException 
-     * @throws InstantiationException 
-     * @throws IOException 
-     */
-    public boolean setReplicationStatus(String pid) throws ServiceFailure,
-            NotImplemented, InvalidToken, NotAuthorized, InvalidRequest,
-            NotFound {
-        
-        boolean result = false;
-        Identifier identifier = new Identifier();
-        identifier.setValue(pid);
-        BaseException failure = null;
-        ReplicationStatus status = null;
-        String replicationStatus = null;
-        NodeReference targetNodeRef = null;
-        String targetNode = null;
-
-        // Parse the params out of the multipart form data
-        // Read the incoming data from its Mime Multipart encoding
-        logMetacat.debug("Parsing ReplicaStatus from the mime multipart entity");
-
-        try {
-            failure = collectReplicationStatus();
-            
-        } catch (IOException e2) {
-            throw new ServiceFailure("4700", "Couldn't resolve the multipart request: " +
-                e2.getMessage());
-            
-        } catch (InstantiationException e2) {
-            throw new ServiceFailure("4700", "Couldn't resolve the multipart request: " +
-                e2.getMessage());
-            
-        } catch (IllegalAccessException e2) {
-            throw new ServiceFailure("4700", "Couldn't resolve the multipart request: " +
-                    e2.getMessage());
-            
-        } catch (JiBXException e2) {
-            throw new ServiceFailure("4700", "Couldn't resolve the multipart request: " +
-                    e2.getMessage());
-            
-        }
-        
-        // get the replication status param
-        try {
-            replicationStatus = multipartparams.get("status").get(0);
-            status = ReplicationStatus.convert(replicationStatus);
-
-        } catch (NullPointerException npe) {
-
-            logMetacat.debug("The 'status' parameter was not found in the "
-                    + "multipartparams map.  Trying the params map.");
-
-            try {
-                replicationStatus = params.get("status")[0];
-                status = ReplicationStatus.convert(replicationStatus
-                        .toLowerCase());
-
-            } catch (Exception e) {
-                String msg = "The 'status' must be provided as a parameter and was not.";
-                logMetacat.error(msg);
-                throw new InvalidRequest("4730", msg);
-
-            }
-
-        }
-
-        // get the target node reference param
-        try {
-            targetNode = multipartparams.get("nodeRef").get(0);
-            targetNodeRef = new NodeReference();
-            targetNodeRef.setValue(targetNode);
-
-        } catch (NullPointerException e) {
-            logMetacat.debug("The 'nodeRef' parameter was not found in the "
-                    + "multipartparams map.  Trying the params map.");
-
-            try {
-                targetNode = params.get("nodeRef")[0];
-                targetNodeRef = new NodeReference();
-                targetNodeRef.setValue(targetNode);
-
-            } catch (Exception e1) {
-                String msg = "The 'nodeRef' must be provided as a parameter and was not.";
-                logMetacat.error(msg);
-                throw new InvalidRequest("4730", msg);
-
-            }
-
-        }
-
-        result = CNodeService.getInstance(request).setReplicationStatus(
-                session, identifier, targetNodeRef, status, failure);
-        response.setStatus(200);
-        response.setContentType("text/xml");
-        return result;
-
-    }
-
-    /**
-     * Pass the request to update the replication metadata to CNodeService
-     * 
-     * @param pid
-     *            the identifier of the object to update the replication
-     *            metadata on
-     * 
-     * @throws ServiceFailure
-     * @throws NotImplemented
-     * @throws InvalidToken
-     * @throws NotAuthorized
-     * @throws InvalidRequest
-     * @throws NotFound
-     * @throws VersionMismatch 
-     */
-    public boolean updateReplicationMetadata(String pid) throws ServiceFailure,
-            NotImplemented, InvalidToken, NotAuthorized, InvalidRequest,
-            NotFound, VersionMismatch {
-
-        boolean result = false;
-        long serialVersion = 0L;
-        String serialVersionStr = null;
-        Replica replica = null;
-        Identifier identifier = new Identifier();
-        identifier.setValue(pid);
-
-        replica = collectReplicaMetadata();
-
-        // get the serialVersion
-        try {
-            serialVersionStr = multipartparams.get("serialVersion").get(0);
-            serialVersion = new Long(serialVersionStr).longValue();
-
-        } catch (NullPointerException e) {
-            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
-            logMetacat.error(msg);
-            throw new InvalidRequest("4853", msg);
-
-        }
-
-        result = CNodeService.getInstance(request).updateReplicationMetadata(
-                session, identifier, replica, serialVersion);
-        response.setStatus(200);
-        response.setContentType("text/xml");
-        return result;
-
-    }
-
-}

Property changes on: src/edu/ucsb/nceas/metacat/restservice/CNResourceHandler.java
___________________________________________________________________
Deleted: svn:eol-style
## -1 +0,0 ##
-native
\ No newline at end of property
Deleted: svn:keywords
## -1 +0,0 ##
-Author Date Id Revision
\ No newline at end of property
Index: src/edu/ucsb/nceas/metacat/restservice/MNRestServlet.java
===================================================================
--- src/edu/ucsb/nceas/metacat/restservice/MNRestServlet.java	(revision 8809)
+++ src/edu/ucsb/nceas/metacat/restservice/MNRestServlet.java	(nonexistent)
@@ -1,47 +0,0 @@
-/**
- *  '$RCSfile$'
- *  Copyright: 2000 Regents of the University of California and the
- *              National Center for Ecological Analysis and Synthesis
- *
- *   '$Author$'
- *     '$Date$'
- *
- * 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 javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-
-/**
- * Routes MN REST service requests to the appropriate handler
- *  
- */
-public class MNRestServlet extends D1RestServlet {
-    
-	/**
-	 * Provide an MNResourceHandler subclass of D1ResourceHandler
-	 */
-	@Override
-    protected D1ResourceHandler createHandler(HttpServletRequest request, HttpServletResponse response) 
-    	throws ServletException, IOException {
-        return new MNResourceHandler(getServletContext(), request, response);
-    }
-
-}

Property changes on: src/edu/ucsb/nceas/metacat/restservice/MNRestServlet.java
___________________________________________________________________
Deleted: svn:eol-style
## -1 +0,0 ##
-native
\ No newline at end of property
Deleted: svn:keywords
## -1 +0,0 ##
-Author Date Id Revision
\ No newline at end of property
Index: src/edu/ucsb/nceas/metacat/restservice/MNResourceHandler.java
===================================================================
--- src/edu/ucsb/nceas/metacat/restservice/MNResourceHandler.java	(revision 8809)
+++ src/edu/ucsb/nceas/metacat/restservice/MNResourceHandler.java	(nonexistent)
@@ -1,1557 +0,0 @@
-/**
- *  '$RCSfile$'
- *  Copyright: 2011 Regents of the University of California and the
- *              National Center for Ecological Analysis and Synthesis
- *
- *   '$Author$'
- *     '$Date$'
- *
- * 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.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.text.DateFormat;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Enumeration;
-import java.util.Map;
-import java.util.TimeZone;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.xml.parsers.ParserConfigurationException;
-
-import org.apache.commons.fileupload.FileUploadException;
-import org.apache.commons.io.IOUtils;
-import org.apache.log4j.Logger;
-import org.dataone.client.ObjectFormatCache;
-import org.dataone.client.formats.ObjectFormatInfo;
-import org.dataone.mimemultipart.MultipartRequest;
-import org.dataone.mimemultipart.MultipartRequestResolver;
-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.NotFound;
-import org.dataone.service.exceptions.NotImplemented;
-import org.dataone.service.exceptions.ServiceFailure;
-import org.dataone.service.exceptions.SynchronizationFailed;
-import org.dataone.service.exceptions.UnsupportedType;
-import org.dataone.service.types.v1.Checksum;
-import org.dataone.service.types.v1.DescribeResponse;
-import org.dataone.service.types.v1.Event;
-import org.dataone.service.types.v1.Identifier;
-import org.dataone.service.types.v1.Log;
-import org.dataone.service.types.v1.MonitorList;
-import org.dataone.service.types.v1.Node;
-import org.dataone.service.types.v1.NodeReference;
-import org.dataone.service.types.v1.ObjectFormat;
-import org.dataone.service.types.v1.ObjectFormatIdentifier;
-import org.dataone.service.types.v1.ObjectList;
-import org.dataone.service.types.v1.Permission;
-import org.dataone.service.types.v1.Subject;
-import org.dataone.service.types.v1.SystemMetadata;
-import org.dataone.service.types.v1_1.QueryEngineDescription;
-import org.dataone.service.types.v1_1.QueryEngineList;
-import org.dataone.service.util.Constants;
-import org.dataone.service.util.DateTimeMarshaller;
-import org.dataone.service.util.ExceptionHandler;
-import org.dataone.service.util.TypeMarshaller;
-import org.jibx.runtime.JiBXException;
-import org.xml.sax.SAXException;
-
-import edu.ucsb.nceas.metacat.common.query.stream.ContentTypeInputStream;
-import edu.ucsb.nceas.metacat.dataone.MNodeService;
-import edu.ucsb.nceas.metacat.properties.PropertyService;
-import edu.ucsb.nceas.metacat.util.DeleteOnCloseFileInputStream;
-import edu.ucsb.nceas.utilities.PropertyNotFoundException;
-
-/**
- * MN REST service implementation handler
- * 
- * ******************
- * MNCore -- DONE
- * 		ping() - GET /d1/mn/monitor/ping
- * 		log() - GET /d1/mn/log
- * 		**getObjectStatistics() - GET /d1/mn/monitor/object
- * 		getOperationsStatistics - GET /d1/mn/monitor/event
- * 		**getStatus - GET /d1/mn/monitor/status
- * 		getCapabilities() - GET /d1/mn/ and /d1/mn/node
- * 	
- * 	MNRead -- DONE
- * 		get() - GET /d1/mn/object/PID
- * 		getSystemMetadata() - GET /d1/mn/meta/PID
- * 		describe() - HEAD /d1/mn/object/PID
- * 		getChecksum() - GET /d1/mn/checksum/PID
- * 		listObjects() - GET /d1/mn/object
- * 		synchronizationFailed() - POST /d1/mn/error
- * 	
- * 	MNAuthorization -- DONE
- * 		isAuthorized() - GET /d1/mn/isAuthorized/PID
- * 		setAccessPolicy() - PUT /d1/mn/accessRules/PID
- * 		
- * 	MNStorage - DONE
- * 		create() - POST /d1/mn/object/PID
- * 		update() - PUT /d1/mn/object/PID
- * 		delete() - DELETE /d1/mn/object/PID
- * 		archive() - PUT /d1/mn/archive/PID
-
- *    systemMetadataChanged() - POST /dirtySystemMetadata/PID
- * 	
- * 	MNReplication
- * 		replicate() - POST /d1/mn/replicate
- *    getReplica() - GET /d1/mn/replica
- * 
- * ******************
- * @author leinfelder
- *
- */
-public class MNResourceHandler extends D1ResourceHandler {
-
-    // MN-specific API Resources
-    protected static final String RESOURCE_MONITOR = "monitor";
-    protected static final String RESOURCE_REPLICATE = "replicate";
-    protected static final String RESOURCE_REPLICAS = "replica";
-    protected static final String RESOURCE_NODE = "node";
-    protected static final String RESOURCE_ERROR = "error";
-    protected static final String RESOURCE_META_CHANGED = "dirtySystemMetadata";
-    protected static final String RESOURCE_GENERATE_ID = "generate";
-    protected static final String RESOURCE_PUBLISH = "publish";
-    protected static final String RESOURCE_PACKAGE = "package";
-    protected static final String RESOURCE_VIEWS = "views";
-
-
-    
-    // shared executor
-	private static ExecutorService executor = null;
-
-	static {
-		// use a shared executor service with nThreads == one less than available processors
-    	int availableProcessors = Runtime.getRuntime().availableProcessors();
-        int nThreads = availableProcessors * 1;
-        nThreads--;
-        nThreads = Math.max(1, nThreads);
-    	executor = Executors.newFixedThreadPool(nThreads);	
-	}
-	
-    /**
-     * Initializes new instance by setting servlet context,request and response
-     * */
-    public MNResourceHandler(ServletContext servletContext,
-            HttpServletRequest request, HttpServletResponse response) {
-    	super(servletContext, request, response);
-        logMetacat = Logger.getLogger(MNResourceHandler.class);
-    }
-    
-    @Override
-    protected boolean isD1Enabled() {
-    	
-    	boolean enabled = false;
-    	try {
-			enabled = Boolean.parseBoolean(PropertyService.getProperty("dataone.mn.services.enabled"));
-		} catch (PropertyNotFoundException e) {
-			logMetacat.error("Could not check if DataONE is enabled: " + e.getMessage());
-		}
-    	
-    	return enabled;	
-    }
-
-    /**
-     * This function is called from REST API servlet and handles each request to the servlet 
-     * 
-     * @param httpVerb (GET, POST, PUT or DELETE)
-     */
-    @Override
-    public void handle(byte httpVerb) {
-    	// prepare the handler
-    	super.handle(httpVerb);
-    	
-        try {
-        	
-        	// only service requests if we have D1 configured
-        	if (!isD1Enabled()) {
-        		ServiceFailure se = new ServiceFailure("0000", "DataONE services are not enabled on this node");
-                serializeException(se, response.getOutputStream());
-                return;
-        	}
-        	
-        	// get the resource
-            String resource = request.getPathInfo();
-            resource = resource.substring(resource.indexOf("/") + 1);
-            
-            // default to node info
-            if (resource.equals("")) {
-                resource = RESOURCE_NODE;
-            }
-            
-            // get the rest of the path info
-            String extra = null;
-                        
-            logMetacat.debug("handling verb " + httpVerb + " request with resource '" + resource + "'");
-            logMetacat.debug("resource: '" + resource + "'");
-            boolean status = false;
-            
-            if (resource != null) {
-
-                if (resource.startsWith(RESOURCE_NODE)) {
-                    // node response
-                    node();
-                    status = true;
-                } else if (resource.startsWith(RESOURCE_IS_AUTHORIZED)) {
-                    if (httpVerb == GET) {
-                    	// after the command
-                        extra = parseTrailing(resource, RESOURCE_IS_AUTHORIZED);
-	                	// check the access rules
-	                    isAuthorized(extra);
-	                    status = true;
-	                    logMetacat.debug("done getting access");
-                    }
-                } else if (resource.startsWith(RESOURCE_META)) {
-                    logMetacat.debug("Using resource 'meta'");
-                    // get
-                    if (httpVerb == GET) {
-                    	// after the command
-                        extra = parseTrailing(resource, RESOURCE_META);
-                        getSystemMetadataObject(extra);
-                        status = true;
-                    }
-                    
-                } else if (resource.startsWith(RESOURCE_OBJECTS)) {
-                    logMetacat.debug("Using resource 'object'");
-                    // after the command
-                    extra = parseTrailing(resource, RESOURCE_OBJECTS);
-                    logMetacat.debug("objectId: " + extra);
-                    logMetacat.debug("verb:" + httpVerb);
-
-                    if (httpVerb == GET) {
-                        getObject(extra);
-                        status = true;
-                    } else if (httpVerb == POST) {
-                    	// part of the params, not the URL
-                        putObject(null, FUNCTION_NAME_INSERT);
-                        status = true;
-                    } else if (httpVerb == PUT) {
-                        putObject(extra, FUNCTION_NAME_UPDATE);
-                        status = true;
-                    } else if (httpVerb == DELETE) {
-                        deleteObject(extra);
-                        status = true;
-                    } else if (httpVerb == HEAD) {
-                        describeObject(extra);
-                        status = true;
-                    }
-                  
-                } else if (resource.startsWith(RESOURCE_LOG)) {
-                    logMetacat.debug("Using resource 'log'");
-                    // handle log events
-                    if (httpVerb == GET) {
-                        getLog();
-                        status = true;
-                    }
-                } else if (resource.startsWith(Constants.RESOURCE_ARCHIVE)) {
-                    logMetacat.debug("Using resource " + Constants.RESOURCE_ARCHIVE);
-                    // handle archive events
-                    if (httpVerb == PUT) {
-                        extra = parseTrailing(resource, Constants.RESOURCE_ARCHIVE);
-                        archive(extra);
-                        status = true;
-                    }
-                } else if (resource.startsWith(Constants.RESOURCE_CHECKSUM)) {
-                    logMetacat.debug("Using resource 'checksum'");
-                    // handle checksum requests
-                    if (httpVerb == GET) {
-                    	// after the command
-                        extra = parseTrailing(resource, Constants.RESOURCE_CHECKSUM);
-                        checksum(extra);
-                        status = true;
-                    }
-                } else if (resource.startsWith(RESOURCE_MONITOR)) {
-                    // there are various parts to monitoring
-                    if (httpVerb == GET) {
-                    	// after the command
-                        extra = parseTrailing(resource, RESOURCE_MONITOR);
-                        
-                        // ping
-                        if (extra.toLowerCase().equals("ping")) {
-                            logMetacat.debug("processing ping request");
-                            Date result = MNodeService.getInstance(request).ping();
-                            // TODO: send to output	
-                            status = true;
-                            
-                        } else {
-	                    	// health monitoring calls
-	                        status = monitor(extra);
-                        }
-                        
-                    }
-                } else if (resource.startsWith(RESOURCE_REPLICATE)) {
-                	if (httpVerb == POST) {
-	                    logMetacat.debug("processing replicate request");
-	                    replicate();
-	                    status = true;
-                	}
-                } else if (resource.startsWith(RESOURCE_ERROR)) {
-	                // sync error
-	                if (httpVerb == POST) {
-	                    syncError();
-	                    status = true;
-	                }
-                } else if (resource.startsWith(RESOURCE_META_CHANGED)) {
-                    // system metadata changed
-                    if (httpVerb == POST) {
-                        systemMetadataChanged();
-                        status = true;
-                    }
-                } else if (resource.startsWith(RESOURCE_REPLICAS)) {
-                    // get replica
-                    if (httpVerb == GET) {
-                        extra = parseTrailing(resource, RESOURCE_REPLICAS);
-                        getReplica(extra);
-                        status = true;
-                    }
-                } else if (resource.startsWith(RESOURCE_QUERY)) {
-	                logMetacat.debug("Using resource " + RESOURCE_QUERY);
-	                // after the command
-	                extra = parseTrailing(resource, RESOURCE_QUERY);
-	                logMetacat.debug("query extra: " + extra);
-
-	                String engine = null;
-	                String query = null;
-
-	                if (extra != null) {
-		                // get the engine
-		                int engineIndex = extra.length();
-		                if (extra.indexOf("/") > -1) {
-		                	engineIndex = extra.indexOf("/");
-		                }
-		                engine = extra.substring(0, engineIndex);
-		                logMetacat.debug("query engine: " + engine);
-		                
-		                // get the query if it is there
-		                query = extra.substring(engineIndex, extra.length());
-		                if (query != null && query.length() == 0) {
-		                	query = null;
-		                } else {
-		                	if (query.startsWith("/")) {
-		                		query = query.substring(1);
-		                    }
-		                	// remove the query delimiter if it exists
-		                	if (query.startsWith("?")) {
-		                		query = query.substring(1);
-		                    }
-		                }
-		                logMetacat.debug("query: " + query);
-
-	                }
-	                logMetacat.debug("verb:" + httpVerb);
-	                if (httpVerb == GET) {
-	                    doQuery(engine, query);
-	                    status = true;
-	                }
-                } else if (resource.startsWith(RESOURCE_GENERATE_ID)) {
-                	// generate an id
-                    if (httpVerb == POST) {
-                        generateIdentifier();
-                        status = true;
-                    }
-                } else if (resource.startsWith(RESOURCE_PUBLISH)) {
-                    logMetacat.debug("Using resource: " + RESOURCE_PUBLISH);
-                    // PUT
-                    if (httpVerb == PUT) {
-                    	// after the command
-                        extra = parseTrailing(resource, RESOURCE_PUBLISH);
-                        publish(extra);
-                        status = true;
-                    }  
-                } else if (resource.startsWith(RESOURCE_PACKAGE)) {
-                    logMetacat.debug("Using resource: " + RESOURCE_PACKAGE);
-                    // get
-                    if (httpVerb == GET) {
-                    	// after the command
-                        extra = parseTrailing(resource, RESOURCE_PACKAGE);
-                        getPackage(extra);
-                        status = true;
-                    }  
-                } else if (resource.startsWith(RESOURCE_VIEWS)) {
-	                logMetacat.debug("Using resource " + RESOURCE_VIEWS);
-	                // after the command
-	                extra = parseTrailing(resource, RESOURCE_VIEWS);
-	                logMetacat.debug("view extra: " + extra);
-
-	                String format = null;
-	                String pid = null;
-
-	                if (extra != null) {
-		                // get the format
-		                int formatIndex = extra.length();
-		                if (extra.indexOf("/") > -1) {
-		                	formatIndex = extra.indexOf("/");
-		                }
-		                format = extra.substring(0, formatIndex);
-		                logMetacat.debug("view format: " + format);
-		                
-		                // get the pid if it is there
-		                pid = extra.substring(formatIndex, extra.length());
-		                if (pid != null && pid.length() == 0) {
-		                	pid = null;
-		                } else {
-		                	if (pid.startsWith("/")) {
-		                		pid = pid.substring(1);
-		                    }
-		                }
-		                logMetacat.debug("pid: " + pid);
-
-	                }
-	                logMetacat.debug("verb:" + httpVerb);
-	                if (httpVerb == GET) {
-	                    doViews(format, pid);
-	                    status = true;
-	                }
-                } 
-                
-                if (!status) {
-                	throw new ServiceFailure("0000", "Unknown error, status = " + status);
-                }
-            } else {
-            	throw new InvalidRequest("0000", "No resource matched for " + resource);
-            }
-        } catch (BaseException be) {
-        	// report Exceptions as clearly as possible
-        	OutputStream out = null;
-			try {
-				out = response.getOutputStream();
-			} catch (IOException e) {
-				logMetacat.error("Could not get output stream from response", e);
-			}
-            serializeException(be, out);
-        } catch (Exception e) {
-            // report Exceptions as clearly and generically as possible
-            logMetacat.error(e.getClass() + ": " + e.getMessage(), e);
-        	OutputStream out = null;
-			try {
-				out = response.getOutputStream();
-			} catch (IOException ioe) {
-				logMetacat.error("Could not get output stream from response", ioe);
-			}
-			ServiceFailure se = new ServiceFailure("0000", e.getMessage());
-            serializeException(se, out);
-        }
-    }
-    
-
-    private void doQuery(String engine, String query) {
-    	
-		OutputStream out = null;
-
-    	try {
-    		// NOTE: we set the session explicitly for the MNode instance since these methods do not provide a parameter			
-	    	if (engine == null) {
-	    		// just looking for list of engines
-	    		MNodeService mnode = MNodeService.getInstance(request);
-    			mnode.setSession(session);
-	    		QueryEngineList qel = mnode.listQueryEngines();
-	    		response.setContentType("text/xml");
-	            response.setStatus(200);
-	            out = response.getOutputStream();
-	            TypeMarshaller.marshalTypeToOutputStream(qel, out);
-	            return;
-	    	} else {
-	    		if (query != null) {
-	    			MNodeService mnode = MNodeService.getInstance(request);
-	    			mnode.setSession(session);
-	    			InputStream stream = mnode.query(engine, query);
-
-	    			// set the content-type if we have it from the implementation
-	    			if (stream instanceof ContentTypeInputStream) {
-		    			//response.setContentType("application/octet-stream");
-		    			//response.setContentType("text/xml");
-	    				response.setContentType(((ContentTypeInputStream) stream).getContentType());
-	    			}
-	                response.setStatus(200);
-	                out = response.getOutputStream();
-	                // write the results to the output stream
-	                IOUtils.copyLarge(stream, out);
-	                return;
-	    		} else {
-	    			MNodeService mnode = MNodeService.getInstance(request);
-	    			mnode.setSession(session);
-	    			QueryEngineDescription qed = mnode.getQueryEngineDescription(engine);
-	    			response.setContentType("text/xml");
-		            response.setStatus(200);
-		            out = response.getOutputStream();
-		            TypeMarshaller.marshalTypeToOutputStream(qed, out);
-		            return;
-	    		}
-	    	}
-	        
-	        
-    	} catch (BaseException be) {
-        	// report Exceptions as clearly as possible
-			try {
-				out = response.getOutputStream();
-			} catch (IOException e) {
-				logMetacat.error("Could not get output stream from response", e);
-			}
-            serializeException(be, out);
-        } catch (Exception e) {
-            // report Exceptions as clearly and generically as possible
-            logMetacat.error(e.getClass() + ": " + e.getMessage(), e);
-			try {
-				out = response.getOutputStream();
-			} catch (IOException ioe) {
-				logMetacat.error("Could not get output stream from response", ioe);
-			}
-			ServiceFailure se = new ServiceFailure("0000", e.getMessage());
-            serializeException(se, out);
-        }
-    }
-    
-    private void doViews(String format, String pid) {
-    	
-		OutputStream out = null;
-		MNodeService mnode = MNodeService.getInstance(request);
-
-    	try {
-    		// get a list of views
-    		if (pid != null) {
-    			Identifier identifier = new Identifier();
-    			identifier.setValue(pid);
-				InputStream stream = mnode.getView(session, identifier, format);
-
-    			// set the content-type if we have it from the implementation
-    			if (stream instanceof ContentTypeInputStream) {
-    				response.setContentType(((ContentTypeInputStream) stream).getContentType());
-    			}
-                response.setStatus(200);
-                out = response.getOutputStream();
-                // write the results to the output stream
-                IOUtils.copyLarge(stream, out);
-                return;
-    		} else {
-    			// TODO: list the registered views
-                BaseException ni = new NotImplemented("9999", "MN.listViews() is not implemented at this node");
-				throw ni;
-    		}
-	    	
-	        
-    	} catch (BaseException be) {
-        	// report Exceptions as clearly as possible
-			try {
-				out = response.getOutputStream();
-			} catch (IOException e) {
-				logMetacat.error("Could not get output stream from response", e);
-			}
-            serializeException(be, out);
-        } catch (Exception e) {
-            // report Exceptions as clearly and generically as possible
-            logMetacat.error(e.getClass() + ": " + e.getMessage(), e);
-			try {
-				out = response.getOutputStream();
-			} catch (IOException ioe) {
-				logMetacat.error("Could not get output stream from response", ioe);
-			}
-			ServiceFailure se = new ServiceFailure("0000", e.getMessage());
-            serializeException(se, out);
-        }
-    }
-    
-    /**
-     * Handles notification of system metadata changes for the given identifier
-     * 
-     * @param id  the identifier for the object
-     * @throws InvalidToken 
-     * @throws InvalidRequest 
-     * @throws NotAuthorized 
-     * @throws ServiceFailure 
-     * @throws NotImplemented 
-     */
-    private void systemMetadataChanged() 
-        throws NotImplemented, ServiceFailure, NotAuthorized, InvalidRequest, 
-        InvalidToken {
-
-        long serialVersion = 0L;
-        String serialVersionStr = null;
-        Date dateSysMetaLastModified = null;
-        String dateSysMetaLastModifiedStr = null;
-        Identifier pid = null;
-        
-        // mkae sure we have the multipart params
-        try {
-			initMultipartParams();
-		} catch (Exception e1) {
-			throw new ServiceFailure("1333", "Could not collect the multipart params for the request");
-		}
-        
-        // get the pid
-        try {
-        	String id = multipartparams.get("pid").get(0);
-        	pid = new Identifier();
-            pid.setValue(id);            
-        } catch (NullPointerException e) {
-            String msg = "The 'pid' must be provided as a parameter and was not.";
-            logMetacat.error(msg);
-            throw new InvalidRequest("1334", msg);
-        }      
-        
-        // get the serialVersion
-        try {
-            serialVersionStr = multipartparams.get("serialVersion").get(0);
-            serialVersion = new Long(serialVersionStr).longValue();
-            
-        } catch (NullPointerException e) {
-            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
-            logMetacat.error(msg);
-            throw new InvalidRequest("1334", msg);
-            
-        }       
-        
-        // get the dateSysMetaLastModified
-        try {
-            dateSysMetaLastModifiedStr = multipartparams.get("dateSysMetaLastModified").get(0);
-            dateSysMetaLastModified = DateTimeMarshaller.deserializeDateToUTC(dateSysMetaLastModifiedStr);
-            
-        } catch (NullPointerException e) {
-            String msg = 
-                "The 'dateSysMetaLastModified' must be provided as a " + 
-                "parameter and was not, or was an invalid representation of the timestamp.";
-            logMetacat.error(msg);
-            throw new InvalidRequest("1334", msg);
-            
-        }       
-        
-        // call the service
-        MNodeService.getInstance(request).systemMetadataChanged(session, pid, serialVersion, dateSysMetaLastModified);
-        response.setStatus(200);
-    }
-    
-    /**
-     * Handles identifier generation calls
-     * 
-     * @throws InvalidRequest 
-     * @throws NotImplemented 
-     * @throws NotAuthorized 
-     * @throws ServiceFailure 
-     * @throws InvalidToken 
-     * @throws IOException 
-     * @throws JiBXException 
-     */
-    private void generateIdentifier() throws InvalidToken, ServiceFailure, NotAuthorized, NotImplemented, InvalidRequest, IOException, JiBXException {
-        
-        // make sure we have the multipart params
-        try {
-			initMultipartParams();
-		} catch (Exception e1) {
-			throw new ServiceFailure("1333", "Could not collect the multipart params for the request");
-		}
-        
-        // get the scheme
-		String scheme = null;
-        try {
-        	scheme = multipartparams.get("scheme").get(0);	           
-        } catch (NullPointerException e) {
-            String msg = "The 'scheme' parameter was not provided, using default";
-            logMetacat.warn(msg);
-        }
-        
-        // get the fragment
-		String fragment = null;
-        try {
-        	fragment = multipartparams.get("fragment").get(0);	           
-        } catch (NullPointerException e) {
-            String msg = "The 'fragment' parameter was not provided, using default";
-            logMetacat.warn(msg);
-        }
-
-        // call the service
-        Identifier identifier = MNodeService.getInstance(request).generateIdentifier(session, scheme, fragment);
-        response.setStatus(200);
-        response.setContentType("text/xml");
-        OutputStream out = response.getOutputStream();
-        TypeMarshaller.marshalTypeToOutputStream(identifier, out);
-    }
-
-    /**
-     * Checks the access policy
-     * @param id
-     * @return
-     * @throws ServiceFailure
-     * @throws InvalidToken
-     * @throws NotFound
-     * @throws NotAuthorized
-     * @throws NotImplemented
-     * @throws InvalidRequest
-     */
-    private boolean isAuthorized(String id) throws ServiceFailure, InvalidToken, NotFound, NotAuthorized, NotImplemented, InvalidRequest {
-		Identifier pid = new Identifier();
-		pid.setValue(id);
-		Permission permission = null;
-		try {
-			String perm = params.get("action")[0];
-			permission = Permission.convert(perm);
-		} catch (Exception e) {
-			logMetacat.warn("No permission specified");
-		}
-		boolean result = MNodeService.getInstance(request).isAuthorized(session, pid, permission);
-		response.setStatus(200);
-		response.setContentType("text/xml");
-		return result;
-    }
-    
-    /**
-     * Processes failed synchronization message
-     * @throws NotImplemented
-     * @throws ServiceFailure
-     * @throws NotAuthorized
-     * @throws InvalidRequest
-     * @throws JiBXException
-     * @throws IllegalAccessException 
-     * @throws InstantiationException 
-     * @throws IOException 
-     */
-    private void syncError() throws NotImplemented, ServiceFailure, NotAuthorized, InvalidRequest, JiBXException, IOException, InstantiationException, IllegalAccessException {
-    	SynchronizationFailed syncFailed = null;
-		try {
-			syncFailed = collectSynchronizationFailed();
-		} catch (ParserConfigurationException e) {
-			throw new ServiceFailure("2161", e.getMessage());
-		} catch (SAXException e) {
-			throw new ServiceFailure("2161", e.getMessage());
-		}
-		
-		MNodeService.getInstance(request).synchronizationFailed(session, syncFailed);
-    }
-    
-
-    /**
-     * Handles the monitoring resources
-     * @return
-     * @throws NotFound
-     * @throws ParseException
-     * @throws NotImplemented
-     * @throws ServiceFailure
-     * @throws NotAuthorized
-     * @throws InvalidRequest
-     * @throws InsufficientResources
-     * @throws UnsupportedType
-     * @throws IOException
-     * @throws JiBXException
-     */
-    private boolean monitor(String pathInfo) 
-      throws NotFound, ParseException, NotImplemented, ServiceFailure, 
-      NotAuthorized, InvalidRequest, InsufficientResources, UnsupportedType, 
-      IOException, JiBXException {
-    	logMetacat.debug("processing monitor request");
-        
-        logMetacat.debug("verb is GET");
-        logMetacat.debug("pathInfo is " + pathInfo);
-        
-        if (pathInfo.toLowerCase().equals("status")) {
-            logMetacat.debug("processing status request");
-            // TODO: implement in MNCore
-            //MNodeService.getInstance().getStatus();
-            return false;
-            
-        } else if (pathInfo.toLowerCase().equals("object")) {
-            logMetacat.debug("processing object request");
-            Identifier pid = null;
-            ObjectFormat format = null;
-            if (params.containsKey("format")) {
-                String f = params.get("format")[0];
-                format = ObjectFormatCache.getInstance().getFormat(f);
-            }
-            if (params.containsKey("pid")) {
-                String id = params.get("pid")[0];
-                pid = new Identifier();
-                pid.setValue(id);
-            }
-            
-            // TODO: implement in MNCore
-            //ObjectStatistics objectStats = MNodeService.getInstance().getObjectStatistics(format, pid);
-            return false;
-            
-        } else if (pathInfo.toLowerCase().equals("event")) {
-            logMetacat.debug("processing event request");
-            ObjectFormatIdentifier fmtid = null;
-            String fromDateStr = null;
-            Date fromDate = null;
-            String toDateStr = null;
-            Date toDate = null;
-            String requestor = null;
-            Subject subject = null;
-            String eventName = null;
-            Event event = null;
-
-            if (params.containsKey("formatId")) {
-                String f = params.get("formatId")[0];
-                fmtid = ObjectFormatCache.getInstance().getFormat(f).getFormatId();
-            }
-            
-            if (params.containsKey("fromDate")) {
-                fromDateStr = params.get("fromDate")[0];
-                fromDate = getDateAsUTC(fromDateStr);
-            }
-            
-            if (params.containsKey("toDate")) {
-              toDateStr = params.get("toDate")[0];
-              toDate = getDateAsUTC(toDateStr);
-            }
-            
-            if (params.containsKey("requestor")) {
-            	requestor = params.get("requestor")[0];
-            	subject = new Subject();
-            	subject.setValue(requestor);
-            }
-            
-            if (params.containsKey("event")) {
-            	eventName = params.get("event")[0];
-                event = Event.convert(eventName);
-            }
-            
-            MonitorList monitorList = MNodeService.getInstance(request).getOperationStatistics(session, fromDate, toDate, subject, event, fmtid);
-            
-            OutputStream out = response.getOutputStream();
-            response.setStatus(200);
-            response.setContentType("text/xml");
-            
-            TypeMarshaller.marshalTypeToOutputStream(monitorList, out);
-            
-            return true;
-            
-        }
-        
-        return false;
-    }
-    
-    /*
-     * Parse an ISO8601 date string, returning a Date in UTC time if the string
-     * ends in 'Z'.
-     * 
-     * @param fromDateStr -  the date string to be parsed
-     * @return date -  the date object represented by the string
-     */
-    private Date getDateAsUTC(String fromDateStr)
-      throws ParseException {
-
-    	Date date = null;
-    	
-    	try {
-    		// try the expected date format
-        // a date format for date string arguments
-        DateFormat dateFormat = 
-        	new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
-
-	      date = dateFormat.parse(fromDateStr);
-      
-    	} catch (ParseException e) {
-    		// try the date with the UTC indicator
-        DateFormat utcDateFormat = 
-        	new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss'Z'");
-        utcDateFormat.setTimeZone(TimeZone.getTimeZone("GMT-0"));
-        date = utcDateFormat.parse(fromDateStr);
-        
-      }
-    	
-    	return date;
-    }
-
-		/**
-     * Calculate the checksum 
-     * @throws NotImplemented
-     * @throws JiBXException
-     * @throws IOException
-     * @throws InvalidToken
-     * @throws ServiceFailure
-     * @throws NotAuthorized
-     * @throws NotFound
-     * @throws InvalidRequest
-     */
-    private void checksum(String pid) throws NotImplemented, JiBXException, IOException, InvalidToken, ServiceFailure, NotAuthorized, NotFound, InvalidRequest {
-    	String checksumAlgorithm = "MD5";
-    	try {
-    		checksumAlgorithm = PropertyService.getProperty("dataone.checksumAlgorithm.default");
-        } catch(Exception e) {
-        	logMetacat.warn("Could not lookup configured default checksum algorithm, using: " + checksumAlgorithm);
-        }    
-        
-        Identifier pidid = new Identifier();
-        pidid.setValue(pid);
-        try {
-            checksumAlgorithm = params.get("checksumAlgorithm")[0];
-        } catch(Exception e) {
-            //do nothing.  use the default
-        	logMetacat.warn("No algorithm specified, using default: " + checksumAlgorithm);
-        }
-        logMetacat.debug("getting checksum for object " + pid + " with algorithm " + checksumAlgorithm);
-        
-        Checksum c = MNodeService.getInstance(request).getChecksum(session, pidid, checksumAlgorithm);
-        logMetacat.debug("got checksum " + c.getValue());
-        response.setStatus(200);
-        logMetacat.debug("serializing response");
-        TypeMarshaller.marshalTypeToOutputStream(c, response.getOutputStream());
-        logMetacat.debug("done serializing response.");
-        
-    }
-    
-	/**
-     * handle the replicate action for MN
-	 * @throws JiBXException 
-	 * @throws FileUploadException 
-	 * @throws IOException 
-	 * @throws InvalidRequest 
-	 * @throws ServiceFailure 
-	 * @throws UnsupportedType 
-	 * @throws InsufficientResources 
-	 * @throws NotAuthorized 
-	 * @throws NotImplemented 
-	 * @throws IllegalAccessException 
-	 * @throws InstantiationException 
-	 * @throws InvalidToken 
-     */
-    private void replicate() 
-        throws ServiceFailure, InvalidRequest, IOException, FileUploadException, 
-        JiBXException, NotImplemented, NotAuthorized, InsufficientResources, 
-        UnsupportedType, InstantiationException, IllegalAccessException, InvalidToken {
-
-        logMetacat.debug("in POST replicate()");
-        
-        // somewhat unorthodox, but the call is asynchronous and we'd like to return this info sooner
-        boolean allowed = false;
-        if (session == null) {
-        	String msg = "No session was provided.";
-            NotAuthorized failure = new NotAuthorized("2152", msg);
-        	throw failure;
-        } else {
-        	allowed = MNodeService.getInstance(request).isAdminAuthorized(session);
-        	if (!allowed) {
-        		String msg = "User is not an admin user";
-                NotAuthorized failure = new NotAuthorized("2152", msg);
-            	throw failure;
-        	}
-        }
-        
-        //parse the systemMetadata
-        final SystemMetadata sysmeta = collectSystemMetadata();
-        
-        String sn = multipartparams.get("sourceNode").get(0);
-        logMetacat.debug("sourceNode: " + sn);
-        final NodeReference sourceNode = new NodeReference();
-        sourceNode.setValue(sn);
-        
-        // run it in a thread to avoid connection timeout
-        Runnable runner = new Runnable() {
-			@Override
-			public void run() {
-				try {
-			        MNodeService.getInstance(request).replicate(session, sysmeta, sourceNode);
-				} catch (Exception e) {
-					logMetacat.error("Error running replication: " + e.getMessage(), e);
-					throw new RuntimeException(e.getMessage(), e);
-				}
-			}
-    	};
-    	// submit the task, and that's it
-    	executor.submit(runner);
-        
-    	// thread was started, so we return success
-        response.setStatus(200);
-        
-    }
-
-    /**
-     * Handle the getReplica action for the MN
-     * @param id  the identifier for the object
-     * @throws NotFound 
-     * @throws ServiceFailure 
-     * @throws NotImplemented 
-     * @throws NotAuthorized 
-     * @throws InvalidToken 
-     * @throws InvalidRequest 
-     */
-    private void getReplica(String id) 
-        throws InvalidRequest, InvalidToken, NotAuthorized, NotImplemented, 
-        ServiceFailure, NotFound {
-        
-        Identifier pid = new Identifier();
-        pid.setValue(id);
-        OutputStream out = null;
-        InputStream dataBytes = null;
-                
-        try {
-            // call the service
-            dataBytes = MNodeService.getInstance(request).getReplica(session, pid);
-
-            response.setContentType("application/octet-stream");
-            response.setStatus(200);
-            out = response.getOutputStream();
-            // write the object to the output stream
-            IOUtils.copyLarge(dataBytes, out);
-            
-        } catch (IOException e) {
-            String msg = "There was an error writing the output: " + e.getMessage();
-            logMetacat.error(msg);
-            throw new ServiceFailure("2181", msg);
-        
-        }
-
-    }
-
-    /**
-     * Get the Node information
-     * 
-     * @throws JiBXException
-     * @throws IOException
-     * @throws InvalidRequest 
-     * @throws ServiceFailure 
-     * @throws NotAuthorized 
-     * @throws NotImplemented 
-     */
-    private void node() 
-        throws JiBXException, IOException, NotImplemented, NotAuthorized, ServiceFailure, InvalidRequest {
-        
-        Node n = MNodeService.getInstance(request).getCapabilities();
-        
-        response.setContentType("text/xml");
-        response.setStatus(200);
-        TypeMarshaller.marshalTypeToOutputStream(n, response.getOutputStream());
-        
-    }
-    
-    /**
-     * MN_crud.describe()
-     * http://mule1.dataone.org/ArchitectureDocs/mn_api_crud.html#MN_crud.describe
-     * @param pid
-     * @throws InvalidRequest 
-     * @throws NotImplemented 
-     * @throws NotFound 
-     * @throws NotAuthorized 
-     * @throws ServiceFailure 
-     * @throws InvalidToken 
-     */
-    private void describeObject(String pid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, InvalidRequest
-    {
-        
-        response.setContentType("text/xml");
-
-        Identifier id = new Identifier();
-        id.setValue(pid);
-
-        DescribeResponse dr = null;
-        try {
-        	dr = MNodeService.getInstance(request).describe(session, id);
-        } catch (BaseException e) {
-        	response.setStatus(e.getCode());
-        	response.addHeader("DataONE-Exception-Name", e.getClass().getName());
-            response.addHeader("DataONE-Exception-DetailCode", e.getDetail_code());
-            response.addHeader("DataONE-Exception-Description", e.getDescription());
-            response.addHeader("DataONE-Exception-PID", id.getValue());
-            return;
-		}
-        
-        response.setStatus(200);
-        
-        //response.addHeader("pid", pid);
-        response.addHeader("DataONE-Checksum", dr.getDataONE_Checksum().getAlgorithm() + "," + dr.getDataONE_Checksum().getValue());
-        response.addHeader("Content-Length", dr.getContent_Length() + "");
-        response.addHeader("Last-Modified", DateTimeMarshaller.serializeDateToUTC(dr.getLast_Modified()));
-        response.addHeader("DataONE-ObjectFormat", dr.getDataONE_ObjectFormatIdentifier().getValue());
-        response.addHeader("DataONE-SerialVersion", dr.getSerialVersion().toString());
-
-        
-    }
-    
-    /**
-     * get the logs based on passed params.  Available 
-     * See http://mule1.dataone.org/ArchitectureDocs/mn_api_crud.html#MN_crud.getLogRecords
-     * for more info
-     * @throws NotImplemented 
-     * @throws InvalidRequest 
-     * @throws NotAuthorized 
-     * @throws ServiceFailure 
-     * @throws InvalidToken 
-     * @throws IOException 
-     * @throws JiBXException 
-     */
-    private void getLog() throws InvalidToken, ServiceFailure, NotAuthorized, InvalidRequest, NotImplemented, IOException, JiBXException
-    {
-            
-        Date fromDate = null;
-        Date toDate = null;
-        Event event = null;
-        Integer start = null;
-        Integer count = null;
-        String pidFilter = null;
-        
-        try {
-        	String fromDateS = params.get("fromDate")[0];
-            logMetacat.debug("param fromDateS: " + fromDateS);
-            fromDate = DateTimeMarshaller.deserializeDateToUTC(fromDateS);
-        } catch (Exception e) {
-        	logMetacat.warn("Could not parse fromDate: " + e.getMessage());
-        }
-        try {
-        	String toDateS = params.get("toDate")[0];
-            logMetacat.debug("param toDateS: " + toDateS);
-            toDate = DateTimeMarshaller.deserializeDateToUTC(toDateS);
-        } catch (Exception e) {
-        	logMetacat.warn("Could not parse toDate: " + e.getMessage());
-		}
-        try {
-        	String eventS = params.get("event")[0];
-            event = Event.convert(eventS);
-        } catch (Exception e) {
-        	logMetacat.warn("Could not parse event: " + e.getMessage());
-		}
-        logMetacat.debug("fromDate: " + fromDate + " toDate: " + toDate);
-        
-        try {
-        	start =  Integer.parseInt(params.get("start")[0]);
-        } catch (Exception e) {
-			logMetacat.warn("Could not parse start: " + e.getMessage());
-		}
-        try {
-        	count =  Integer.parseInt(params.get("count")[0]);
-        } catch (Exception e) {
-			logMetacat.warn("Could not parse count: " + e.getMessage());
-		}
-        
-        try {
-            pidFilter = params.get("pidFilter")[0];
-        } catch (Exception e) {
-            logMetacat.warn("Could not parse pidFilter: " + e.getMessage());
-        }
-        
-        logMetacat.debug("calling getLogRecords");
-        Log log = MNodeService.getInstance(request).getLogRecords(session, fromDate, toDate, event, pidFilter, start, count);
-        
-        OutputStream out = response.getOutputStream();
-        response.setStatus(200);
-        response.setContentType("text/xml");
-        
-        TypeMarshaller.marshalTypeToOutputStream(log, out);
-        
-    }
-    
-    
-    
-    /**
-     * Implements REST version of DataONE CRUD API --> get
-     * @param pid ID of data object to be read
-     * @throws NotImplemented 
-     * @throws InvalidRequest 
-     * @throws NotFound 
-     * @throws NotAuthorized 
-     * @throws ServiceFailure 
-     * @throws InvalidToken 
-     * @throws IOException 
-     * @throws JiBXException 
-     */
-    protected void getObject(String pid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, InvalidRequest, NotImplemented, IOException, JiBXException {
-        OutputStream out = null;
-        
-        if (pid != null) { //get a specific document                
-            Identifier id = new Identifier();
-            id.setValue(pid);
-                
-            SystemMetadata sm = MNodeService.getInstance(request).getSystemMetadata(session, id);
-            
-            // set the headers for the content
-            String mimeType = ObjectFormatInfo.instance().getMimeType(sm.getFormatId().getValue());
-            if (mimeType == null) {
-            	mimeType = "application/octet-stream";
-            }
-            String extension = ObjectFormatInfo.instance().getExtension(sm.getFormatId().getValue());
-            String filename = id.getValue();
-            if (extension != null) {
-            	filename = id.getValue() + extension;
-            }
-            response.setContentType(mimeType);
-            response.setHeader("Content-Disposition", "inline; filename=" + filename);
-            
-            InputStream data = MNodeService.getInstance(request).get(session, id);
-
-            out = response.getOutputStream();  
-            IOUtils.copyLarge(data, out);
-            
-        }
-        else
-        { //call listObjects with specified params
-            Date startTime = null;
-            Date endTime = null;
-            ObjectFormatIdentifier formatId = null;
-            boolean replicaStatus = true;
-            int start = 0;
-            //TODO: make the max count into a const
-            int count = 1000;
-            Enumeration paramlist = request.getParameterNames();
-            while (paramlist.hasMoreElements()) 
-            { //parse the params and make the crud call
-                String name = (String) paramlist.nextElement();
-                String[] value = (String[])request.getParameterValues(name);
-
-                if (name.equals("fromDate") && value != null)
-                {
-                    try
-                    {
-                      //startTime = dateFormat.parse(value[0]);
-                    	startTime = DateTimeMarshaller.deserializeDateToUTC(value[0]);
-                        //startTime = parseDateAndConvertToGMT(value[0]);
-                    }
-                    catch(Exception e)
-                    {  //if we can't parse it, just don't use the fromDate param
-                        logMetacat.warn("Could not parse fromDate: " + value[0]);
-                        startTime = null;
-                    }
-                }
-                else if(name.equals("toDate") && value != null)
-                {
-                    try
-                    {
-                    	endTime = DateTimeMarshaller.deserializeDateToUTC(value[0]);
-                    }
-                    catch(Exception e)
-                    {  //if we can't parse it, just don't use the toDate param
-                        logMetacat.warn("Could not parse toDate: " + value[0]);
-                        endTime = null;
-                    }
-                }
-                else if(name.equals("formatId") && value != null) 
-                {
-                	formatId = new ObjectFormatIdentifier();
-                	formatId.setValue(value[0]);
-                }
-                else if(name.equals("replicaStatus") && value != null)
-                {
-                    if(value != null && 
-                       value.length > 0 && 
-                       (value[0].equalsIgnoreCase("false") || value[0].equalsIgnoreCase("no")))
-                    {
-                        replicaStatus = false;
-                    }
-                }
-                else if(name.equals("start") && value != null)
-                {
-                    start = new Integer(value[0]).intValue();
-                }
-                else if(name.equals("count") && value != null)
-                {
-                    count = new Integer(value[0]).intValue();
-                }
-            }
-            //make the crud call
-            logMetacat.debug("session: " + session + " startTime: " + startTime +
-                    " endTime: " + endTime + " formatId: " + 
-                    formatId + " replicaStatus: " + replicaStatus + 
-                    " start: " + start + " count: " + count);
-           
-            ObjectList ol = 
-           	 MNodeService.getInstance(request).listObjects(session, startTime, endTime, 
-           			formatId, replicaStatus, start, count);
-           
-            out = response.getOutputStream();  
-            response.setStatus(200);
-            response.setContentType("text/xml");
-            // Serialize and write it to the output stream
-            TypeMarshaller.marshalTypeToOutputStream(ol, out);
-            
-        }
-        
-    }
-    
-
-    /**
-     * Retrieve data package as Bagit zip
-     * @param pid
-     * @throws NotImplemented 
-     * @throws NotFound 
-     * @throws NotAuthorized 
-     * @throws ServiceFailure 
-     * @throws InvalidToken 
-     * @throws IOException 
-     */
-    protected void getPackage(String pid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, IOException {
-
-        Identifier id = new Identifier();
-        id.setValue(pid);
-        InputStream is = MNodeService.getInstance(request).getPackage(session, id);
-        
-        // use the provided filename
-        String filename = null;
-        if (is instanceof DeleteOnCloseFileInputStream) {
-            filename = ((DeleteOnCloseFileInputStream)is).getFile().getName();
-        } else {
-        	filename = "dataPackage-" + System.currentTimeMillis() + ".zip";
-        }
-        response.setHeader("Content-Disposition", "inline; filename=" + filename);
-        response.setContentType("application/zip");
-        response.setStatus(200);
-        OutputStream out = response.getOutputStream();
-        
-        // write it to the output stream
-        IOUtils.copyLarge(is, out);
-   }
-    
-	protected void publish(String pid) throws InvalidToken, ServiceFailure,
-			NotAuthorized, NotFound, NotImplemented, IOException,
-			JiBXException, InvalidRequest, IdentifierNotUnique,
-			UnsupportedType, InsufficientResources, InvalidSystemMetadata {
-
-		// publish the object
-		Identifier originalIdentifier = new Identifier();
-		originalIdentifier.setValue(pid);
-		Identifier newIdentifier = MNodeService.getInstance(request).publish(session, originalIdentifier);
-
-		response.setStatus(200);
-		response.setContentType("text/xml");
-		OutputStream out = response.getOutputStream();
-
-		// write new identifier to the output stream
-		TypeMarshaller.marshalTypeToOutputStream(newIdentifier, out);
-	}
-    
-    /**
-     * Retrieve System Metadata
-     * @param pid
-     * @throws InvalidToken
-     * @throws ServiceFailure
-     * @throws NotAuthorized
-     * @throws NotFound
-     * @throws InvalidRequest
-     * @throws NotImplemented
-     * @throws IOException
-     * @throws JiBXException
-     */
-    protected void getSystemMetadataObject(String pid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, InvalidRequest, NotImplemented, IOException, JiBXException {
-
-        Identifier id = new Identifier();
-        id.setValue(pid);
-        SystemMetadata sysmeta = MNodeService.getInstance(request).getSystemMetadata(session, id);
-        
-        response.setContentType("text/xml");
-        response.setStatus(200);
-        OutputStream out = response.getOutputStream();
-        
-        // Serialize and write it to the output stream
-        TypeMarshaller.marshalTypeToOutputStream(sysmeta, out);
-   }
-    
-    
-    /**
-     * Inserts or updates the object
-     * 
-     * @param pid - ID of data object to be inserted or updated.  If action is update, the pid
-     *               is the existing pid.  If insert, the pid is the new one
-     * @throws InvalidRequest 
-     * @throws ServiceFailure 
-     * @throws JiBXException 
-     * @throws NotImplemented 
-     * @throws InvalidSystemMetadata 
-     * @throws InsufficientResources 
-     * @throws UnsupportedType 
-     * @throws IdentifierNotUnique 
-     * @throws NotAuthorized 
-     * @throws InvalidToken 
-     * @throws NotFound 
-     * @throws IOException 
-     * @throws IllegalAccessException 
-     * @throws InstantiationException 
-     */
-    protected void putObject(String trailingPid, String action) throws ServiceFailure, InvalidRequest, JiBXException, InvalidToken, NotAuthorized, IdentifierNotUnique, UnsupportedType, InsufficientResources, InvalidSystemMetadata, NotImplemented, NotFound, IOException, InstantiationException, IllegalAccessException {
-       
-    	// Read the incoming data from its Mime Multipart encoding
-    	Map<String, File> files = collectMultipartFiles();
-               
-    	Identifier pid = new Identifier();
-        if (trailingPid == null) {
-	        // get the pid string from the body and set the value
-	        String pidString = multipartparams.get("pid").get(0);
-	        if (pidString != null) {
-            pid.setValue(pidString);
-            
-          } else {
-              throw new InvalidRequest("1102", "The pid param must be included and contain the identifier.");
-              
-          }
-        } else {
-        	// use the pid included in the URL
-        	pid.setValue(trailingPid);
-        }
-        logMetacat.debug("putObject with pid " + pid.getValue());
-        logMetacat.debug("Entering putObject: " + pid.getValue() + "/" + action);
-
-        InputStream object = null;
-        InputStream sysmeta = null;
-        File smFile = files.get("sysmeta");
-        sysmeta = new FileInputStream(smFile);
-        File objFile = files.get("object");
-        object = new FileInputStream(objFile);
-        
-        // ensure we have the object bytes
-        if  ( objFile == null ) {
-            throw new InvalidRequest("1102", "The object param must contain the object bytes.");
-            
-        }
-        
-        // ensure we have the system metadata
-        if  ( smFile == null ) {
-            throw new InvalidRequest("1102", "The sysmeta param must contain the system metadata document.");
-            
-        }
-        
-        response.setStatus(200);
-        response.setContentType("text/xml");
-        OutputStream out = response.getOutputStream();
-        
-        if (action.equals(FUNCTION_NAME_INSERT)) { 
-            // handle inserts
-            logMetacat.debug("Commence creation...");
-            SystemMetadata smd = TypeMarshaller.unmarshalTypeFromStream(SystemMetadata.class, sysmeta);
-
-            logMetacat.debug("creating object with pid " + pid.getValue());
-            Identifier rId = MNodeService.getInstance(request).create(session, pid, object, smd);
-            TypeMarshaller.marshalTypeToOutputStream(rId, out);
-            
-        } else if (action.equals(FUNCTION_NAME_UPDATE)) {
-        	// handle updates
-        	
-            // construct pids
-            Identifier newPid = null;
-            try {
-            	String newPidString = multipartparams.get("newPid").get(0);
-            	newPid = new Identifier();
-            	newPid.setValue(newPidString);
-            } catch (Exception e) {
-				logMetacat.error("Could not get newPid from request");
-			}
-            logMetacat.debug("Commence update...");
-            
-            // get the systemmetadata object
-            SystemMetadata smd = TypeMarshaller.unmarshalTypeFromStream(SystemMetadata.class, sysmeta);
-
-            Identifier rId = MNodeService.getInstance(request).update(session, pid, object, newPid, smd);
-            TypeMarshaller.marshalTypeToOutputStream(rId, out);
-        } else {
-            throw new InvalidRequest("1000", "Operation must be create or update.");
-        }
-   
-    }
-
-    /**
-     * Handle delete 
-     * @param pid ID of data object to be deleted
-     * @throws IOException
-     * @throws InvalidRequest 
-     * @throws NotImplemented 
-     * @throws NotFound 
-     * @throws NotAuthorized 
-     * @throws ServiceFailure 
-     * @throws InvalidToken 
-     * @throws JiBXException 
-     */
-    private void deleteObject(String pid) throws IOException, InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, InvalidRequest, JiBXException 
-    {
-
-        OutputStream out = response.getOutputStream();
-        response.setStatus(200);
-        response.setContentType("text/xml");
-
-        Identifier id = new Identifier();
-        id.setValue(pid);
-
-        logMetacat.debug("Calling delete");
-        MNodeService.getInstance(request).delete(session, id);
-        TypeMarshaller.marshalTypeToOutputStream(id, out);
-        
-    }
-    
-    /**
-     * Archives the given pid
-     * @param pid
-     * @throws InvalidToken
-     * @throws ServiceFailure
-     * @throws NotAuthorized
-     * @throws NotFound
-     * @throws NotImplemented
-     * @throws IOException
-     * @throws JiBXException
-     */
-    private void archive(String pid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, IOException, JiBXException {
-
-        OutputStream out = response.getOutputStream();
-        response.setStatus(200);
-        response.setContentType("text/xml");
-
-        Identifier id = new Identifier();
-        id.setValue(pid);
-
-        logMetacat.debug("Calling archive");
-        MNodeService.getInstance(request).archive(session, id);
-        
-        TypeMarshaller.marshalTypeToOutputStream(id, out);
-        
-    }
-
-	protected SynchronizationFailed collectSynchronizationFailed() throws IOException, ServiceFailure, InvalidRequest, JiBXException, InstantiationException, IllegalAccessException, ParserConfigurationException, SAXException  {
-		
-		// Read the incoming data from its Mime Multipart encoding
-		logMetacat.debug("Disassembling MIME multipart form");
-		InputStream sf = null;
-	
-		// handle MMP inputs
-		File tmpDir = getTempDirectory();
-		logMetacat.debug("temp dir: " + tmpDir.getAbsolutePath());
-		MultipartRequestResolver mrr = 
-			new MultipartRequestResolver(tmpDir.getAbsolutePath(), 1000000000, 0);
-		MultipartRequest mr = null;
-		try {
-			mr = mrr.resolveMultipart(request);
-		} catch (Exception e) {
-			throw new ServiceFailure("2161", 
-					"Could not resolve multipart: " + e.getMessage());
-		}
-		logMetacat.debug("resolved multipart request");
-		Map<String, File> files = mr.getMultipartFiles();
-		if (files == null || files.keySet() == null) {
-			throw new InvalidRequest("2163",
-					"must have multipart file with name 'message'");
-		}
-		logMetacat.debug("got multipart files");
-	
-		multipartparams = mr.getMultipartParameters();
-	
-		File sfFile = files.get("message");
-		if (sfFile == null) {
-			throw new InvalidRequest("2163",
-					"Missing the required file-part 'message' from the multipart request.");
-		}
-		logMetacat.debug("sfFile: " + sfFile.getAbsolutePath());
-		sf = new FileInputStream(sfFile);
-	
-		SynchronizationFailed syncFailed = (SynchronizationFailed) ExceptionHandler.deserializeXml(sf, "Error deserializing exception");
-		return syncFailed;
-	}
-
-}

Property changes on: src/edu/ucsb/nceas/metacat/restservice/MNResourceHandler.java
___________________________________________________________________
Deleted: svn:eol-style
## -1 +0,0 ##
-native
\ No newline at end of property
Deleted: svn:keywords
## -1 +0,0 ##
-Author Date Id Revision
\ No newline at end of property
Index: src/edu/ucsb/nceas/metacat/dataone/ObjectFormatService.java
===================================================================
--- src/edu/ucsb/nceas/metacat/dataone/ObjectFormatService.java	(revision 8809)
+++ src/edu/ucsb/nceas/metacat/dataone/ObjectFormatService.java	(revision 8810)
@@ -29,14 +29,12 @@
 
 import org.apache.log4j.Logger;
 import org.dataone.service.util.TypeMarshaller;
-import org.dataone.service.exceptions.InsufficientResources;
-import org.dataone.service.exceptions.InvalidRequest;
 import org.dataone.service.exceptions.NotFound;
 import org.dataone.service.exceptions.NotImplemented;
 import org.dataone.service.exceptions.ServiceFailure;
-import org.dataone.service.types.v1.ObjectFormat;
+import org.dataone.service.types.v2.ObjectFormat;
 import org.dataone.service.types.v1.ObjectFormatIdentifier;
-import org.dataone.service.types.v1.ObjectFormatList;
+import org.dataone.service.types.v2.ObjectFormatList;
 import org.jibx.runtime.JiBXException;
 
 import edu.ucsb.nceas.metacat.DBUtil;
Index: src/edu/ucsb/nceas/metacat/dataone/v1/CNodeService.java
===================================================================
--- src/edu/ucsb/nceas/metacat/dataone/v1/CNodeService.java	(nonexistent)
+++ src/edu/ucsb/nceas/metacat/dataone/v1/CNodeService.java	(revision 8810)
@@ -0,0 +1,585 @@
+/**
+ *  '$RCSfile$'
+ *  Copyright: 2000-2011 Regents of the University of California and the
+ *              National Center for Ecological Analysis and Synthesis
+ *
+ *   '$Author$'
+ *     '$Date$'
+ *
+ * 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.dataone.v1;
+
+import java.io.InputStream;
+import java.util.Date;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.log4j.Logger;
+import org.dataone.service.cn.v1.CNAuthorization;
+import org.dataone.service.cn.v1.CNCore;
+import org.dataone.service.cn.v1.CNRead;
+import org.dataone.service.cn.v1.CNReplication;
+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.NotFound;
+import org.dataone.service.exceptions.NotImplemented;
+import org.dataone.service.exceptions.ServiceFailure;
+import org.dataone.service.exceptions.UnsupportedType;
+import org.dataone.service.exceptions.VersionMismatch;
+import org.dataone.service.types.v1.AccessPolicy;
+import org.dataone.service.types.v1.Checksum;
+import org.dataone.service.types.v1.ChecksumAlgorithmList;
+import org.dataone.service.types.v1.DescribeResponse;
+import org.dataone.service.types.v1.Event;
+import org.dataone.service.types.v1.Identifier;
+import org.dataone.service.types.v1.Log;
+import org.dataone.service.types.v1.NodeList;
+import org.dataone.service.types.v1.NodeReference;
+import org.dataone.service.types.v1.ObjectFormat;
+import org.dataone.service.types.v1.ObjectFormatIdentifier;
+import org.dataone.service.types.v1.ObjectFormatList;
+import org.dataone.service.types.v1.ObjectList;
+import org.dataone.service.types.v1.ObjectLocationList;
+import org.dataone.service.types.v1.Permission;
+import org.dataone.service.types.v1.Replica;
+import org.dataone.service.types.v1.ReplicationPolicy;
+import org.dataone.service.types.v1.ReplicationStatus;
+import org.dataone.service.types.v1.Session;
+import org.dataone.service.types.v1.Subject;
+import org.dataone.service.types.v1.SystemMetadata;
+import org.dataone.service.types.v1_1.QueryEngineDescription;
+import org.dataone.service.types.v1_1.QueryEngineList;
+import org.dataone.service.util.TypeMarshaller;
+
+/**
+ * Represents Metacat's implementation of the DataONE Coordinating Node service
+ * API. Methods implement the various CN* interfaces, and methods common to both
+ * Member Node and Coordinating Node interfaces are found in the D1NodeService
+ * super class.
+ * 
+ */
+public class CNodeService implements CNAuthorization, CNCore, CNRead,
+		CNReplication {
+
+	// pass through to the most recent implementation
+	private edu.ucsb.nceas.metacat.dataone.CNodeService impl = null;
+
+	/* the logger instance */
+	private Logger logMetacat = null;
+
+	/**
+	 * singleton accessor
+	 */
+	public static CNodeService getInstance(HttpServletRequest request) {
+		return new CNodeService(request);
+	}
+
+	/**
+	 * Constructor, private for singleton access
+	 */
+	private CNodeService(HttpServletRequest request) {
+
+		logMetacat = Logger.getLogger(CNodeService.class);
+
+		impl = edu.ucsb.nceas.metacat.dataone.CNodeService.getInstance(request);
+
+	}
+
+	@Override
+	public boolean deleteReplicationMetadata(Identifier pid,
+			NodeReference nodeId, long serialVersion) throws InvalidToken, InvalidRequest,
+			ServiceFailure, NotAuthorized, NotFound, NotImplemented,
+			VersionMismatch {
+		return impl.deleteReplicationMetadata(null, pid, nodeId, serialVersion);
+	}
+
+	@Override
+	@Deprecated
+	public boolean deleteReplicationMetadata(Session session, Identifier pid,
+			NodeReference nodeId, long serialVersion) throws InvalidToken, InvalidRequest,
+			ServiceFailure, NotAuthorized, NotFound, NotImplemented,
+			VersionMismatch {
+		return impl.deleteReplicationMetadata(session, pid, nodeId, serialVersion);
+
+	}
+
+	@Override
+	public boolean isNodeAuthorized(Subject targetNodeSubject, Identifier pid)
+			throws NotImplemented, NotAuthorized, InvalidToken, ServiceFailure,
+			NotFound, InvalidRequest {
+		return impl.isNodeAuthorized(null, targetNodeSubject, pid);
+
+	}
+
+	@Override
+	@Deprecated
+	public boolean isNodeAuthorized(Session originatingNodeSession, Subject targetNodeSubject, Identifier pid)
+			throws NotImplemented, NotAuthorized, InvalidToken, ServiceFailure,
+			NotFound, InvalidRequest {
+		return impl.isNodeAuthorized(originatingNodeSession, targetNodeSubject, pid);
+	}
+
+	@Override
+	public boolean setReplicationPolicy(Identifier pid,
+			ReplicationPolicy policy, long serialVersion) throws NotImplemented, NotFound,
+			NotAuthorized, ServiceFailure, InvalidRequest, InvalidToken,
+			VersionMismatch {
+		return impl.setReplicationPolicy(null, pid, policy, serialVersion);
+	}
+
+	@Override
+	@Deprecated
+	public boolean setReplicationPolicy(Session session, Identifier pid,
+			ReplicationPolicy policy, long serialVersion) throws NotImplemented, NotFound,
+			NotAuthorized, ServiceFailure, InvalidRequest, InvalidToken,
+			VersionMismatch {
+		return impl.setReplicationPolicy(session, pid, policy, serialVersion);
+
+	}
+
+	@Override
+	public boolean setReplicationStatus(Identifier pid,
+			NodeReference targetNode, ReplicationStatus status, BaseException failure) 
+			throws ServiceFailure, NotImplemented, InvalidToken, NotAuthorized, InvalidRequest, NotFound {
+		return impl.setReplicationStatus(null, pid, targetNode, status, failure);
+	}
+
+	@Override
+	@Deprecated
+	public boolean setReplicationStatus(Session session, Identifier pid,
+			NodeReference targetNode, ReplicationStatus status, BaseException failure)
+			throws ServiceFailure, NotImplemented, InvalidToken, NotAuthorized,
+			InvalidRequest, NotFound {
+		return impl.setReplicationStatus(session, pid, targetNode, status, failure);
+	}
+
+	@Override
+	public boolean updateReplicationMetadata(Identifier pid,
+			Replica replica, long serialVersion) throws NotImplemented, NotAuthorized, ServiceFailure,
+			NotFound, InvalidRequest, InvalidToken, VersionMismatch {
+		return impl.updateReplicationMetadata(null, pid, replica, serialVersion);
+	}
+
+	@Override
+	@Deprecated
+	public boolean updateReplicationMetadata(Session session, Identifier pid,
+			Replica replica, long serialVersion) throws NotImplemented, NotAuthorized,
+			ServiceFailure, NotFound, InvalidRequest, InvalidToken,
+			VersionMismatch {
+		return impl.updateReplicationMetadata(session, pid, replica, serialVersion);
+	}
+
+	@Override
+	public DescribeResponse describe(Identifier pid) throws InvalidToken,
+			NotAuthorized, NotImplemented, ServiceFailure, NotFound {
+		return impl.describe(null, pid);
+	}
+
+	@Override
+	@Deprecated
+	public DescribeResponse describe(Session session, Identifier pid)
+			throws InvalidToken, NotAuthorized, NotImplemented, ServiceFailure,
+			NotFound {
+		return impl.describe(session, pid);
+	}
+
+	@Override
+	public InputStream get(Identifier pid) throws InvalidToken,
+			ServiceFailure, NotAuthorized, NotFound, NotImplemented {
+		return impl.get(null, pid);
+	}
+
+	@Override
+	@Deprecated
+	public InputStream get(Session session, Identifier pid) throws InvalidToken,
+			ServiceFailure, NotAuthorized, NotFound, NotImplemented {
+		return impl.get(session, pid);
+	}
+
+	@Override
+	public Checksum getChecksum(Identifier pid) throws InvalidToken,
+			ServiceFailure, NotAuthorized, NotFound, NotImplemented {
+		return impl.getChecksum(null, pid);
+	}
+
+	@Override
+	@Deprecated
+	public Checksum getChecksum(Session session, Identifier pid)
+			throws InvalidToken, ServiceFailure, NotAuthorized, NotFound,
+			NotImplemented {
+		return impl.getChecksum(session, pid);
+	}
+
+	@Override
+	public QueryEngineDescription getQueryEngineDescription(String queryEngine)
+			throws InvalidToken, ServiceFailure, NotAuthorized, NotImplemented,
+			NotFound {
+		return impl.getQueryEngineDescription(null, queryEngine);
+	}
+
+	@Override
+	public SystemMetadata getSystemMetadata(Identifier pid)
+			throws InvalidToken, ServiceFailure, NotAuthorized, NotFound,
+			NotImplemented {
+		return impl.getSystemMetadata(null, pid);
+	}
+
+	@Override
+	@Deprecated
+	public SystemMetadata getSystemMetadata(Session session, Identifier pid)
+			throws InvalidToken, ServiceFailure, NotAuthorized, NotFound,
+			NotImplemented {
+		return impl.getSystemMetadata(session, pid);
+	}
+
+	@Override
+	public ObjectList listObjects(Date startTime, Date endTime,
+			ObjectFormatIdentifier formatid, Boolean replicaStatus, Integer start,
+			Integer count) throws InvalidRequest, InvalidToken, NotAuthorized,
+			NotImplemented, ServiceFailure {
+		return impl.listObjects(null, startTime, endTime, formatid, null, replicaStatus, start, count);
+	}
+
+	@Override
+	@Deprecated
+	public ObjectList listObjects(Session session, Date startTime, Date endTime,
+			ObjectFormatIdentifier formatid, Boolean replicaStatus, Integer start,
+			Integer count) throws InvalidRequest, InvalidToken, NotAuthorized,
+			NotImplemented, ServiceFailure {
+		return impl.listObjects(session, startTime, endTime, formatid, null, replicaStatus, start, count);
+	}
+
+	@Override
+	public QueryEngineList listQueryEngines() throws InvalidToken,
+			ServiceFailure, NotAuthorized, NotImplemented {
+		return impl.listQueryEngines(null);
+	}
+
+	@Override
+	public InputStream query(String queryEngine, String query) throws InvalidToken,
+			ServiceFailure, NotAuthorized, InvalidRequest, NotImplemented,
+			NotFound {
+		return impl.query(null, queryEngine, query);
+	}
+
+	@Override
+	public ObjectLocationList resolve(Identifier pid) throws InvalidToken,
+			ServiceFailure, NotAuthorized, NotFound, NotImplemented {
+		return impl.resolve(null, pid);
+	}
+
+	@Override
+	@Deprecated
+	public ObjectLocationList resolve(Session session, Identifier pid)
+			throws InvalidToken, ServiceFailure, NotAuthorized, NotFound,
+			NotImplemented {
+		return impl.resolve(session, pid);
+	}
+
+	@Override
+	public ObjectList search(String queryType, String query) throws InvalidToken,
+			ServiceFailure, NotAuthorized, InvalidRequest, NotImplemented {
+		return impl.search(null, queryType, query);
+	}
+
+	@Override
+	@Deprecated
+	public ObjectList search(Session session, String queryType, String query)
+			throws InvalidToken, ServiceFailure, NotAuthorized, InvalidRequest,
+			NotImplemented {
+		return impl.search(session, queryType, query);
+	}
+
+	@Override
+	public Identifier archive(Identifier pid) throws InvalidToken,
+			ServiceFailure, NotAuthorized, NotFound, NotImplemented {
+		return impl.archive(null, pid);
+	}
+
+	@Override
+	@Deprecated
+	public Identifier archive(Session session, Identifier pid)
+			throws InvalidToken, ServiceFailure, InvalidRequest, NotAuthorized,
+			NotFound, NotImplemented {
+		return impl.archive(session, pid);
+	}
+
+	@Override
+	public Identifier create(Identifier pid, InputStream object,
+			SystemMetadata sysmeta) throws InvalidToken, ServiceFailure,
+			NotAuthorized, IdentifierNotUnique, UnsupportedType,
+			InsufficientResources, InvalidSystemMetadata, NotImplemented,
+			InvalidRequest {
+		return this.create(null, pid, object, sysmeta);
+	}
+
+	@Override
+	@Deprecated
+	public Identifier create(Session session, Identifier pid, InputStream object,
+			SystemMetadata sysmeta) throws InvalidToken, ServiceFailure,
+			NotAuthorized, IdentifierNotUnique, UnsupportedType,
+			InsufficientResources, InvalidSystemMetadata, NotImplemented,
+			InvalidRequest {
+		
+		//convert sysmeta to newer version
+		org.dataone.service.types.v2.SystemMetadata v2Sysmeta = null;
+		try {
+			v2Sysmeta = TypeMarshaller.convertTypeFromType(sysmeta, org.dataone.service.types.v2.SystemMetadata.class);
+		} catch (Exception e) {
+			// report as service failure
+			ServiceFailure sf = new ServiceFailure("1030", e.getMessage());
+			sf.initCause(e);
+			throw sf;
+		}
+		
+		return impl.create(session, pid, object, v2Sysmeta);
+	}
+
+	@Override
+	public Identifier delete(Identifier pid) throws InvalidToken,
+			ServiceFailure, NotAuthorized, NotFound, NotImplemented {
+		return impl.delete(null, pid);
+	}
+
+	@Override
+	@Deprecated
+	public Identifier delete(Session session, Identifier pid)
+			throws InvalidToken, ServiceFailure, InvalidRequest, NotAuthorized,
+			NotFound, NotImplemented {
+		return impl.delete(session, pid);
+	}
+
+	@Override
+	public Identifier generateIdentifier(String scheme, String fragment)
+			throws InvalidToken, ServiceFailure, NotAuthorized, NotImplemented,
+			InvalidRequest {
+		return impl.generateIdentifier(null, scheme, fragment);
+	}
+
+	@Override
+	@Deprecated
+	public Identifier generateIdentifier(Session session, String scheme, String fragment)
+			throws InvalidToken, ServiceFailure, NotAuthorized, NotImplemented,
+			InvalidRequest {
+		return impl.generateIdentifier(session, scheme, fragment);
+	}
+
+	@Override
+	public ObjectFormat getFormat(ObjectFormatIdentifier fmtid)
+			throws ServiceFailure, NotFound, NotImplemented, InvalidRequest {
+		return impl.getFormat(fmtid);
+	}
+
+	@Override
+	public Log getLogRecords(Date fromDate, Date toDate, Event event,
+			String pidFilter, Integer start, Integer count) throws InvalidToken, InvalidRequest,
+			ServiceFailure, NotAuthorized, NotImplemented,
+			InsufficientResources {
+		return this.getLogRecords(null, fromDate, toDate, event, pidFilter, start, count);
+	}
+
+	@Override
+	@Deprecated
+	public Log getLogRecords(Session session, Date fromDate, Date toDate, Event event,
+			String pidFilter, Integer start, Integer count) throws InvalidToken,
+			InvalidRequest, ServiceFailure, NotAuthorized, NotImplemented,
+			InsufficientResources {
+		org.dataone.service.types.v2.Log log = impl.getLogRecords(session, fromDate, toDate, event.xmlValue(), pidFilter, start, count);
+		Log retLog = null;
+		try {
+			retLog = TypeMarshaller.convertTypeFromType(log, Log.class);
+		} catch (Exception e) {
+			// report as service failure
+			ServiceFailure sf = new ServiceFailure("1490", e.getMessage());
+			sf.initCause(e);
+			throw sf;
+		}
+		return retLog;
+	}
+
+	@Override
+	public boolean hasReservation(Subject subject, Identifier pid)
+			throws InvalidToken, ServiceFailure, NotFound, NotAuthorized,
+			NotImplemented, InvalidRequest, IdentifierNotUnique {
+		return impl.hasReservation(null, subject, pid);
+	}
+
+	@Override
+	@Deprecated
+	public boolean hasReservation(Session session, Subject subject, Identifier pid)
+			throws InvalidToken, ServiceFailure, NotFound, NotAuthorized,
+			NotImplemented, InvalidRequest, IdentifierNotUnique {
+		return impl.hasReservation(session, subject, pid);
+
+	}
+
+	@Override
+	public ChecksumAlgorithmList listChecksumAlgorithms()
+			throws ServiceFailure, NotImplemented {
+		return impl.listChecksumAlgorithms();
+	}
+
+	@Override
+	public ObjectFormatList listFormats() throws ServiceFailure, NotImplemented {
+		org.dataone.service.types.v2.ObjectFormatList formats = impl.listFormats();
+		ObjectFormatList retFormats = null;
+		try {
+			retFormats = TypeMarshaller.convertTypeFromType(formats, ObjectFormatList.class);
+		} catch (Exception e) {
+			// report as service failure
+			ServiceFailure sf = new ServiceFailure("4841", e.getMessage());
+			sf.initCause(e);
+			throw sf;
+		}
+		return retFormats;
+	}
+
+	@Override
+	public NodeList listNodes() throws NotImplemented, ServiceFailure {
+		org.dataone.service.types.v2.NodeList nodes = impl.listNodes();
+		NodeList retNodes = null;
+		try {
+			retNodes = TypeMarshaller.convertTypeFromType(nodes, NodeList.class);
+		} catch (Exception e) {
+			// report as service failure
+			ServiceFailure sf = new ServiceFailure("4801", e.getMessage());
+			sf.initCause(e);
+			throw sf;
+		}
+		return retNodes;
+	}
+
+	@Override
+	public Date ping() throws NotImplemented, ServiceFailure,
+			InsufficientResources {
+		return impl.ping();
+	}
+
+	@Override
+	public Identifier registerSystemMetadata(Identifier pid,
+			SystemMetadata sysmeta) throws NotImplemented, NotAuthorized,
+			ServiceFailure, InvalidRequest, InvalidSystemMetadata, InvalidToken {
+		return this.registerSystemMetadata(null, pid, sysmeta);
+		
+	}
+
+	@Override
+	@Deprecated
+	public Identifier registerSystemMetadata(Session session, Identifier pid,
+			SystemMetadata sysmeta) throws NotImplemented, NotAuthorized,
+			ServiceFailure, InvalidRequest, InvalidSystemMetadata, InvalidToken {
+		//convert sysmeta to newer version
+		org.dataone.service.types.v2.SystemMetadata v2Sysmeta = null;
+		try {
+			v2Sysmeta = TypeMarshaller.convertTypeFromType(sysmeta, org.dataone.service.types.v2.SystemMetadata.class);
+		} catch (Exception e) {
+			// report as service failure
+			ServiceFailure sf = new ServiceFailure("1030", e.getMessage());
+			sf.initCause(e);
+			throw sf;
+		}
+		
+		return impl.registerSystemMetadata(session, pid, v2Sysmeta);
+	}
+
+	@Override
+	public Identifier reserveIdentifier(Identifier pid) throws InvalidToken,
+			ServiceFailure, NotAuthorized, IdentifierNotUnique, NotImplemented,
+			InvalidRequest {
+		return impl.reserveIdentifier(null, pid);
+	}
+
+	@Override
+	@Deprecated
+	public Identifier reserveIdentifier(Session session, Identifier pid)
+			throws InvalidToken, ServiceFailure, NotAuthorized,
+			IdentifierNotUnique, NotImplemented, InvalidRequest {
+		return impl.reserveIdentifier(session, pid);
+	}
+
+	@Override
+	public boolean setObsoletedBy(Identifier pid, Identifier obsoletedByPid, long serialVersion)
+			throws NotImplemented, NotFound, NotAuthorized, ServiceFailure,
+			InvalidRequest, InvalidToken, VersionMismatch {
+		return impl.setObsoletedBy(null, pid, obsoletedByPid, serialVersion);
+	}
+
+	@Override
+	@Deprecated
+	public boolean setObsoletedBy(Session session, Identifier pid, Identifier obsoletedByPid, long serialVersion) 
+			throws NotImplemented, NotFound,
+			NotAuthorized, ServiceFailure, InvalidRequest, InvalidToken,
+			VersionMismatch {
+		return impl.setObsoletedBy(session, pid, obsoletedByPid, serialVersion);
+
+	}
+
+	@Override
+	public boolean isAuthorized(Identifier pid, Permission permission)
+			throws ServiceFailure, InvalidToken, NotFound, NotAuthorized,
+			NotImplemented, InvalidRequest {
+		return impl.isAuthorized(null, pid, permission);
+	}
+
+	@Override
+	@Deprecated
+	public boolean isAuthorized(Session session, Identifier pid, Permission permission)
+			throws ServiceFailure, InvalidToken, NotFound, NotAuthorized,
+			NotImplemented, InvalidRequest {
+		return impl.isAuthorized(session, pid, permission);
+	}
+
+	@Override
+	public boolean setAccessPolicy(Identifier pid,
+			AccessPolicy accessPolicy, long serialVersion)
+			throws InvalidToken, NotFound, NotImplemented, NotAuthorized,
+			ServiceFailure, InvalidRequest, VersionMismatch {
+		return impl.setAccessPolicy(null, pid, accessPolicy, serialVersion);
+	}
+
+	@Override
+	@Deprecated
+	public boolean setAccessPolicy(Session session, Identifier pid,
+			AccessPolicy accessPolicy, long serialVersion) throws InvalidToken, NotFound,
+			NotImplemented, NotAuthorized, ServiceFailure, InvalidRequest,
+			VersionMismatch {
+		return impl.setAccessPolicy(session, pid, accessPolicy, serialVersion);
+	}
+
+	@Override
+	public Identifier setRightsHolder(Identifier pid, Subject userId, long serialVersion)
+			throws InvalidToken, ServiceFailure, NotFound, NotAuthorized,
+			NotImplemented, InvalidRequest, VersionMismatch {
+		return impl.setRightsHolder(null, pid, userId, serialVersion);
+	}
+
+	@Override
+	@Deprecated
+	public Identifier setRightsHolder(Session session, Identifier pid,
+			Subject userId, long serialVersion) throws InvalidToken, ServiceFailure,
+			NotFound, NotAuthorized, NotImplemented, InvalidRequest,
+			VersionMismatch {
+		return impl.setRightsHolder(session, pid, userId, serialVersion);
+
+	}
+
+}

Property changes on: src/edu/ucsb/nceas/metacat/dataone/v1/CNodeService.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property
Index: src/edu/ucsb/nceas/metacat/dataone/DOIService.java
===================================================================
--- src/edu/ucsb/nceas/metacat/dataone/DOIService.java	(revision 8809)
+++ src/edu/ucsb/nceas/metacat/dataone/DOIService.java	(revision 8810)
@@ -31,7 +31,8 @@
 
 import org.apache.log4j.Logger;
 import org.apache.wicket.protocol.http.mock.MockHttpServletRequest;
-import org.dataone.client.D1Client;
+import org.dataone.client.v2.itk.D1Client;
+import org.dataone.service.exceptions.BaseException;
 import org.dataone.service.exceptions.InvalidRequest;
 import org.dataone.service.exceptions.InvalidToken;
 import org.dataone.service.exceptions.NotAuthorized;
@@ -39,14 +40,14 @@
 import org.dataone.service.exceptions.NotImplemented;
 import org.dataone.service.exceptions.ServiceFailure;
 import org.dataone.service.types.v1.Identifier;
-import org.dataone.service.types.v1.Node;
-import org.dataone.service.types.v1.ObjectFormat;
+import org.dataone.service.types.v2.Node;
+import org.dataone.service.types.v2.ObjectFormat;
 import org.dataone.service.types.v1.Permission;
 import org.dataone.service.types.v1.Person;
 import org.dataone.service.types.v1.Session;
 import org.dataone.service.types.v1.Subject;
 import org.dataone.service.types.v1.SubjectInfo;
-import org.dataone.service.types.v1.SystemMetadata;
+import org.dataone.service.types.v2.SystemMetadata;
 import org.dataone.service.types.v1.util.AuthUtils;
 import org.dataone.service.util.Constants;
 import org.ecoinformatics.datamanager.parser.DataPackage;
@@ -200,7 +201,7 @@
 				ObjectFormat objectFormat = null;
 				try {
 					objectFormat = D1Client.getCN().getFormat(sysMeta.getFormatId());
-				} catch (NotFound e1) {
+				} catch (BaseException e1) {
 					logMetacat.warn("Could not check format type for: " + sysMeta.getFormatId());
 				}
 				if (objectFormat != null && objectFormat.getFormatType().equals("METADATA")) {
@@ -339,7 +340,7 @@
 		// default to given DN
 		String fullName = subject.getValue();
 		
-		SubjectInfo subjectInfo = D1Client.getCN().getSubjectInfo(subject);
+		SubjectInfo subjectInfo = D1Client.getCN().getSubjectInfo(null, subject);
 		if (subjectInfo != null && subjectInfo.getPersonList() != null) {
 			for (Person p: subjectInfo.getPersonList()) {
 				if (p.getSubject().equals(subject)) {
Index: src/edu/ucsb/nceas/metacat/dataone/hazelcast/HazelcastService.java
===================================================================
--- src/edu/ucsb/nceas/metacat/dataone/hazelcast/HazelcastService.java	(revision 8809)
+++ src/edu/ucsb/nceas/metacat/dataone/hazelcast/HazelcastService.java	(revision 8810)
@@ -39,7 +39,7 @@
 import org.apache.log4j.Logger;
 import org.dataone.service.exceptions.InvalidSystemMetadata;
 import org.dataone.service.types.v1.Identifier;
-import org.dataone.service.types.v1.SystemMetadata;
+import org.dataone.service.types.v2.SystemMetadata;
 
 import com.hazelcast.config.Config;
 import com.hazelcast.config.FileSystemXmlConfig;
Index: src/edu/ucsb/nceas/metacat/admin/upgrade/UpdateDOI.java
===================================================================
--- src/edu/ucsb/nceas/metacat/admin/upgrade/UpdateDOI.java	(revision 8809)
+++ src/edu/ucsb/nceas/metacat/admin/upgrade/UpdateDOI.java	(revision 8810)
@@ -31,7 +31,7 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.dataone.service.types.v1.Identifier;
-import org.dataone.service.types.v1.SystemMetadata;
+import org.dataone.service.types.v2.SystemMetadata;
 
 import edu.ucsb.nceas.metacat.DBUtil;
 import edu.ucsb.nceas.metacat.DocumentImpl;
@@ -39,9 +39,7 @@
 import edu.ucsb.nceas.metacat.admin.AdminException;
 import edu.ucsb.nceas.metacat.dataone.DOIService;
 import edu.ucsb.nceas.metacat.dataone.hazelcast.HazelcastService;
-import edu.ucsb.nceas.metacat.properties.PropertyService;
 import edu.ucsb.nceas.metacat.util.DocumentUtil;
-import edu.ucsb.nceas.utilities.PropertyNotFoundException;
 
 
 
Index: test/edu/ucsb/nceas/metacat/admin/upgrade/dataone/SyncAccessPolicyTest.java
===================================================================
--- test/edu/ucsb/nceas/metacat/admin/upgrade/dataone/SyncAccessPolicyTest.java	(revision 8809)
+++ test/edu/ucsb/nceas/metacat/admin/upgrade/dataone/SyncAccessPolicyTest.java	(revision 8810)
@@ -34,8 +34,8 @@
 import junit.framework.Test;
 import junit.framework.TestSuite;
 
-import org.dataone.client.CNode;
-import org.dataone.client.D1Client;
+import org.dataone.client.v2.CNode;
+import org.dataone.client.v2.itk.D1Client;
 import org.dataone.service.exceptions.ServiceFailure;
 import org.dataone.service.types.v1.AccessPolicy;
 import org.dataone.service.types.v1.AccessRule;
@@ -43,7 +43,7 @@
 import org.dataone.service.types.v1.Permission;
 import org.dataone.service.types.v1.Session;
 import org.dataone.service.types.v1.Subject;
-import org.dataone.service.types.v1.SystemMetadata;
+import org.dataone.service.types.v2.SystemMetadata;
 import org.junit.Before;
 
 import edu.ucsb.nceas.metacat.IdentifierManager;
@@ -199,7 +199,7 @@
 				// Get sm, access policy for requested pid from the CN
 				// Get sm, access policy for requested pid from the CN
 				try {
-					cnSysMeta = cn.getSystemMetadata(pid);
+					cnSysMeta = cn.getSystemMetadata(null, pid);
 					debug("Got SM from CN");
 
 				} catch (Exception e) {
@@ -222,7 +222,7 @@
 			/* Read SM from MN */
 			try {
 				mnSysMeta = MNodeService.getInstance(request)
-						.getSystemMetadata(pid);
+						.getSystemMetadata(null, pid);
 				debug("Got SM from MN");
 			} catch (Exception e) {
 				fail("Error getting system metadata for new pid: "
@@ -268,7 +268,7 @@
 			/* Reread SM from MN after updating access */
 			try {
 				mnSysMeta = MNodeService.getInstance(request)
-						.getSystemMetadata(pid);
+						.getSystemMetadata(null, pid);
 				debug("Got SM from MN");
 			} catch (Exception e) {
 				fail("Error getting system metadata for new pid: "
@@ -309,7 +309,7 @@
 
 			/* Reread SM from CN */
 			try {
-				cnSysMeta = cn.getSystemMetadata(pid);
+				cnSysMeta = cn.getSystemMetadata(null, pid);
 				debug("Got SM from CN");
 			} catch (Exception e) {
 				fail("Error getting system metadata for pid: " + pid.getValue()
@@ -448,7 +448,7 @@
 				Thread.sleep(1000 * 60);
 				// Get sm for data object pid from the CN
 				try {
-					cnSysMeta = cn.getSystemMetadata(pid);
+					cnSysMeta = cn.getSystemMetadata(null, pid);
 				} catch (Exception e) {
 					debug("Error getting system metadata for pid: "
 							+ pid.getValue() + " from cn: " + e.getMessage());
@@ -501,7 +501,7 @@
 			}
 			/* Get CN access policy for data object */
 			try {
-				cnSysMeta = cn.getSystemMetadata(pid);
+				cnSysMeta = cn.getSystemMetadata(null, pid);
 			} catch (Exception e) {
 				debug("Error getting system metadata for pid: "
 						+ pid.getValue() + " from cn: " + e.getMessage());
Index: test/edu/ucsb/nceas/metacat/annotation/OrePackageTest.java
===================================================================
--- test/edu/ucsb/nceas/metacat/annotation/OrePackageTest.java	(revision 8809)
+++ test/edu/ucsb/nceas/metacat/annotation/OrePackageTest.java	(revision 8810)
@@ -33,7 +33,7 @@
 import org.dataone.service.types.v1.Identifier;
 import org.dataone.service.types.v1.ObjectFormatIdentifier;
 import org.dataone.service.types.v1.Session;
-import org.dataone.service.types.v1.SystemMetadata;
+import org.dataone.service.types.v2.SystemMetadata;
 import org.dspace.foresite.OREFactory;
 import org.dspace.foresite.Predicate;
 import org.dspace.foresite.ResourceMap;
Index: test/edu/ucsb/nceas/metacat/annotation/DatapackageSummarizerTest.java
===================================================================
--- test/edu/ucsb/nceas/metacat/annotation/DatapackageSummarizerTest.java	(revision 8809)
+++ test/edu/ucsb/nceas/metacat/annotation/DatapackageSummarizerTest.java	(revision 8810)
@@ -36,7 +36,7 @@
 import org.dataone.service.types.v1.Identifier;
 import org.dataone.service.types.v1.ObjectFormatIdentifier;
 import org.dataone.service.types.v1.Session;
-import org.dataone.service.types.v1.SystemMetadata;
+import org.dataone.service.types.v2.SystemMetadata;
 
 import edu.ucsb.nceas.metacat.DBUtil;
 import edu.ucsb.nceas.metacat.DocumentImpl;
@@ -215,7 +215,7 @@
 				// look for the latest version of the annotation, if there is one
 				do {
 					try {
-						sysmeta = MNodeService.getInstance(request).getSystemMetadata(annotationPid);
+						sysmeta = MNodeService.getInstance(request).getSystemMetadata(null, annotationPid);
 						if (sysmeta.getObsoletedBy() != null) {
 							annotationPid.setValue(sysmeta.getObsoletedBy().getValue());
 						}
Index: test/edu/ucsb/nceas/metacat/dataone/RegisterDOITest.java
===================================================================
--- test/edu/ucsb/nceas/metacat/dataone/RegisterDOITest.java	(revision 8809)
+++ test/edu/ucsb/nceas/metacat/dataone/RegisterDOITest.java	(revision 8810)
@@ -37,12 +37,12 @@
 import junit.framework.TestSuite;
 
 import org.apache.commons.io.IOUtils;
-import org.dataone.client.ObjectFormatCache;
+import org.dataone.client.v2.formats.ObjectFormatCache;
 import org.dataone.configuration.Settings;
 import org.dataone.service.types.v1.Identifier;
 import org.dataone.service.types.v1.Session;
 import org.dataone.service.types.v1.Subject;
-import org.dataone.service.types.v1.SystemMetadata;
+import org.dataone.service.types.v2.SystemMetadata;
 import org.junit.After;
 import org.junit.Before;
 
Index: test/edu/ucsb/nceas/metacat/dataone/MockCNode.java
===================================================================
--- test/edu/ucsb/nceas/metacat/dataone/MockCNode.java	(revision 8809)
+++ test/edu/ucsb/nceas/metacat/dataone/MockCNode.java	(revision 8810)
@@ -19,9 +19,8 @@
  */
 package edu.ucsb.nceas.metacat.dataone;
 
-import org.dataone.client.CNode;
+import org.dataone.client.v2.impl.MultipartCNode;
 import org.dataone.service.exceptions.IdentifierNotUnique;
-import org.dataone.service.exceptions.InvalidRequest;
 import org.dataone.service.exceptions.InvalidToken;
 import org.dataone.service.exceptions.NotAuthorized;
 import org.dataone.service.exceptions.NotFound;
@@ -30,13 +29,13 @@
 import org.dataone.service.types.v1.Identifier;
 import org.dataone.service.types.v1.Session;
 import org.dataone.service.types.v1.Subject;
-import org.dataone.service.types.v1.SystemMetadata;
+import org.dataone.service.types.v2.SystemMetadata;
 
 /**
  * MockCNode mimics a DataONE Coordinating Node, and should be used only for testing
  * when there is a dependency on CN services
  */
-public class MockCNode extends CNode {
+public class MockCNode extends MultipartCNode {
 
     /**
      * See superclass for documentation
@@ -65,18 +64,4 @@
         return true;
     }
     
-    /**
-     * we only want to test against ourselves
-     */
-    @Override
-    public String lookupNodeBaseUrl(String nodeId) throws ServiceFailure, NotImplemented {
-
-    	try {
-			return MNodeService.getInstance(null).getCapabilities().getBaseURL();
-		} catch (Exception e) {
-			// TODO Auto-generated catch block
-			e.printStackTrace();
-		}
-		return null;
-    }
 }
Index: test/edu/ucsb/nceas/metacat/dataone/MNodeServiceTest.java
===================================================================
--- test/edu/ucsb/nceas/metacat/dataone/MNodeServiceTest.java	(revision 8809)
+++ test/edu/ucsb/nceas/metacat/dataone/MNodeServiceTest.java	(revision 8810)
@@ -51,7 +51,7 @@
 import junit.framework.TestSuite;
 
 import org.apache.commons.io.IOUtils;
-import org.dataone.client.ObjectFormatCache;
+import org.dataone.client.v2.formats.ObjectFormatCache;
 import org.dataone.configuration.Settings;
 import org.dataone.ore.ResourceMapFactory;
 import org.dataone.service.util.TypeMarshaller;
@@ -72,9 +72,8 @@
 import org.dataone.service.types.v1.DescribeResponse;
 import org.dataone.service.types.v1.Event;
 import org.dataone.service.types.v1.Identifier;
-import org.dataone.service.types.v1.Log;
-import org.dataone.service.types.v1.MonitorList;
-import org.dataone.service.types.v1.Node;
+import org.dataone.service.types.v2.Log;
+import org.dataone.service.types.v2.Node;
 import org.dataone.service.types.v1.NodeReference;
 import org.dataone.service.types.v1.ObjectFormatIdentifier;
 import org.dataone.service.types.v1.ObjectList;
@@ -83,7 +82,7 @@
 import org.dataone.service.types.v1.Session;
 import org.dataone.service.types.v1.Subject;
 import org.dataone.service.types.v1.SubjectInfo;
-import org.dataone.service.types.v1.SystemMetadata;
+import org.dataone.service.types.v2.SystemMetadata;
 import org.dspace.foresite.ResourceMap;
 import org.jibx.runtime.JiBXException;
 import org.junit.After;
@@ -693,7 +692,7 @@
         // now check that we have at least one
         ObjectList objectList = 
           MNodeService.getInstance(request).listObjects(session, startTime, endTime, 
-              objectFormatId, replicaStatus, start, count);
+              objectFormatId, null, replicaStatus, start, count);
         assertNotNull(objectList);
         assertTrue(objectList.getCount() == count);
         assertTrue(objectList.getStart() == 0);
@@ -731,31 +730,6 @@
     
   }
 
-  public void testGetOperationStatistics() {
-      printTestHeader("testGetOperationStatistics");
-    try {
-      Session session = getCNSession();
-      SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
-        Date startTime = sdf.parse("2010-01-01");
-        Date endTime = new Date();
-      MonitorList monitorList = 
-        MNodeService.getInstance(request).getOperationStatistics(
-            session, 
-            startTime, 
-            endTime, 
-            session.getSubject(), 
-            Event.CREATE, 
-            null //formatId
-            );
-      
-      assertNotNull(monitorList);
-      // TODO: should probably test other parts of the information
-    } catch (Exception e) {
-      e.printStackTrace();
-      fail("Probably not yet implemented: " + e.getMessage());
-    }
-  }
-
   public void testPing() {
 
     try {
@@ -850,7 +824,7 @@
 	    int count = 1;
     
       log = MNodeService.getInstance(request).getLogRecords(session, fromDate, toDate, 
-        event, null, start, count);
+        event.xmlValue(), null, start, count);
       
       assertNotNull(log);      
       assertTrue(log.getCount() == count);
@@ -1157,7 +1131,7 @@
 			InputStream object = new ByteArrayInputStream("test".getBytes("UTF-8"));
 			SystemMetadata sysmeta = createSystemMetadata(guid, session.getSubject(), object);
 			Identifier pid = MNodeService.getInstance(request).create(session, guid, object, sysmeta);
-			InputStream bagStream = MNodeService.getInstance(request).getPackage(session, pid);
+			InputStream bagStream = MNodeService.getInstance(request).getPackage(session, null, pid);
 			File bagFile = File.createTempFile("bagit.", ".zip");
 			IOUtils.copy(bagStream, new FileOutputStream(bagFile));
 			BagFactory bagFactory = new BagFactory();
@@ -1234,7 +1208,7 @@
 			Identifier pid = MNodeService.getInstance(request).create(session, resourceMapId, object, sysmeta);
 			
 			// get the package we uploaded
-			InputStream bagStream = MNodeService.getInstance(request).getPackage(session, pid);
+			InputStream bagStream = MNodeService.getInstance(request).getPackage(session, null, pid);
 			File bagFile = File.createTempFile("bagit.", ".zip");
 			IOUtils.copy(bagStream, new FileOutputStream(bagFile));
 			BagFactory bagFactory = new BagFactory();
Index: test/edu/ucsb/nceas/metacat/dataone/CNodeServiceTest.java
===================================================================
--- test/edu/ucsb/nceas/metacat/dataone/CNodeServiceTest.java	(revision 8809)
+++ test/edu/ucsb/nceas/metacat/dataone/CNodeServiceTest.java	(revision 8810)
@@ -36,7 +36,7 @@
 import junit.framework.TestSuite;
 
 import org.apache.commons.io.IOUtils;
-import org.dataone.client.D1Client;
+import org.dataone.client.v2.itk.D1Client;
 import org.dataone.service.exceptions.BaseException;
 import org.dataone.service.exceptions.NotAuthorized;
 import org.dataone.service.exceptions.NotFound;
@@ -47,14 +47,14 @@
 import org.dataone.service.types.v1.Checksum;
 import org.dataone.service.types.v1.Event;
 import org.dataone.service.types.v1.Identifier;
-import org.dataone.service.types.v1.Log;
-import org.dataone.service.types.v1.Node;
-import org.dataone.service.types.v1.NodeList;
+import org.dataone.service.types.v2.Log;
+import org.dataone.service.types.v2.Node;
+import org.dataone.service.types.v2.NodeList;
 import org.dataone.service.types.v1.NodeReference;
 import org.dataone.service.types.v1.NodeType;
-import org.dataone.service.types.v1.ObjectFormat;
+import org.dataone.service.types.v2.ObjectFormat;
 import org.dataone.service.types.v1.ObjectFormatIdentifier;
-import org.dataone.service.types.v1.ObjectFormatList;
+import org.dataone.service.types.v2.ObjectFormatList;
 import org.dataone.service.types.v1.ObjectList;
 import org.dataone.service.types.v1.Permission;
 import org.dataone.service.types.v1.Replica;
@@ -62,7 +62,7 @@
 import org.dataone.service.types.v1.ReplicationStatus;
 import org.dataone.service.types.v1.Session;
 import org.dataone.service.types.v1.Subject;
-import org.dataone.service.types.v1.SystemMetadata;
+import org.dataone.service.types.v2.SystemMetadata;
 import org.dataone.service.util.Constants;
 
 /**
@@ -165,7 +165,7 @@
 		    int count = 1;
 	    
 		    Log log = CNodeService.getInstance(request).getLogRecords(session, fromDate, toDate, 
-		    	event, null, start, count);
+		    	event.xmlValue(), null, start, count);
 		    assertNotNull(log);
 		    assertTrue(log.getCount() == count);
 		    assertTrue(log.getStart() == start);
Index: test/edu/ucsb/nceas/metacat/dataone/D1NodeServiceTest.java
===================================================================
--- test/edu/ucsb/nceas/metacat/dataone/D1NodeServiceTest.java	(revision 8809)
+++ test/edu/ucsb/nceas/metacat/dataone/D1NodeServiceTest.java	(revision 8810)
@@ -33,23 +33,22 @@
 import java.util.List;
 
 import org.apache.wicket.protocol.http.mock.MockHttpServletRequest;
-import org.dataone.client.CNode;
-import org.dataone.client.D1Client;
-import org.dataone.client.ObjectFormatCache;
-import org.dataone.service.exceptions.ServiceFailure;
+import org.dataone.client.v2.CNode;
+import org.dataone.client.v2.itk.D1Client;
+import org.dataone.client.v2.formats.ObjectFormatCache;
 import org.dataone.service.types.v1.AccessPolicy;
 import org.dataone.service.types.v1.AccessRule;
 import org.dataone.service.types.v1.Checksum;
 import org.dataone.service.types.v1.Identifier;
-import org.dataone.service.types.v1.Node;
+import org.dataone.service.types.v2.Node;
 import org.dataone.service.types.v1.NodeReference;
 import org.dataone.service.types.v1.NodeType;
 import org.dataone.service.types.v1.Permission;
 import org.dataone.service.types.v1.Session;
 import org.dataone.service.types.v1.Subject;
-import org.dataone.service.types.v1.SystemMetadata;
+import org.dataone.service.types.v2.SystemMetadata;
 import org.dataone.service.types.v1.util.ChecksumUtil;
-import org.dataone.service.types.v1.util.ObjectFormatServiceImpl;
+import org.dataone.service.types.v2.util.ObjectFormatServiceImpl;
 import org.dataone.service.util.Constants;
 
 import edu.ucsb.nceas.MCTestCase;
Index: test/edu/ucsb/nceas/metacat/dataone/SolrQueryAccessFilterTest.java
===================================================================
--- test/edu/ucsb/nceas/metacat/dataone/SolrQueryAccessFilterTest.java	(revision 8809)
+++ test/edu/ucsb/nceas/metacat/dataone/SolrQueryAccessFilterTest.java	(revision 8810)
@@ -19,11 +19,10 @@
 import junit.framework.TestSuite;
 
 import org.apache.http.HttpResponse;
-import org.dataone.client.D1Client;
-import org.dataone.client.D1RestClient;
-import org.dataone.client.MNode;
-import org.dataone.client.ObjectFormatCache;
-import org.dataone.client.RestClient;
+import org.dataone.client.v2.itk.D1Client;
+import org.dataone.client.v2.MNode;
+import org.dataone.client.v2.formats.ObjectFormatCache;
+import org.dataone.client.rest.RestClient;
 import org.dataone.client.auth.CertificateManager;
 import org.dataone.configuration.Settings;
 import org.dataone.service.types.v1.AccessPolicy;
@@ -34,7 +33,7 @@
 import org.dataone.service.types.v1.Session;
 import org.dataone.service.types.v1.Subject;
 import org.dataone.service.types.v1.SubjectInfo;
-import org.dataone.service.types.v1.SystemMetadata;
+import org.dataone.service.types.v2.SystemMetadata;
 import org.dataone.service.util.Constants;
 import org.junit.Before;
 import org.w3c.dom.Document;
@@ -263,7 +262,7 @@
         assertTrue(title.equals(TITLE));
         
         //Use the libclient without the session, the user shouldn't query the document since its certificate is distrusted and it will be considered as the public.
-        org.dataone.service.types.v1.Node node = MNodeService.getInstance(request).getCapabilities();
+        org.dataone.service.types.v2.Node node = MNodeService.getInstance(request).getCapabilities();
         CertificateManager.getInstance().setCertificateLocation(INTRUSTCERTFILE);
         String baseURL = node.getBaseURL();
         System.out.println("================The base url is "+baseURL);
@@ -275,7 +274,7 @@
         }
         System.out.println("================The MODIFIED base url is "+baseURL);
         MNode mnNode = D1Client.getMN(baseURL);
-        input = mnNode.query(SOLR, generateQuery(id.getValue()));
+        input = mnNode.query(querySession, SOLR, generateQuery(id.getValue()));
         doc = generateDoc(input);
         String resultId2 = extractElementValue(doc, IDXPATH);
         assertTrue("In the testDistrustCertificate method, the query result id should be null", resultId2==null);
@@ -365,7 +364,7 @@
         String query = generateQuery(id.getValue());
         MNodeService service = MNodeService.getInstance(request);
         service.setSession(session);
-        InputStream input = service.query(SOLR, query);
+        InputStream input = service.query(session, SOLR, query);
         return input;
     }
     
Index: test/edu/ucsb/nceas/metacattest/DryadTest.java
===================================================================
--- test/edu/ucsb/nceas/metacattest/DryadTest.java	(revision 8809)
+++ test/edu/ucsb/nceas/metacattest/DryadTest.java	(revision 8810)
@@ -36,7 +36,7 @@
 import org.dataone.service.types.v1.Identifier;
 import org.dataone.service.types.v1.ObjectFormatIdentifier;
 import org.dataone.service.types.v1.Session;
-import org.dataone.service.types.v1.SystemMetadata;
+import org.dataone.service.types.v2.SystemMetadata;
 
 import edu.ucsb.nceas.metacat.dataone.D1NodeServiceTest;
 import edu.ucsb.nceas.metacat.dataone.MNodeService;
Index: metacat-index/pom.xml
===================================================================
--- metacat-index/pom.xml	(revision 8809)
+++ metacat-index/pom.xml	(revision 8810)
@@ -4,7 +4,7 @@
 	<groupId>edu.ucsb.nceas.metacat.index</groupId>
 	<artifactId>metacat-index</artifactId>
 	<packaging>war</packaging>
-	<version>2.4.2-SNAPSHOT</version>
+	<version>2.5.0-SNAPSHOT</version>
 	<name>metacat-index</name>
 	<url>http://maven.apache.org</url>
 
@@ -32,7 +32,7 @@
 		<dependency>
 			<groupId>edu.ucsb.nceas.metacat.common</groupId>
 			<artifactId>metacat-common</artifactId>
-			<version>2.4.2-SNAPSHOT</version>
+			<version>2.5.0-SNAPSHOT</version>
 			<type>jar</type>
 		</dependency>
 		<dependency>
Index: metacat-common/pom.xml
===================================================================
--- metacat-common/pom.xml	(revision 8809)
+++ metacat-common/pom.xml	(revision 8810)
@@ -4,7 +4,7 @@
 	<groupId>edu.ucsb.nceas.metacat.common</groupId>
 	<artifactId>metacat-common</artifactId>
 	<packaging>jar</packaging>
-	<version>2.4.2-SNAPSHOT</version>
+	<version>2.5.0-SNAPSHOT</version>
 	<name>metacat-common</name>
 	<url>http://maven.apache.org</url>
 	<properties>
@@ -61,7 +61,7 @@
 		<dependency>
 			<groupId>org.dataone</groupId>
 			<artifactId>d1_common_java</artifactId>
-			<version>1.3.0-SNAPSHOT</version>
+			<version>2.0.0-SNAPSHOT</version>
 			<type>jar</type>
 			<!-- exclude extraneous artifacts (jars) -->
 			<exclusions>
Index: lib/web.xml.tomcat6
===================================================================
--- lib/web.xml.tomcat6	(revision 8809)
+++ lib/web.xml.tomcat6	(revision 8810)
@@ -159,10 +159,10 @@
     <load-on-startup>100</load-on-startup>
   </servlet>
     
-	<!-- CN REST Servlet -->
+	<!-- CN REST Servlet v1 -->
     <servlet>
-      <servlet-name>CNRestServlet</servlet-name>
-      <servlet-class>edu.ucsb.nceas.metacat.restservice.CNRestServlet</servlet-class>
+      <servlet-name>CNRestServletV1</servlet-name>
+      <servlet-class>edu.ucsb.nceas.metacat.restservice.v1.CNRestServlet</servlet-class>
       <init-param>
         <param-name>debug</param-name>
         <param-value>1</param-value>
@@ -174,10 +174,10 @@
       <load-on-startup>15</load-on-startup>
     </servlet>
     
-    <!-- MN REST Servlet -->
+    <!-- CN REST Servlet v2 -->
     <servlet>
-      <servlet-name>MNRestServlet</servlet-name>
-      <servlet-class>edu.ucsb.nceas.metacat.restservice.MNRestServlet</servlet-class>
+      <servlet-name>CNRestServletV2</servlet-name>
+      <servlet-class>edu.ucsb.nceas.metacat.restservice.v2.CNRestServlet</servlet-class>
       <init-param>
         <param-name>debug</param-name>
         <param-value>1</param-value>
@@ -186,8 +186,38 @@
         <param-name>listings</param-name>
         <param-value>true</param-value>
       </init-param>
+      <load-on-startup>15</load-on-startup>
+    </servlet>
+    
+    <!-- MN REST Servlet V1 -->
+    <servlet>
+      <servlet-name>MNRestServletV1</servlet-name>
+      <servlet-class>edu.ucsb.nceas.metacat.restservice.v1.MNRestServlet</servlet-class>
+      <init-param>
+        <param-name>debug</param-name>
+        <param-value>1</param-value>
+      </init-param>
+      <init-param>
+        <param-name>listings</param-name>
+        <param-value>true</param-value>
+      </init-param>
       <load-on-startup>20</load-on-startup>
     </servlet>
+    
+    <!-- MN REST Servlet V2 -->
+    <servlet>
+      <servlet-name>MNRestServletV2</servlet-name>
+      <servlet-class>edu.ucsb.nceas.metacat.restservice.v2.MNRestServlet</servlet-class>
+      <init-param>
+        <param-name>debug</param-name>
+        <param-value>1</param-value>
+      </init-param>
+      <init-param>
+        <param-name>listings</param-name>
+        <param-value>true</param-value>
+      </init-param>
+      <load-on-startup>20</load-on-startup>
+    </servlet>
   
     <servlet-mapping>
         <servlet-name>metacat</servlet-name>
@@ -256,24 +286,28 @@
   </servlet-mapping>
 
 
-	<!-- CN REST services -->
+	<!-- CN REST services v1-->
 	<servlet-mapping>
-		<servlet-name>CNRestServlet</servlet-name>
-		<url-pattern>/d1/cn/*</url-pattern>
-	</servlet-mapping>
-	<servlet-mapping>
-		<servlet-name>CNRestServlet</servlet-name>
+		<servlet-name>CNRestServletV1</servlet-name>
 		<url-pattern>/d1/cn/v1/*</url-pattern>
 	</servlet-mapping>	
 	
-	<!-- MN REST services -->
+	<!-- MN REST services v1 -->
 	<servlet-mapping>
-		<servlet-name>MNRestServlet</servlet-name>
-		<url-pattern>/d1/mn/*</url-pattern>
+		<servlet-name>MNRestServletV1</servlet-name>
+		<url-pattern>/d1/mn/v1/*</url-pattern>
 	</servlet-mapping>
+	
+	<!-- CN REST services v2-->
 	<servlet-mapping>
-		<servlet-name>MNRestServlet</servlet-name>
-		<url-pattern>/d1/mn/v1/*</url-pattern>
+		<servlet-name>CNRestServletV2</servlet-name>
+		<url-pattern>/d1/cn/v2/*</url-pattern>
+	</servlet-mapping>	
+	
+	<!-- MN REST services v2-->
+	<servlet-mapping>
+		<servlet-name>MNRestServletV2</servlet-name>
+		<url-pattern>/d1/mn/v2/*</url-pattern>
 	</servlet-mapping>
 	
  <!-- uncomment this if you want the admin servlet -->
Index: lib/metacat.properties
===================================================================
--- lib/metacat.properties	(revision 8809)
+++ lib/metacat.properties	(revision 8810)
@@ -22,7 +22,7 @@
 ############### Application Values ############
 
 ## one of the few places where we use ANT tokens
-application.metacatVersion=2.4.1
+application.metacatVersion=2.5.0
 application.metacatReleaseInfo=-1
 
 application.deployDir=
@@ -88,6 +88,7 @@
 database.upgradeVersion.2.3.1=upgrade-db-to-2.3.1
 database.upgradeVersion.2.4.0=upgrade-db-to-2.4.0
 database.upgradeVersion.2.4.1=upgrade-db-to-2.4.1
+database.upgradeVersion.2.5.0=upgrade-db-to-2.5.0
 ## for running java-based utilities
 database.upgradeUtility.1.5.0=edu.ucsb.nceas.metacat.admin.upgrade.Upgrade1_5_0
 database.upgradeUtility.2.0.0=edu.ucsb.nceas.metacat.admin.upgrade.Upgrade2_0_0
@@ -521,6 +522,7 @@
 
 # Interval (in milliseconds) between rebuilding the sitemap
 sitemap.interval=86400000
+sitemap.excludedata=false
 
 ######## Workflow engine section              #########################################
 executionEngine.workflowRunEngineName=localWorkflowEngine
Index: src/xmltables-oracle.sql
===================================================================
--- src/xmltables-oracle.sql	(revision 8809)
+++ src/xmltables-oracle.sql	(revision 8810)
@@ -406,6 +406,7 @@
  */
 CREATE TABLE systemMetadata (
    guid   VARCHAR2(2000),    -- the globally unique string identifier
+   series_id   VARCHAR2(2000),    -- the series identifier
    serial_version VARCHAR2(256), --the serial version of the object   
    date_uploaded DATE, -- the date/time the document was first submitted
    rights_holder VARCHAR2(250), --the user who has rights to the document, usually the first persons to upload it
Index: src/upgrade-db-to-2.5.0-postgres.sql
===================================================================
--- src/upgrade-db-to-2.5.0-postgres.sql	(nonexistent)
+++ src/upgrade-db-to-2.5.0-postgres.sql	(revision 8810)
@@ -0,0 +1,12 @@
+/*
+ * Alter the system metadata table to suport seriesId
+ */
+ALTER TABLE systemMetadata ADD COLUMN series_id text;
+
+/*
+ * update the database version
+ */
+UPDATE db_version SET status=0;
+
+INSERT INTO db_version (version, status, date_created) 
+  VALUES ('2.5.0', 1, CURRENT_DATE);

Property changes on: src/upgrade-db-to-2.5.0-postgres.sql
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property
Index: src/upgrade-db-to-2.5.0-oracle.sql
===================================================================
--- src/upgrade-db-to-2.5.0-oracle.sql	(nonexistent)
+++ src/upgrade-db-to-2.5.0-oracle.sql	(revision 8810)
@@ -0,0 +1,12 @@
+/*
+ * Alter the system metadata table to suport seriesId
+ */
+ALTER TABLE systemMetadata ADD (guid VARCHAR2(2000));
+
+/*
+ * update the database version
+ */
+UPDATE db_version SET status=0;
+
+INSERT INTO db_version (version, status, date_created) 
+  VALUES ('2.5.0', 1, CURRENT_DATE);

Property changes on: src/upgrade-db-to-2.5.0-oracle.sql
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property
Index: src/xmltables-postgres.sql
===================================================================
--- src/xmltables-postgres.sql	(revision 8809)
+++ src/xmltables-postgres.sql	(revision 8810)
@@ -299,6 +299,7 @@
  */
 CREATE TABLE systemMetadata (
 	guid   text,          -- the globally unique string identifier of the object that the system metadata describes
+	series_id text, -- the series identifier
 	serial_version VARCHAR(256), --the serial version of the object
 	date_uploaded TIMESTAMP, -- the date/time the document was first submitted
 	rights_holder VARCHAR(250), --the user who has rights to the document, usually the first persons to upload it
Index: src/loaddtdschema-postgres.sql
===================================================================
--- src/loaddtdschema-postgres.sql	(revision 8809)
+++ src/loaddtdschema-postgres.sql	(revision 8810)
@@ -123,4 +123,4 @@
 
 
 INSERT INTO db_version (version, status, date_created) 
-  VALUES ('2.4.1',1,CURRENT_DATE);
+  VALUES ('2.5.0',1,CURRENT_DATE);
Index: src/loaddtdschema-oracle.sql
===================================================================
--- src/loaddtdschema-oracle.sql	(revision 8809)
+++ src/loaddtdschema-oracle.sql	(revision 8810)
@@ -121,4 +121,4 @@
   VALUES ('Schema', 'http://rs.tdwg.org/dwc/terms/', '/schema/dwc/tdwg_dwcterms.xsd');
 
 INSERT INTO db_version (version, status, date_created) 
-  VALUES ('2.4.1',1,CURRENT_DATE);
+  VALUES ('2.5.0',1,CURRENT_DATE);
Index: src/edu/ucsb/nceas/metacat/restservice/v1/MNResourceHandler.java
===================================================================
--- src/edu/ucsb/nceas/metacat/restservice/v1/MNResourceHandler.java	(nonexistent)
+++ src/edu/ucsb/nceas/metacat/restservice/v1/MNResourceHandler.java	(revision 8810)
@@ -0,0 +1,1419 @@
+/**
+ *  '$RCSfile$'
+ *  Copyright: 2011 Regents of the University of California and the
+ *              National Center for Ecological Analysis and Synthesis
+ *
+ *   '$Author$'
+ *     '$Date$'
+ *
+ * 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.v1;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.commons.fileupload.FileUploadException;
+import org.apache.commons.io.IOUtils;
+import org.apache.log4j.Logger;
+import org.dataone.client.v2.formats.ObjectFormatInfo;
+import org.dataone.mimemultipart.MultipartRequest;
+import org.dataone.mimemultipart.MultipartRequestResolver;
+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.NotFound;
+import org.dataone.service.exceptions.NotImplemented;
+import org.dataone.service.exceptions.ServiceFailure;
+import org.dataone.service.exceptions.SynchronizationFailed;
+import org.dataone.service.exceptions.UnsupportedType;
+import org.dataone.service.types.v1.Checksum;
+import org.dataone.service.types.v1.DescribeResponse;
+import org.dataone.service.types.v1.Event;
+import org.dataone.service.types.v1.Identifier;
+import org.dataone.service.types.v1.Log;
+import org.dataone.service.types.v1.Node;
+import org.dataone.service.types.v1.NodeReference;
+import org.dataone.service.types.v1.ObjectFormatIdentifier;
+import org.dataone.service.types.v1.ObjectList;
+import org.dataone.service.types.v1.Permission;
+import org.dataone.service.types.v1.SystemMetadata;
+import org.dataone.service.types.v1_1.QueryEngineDescription;
+import org.dataone.service.types.v1_1.QueryEngineList;
+import org.dataone.service.util.Constants;
+import org.dataone.service.util.DateTimeMarshaller;
+import org.dataone.service.util.ExceptionHandler;
+import org.dataone.service.util.TypeMarshaller;
+import org.jibx.runtime.JiBXException;
+import org.xml.sax.SAXException;
+
+import edu.ucsb.nceas.metacat.common.query.stream.ContentTypeInputStream;
+import edu.ucsb.nceas.metacat.dataone.v1.MNodeService;
+import edu.ucsb.nceas.metacat.properties.PropertyService;
+import edu.ucsb.nceas.metacat.restservice.D1ResourceHandler;
+import edu.ucsb.nceas.metacat.util.DeleteOnCloseFileInputStream;
+import edu.ucsb.nceas.utilities.PropertyNotFoundException;
+
+/**
+ * MN REST service implementation handler
+ * 
+ * ******************
+ * MNCore -- DONE
+ * 		ping() - GET /d1/mn/monitor/ping
+ * 		log() - GET /d1/mn/log
+ * 		**getObjectStatistics() - GET /d1/mn/monitor/object
+ * 		getOperationsStatistics - GET /d1/mn/monitor/event
+ * 		**getStatus - GET /d1/mn/monitor/status
+ * 		getCapabilities() - GET /d1/mn/ and /d1/mn/node
+ * 	
+ * 	MNRead -- DONE
+ * 		get() - GET /d1/mn/object/PID
+ * 		getSystemMetadata() - GET /d1/mn/meta/PID
+ * 		describe() - HEAD /d1/mn/object/PID
+ * 		getChecksum() - GET /d1/mn/checksum/PID
+ * 		listObjects() - GET /d1/mn/object
+ * 		synchronizationFailed() - POST /d1/mn/error
+ * 	
+ * 	MNAuthorization -- DONE
+ * 		isAuthorized() - GET /d1/mn/isAuthorized/PID
+ * 		setAccessPolicy() - PUT /d1/mn/accessRules/PID
+ * 		
+ * 	MNStorage - DONE
+ * 		create() - POST /d1/mn/object/PID
+ * 		update() - PUT /d1/mn/object/PID
+ * 		delete() - DELETE /d1/mn/object/PID
+ * 		archive() - PUT /d1/mn/archive/PID
+
+ *    systemMetadataChanged() - POST /dirtySystemMetadata/PID
+ * 	
+ * 	MNReplication
+ * 		replicate() - POST /d1/mn/replicate
+ *    getReplica() - GET /d1/mn/replica
+ * 
+ * ******************
+ * @author leinfelder
+ *
+ */
+public class MNResourceHandler extends D1ResourceHandler {
+
+    // MN-specific API Resources
+    protected static final String RESOURCE_MONITOR = "monitor";
+    protected static final String RESOURCE_REPLICATE = "replicate";
+    protected static final String RESOURCE_REPLICAS = "replica";
+    protected static final String RESOURCE_NODE = "node";
+    protected static final String RESOURCE_ERROR = "error";
+    protected static final String RESOURCE_META_CHANGED = "dirtySystemMetadata";
+    protected static final String RESOURCE_GENERATE_ID = "generate";
+    protected static final String RESOURCE_PUBLISH = "publish";
+    protected static final String RESOURCE_PACKAGE = "package";
+    protected static final String RESOURCE_VIEWS = "views";
+
+
+    
+    // shared executor
+	private static ExecutorService executor = null;
+
+	static {
+		// use a shared executor service with nThreads == one less than available processors
+    	int availableProcessors = Runtime.getRuntime().availableProcessors();
+        int nThreads = availableProcessors * 1;
+        nThreads--;
+        nThreads = Math.max(1, nThreads);
+    	executor = Executors.newFixedThreadPool(nThreads);	
+	}
+	
+    /**
+     * Initializes new instance by setting servlet context,request and response
+     * */
+    public MNResourceHandler(ServletContext servletContext,
+            HttpServletRequest request, HttpServletResponse response) {
+    	super(servletContext, request, response);
+        logMetacat = Logger.getLogger(MNResourceHandler.class);
+    }
+    
+    @Override
+    protected boolean isD1Enabled() {
+    	
+    	boolean enabled = false;
+    	try {
+			enabled = Boolean.parseBoolean(PropertyService.getProperty("dataone.mn.services.enabled"));
+		} catch (PropertyNotFoundException e) {
+			logMetacat.error("Could not check if DataONE is enabled: " + e.getMessage());
+		}
+    	
+    	return enabled;	
+    }
+
+    /**
+     * This function is called from REST API servlet and handles each request to the servlet 
+     * 
+     * @param httpVerb (GET, POST, PUT or DELETE)
+     */
+    @Override
+    public void handle(byte httpVerb) {
+    	// prepare the handler
+    	super.handle(httpVerb);
+    	
+        try {
+        	
+        	// only service requests if we have D1 configured
+        	if (!isD1Enabled()) {
+        		ServiceFailure se = new ServiceFailure("0000", "DataONE services are not enabled on this node");
+                serializeException(se, response.getOutputStream());
+                return;
+        	}
+        	
+        	// get the resource
+            String resource = request.getPathInfo();
+            resource = resource.substring(resource.indexOf("/") + 1);
+            
+            // default to node info
+            if (resource.equals("")) {
+                resource = RESOURCE_NODE;
+            }
+            
+            // get the rest of the path info
+            String extra = null;
+                        
+            logMetacat.debug("handling verb " + httpVerb + " request with resource '" + resource + "'");
+            logMetacat.debug("resource: '" + resource + "'");
+            boolean status = false;
+            
+            if (resource != null) {
+
+                if (resource.startsWith(RESOURCE_NODE)) {
+                    // node response
+                    node();
+                    status = true;
+                } else if (resource.startsWith(RESOURCE_IS_AUTHORIZED)) {
+                    if (httpVerb == GET) {
+                    	// after the command
+                        extra = parseTrailing(resource, RESOURCE_IS_AUTHORIZED);
+	                	// check the access rules
+	                    isAuthorized(extra);
+	                    status = true;
+	                    logMetacat.debug("done getting access");
+                    }
+                } else if (resource.startsWith(RESOURCE_META)) {
+                    logMetacat.debug("Using resource 'meta'");
+                    // get
+                    if (httpVerb == GET) {
+                    	// after the command
+                        extra = parseTrailing(resource, RESOURCE_META);
+                        getSystemMetadataObject(extra);
+                        status = true;
+                    }
+                    
+                } else if (resource.startsWith(RESOURCE_OBJECTS)) {
+                    logMetacat.debug("Using resource 'object'");
+                    // after the command
+                    extra = parseTrailing(resource, RESOURCE_OBJECTS);
+                    logMetacat.debug("objectId: " + extra);
+                    logMetacat.debug("verb:" + httpVerb);
+
+                    if (httpVerb == GET) {
+                        getObject(extra);
+                        status = true;
+                    } else if (httpVerb == POST) {
+                    	// part of the params, not the URL
+                        putObject(null, FUNCTION_NAME_INSERT);
+                        status = true;
+                    } else if (httpVerb == PUT) {
+                        putObject(extra, FUNCTION_NAME_UPDATE);
+                        status = true;
+                    } else if (httpVerb == DELETE) {
+                        deleteObject(extra);
+                        status = true;
+                    } else if (httpVerb == HEAD) {
+                        describeObject(extra);
+                        status = true;
+                    }
+                  
+                } else if (resource.startsWith(RESOURCE_LOG)) {
+                    logMetacat.debug("Using resource 'log'");
+                    // handle log events
+                    if (httpVerb == GET) {
+                        getLog();
+                        status = true;
+                    }
+                } else if (resource.startsWith(Constants.RESOURCE_ARCHIVE)) {
+                    logMetacat.debug("Using resource " + Constants.RESOURCE_ARCHIVE);
+                    // handle archive events
+                    if (httpVerb == PUT) {
+                        extra = parseTrailing(resource, Constants.RESOURCE_ARCHIVE);
+                        archive(extra);
+                        status = true;
+                    }
+                } else if (resource.startsWith(Constants.RESOURCE_CHECKSUM)) {
+                    logMetacat.debug("Using resource 'checksum'");
+                    // handle checksum requests
+                    if (httpVerb == GET) {
+                    	// after the command
+                        extra = parseTrailing(resource, Constants.RESOURCE_CHECKSUM);
+                        checksum(extra);
+                        status = true;
+                    }
+                } else if (resource.startsWith(RESOURCE_MONITOR)) {
+                    // there are various parts to monitoring
+                    if (httpVerb == GET) {
+                    	// after the command
+                        extra = parseTrailing(resource, RESOURCE_MONITOR);
+                        
+                        // ping
+                        if (extra.toLowerCase().equals("ping")) {
+                            logMetacat.debug("processing ping request");
+                            Date result = MNodeService.getInstance(request).ping();
+                            // TODO: send to output	
+                            status = true;
+                            
+                        }
+                        
+                    }
+                } else if (resource.startsWith(RESOURCE_REPLICATE)) {
+                	if (httpVerb == POST) {
+	                    logMetacat.debug("processing replicate request");
+	                    replicate();
+	                    status = true;
+                	}
+                } else if (resource.startsWith(RESOURCE_ERROR)) {
+	                // sync error
+	                if (httpVerb == POST) {
+	                    syncError();
+	                    status = true;
+	                }
+                } else if (resource.startsWith(RESOURCE_META_CHANGED)) {
+                    // system metadata changed
+                    if (httpVerb == POST) {
+                        systemMetadataChanged();
+                        status = true;
+                    }
+                } else if (resource.startsWith(RESOURCE_REPLICAS)) {
+                    // get replica
+                    if (httpVerb == GET) {
+                        extra = parseTrailing(resource, RESOURCE_REPLICAS);
+                        getReplica(extra);
+                        status = true;
+                    }
+                } else if (resource.startsWith(RESOURCE_QUERY)) {
+	                logMetacat.debug("Using resource " + RESOURCE_QUERY);
+	                // after the command
+	                extra = parseTrailing(resource, RESOURCE_QUERY);
+	                logMetacat.debug("query extra: " + extra);
+
+	                String engine = null;
+	                String query = null;
+
+	                if (extra != null) {
+		                // get the engine
+		                int engineIndex = extra.length();
+		                if (extra.indexOf("/") > -1) {
+		                	engineIndex = extra.indexOf("/");
+		                }
+		                engine = extra.substring(0, engineIndex);
+		                logMetacat.debug("query engine: " + engine);
+		                
+		                // get the query if it is there
+		                query = extra.substring(engineIndex, extra.length());
+		                if (query != null && query.length() == 0) {
+		                	query = null;
+		                } else {
+		                	if (query.startsWith("/")) {
+		                		query = query.substring(1);
+		                    }
+		                	// remove the query delimiter if it exists
+		                	if (query.startsWith("?")) {
+		                		query = query.substring(1);
+		                    }
+		                }
+		                logMetacat.debug("query: " + query);
+
+	                }
+	                logMetacat.debug("verb:" + httpVerb);
+	                if (httpVerb == GET) {
+	                    doQuery(engine, query);
+	                    status = true;
+	                }
+                } else if (resource.startsWith(RESOURCE_GENERATE_ID)) {
+                	// generate an id
+                    if (httpVerb == POST) {
+                        generateIdentifier();
+                        status = true;
+                    }
+                } else if (resource.startsWith(RESOURCE_PUBLISH)) {
+                    logMetacat.debug("Using resource: " + RESOURCE_PUBLISH);
+                    // PUT
+                    if (httpVerb == PUT) {
+                    	// after the command
+                        extra = parseTrailing(resource, RESOURCE_PUBLISH);
+                        publish(extra);
+                        status = true;
+                    }  
+                } else if (resource.startsWith(RESOURCE_PACKAGE)) {
+                    logMetacat.debug("Using resource: " + RESOURCE_PACKAGE);
+                    // get
+                    if (httpVerb == GET) {
+                    	// after the command
+                        extra = parseTrailing(resource, RESOURCE_PACKAGE);
+                        getPackage(extra);
+                        status = true;
+                    }  
+                } else if (resource.startsWith(RESOURCE_VIEWS)) {
+	                logMetacat.debug("Using resource " + RESOURCE_VIEWS);
+	                // after the command
+	                extra = parseTrailing(resource, RESOURCE_VIEWS);
+	                logMetacat.debug("view extra: " + extra);
+
+	                String format = null;
+	                String pid = null;
+
+	                if (extra != null) {
+		                // get the format
+		                int formatIndex = extra.length();
+		                if (extra.indexOf("/") > -1) {
+		                	formatIndex = extra.indexOf("/");
+		                }
+		                format = extra.substring(0, formatIndex);
+		                logMetacat.debug("view format: " + format);
+		                
+		                // get the pid if it is there
+		                pid = extra.substring(formatIndex, extra.length());
+		                if (pid != null && pid.length() == 0) {
+		                	pid = null;
+		                } else {
+		                	if (pid.startsWith("/")) {
+		                		pid = pid.substring(1);
+		                    }
+		                }
+		                logMetacat.debug("pid: " + pid);
+
+	                }
+	                logMetacat.debug("verb:" + httpVerb);
+	                if (httpVerb == GET) {
+	                    doViews(format, pid);
+	                    status = true;
+	                }
+                } 
+                
+                if (!status) {
+                	throw new ServiceFailure("0000", "Unknown error, status = " + status);
+                }
+            } else {
+            	throw new InvalidRequest("0000", "No resource matched for " + resource);
+            }
+        } catch (BaseException be) {
+        	// report Exceptions as clearly as possible
+        	OutputStream out = null;
+			try {
+				out = response.getOutputStream();
+			} catch (IOException e) {
+				logMetacat.error("Could not get output stream from response", e);
+			}
+            serializeException(be, out);
+        } catch (Exception e) {
+            // report Exceptions as clearly and generically as possible
+            logMetacat.error(e.getClass() + ": " + e.getMessage(), e);
+        	OutputStream out = null;
+			try {
+				out = response.getOutputStream();
+			} catch (IOException ioe) {
+				logMetacat.error("Could not get output stream from response", ioe);
+			}
+			ServiceFailure se = new ServiceFailure("0000", e.getMessage());
+            serializeException(se, out);
+        }
+    }
+    
+
+    private void doQuery(String engine, String query) {
+    	
+		OutputStream out = null;
+
+    	try {
+    		// NOTE: we set the session explicitly for the MNode instance since these methods do not provide a parameter			
+	    	if (engine == null) {
+	    		// just looking for list of engines
+	    		MNodeService mnode = MNodeService.getInstance(request);
+    			mnode.setSession(session);
+	    		QueryEngineList qel = mnode.listQueryEngines();
+	    		response.setContentType("text/xml");
+	            response.setStatus(200);
+	            out = response.getOutputStream();
+	            TypeMarshaller.marshalTypeToOutputStream(qel, out);
+	            return;
+	    	} else {
+	    		if (query != null) {
+	    			MNodeService mnode = MNodeService.getInstance(request);
+	    			mnode.setSession(session);
+	    			InputStream stream = mnode.query(engine, query);
+
+	    			// set the content-type if we have it from the implementation
+	    			if (stream instanceof ContentTypeInputStream) {
+		    			//response.setContentType("application/octet-stream");
+		    			//response.setContentType("text/xml");
+	    				response.setContentType(((ContentTypeInputStream) stream).getContentType());
+	    			}
+	                response.setStatus(200);
+	                out = response.getOutputStream();
+	                // write the results to the output stream
+	                IOUtils.copyLarge(stream, out);
+	                return;
+	    		} else {
+	    			MNodeService mnode = MNodeService.getInstance(request);
+	    			mnode.setSession(session);
+	    			QueryEngineDescription qed = mnode.getQueryEngineDescription(engine);
+	    			response.setContentType("text/xml");
+		            response.setStatus(200);
+		            out = response.getOutputStream();
+		            TypeMarshaller.marshalTypeToOutputStream(qed, out);
+		            return;
+	    		}
+	    	}
+	        
+	        
+    	} catch (BaseException be) {
+        	// report Exceptions as clearly as possible
+			try {
+				out = response.getOutputStream();
+			} catch (IOException e) {
+				logMetacat.error("Could not get output stream from response", e);
+			}
+            serializeException(be, out);
+        } catch (Exception e) {
+            // report Exceptions as clearly and generically as possible
+            logMetacat.error(e.getClass() + ": " + e.getMessage(), e);
+			try {
+				out = response.getOutputStream();
+			} catch (IOException ioe) {
+				logMetacat.error("Could not get output stream from response", ioe);
+			}
+			ServiceFailure se = new ServiceFailure("0000", e.getMessage());
+            serializeException(se, out);
+        }
+    }
+    
+    private void doViews(String format, String pid) {
+    	
+		OutputStream out = null;
+		MNodeService mnode = MNodeService.getInstance(request);
+
+    	try {
+    		// get a list of views
+    		if (pid != null) {
+    			Identifier identifier = new Identifier();
+    			identifier.setValue(pid);
+				InputStream stream = mnode.view(session, format, identifier);
+
+    			// set the content-type if we have it from the implementation
+    			if (stream instanceof ContentTypeInputStream) {
+    				response.setContentType(((ContentTypeInputStream) stream).getContentType());
+    			}
+                response.setStatus(200);
+                out = response.getOutputStream();
+                // write the results to the output stream
+                IOUtils.copyLarge(stream, out);
+                return;
+    		} else {
+    			// TODO: list the registered views
+                BaseException ni = new NotImplemented("9999", "MN.listViews() is not implemented at this node");
+				throw ni;
+    		}
+	    	
+	        
+    	} catch (BaseException be) {
+        	// report Exceptions as clearly as possible
+			try {
+				out = response.getOutputStream();
+			} catch (IOException e) {
+				logMetacat.error("Could not get output stream from response", e);
+			}
+            serializeException(be, out);
+        } catch (Exception e) {
+            // report Exceptions as clearly and generically as possible
+            logMetacat.error(e.getClass() + ": " + e.getMessage(), e);
+			try {
+				out = response.getOutputStream();
+			} catch (IOException ioe) {
+				logMetacat.error("Could not get output stream from response", ioe);
+			}
+			ServiceFailure se = new ServiceFailure("0000", e.getMessage());
+            serializeException(se, out);
+        }
+    }
+    
+    /**
+     * Handles notification of system metadata changes for the given identifier
+     * 
+     * @param id  the identifier for the object
+     * @throws InvalidToken 
+     * @throws InvalidRequest 
+     * @throws NotAuthorized 
+     * @throws ServiceFailure 
+     * @throws NotImplemented 
+     */
+    private void systemMetadataChanged() 
+        throws NotImplemented, ServiceFailure, NotAuthorized, InvalidRequest, 
+        InvalidToken {
+
+        long serialVersion = 0L;
+        String serialVersionStr = null;
+        Date dateSysMetaLastModified = null;
+        String dateSysMetaLastModifiedStr = null;
+        Identifier pid = null;
+        
+        // mkae sure we have the multipart params
+        try {
+			initMultipartParams();
+		} catch (Exception e1) {
+			throw new ServiceFailure("1333", "Could not collect the multipart params for the request");
+		}
+        
+        // get the pid
+        try {
+        	String id = multipartparams.get("pid").get(0);
+        	pid = new Identifier();
+            pid.setValue(id);            
+        } catch (NullPointerException e) {
+            String msg = "The 'pid' must be provided as a parameter and was not.";
+            logMetacat.error(msg);
+            throw new InvalidRequest("1334", msg);
+        }      
+        
+        // get the serialVersion
+        try {
+            serialVersionStr = multipartparams.get("serialVersion").get(0);
+            serialVersion = new Long(serialVersionStr).longValue();
+            
+        } catch (NullPointerException e) {
+            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
+            logMetacat.error(msg);
+            throw new InvalidRequest("1334", msg);
+            
+        }       
+        
+        // get the dateSysMetaLastModified
+        try {
+            dateSysMetaLastModifiedStr = multipartparams.get("dateSysMetaLastModified").get(0);
+            dateSysMetaLastModified = DateTimeMarshaller.deserializeDateToUTC(dateSysMetaLastModifiedStr);
+            
+        } catch (NullPointerException e) {
+            String msg = 
+                "The 'dateSysMetaLastModified' must be provided as a " + 
+                "parameter and was not, or was an invalid representation of the timestamp.";
+            logMetacat.error(msg);
+            throw new InvalidRequest("1334", msg);
+            
+        }       
+        
+        // call the service
+        MNodeService.getInstance(request).systemMetadataChanged(session, pid, serialVersion, dateSysMetaLastModified);
+        response.setStatus(200);
+    }
+    
+    /**
+     * Handles identifier generation calls
+     * 
+     * @throws InvalidRequest 
+     * @throws NotImplemented 
+     * @throws NotAuthorized 
+     * @throws ServiceFailure 
+     * @throws InvalidToken 
+     * @throws IOException 
+     * @throws JiBXException 
+     */
+    private void generateIdentifier() throws InvalidToken, ServiceFailure, NotAuthorized, NotImplemented, InvalidRequest, IOException, JiBXException {
+        
+        // make sure we have the multipart params
+        try {
+			initMultipartParams();
+		} catch (Exception e1) {
+			throw new ServiceFailure("1333", "Could not collect the multipart params for the request");
+		}
+        
+        // get the scheme
+		String scheme = null;
+        try {
+        	scheme = multipartparams.get("scheme").get(0);	           
+        } catch (NullPointerException e) {
+            String msg = "The 'scheme' parameter was not provided, using default";
+            logMetacat.warn(msg);
+        }
+        
+        // get the fragment
+		String fragment = null;
+        try {
+        	fragment = multipartparams.get("fragment").get(0);	           
+        } catch (NullPointerException e) {
+            String msg = "The 'fragment' parameter was not provided, using default";
+            logMetacat.warn(msg);
+        }
+
+        // call the service
+        Identifier identifier = MNodeService.getInstance(request).generateIdentifier(session, scheme, fragment);
+        response.setStatus(200);
+        response.setContentType("text/xml");
+        OutputStream out = response.getOutputStream();
+        TypeMarshaller.marshalTypeToOutputStream(identifier, out);
+    }
+
+    /**
+     * Checks the access policy
+     * @param id
+     * @return
+     * @throws ServiceFailure
+     * @throws InvalidToken
+     * @throws NotFound
+     * @throws NotAuthorized
+     * @throws NotImplemented
+     * @throws InvalidRequest
+     */
+    private boolean isAuthorized(String id) throws ServiceFailure, InvalidToken, NotFound, NotAuthorized, NotImplemented, InvalidRequest {
+		Identifier pid = new Identifier();
+		pid.setValue(id);
+		Permission permission = null;
+		try {
+			String perm = params.get("action")[0];
+			permission = Permission.convert(perm);
+		} catch (Exception e) {
+			logMetacat.warn("No permission specified");
+		}
+		boolean result = MNodeService.getInstance(request).isAuthorized(session, pid, permission);
+		response.setStatus(200);
+		response.setContentType("text/xml");
+		return result;
+    }
+    
+    /**
+     * Processes failed synchronization message
+     * @throws NotImplemented
+     * @throws ServiceFailure
+     * @throws NotAuthorized
+     * @throws InvalidRequest
+     * @throws JiBXException
+     * @throws IllegalAccessException 
+     * @throws InstantiationException 
+     * @throws IOException 
+     * @throws InvalidToken 
+     */
+    private void syncError() throws NotImplemented, ServiceFailure, NotAuthorized, InvalidRequest, JiBXException, IOException, InstantiationException, IllegalAccessException, InvalidToken {
+    	SynchronizationFailed syncFailed = null;
+		try {
+			syncFailed = collectSynchronizationFailed();
+		} catch (ParserConfigurationException e) {
+			throw new ServiceFailure("2161", e.getMessage());
+		} catch (SAXException e) {
+			throw new ServiceFailure("2161", e.getMessage());
+		}
+		
+		MNodeService.getInstance(request).synchronizationFailed(session, syncFailed);
+    }
+
+	/**
+     * Calculate the checksum 
+     * @throws NotImplemented
+     * @throws JiBXException
+     * @throws IOException
+     * @throws InvalidToken
+     * @throws ServiceFailure
+     * @throws NotAuthorized
+     * @throws NotFound
+     * @throws InvalidRequest
+     */
+    private void checksum(String pid) throws NotImplemented, JiBXException, IOException, InvalidToken, ServiceFailure, NotAuthorized, NotFound, InvalidRequest {
+    	String checksumAlgorithm = "MD5";
+    	try {
+    		checksumAlgorithm = PropertyService.getProperty("dataone.checksumAlgorithm.default");
+        } catch(Exception e) {
+        	logMetacat.warn("Could not lookup configured default checksum algorithm, using: " + checksumAlgorithm);
+        }    
+        
+        Identifier pidid = new Identifier();
+        pidid.setValue(pid);
+        try {
+            checksumAlgorithm = params.get("checksumAlgorithm")[0];
+        } catch(Exception e) {
+            //do nothing.  use the default
+        	logMetacat.warn("No algorithm specified, using default: " + checksumAlgorithm);
+        }
+        logMetacat.debug("getting checksum for object " + pid + " with algorithm " + checksumAlgorithm);
+        
+        Checksum c = MNodeService.getInstance(request).getChecksum(session, pidid, checksumAlgorithm);
+        logMetacat.debug("got checksum " + c.getValue());
+        response.setStatus(200);
+        logMetacat.debug("serializing response");
+        TypeMarshaller.marshalTypeToOutputStream(c, response.getOutputStream());
+        logMetacat.debug("done serializing response.");
+        
+    }
+    
+	/**
+     * handle the replicate action for MN
+	 * @throws JiBXException 
+	 * @throws FileUploadException 
+	 * @throws IOException 
+	 * @throws InvalidRequest 
+	 * @throws ServiceFailure 
+	 * @throws UnsupportedType 
+	 * @throws InsufficientResources 
+	 * @throws NotAuthorized 
+	 * @throws NotImplemented 
+	 * @throws IllegalAccessException 
+	 * @throws InstantiationException 
+	 * @throws InvalidToken 
+     */
+    private void replicate() 
+        throws ServiceFailure, InvalidRequest, IOException, FileUploadException, 
+        JiBXException, NotImplemented, NotAuthorized, InsufficientResources, 
+        UnsupportedType, InstantiationException, IllegalAccessException, InvalidToken {
+
+        logMetacat.debug("in POST replicate()");
+        
+        // somewhat unorthodox, but the call is asynchronous and we'd like to return this info sooner
+        boolean allowed = false;
+        if (session == null) {
+        	String msg = "No session was provided.";
+            NotAuthorized failure = new NotAuthorized("2152", msg);
+        	throw failure;
+        } else {
+        	allowed = MNodeService.getInstance(request).isAdminAuthorized(session);
+        	if (!allowed) {
+        		String msg = "User is not an admin user";
+                NotAuthorized failure = new NotAuthorized("2152", msg);
+            	throw failure;
+        	}
+        }
+        
+        // parse the systemMetadata
+        Map<String, File> files = collectMultipartFiles();        
+        final SystemMetadata sysmeta = TypeMarshaller.unmarshalTypeFromFile(SystemMetadata.class, files.get("sysmeta"));
+        
+        String sn = multipartparams.get("sourceNode").get(0);
+        logMetacat.debug("sourceNode: " + sn);
+        final NodeReference sourceNode = new NodeReference();
+        sourceNode.setValue(sn);
+        
+        // run it in a thread to avoid connection timeout
+        Runnable runner = new Runnable() {
+			@Override
+			public void run() {
+				try {
+			        MNodeService.getInstance(request).replicate(session, sysmeta, sourceNode);
+				} catch (Exception e) {
+					logMetacat.error("Error running replication: " + e.getMessage(), e);
+					throw new RuntimeException(e.getMessage(), e);
+				}
+			}
+    	};
+    	// submit the task, and that's it
+    	executor.submit(runner);
+        
+    	// thread was started, so we return success
+        response.setStatus(200);
+        
+    }
+
+    /**
+     * Handle the getReplica action for the MN
+     * @param id  the identifier for the object
+     * @throws NotFound 
+     * @throws ServiceFailure 
+     * @throws NotImplemented 
+     * @throws NotAuthorized 
+     * @throws InvalidToken 
+     * @throws InvalidRequest 
+     * @throws InsufficientResources 
+     */
+    private void getReplica(String id) 
+        throws InvalidRequest, InvalidToken, NotAuthorized, NotImplemented, 
+        ServiceFailure, NotFound, InsufficientResources {
+        
+        Identifier pid = new Identifier();
+        pid.setValue(id);
+        OutputStream out = null;
+        InputStream dataBytes = null;
+                
+        try {
+            // call the service
+            dataBytes = MNodeService.getInstance(request).getReplica(session, pid);
+
+            response.setContentType("application/octet-stream");
+            response.setStatus(200);
+            out = response.getOutputStream();
+            // write the object to the output stream
+            IOUtils.copyLarge(dataBytes, out);
+            
+        } catch (IOException e) {
+            String msg = "There was an error writing the output: " + e.getMessage();
+            logMetacat.error(msg);
+            throw new ServiceFailure("2181", msg);
+        
+        }
+
+    }
+
+    /**
+     * Get the Node information
+     * 
+     * @throws JiBXException
+     * @throws IOException
+     * @throws InvalidRequest 
+     * @throws ServiceFailure 
+     * @throws NotAuthorized 
+     * @throws NotImplemented 
+     */
+    private void node() 
+        throws JiBXException, IOException, NotImplemented, NotAuthorized, ServiceFailure, InvalidRequest {
+        
+        Node n = MNodeService.getInstance(request).getCapabilities();
+        
+        response.setContentType("text/xml");
+        response.setStatus(200);
+        TypeMarshaller.marshalTypeToOutputStream(n, response.getOutputStream());
+        
+    }
+    
+    /**
+     * MN_crud.describe()
+     * http://mule1.dataone.org/ArchitectureDocs/mn_api_crud.html#MN_crud.describe
+     * @param pid
+     * @throws InvalidRequest 
+     * @throws NotImplemented 
+     * @throws NotFound 
+     * @throws NotAuthorized 
+     * @throws ServiceFailure 
+     * @throws InvalidToken 
+     */
+    private void describeObject(String pid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, InvalidRequest
+    {
+        
+        response.setContentType("text/xml");
+
+        Identifier id = new Identifier();
+        id.setValue(pid);
+
+        DescribeResponse dr = null;
+        try {
+        	dr = MNodeService.getInstance(request).describe(session, id);
+        } catch (BaseException e) {
+        	response.setStatus(e.getCode());
+        	response.addHeader("DataONE-Exception-Name", e.getClass().getName());
+            response.addHeader("DataONE-Exception-DetailCode", e.getDetail_code());
+            response.addHeader("DataONE-Exception-Description", e.getDescription());
+            response.addHeader("DataONE-Exception-PID", id.getValue());
+            return;
+		}
+        
+        response.setStatus(200);
+        
+        //response.addHeader("pid", pid);
+        response.addHeader("DataONE-Checksum", dr.getDataONE_Checksum().getAlgorithm() + "," + dr.getDataONE_Checksum().getValue());
+        response.addHeader("Content-Length", dr.getContent_Length() + "");
+        response.addHeader("Last-Modified", DateTimeMarshaller.serializeDateToUTC(dr.getLast_Modified()));
+        response.addHeader("DataONE-ObjectFormat", dr.getDataONE_ObjectFormatIdentifier().getValue());
+        response.addHeader("DataONE-SerialVersion", dr.getSerialVersion().toString());
+
+        
+    }
+    
+    /**
+     * get the logs based on passed params.  Available 
+     * See http://mule1.dataone.org/ArchitectureDocs/mn_api_crud.html#MN_crud.getLogRecords
+     * for more info
+     * @throws NotImplemented 
+     * @throws InvalidRequest 
+     * @throws NotAuthorized 
+     * @throws ServiceFailure 
+     * @throws InvalidToken 
+     * @throws IOException 
+     * @throws JiBXException 
+     */
+    private void getLog() throws InvalidToken, ServiceFailure, NotAuthorized, InvalidRequest, NotImplemented, IOException, JiBXException
+    {
+            
+        Date fromDate = null;
+        Date toDate = null;
+        Event event = null;
+        Integer start = null;
+        Integer count = null;
+        String pidFilter = null;
+        
+        try {
+        	String fromDateS = params.get("fromDate")[0];
+            logMetacat.debug("param fromDateS: " + fromDateS);
+            fromDate = DateTimeMarshaller.deserializeDateToUTC(fromDateS);
+        } catch (Exception e) {
+        	logMetacat.warn("Could not parse fromDate: " + e.getMessage());
+        }
+        try {
+        	String toDateS = params.get("toDate")[0];
+            logMetacat.debug("param toDateS: " + toDateS);
+            toDate = DateTimeMarshaller.deserializeDateToUTC(toDateS);
+        } catch (Exception e) {
+        	logMetacat.warn("Could not parse toDate: " + e.getMessage());
+		}
+        try {
+        	String eventS = params.get("event")[0];
+            event = Event.convert(eventS);
+        } catch (Exception e) {
+        	logMetacat.warn("Could not parse event: " + e.getMessage());
+		}
+        logMetacat.debug("fromDate: " + fromDate + " toDate: " + toDate);
+        
+        try {
+        	start =  Integer.parseInt(params.get("start")[0]);
+        } catch (Exception e) {
+			logMetacat.warn("Could not parse start: " + e.getMessage());
+		}
+        try {
+        	count =  Integer.parseInt(params.get("count")[0]);
+        } catch (Exception e) {
+			logMetacat.warn("Could not parse count: " + e.getMessage());
+		}
+        
+        try {
+            pidFilter = params.get("pidFilter")[0];
+        } catch (Exception e) {
+            logMetacat.warn("Could not parse pidFilter: " + e.getMessage());
+        }
+        
+        logMetacat.debug("calling getLogRecords");
+        Log log = MNodeService.getInstance(request).getLogRecords(session, fromDate, toDate, event, pidFilter, start, count);
+        
+        OutputStream out = response.getOutputStream();
+        response.setStatus(200);
+        response.setContentType("text/xml");
+        
+        TypeMarshaller.marshalTypeToOutputStream(log, out);
+        
+    }
+    
+    
+    
+    /**
+     * Implements REST version of DataONE CRUD API --> get
+     * @param pid ID of data object to be read
+     * @throws NotImplemented 
+     * @throws InvalidRequest 
+     * @throws NotFound 
+     * @throws NotAuthorized 
+     * @throws ServiceFailure 
+     * @throws InvalidToken 
+     * @throws IOException 
+     * @throws JiBXException 
+     * @throws InsufficientResources 
+     */
+    protected void getObject(String pid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, InvalidRequest, NotImplemented, IOException, JiBXException, InsufficientResources {
+        OutputStream out = null;
+        
+        if (pid != null) { //get a specific document                
+            Identifier id = new Identifier();
+            id.setValue(pid);
+                
+            SystemMetadata sm = MNodeService.getInstance(request).getSystemMetadata(session, id);
+            
+            // set the headers for the content
+            String mimeType = ObjectFormatInfo.instance().getMimeType(sm.getFormatId().getValue());
+            if (mimeType == null) {
+            	mimeType = "application/octet-stream";
+            }
+            String extension = ObjectFormatInfo.instance().getExtension(sm.getFormatId().getValue());
+            String filename = id.getValue();
+            if (extension != null) {
+            	filename = id.getValue() + extension;
+            }
+            response.setContentType(mimeType);
+            response.setHeader("Content-Disposition", "inline; filename=" + filename);
+            
+            InputStream data = MNodeService.getInstance(request).get(session, id);
+
+            out = response.getOutputStream();  
+            IOUtils.copyLarge(data, out);
+            
+        }
+        else
+        { //call listObjects with specified params
+            Date startTime = null;
+            Date endTime = null;
+            ObjectFormatIdentifier formatId = null;
+            boolean replicaStatus = true;
+            int start = 0;
+            //TODO: make the max count into a const
+            int count = 1000;
+            Enumeration paramlist = request.getParameterNames();
+            while (paramlist.hasMoreElements()) 
+            { //parse the params and make the crud call
+                String name = (String) paramlist.nextElement();
+                String[] value = (String[])request.getParameterValues(name);
+
+                if (name.equals("fromDate") && value != null)
+                {
+                    try
+                    {
+                      //startTime = dateFormat.parse(value[0]);
+                    	startTime = DateTimeMarshaller.deserializeDateToUTC(value[0]);
+                        //startTime = parseDateAndConvertToGMT(value[0]);
+                    }
+                    catch(Exception e)
+                    {  //if we can't parse it, just don't use the fromDate param
+                        logMetacat.warn("Could not parse fromDate: " + value[0]);
+                        startTime = null;
+                    }
+                }
+                else if(name.equals("toDate") && value != null)
+                {
+                    try
+                    {
+                    	endTime = DateTimeMarshaller.deserializeDateToUTC(value[0]);
+                    }
+                    catch(Exception e)
+                    {  //if we can't parse it, just don't use the toDate param
+                        logMetacat.warn("Could not parse toDate: " + value[0]);
+                        endTime = null;
+                    }
+                }
+                else if(name.equals("formatId") && value != null) 
+                {
+                	formatId = new ObjectFormatIdentifier();
+                	formatId.setValue(value[0]);
+                }
+                else if(name.equals("replicaStatus") && value != null)
+                {
+                    if(value != null && 
+                       value.length > 0 && 
+                       (value[0].equalsIgnoreCase("false") || value[0].equalsIgnoreCase("no")))
+                    {
+                        replicaStatus = false;
+                    }
+                }
+                else if(name.equals("start") && value != null)
+                {
+                    start = new Integer(value[0]).intValue();
+                }
+                else if(name.equals("count") && value != null)
+                {
+                    count = new Integer(value[0]).intValue();
+                }
+            }
+            //make the crud call
+            logMetacat.debug("session: " + session + " startTime: " + startTime +
+                    " endTime: " + endTime + " formatId: " + 
+                    formatId + " replicaStatus: " + replicaStatus + 
+                    " start: " + start + " count: " + count);
+           
+            ObjectList ol = 
+           	 MNodeService.getInstance(request).listObjects(session, startTime, endTime, 
+           			formatId, replicaStatus, start, count);
+           
+            out = response.getOutputStream();  
+            response.setStatus(200);
+            response.setContentType("text/xml");
+            // Serialize and write it to the output stream
+            TypeMarshaller.marshalTypeToOutputStream(ol, out);
+            
+        }
+        
+    }
+    
+
+    /**
+     * Retrieve data package as Bagit zip
+     * @param pid
+     * @throws NotImplemented 
+     * @throws NotFound 
+     * @throws NotAuthorized 
+     * @throws ServiceFailure 
+     * @throws InvalidToken 
+     * @throws IOException 
+     * @throws InvalidRequest 
+     */
+    protected void getPackage(String pid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, IOException, InvalidRequest {
+
+        Identifier id = new Identifier();
+        id.setValue(pid);
+        InputStream is = MNodeService.getInstance(request).getPackage(session, null, id);
+        
+        // use the provided filename
+        String filename = null;
+        if (is instanceof DeleteOnCloseFileInputStream) {
+            filename = ((DeleteOnCloseFileInputStream)is).getFile().getName();
+        } else {
+        	filename = "dataPackage-" + System.currentTimeMillis() + ".zip";
+        }
+        response.setHeader("Content-Disposition", "inline; filename=" + filename);
+        response.setContentType("application/zip");
+        response.setStatus(200);
+        OutputStream out = response.getOutputStream();
+        
+        // write it to the output stream
+        IOUtils.copyLarge(is, out);
+   }
+    
+	protected void publish(String pid) throws InvalidToken, ServiceFailure,
+			NotAuthorized, NotFound, NotImplemented, IOException,
+			JiBXException, InvalidRequest, IdentifierNotUnique,
+			UnsupportedType, InsufficientResources, InvalidSystemMetadata {
+
+		// publish the object
+		Identifier originalIdentifier = new Identifier();
+		originalIdentifier.setValue(pid);
+		Identifier newIdentifier = MNodeService.getInstance(request).publish(session, originalIdentifier);
+
+		response.setStatus(200);
+		response.setContentType("text/xml");
+		OutputStream out = response.getOutputStream();
+
+		// write new identifier to the output stream
+		TypeMarshaller.marshalTypeToOutputStream(newIdentifier, out);
+	}
+    
+    /**
+     * Retrieve System Metadata
+     * @param pid
+     * @throws InvalidToken
+     * @throws ServiceFailure
+     * @throws NotAuthorized
+     * @throws NotFound
+     * @throws InvalidRequest
+     * @throws NotImplemented
+     * @throws IOException
+     * @throws JiBXException
+     */
+    protected void getSystemMetadataObject(String pid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, InvalidRequest, NotImplemented, IOException, JiBXException {
+
+        Identifier id = new Identifier();
+        id.setValue(pid);
+        SystemMetadata sysmeta = MNodeService.getInstance(request).getSystemMetadata(session, id);
+        
+        response.setContentType("text/xml");
+        response.setStatus(200);
+        OutputStream out = response.getOutputStream();
+        
+        // Serialize and write it to the output stream
+        TypeMarshaller.marshalTypeToOutputStream(sysmeta, out);
+   }
+    
+    
+    /**
+     * Inserts or updates the object
+     * 
+     * @param pid - ID of data object to be inserted or updated.  If action is update, the pid
+     *               is the existing pid.  If insert, the pid is the new one
+     * @throws InvalidRequest 
+     * @throws ServiceFailure 
+     * @throws JiBXException 
+     * @throws NotImplemented 
+     * @throws InvalidSystemMetadata 
+     * @throws InsufficientResources 
+     * @throws UnsupportedType 
+     * @throws IdentifierNotUnique 
+     * @throws NotAuthorized 
+     * @throws InvalidToken 
+     * @throws NotFound 
+     * @throws IOException 
+     * @throws IllegalAccessException 
+     * @throws InstantiationException 
+     */
+    protected void putObject(String trailingPid, String action) throws ServiceFailure, InvalidRequest, JiBXException, InvalidToken, NotAuthorized, IdentifierNotUnique, UnsupportedType, InsufficientResources, InvalidSystemMetadata, NotImplemented, NotFound, IOException, InstantiationException, IllegalAccessException {
+       
+    	// Read the incoming data from its Mime Multipart encoding
+    	Map<String, File> files = collectMultipartFiles();
+               
+    	Identifier pid = new Identifier();
+        if (trailingPid == null) {
+	        // get the pid string from the body and set the value
+	        String pidString = multipartparams.get("pid").get(0);
+	        if (pidString != null) {
+            pid.setValue(pidString);
+            
+          } else {
+              throw new InvalidRequest("1102", "The pid param must be included and contain the identifier.");
+              
+          }
+        } else {
+        	// use the pid included in the URL
+        	pid.setValue(trailingPid);
+        }
+        logMetacat.debug("putObject with pid " + pid.getValue());
+        logMetacat.debug("Entering putObject: " + pid.getValue() + "/" + action);
+
+        InputStream object = null;
+        InputStream sysmeta = null;
+        File smFile = files.get("sysmeta");
+        sysmeta = new FileInputStream(smFile);
+        File objFile = files.get("object");
+        object = new FileInputStream(objFile);
+        
+        // ensure we have the object bytes
+        if  ( objFile == null ) {
+            throw new InvalidRequest("1102", "The object param must contain the object bytes.");
+            
+        }
+        
+        // ensure we have the system metadata
+        if  ( smFile == null ) {
+            throw new InvalidRequest("1102", "The sysmeta param must contain the system metadata document.");
+            
+        }
+        
+        response.setStatus(200);
+        response.setContentType("text/xml");
+        OutputStream out = response.getOutputStream();
+        
+        if (action.equals(FUNCTION_NAME_INSERT)) { 
+            // handle inserts
+            logMetacat.debug("Commence creation...");
+            SystemMetadata smd = TypeMarshaller.unmarshalTypeFromStream(SystemMetadata.class, sysmeta);
+
+            logMetacat.debug("creating object with pid " + pid.getValue());
+            Identifier rId = MNodeService.getInstance(request).create(session, pid, object, smd);
+            TypeMarshaller.marshalTypeToOutputStream(rId, out);
+            
+        } else if (action.equals(FUNCTION_NAME_UPDATE)) {
+        	// handle updates
+        	
+            // construct pids
+            Identifier newPid = null;
+            try {
+            	String newPidString = multipartparams.get("newPid").get(0);
+            	newPid = new Identifier();
+            	newPid.setValue(newPidString);
+            } catch (Exception e) {
+				logMetacat.error("Could not get newPid from request");
+			}
+            logMetacat.debug("Commence update...");
+            
+            // get the systemmetadata object
+            SystemMetadata smd = TypeMarshaller.unmarshalTypeFromStream(SystemMetadata.class, sysmeta);
+
+            Identifier rId = MNodeService.getInstance(request).update(session, pid, object, newPid, smd);
+            TypeMarshaller.marshalTypeToOutputStream(rId, out);
+        } else {
+            throw new InvalidRequest("1000", "Operation must be create or update.");
+        }
+   
+    }
+
+    /**
+     * Handle delete 
+     * @param pid ID of data object to be deleted
+     * @throws IOException
+     * @throws InvalidRequest 
+     * @throws NotImplemented 
+     * @throws NotFound 
+     * @throws NotAuthorized 
+     * @throws ServiceFailure 
+     * @throws InvalidToken 
+     * @throws JiBXException 
+     */
+    private void deleteObject(String pid) throws IOException, InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, InvalidRequest, JiBXException 
+    {
+
+        OutputStream out = response.getOutputStream();
+        response.setStatus(200);
+        response.setContentType("text/xml");
+
+        Identifier id = new Identifier();
+        id.setValue(pid);
+
+        logMetacat.debug("Calling delete");
+        MNodeService.getInstance(request).delete(session, id);
+        TypeMarshaller.marshalTypeToOutputStream(id, out);
+        
+    }
+    
+    /**
+     * Archives the given pid
+     * @param pid
+     * @throws InvalidToken
+     * @throws ServiceFailure
+     * @throws NotAuthorized
+     * @throws NotFound
+     * @throws NotImplemented
+     * @throws IOException
+     * @throws JiBXException
+     */
+    private void archive(String pid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, IOException, JiBXException {
+
+        OutputStream out = response.getOutputStream();
+        response.setStatus(200);
+        response.setContentType("text/xml");
+
+        Identifier id = new Identifier();
+        id.setValue(pid);
+
+        logMetacat.debug("Calling archive");
+        MNodeService.getInstance(request).archive(session, id);
+        
+        TypeMarshaller.marshalTypeToOutputStream(id, out);
+        
+    }
+
+	protected SynchronizationFailed collectSynchronizationFailed() throws IOException, ServiceFailure, InvalidRequest, JiBXException, InstantiationException, IllegalAccessException, ParserConfigurationException, SAXException  {
+		
+		// Read the incoming data from its Mime Multipart encoding
+		logMetacat.debug("Disassembling MIME multipart form");
+		InputStream sf = null;
+	
+		// handle MMP inputs
+		File tmpDir = getTempDirectory();
+		logMetacat.debug("temp dir: " + tmpDir.getAbsolutePath());
+		MultipartRequestResolver mrr = 
+			new MultipartRequestResolver(tmpDir.getAbsolutePath(), 1000000000, 0);
+		MultipartRequest mr = null;
+		try {
+			mr = mrr.resolveMultipart(request);
+		} catch (Exception e) {
+			throw new ServiceFailure("2161", 
+					"Could not resolve multipart: " + e.getMessage());
+		}
+		logMetacat.debug("resolved multipart request");
+		Map<String, File> files = mr.getMultipartFiles();
+		if (files == null || files.keySet() == null) {
+			throw new InvalidRequest("2163",
+					"must have multipart file with name 'message'");
+		}
+		logMetacat.debug("got multipart files");
+	
+		multipartparams = mr.getMultipartParameters();
+	
+		File sfFile = files.get("message");
+		if (sfFile == null) {
+			throw new InvalidRequest("2163",
+					"Missing the required file-part 'message' from the multipart request.");
+		}
+		logMetacat.debug("sfFile: " + sfFile.getAbsolutePath());
+		sf = new FileInputStream(sfFile);
+	
+		SynchronizationFailed syncFailed = (SynchronizationFailed) ExceptionHandler.deserializeXml(sf, "Error deserializing exception");
+		return syncFailed;
+	}
+
+}

Property changes on: src/edu/ucsb/nceas/metacat/restservice/v1/MNResourceHandler.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property
Index: src/edu/ucsb/nceas/metacat/restservice/v1/CNRestServlet.java
===================================================================
--- src/edu/ucsb/nceas/metacat/restservice/v1/CNRestServlet.java	(nonexistent)
+++ src/edu/ucsb/nceas/metacat/restservice/v1/CNRestServlet.java	(revision 8810)
@@ -0,0 +1,50 @@
+/**
+ *  '$RCSfile$'
+ *  Copyright: 2000 Regents of the University of California and the
+ *              National Center for Ecological Analysis and Synthesis
+ *
+ *   '$Author$'
+ *     '$Date$'
+ *
+ * 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.v1;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import edu.ucsb.nceas.metacat.restservice.D1ResourceHandler;
+import edu.ucsb.nceas.metacat.restservice.D1RestServlet;
+
+
+/**
+ * Routes CN REST service requests to the appropriate handler
+ *  
+ */
+public class CNRestServlet extends D1RestServlet {
+    
+	/**
+	 * Provide a CNResourceHandler subclass of D1ResourceHandler
+	 */
+	@Override
+    protected D1ResourceHandler createHandler(HttpServletRequest request, HttpServletResponse response) 
+    	throws ServletException, IOException {
+        return new CNResourceHandler(getServletContext(), request, response);
+    }
+
+}

Property changes on: src/edu/ucsb/nceas/metacat/restservice/v1/CNRestServlet.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property
Index: src/edu/ucsb/nceas/metacat/restservice/v1/CNResourceHandler.java
===================================================================
--- src/edu/ucsb/nceas/metacat/restservice/v1/CNResourceHandler.java	(nonexistent)
+++ src/edu/ucsb/nceas/metacat/restservice/v1/CNResourceHandler.java	(revision 8810)
@@ -0,0 +1,1706 @@
+/**
+ *  '$RCSfile$'
+ *  Copyright: 2011 Regents of the University of California and the
+ *              National Center for Ecological Analysis and Synthesis
+ *
+ *   '$Author$'
+ *     '$Date$'
+ *
+ * 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.v1;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Map;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.commons.fileupload.FileUploadException;
+import org.apache.commons.io.IOUtils;
+import org.apache.log4j.Logger;
+import org.dataone.client.v2.formats.ObjectFormatInfo;
+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.NotFound;
+import org.dataone.service.exceptions.NotImplemented;
+import org.dataone.service.exceptions.ServiceFailure;
+import org.dataone.service.exceptions.UnsupportedType;
+import org.dataone.service.exceptions.VersionMismatch;
+import org.dataone.service.types.v1.AccessPolicy;
+import org.dataone.service.types.v1.Checksum;
+import org.dataone.service.types.v1.ChecksumAlgorithmList;
+import org.dataone.service.types.v1.DescribeResponse;
+import org.dataone.service.types.v1.Event;
+import org.dataone.service.types.v1.Identifier;
+import org.dataone.service.types.v1.Log;
+import org.dataone.service.types.v1.NodeReference;
+import org.dataone.service.types.v1.ObjectFormat;
+import org.dataone.service.types.v1.ObjectFormatIdentifier;
+import org.dataone.service.types.v1.ObjectFormatList;
+import org.dataone.service.types.v1.ObjectList;
+import org.dataone.service.types.v1.ObjectLocationList;
+import org.dataone.service.types.v1.Permission;
+import org.dataone.service.types.v1.Replica;
+import org.dataone.service.types.v1.ReplicationPolicy;
+import org.dataone.service.types.v1.ReplicationStatus;
+import org.dataone.service.types.v1.Subject;
+import org.dataone.service.types.v1.SystemMetadata;
+import org.dataone.service.util.Constants;
+import org.dataone.service.util.DateTimeMarshaller;
+import org.dataone.service.util.EncodingUtilities;
+import org.dataone.service.util.ExceptionHandler;
+import org.dataone.service.util.TypeMarshaller;
+import org.jibx.runtime.JiBXException;
+import org.xml.sax.SAXException;
+
+import edu.ucsb.nceas.metacat.dataone.v1.CNodeService;
+import edu.ucsb.nceas.metacat.properties.PropertyService;
+import edu.ucsb.nceas.metacat.restservice.D1ResourceHandler;
+import edu.ucsb.nceas.utilities.PropertyNotFoundException;
+
+/**
+ * CN REST service implementation handler
+ * 
+ * ****************** CNCore -- DONE create() - POST /d1/cn/object/PID
+ * listFormats() - GET /d1/cn/formats getFormat() - GET /d1/cn/formats/FMTID
+ * getLogRecords - GET /d1/cn/log reserveIdentifier() - POST /d1/cn/reserve
+ * listNodes() - Not implemented registerSystemMetadata() - POST /d1/meta/PID
+ * 
+ * CNRead -- DONE get() - GET /d1/cn/object/PID getSystemMetadata() - GET
+ * /d1/cn/meta/PID resolve() - GET /d1/cn/resolve/PID assertRelation() - GET
+ * /d1/cn/assertRelation/PID getChecksum() - GET /d1/cn/checksum search() - Not
+ * implemented in Metacat
+ * 
+ * CNAuthorization setOwner() - PUT /d1/cn/owner/PID isAuthorized() - GET
+ * /d1/cn/isAuthorized/PID setAccessPolicy() - POST /d1/cn/accessRules
+ * 
+ * CNIdentity - not implemented at all on Metacat
+ * 
+ * CNReplication setReplicationStatus() - PUT /replicaNotifications/PID
+ * updateReplicationMetadata() - PUT /replicaMetadata/PID setReplicationPolicy()
+ * - PUT /replicaPolicies/PID isNodeAuthorized() - GET
+ * /replicaAuthorizations/PID
+ * 
+ * CNRegister -- not implemented at all in Metacat ******************
+ * 
+ * @author leinfelder
+ * 
+ */
+public class CNResourceHandler extends D1ResourceHandler {
+
+    /** CN-specific operations **/
+    protected static final String RESOURCE_RESERVE = "reserve";
+    protected static final String RESOURCE_FORMATS = "formats";
+    protected static final String RESOURCE_RESOLVE = "resolve";
+    protected static final String RESOURCE_OWNER = "owner";
+    protected static final String RESOURCE_REPLICATION_POLICY = "replicaPolicies";
+    protected static final String RESOURCE_REPLICATION_META = "replicaMetadata";
+    protected static final String RESOURCE_REPLICATION_AUTHORIZED = "replicaAuthorizations";
+    protected static final String RESOURCE_REPLICATION_NOTIFY = "replicaNotifications";
+
+    public CNResourceHandler(ServletContext servletContext,
+            HttpServletRequest request, HttpServletResponse response) {
+        super(servletContext, request, response);
+        logMetacat = Logger.getLogger(CNResourceHandler.class);
+    }
+
+    /**
+     * This function is called from REST API servlet and handles each request to
+     * the servlet
+     * 
+     * @param httpVerb
+     *            (GET, POST, PUT or DELETE)
+     */
+    @Override
+    public void handle(byte httpVerb) {
+        // prepare the handler
+        super.handle(httpVerb);
+
+        try {
+
+        	// only service requests if we have D1 configured
+        	if (!isD1Enabled()) {
+        		ServiceFailure se = new ServiceFailure("0000", "DataONE services are not enabled on this node");
+                serializeException(se, response.getOutputStream());
+                return;
+        	}
+        	
+            // get the resource
+            String resource = request.getPathInfo();
+            resource = resource.substring(resource.indexOf("/") + 1);
+
+            // for the rest of the resouce
+            String extra = null;
+
+            logMetacat.debug("handling verb " + httpVerb
+                    + " request with resource '" + resource + "'");
+            boolean status = false;
+
+            if (resource != null) {
+
+                if (resource.startsWith(RESOURCE_ACCESS_RULES)
+                        && httpVerb == PUT) {
+                    logMetacat.debug("Setting access policy");
+                    // after the command
+                    extra = parseTrailing(resource, RESOURCE_ACCESS_RULES);
+                    setAccess(extra);
+                    status = true;
+                    logMetacat.debug("done setting access");
+
+                } else if (resource.startsWith(RESOURCE_META)) {
+                    logMetacat.debug("Using resource: " + RESOURCE_META);
+
+                    // after the command
+                    extra = parseTrailing(resource, RESOURCE_META);
+
+                    // get
+                    if (httpVerb == GET) {
+                        getSystemMetadataObject(extra);
+                        status = true;
+                    }
+                    // post to register system metadata
+                    if (httpVerb == POST) {
+                        registerSystemMetadata();
+                        status = true;
+                    }
+
+                } else if (resource.startsWith(RESOURCE_RESERVE)) {
+                    // reserve the ID (in params)
+                    if (httpVerb == POST) {
+                        reserve();
+                        status = true;
+                    }
+                } else if (resource.startsWith(RESOURCE_RESOLVE)) {
+
+                    // after the command
+                    extra = parseTrailing(resource, RESOURCE_RESOLVE);
+
+                    // resolve the object location
+                    if (httpVerb == GET) {
+                        resolve(extra);
+                        status = true;
+                    }
+                } else if (resource.startsWith(RESOURCE_OWNER)) {
+
+                    // after the command
+                    extra = parseTrailing(resource, RESOURCE_OWNER);
+
+                    // set the owner
+                    if (httpVerb == PUT) {
+                        owner(extra);
+                        status = true;
+                    }
+                } else if (resource.startsWith(RESOURCE_IS_AUTHORIZED)) {
+
+                    // after the command
+                    extra = parseTrailing(resource, RESOURCE_IS_AUTHORIZED);
+
+                    // authorized?
+                    if (httpVerb == GET) {
+                        isAuthorized(extra);
+                        status = true;
+                    }
+                } else if (resource.startsWith(RESOURCE_OBJECTS)) {
+                    logMetacat.debug("Using resource 'object'");
+                    logMetacat
+                            .debug("D1 Rest: Starting resource processing...");
+
+                    // after the command
+                    extra = parseTrailing(resource, RESOURCE_OBJECTS);
+
+                    logMetacat.debug("objectId: " + extra);
+                    logMetacat.debug("verb:" + httpVerb);
+
+                    if (httpVerb == GET) {
+                        if (extra != null) {
+                            getObject(extra);
+                        } else {
+                            listObjects();
+                        }
+                        status = true;
+                    } else if (httpVerb == POST) {
+                        putObject(FUNCTION_NAME_INSERT);
+                        status = true;
+                    } else if (httpVerb == HEAD) {
+                        describeObject(extra);
+                        status = true;
+                    } else if (httpVerb == DELETE) {
+                        deleteObject(extra);
+                        status = true;
+                    } 
+
+                } else if (resource.startsWith(RESOURCE_FORMATS)) {
+                    logMetacat.debug("Using resource: " + RESOURCE_FORMATS);
+
+                    // after the command
+                    extra = parseTrailing(resource, RESOURCE_FORMATS);
+
+                    // handle each verb
+                    if (httpVerb == GET) {
+                        if (extra == null) {
+                            // list the formats collection
+                            listFormats();
+                        } else {
+                            // get the specified format
+                            getFormat(extra);
+                        }
+                        status = true;
+                    }
+
+                } else if (resource.startsWith(RESOURCE_LOG)) {
+                    logMetacat.debug("Using resource: " + RESOURCE_LOG);
+                    // handle log events
+                    if (httpVerb == GET) {
+                        getLog();
+                        status = true;
+                    }
+
+                } else if (resource.startsWith(Constants.RESOURCE_ARCHIVE)) {
+                    logMetacat.debug("Using resource " + Constants.RESOURCE_ARCHIVE);
+                    // handle archive events
+                    if (httpVerb == PUT) {
+                        extra = parseTrailing(resource, Constants.RESOURCE_ARCHIVE);
+                        archive(extra);
+                        status = true;
+                    }
+                } else if (resource.startsWith(Constants.RESOURCE_CHECKSUM)) {
+                    logMetacat.debug("Using resource: " + Constants.RESOURCE_CHECKSUM);
+
+                    // after the command
+                    extra = parseTrailing(resource, Constants.RESOURCE_CHECKSUM);
+
+                    // handle checksum requests
+                    if (httpVerb == GET) {
+
+                    	if (extra != null && extra.length() > 0) {
+	                        checksum(extra);
+	                        status = true;
+                    	} else {
+                    		listChecksumAlgorithms();
+                    		status = true;
+                    	}
+
+                    }
+
+                } else if (resource.startsWith(RESOURCE_REPLICATION_POLICY)
+                        && httpVerb == PUT) {
+
+                    logMetacat.debug("Using resource: "
+                            + RESOURCE_REPLICATION_POLICY);
+                    // get the trailing pid
+                    extra = parseTrailing(resource, RESOURCE_REPLICATION_POLICY);
+                    setReplicationPolicy(extra);
+                    status = true;
+
+                } else if (resource.startsWith(RESOURCE_REPLICATION_META)
+                        && httpVerb == PUT) {
+
+                    logMetacat.debug("Using resource: "
+                            + RESOURCE_REPLICATION_META);
+                    // get the trailing pid
+                    extra = parseTrailing(resource, RESOURCE_REPLICATION_META);
+                    updateReplicationMetadata(extra);
+                    status = true;
+
+                } else if (resource.startsWith(RESOURCE_REPLICATION_NOTIFY)
+                        && httpVerb == PUT) {
+
+                    logMetacat.debug("Using resource: "
+                            + RESOURCE_REPLICATION_NOTIFY);
+                    // get the trailing pid
+                    extra = parseTrailing(resource, RESOURCE_REPLICATION_NOTIFY);
+                    setReplicationStatus(extra);
+                    status = true;
+
+                } else if (resource.startsWith(RESOURCE_REPLICATION_AUTHORIZED)
+                        && httpVerb == GET) {
+
+                    logMetacat.debug("Using resource: "
+                            + RESOURCE_REPLICATION_AUTHORIZED);
+                    // get the trailing pid
+                    extra = parseTrailing(resource,
+                            RESOURCE_REPLICATION_AUTHORIZED);
+                    isNodeAuthorized(extra);
+                    status = true;
+
+                } else if (resource.startsWith(Constants.RESOURCE_MONITOR_PING)) {
+                    if (httpVerb == GET) {
+                    	// after the command
+                        extra = parseTrailing(resource, Constants.RESOURCE_MONITOR_PING);
+                        
+                        logMetacat.debug("processing ping request");
+                        Date result = CNodeService.getInstance(request).ping();
+                        // TODO: send to output	
+                        status = true;
+                    }
+                } else if (resource.startsWith(Constants.RESOURCE_META_OBSOLETEDBY)
+                        && httpVerb == PUT) {
+
+                    logMetacat.debug("Using resource: "
+                            + Constants.RESOURCE_META_OBSOLETEDBY);
+                    // get the trailing pid
+                    extra = parseTrailing(resource, Constants.RESOURCE_META_OBSOLETEDBY);
+                    setObsoletedBy(extra);
+                    status = true;
+                } else if (resource.startsWith(Constants.RESOURCE_REPLICATION_DELETE_REPLICA)
+                        && httpVerb == PUT) {
+
+                    logMetacat.debug("Using resource: "
+                            + Constants.RESOURCE_REPLICATION_DELETE_REPLICA);
+                    // get the trailing pid
+                    extra = parseTrailing(resource, Constants.RESOURCE_REPLICATION_DELETE_REPLICA);
+                    deleteReplica(extra);
+                    status = true;
+                }
+
+                if (!status) {
+                    throw new ServiceFailure("0000", "Unknown error, status = "
+                            + status);
+                }
+            } else {
+                throw new InvalidRequest("0000", "No resource matched for "
+                        + resource);
+            }
+        } catch (BaseException be) {
+            // report Exceptions as clearly and generically as possible
+            OutputStream out = null;
+            try {
+                out = response.getOutputStream();
+            } catch (IOException ioe) {
+                logMetacat.error("Could not get output stream from response",
+                        ioe);
+            }
+            serializeException(be, out);
+        } catch (Exception e) {
+            // report Exceptions as clearly and generically as possible
+            logMetacat.error(e.getClass() + ": " + e.getMessage(), e);
+            OutputStream out = null;
+            try {
+                out = response.getOutputStream();
+            } catch (IOException ioe) {
+                logMetacat.error("Could not get output stream from response",
+                        ioe);
+            }
+            ServiceFailure se = new ServiceFailure("0000", e.getMessage());
+            serializeException(se, out);
+        }
+    }
+
+    /**
+     * Get the checksum for the given guid
+     * 
+     * @param guid
+     * @throws NotImplemented
+     * @throws InvalidRequest
+     * @throws NotFound
+     * @throws NotAuthorized
+     * @throws ServiceFailure
+     * @throws InvalidToken
+     * @throws IOException
+     * @throws JiBXException
+     */
+    private void checksum(String guid) throws InvalidToken, ServiceFailure,
+            NotAuthorized, NotFound, InvalidRequest, NotImplemented,
+            JiBXException, IOException {
+        Identifier guidid = new Identifier();
+        guidid.setValue(guid);
+        logMetacat.debug("getting checksum for object " + guid);
+        Checksum c = CNodeService.getInstance(request).getChecksum(session,
+                guidid);
+        logMetacat.debug("got checksum " + c.getValue());
+        response.setStatus(200);
+        logMetacat.debug("serializing response");
+        TypeMarshaller.marshalTypeToOutputStream(c, response.getOutputStream());
+        logMetacat.debug("done serializing response.");
+
+    }
+
+    /**
+     * get the logs based on passed params. Available params are token,
+     * fromDate, toDate, event. See
+     * http://mule1.dataone.org/ArchitectureDocs/mn_api_crud
+     * .html#MN_crud.getLogRecords for more info
+     * 
+     * @throws NotImplemented
+     * @throws InvalidRequest
+     * @throws NotAuthorized
+     * @throws ServiceFailure
+     * @throws InvalidToken
+     * @throws IOException
+     * @throws JiBXException
+     * @throws InsufficientResources 
+     */
+    private void getLog() throws InvalidToken, ServiceFailure, NotAuthorized,
+            InvalidRequest, NotImplemented, IOException, JiBXException, InsufficientResources {
+
+        Date fromDate = null;
+        Date toDate = null;
+        Event event = null;
+        Integer start = null;
+        Integer count = null;
+        String pidFilter = null;
+
+        try {
+            String fromDateS = params.get("fromDate")[0];
+            logMetacat.debug("param fromDateS: " + fromDateS);
+            fromDate = DateTimeMarshaller.deserializeDateToUTC(fromDateS);
+        } catch (Exception e) {
+            logMetacat.warn("Could not parse fromDate: " + e.getMessage());
+        }
+        try {
+            String toDateS = params.get("toDate")[0];
+            logMetacat.debug("param toDateS: " + toDateS);
+            toDate = DateTimeMarshaller.deserializeDateToUTC(toDateS);
+        } catch (Exception e) {
+            logMetacat.warn("Could not parse toDate: " + e.getMessage());
+        }
+        try {
+            String eventS = params.get("event")[0];
+            event = Event.convert(eventS);
+        } catch (Exception e) {
+            logMetacat.warn("Could not parse event: " + e.getMessage());
+        }
+        logMetacat.debug("fromDate: " + fromDate + " toDate: " + toDate);
+
+        try {
+            start = Integer.parseInt(params.get("start")[0]);
+        } catch (Exception e) {
+            logMetacat.warn("Could not parse start: " + e.getMessage());
+        }
+        try {
+            count = Integer.parseInt(params.get("count")[0]);
+        } catch (Exception e) {
+            logMetacat.warn("Could not parse count: " + e.getMessage());
+        }
+
+        try {
+            pidFilter = params.get("pidFilter")[0];
+        } catch (Exception e) {
+            logMetacat.warn("Could not parse pidFilter: " + e.getMessage());
+        }
+        
+        logMetacat.debug("calling getLogRecords");
+        Log log = CNodeService.getInstance(request).getLogRecords(session,
+                fromDate, toDate, event, pidFilter, start, count);
+
+        OutputStream out = response.getOutputStream();
+        response.setStatus(200);
+        response.setContentType("text/xml");
+
+        TypeMarshaller.marshalTypeToOutputStream(log, out);
+
+    }
+
+    /**
+     * Implements REST version of DataONE CRUD API --> get
+     * 
+     * @param guid
+     *            ID of data object to be read
+     * @throws NotImplemented
+     * @throws InvalidRequest
+     * @throws NotFound
+     * @throws NotAuthorized
+     * @throws ServiceFailure
+     * @throws InvalidToken
+     * @throws IOException
+     */
+    protected void getObject(String guid) throws InvalidToken, ServiceFailure,
+            NotAuthorized, NotFound, InvalidRequest, NotImplemented,
+            IOException {
+
+        Identifier id = new Identifier();
+        id.setValue(guid);
+
+        SystemMetadata sm = CNodeService.getInstance(request)
+                .getSystemMetadata(session, id);
+
+        // set the headers for the content
+        String mimeType = ObjectFormatInfo.instance().getMimeType(sm.getFormatId().getValue());
+        if (mimeType == null) {
+        	mimeType = "application/octet-stream";
+        }
+        String extension = ObjectFormatInfo.instance().getExtension(sm.getFormatId().getValue());
+        String filename = id.getValue();
+        if (extension != null) {
+        	filename = id.getValue() + extension;
+        }
+        response.setContentType(mimeType);
+        response.setHeader("Content-Disposition", "inline; filename=" + filename);
+
+        InputStream data = CNodeService.getInstance(request).get(session, id);
+
+        OutputStream out = response.getOutputStream();
+        response.setStatus(200);
+        IOUtils.copyLarge(data, out);
+
+    }
+
+    /**
+     * Implements REST version of DataONE CRUD API --> getSystemMetadata
+     * 
+     * @param guid
+     *            ID of data object to be read
+     * @throws NotImplemented
+     * @throws InvalidRequest
+     * @throws NotFound
+     * @throws NotAuthorized
+     * @throws ServiceFailure
+     * @throws InvalidToken
+     * @throws IOException
+     * @throws JiBXException
+     */
+    protected void getSystemMetadataObject(String guid) throws InvalidToken,
+            ServiceFailure, NotAuthorized, NotFound, InvalidRequest,
+            NotImplemented, IOException, JiBXException {
+
+        Identifier id = new Identifier();
+        id.setValue(guid);
+        SystemMetadata sysmeta = CNodeService.getInstance(request)
+                .getSystemMetadata(session, id);
+
+        response.setContentType("text/xml");
+        response.setStatus(200);
+        OutputStream out = response.getOutputStream();
+
+        // Serialize and write it to the output stream
+        TypeMarshaller.marshalTypeToOutputStream(sysmeta, out);
+    }
+
+    /**
+     * Earthgrid API > Put Service >Put Function : calls MetacatHandler >
+     * handleInsertOrUpdateAction
+     * 
+     * @param guid
+     *            - ID of data object to be inserted or updated. If action is
+     *            update, the pid is the existing pid. If insert, the pid is the
+     *            new one
+     * @throws InvalidRequest
+     * @throws ServiceFailure
+     * @throws IdentifierNotUnique
+     * @throws JiBXException
+     * @throws NotImplemented
+     * @throws InvalidSystemMetadata
+     * @throws InsufficientResources
+     * @throws UnsupportedType
+     * @throws NotAuthorized
+     * @throws InvalidToken
+     * @throws IOException
+     * @throws IllegalAccessException
+     * @throws InstantiationException
+     */
+    protected void putObject(String action) throws ServiceFailure,
+            InvalidRequest, IdentifierNotUnique, JiBXException, InvalidToken,
+            NotAuthorized, UnsupportedType, InsufficientResources,
+            InvalidSystemMetadata, NotImplemented, IOException,
+            InstantiationException, IllegalAccessException {
+    	
+        // Read the incoming data from its Mime Multipart encoding
+        Map<String, File> files = collectMultipartFiles();
+        
+	    // get the encoded pid string from the body and make the object
+        String pidString = multipartparams.get("pid").get(0);
+        Identifier pid = new Identifier();
+        pid.setValue(pidString);
+        
+        logMetacat.debug("putObject: " + pid.getValue() + "/" + action);
+        
+        InputStream object = null;
+        InputStream sysmeta = null;
+
+        File smFile = files.get("sysmeta");
+        sysmeta = new FileInputStream(smFile);
+        File objFile = files.get("object");
+        object = new FileInputStream(objFile);
+
+        if (action.equals(FUNCTION_NAME_INSERT)) { // handle inserts
+
+            logMetacat.debug("Commence creation...");
+            SystemMetadata smd = TypeMarshaller.unmarshalTypeFromStream(
+                    SystemMetadata.class, sysmeta);
+
+           
+            logMetacat.debug("creating object with pid " + pid.getValue());
+            Identifier rId = CNodeService.getInstance(request).create(session, pid, object, smd);
+
+            OutputStream out = response.getOutputStream();
+            response.setStatus(200);
+            response.setContentType("text/xml");
+
+            TypeMarshaller.marshalTypeToOutputStream(rId, out);
+
+        } else {
+            throw new InvalidRequest("1000", "Operation must be create.");
+        }
+    }
+
+    /**
+     * List the object formats registered with the system
+     * 
+     * @throws NotImplemented
+     * @throws InsufficientResources
+     * @throws NotFound
+     * @throws ServiceFailure
+     * @throws InvalidRequest
+     * @throws IOException
+     * @throws JiBXException
+     */
+    private void listFormats() throws InvalidRequest, ServiceFailure, NotFound,
+            InsufficientResources, NotImplemented, IOException, JiBXException {
+        logMetacat.debug("Entering listFormats()");
+
+        ObjectFormatList objectFormatList = CNodeService.getInstance(request)
+                .listFormats();
+        // get the response output stream
+        OutputStream out = response.getOutputStream();
+        response.setStatus(200);
+        response.setContentType("text/xml");
+
+        // style the object with a processing directive
+        String stylesheet = null;
+        try {
+            stylesheet = PropertyService.getProperty("dataone.types.xsl");
+        } catch (PropertyNotFoundException e) {
+            logMetacat.warn("Could not locate DataONE types XSLT: "
+                    + e.getMessage());
+        }
+
+        TypeMarshaller.marshalTypeToOutputStream(objectFormatList, out,
+                stylesheet);
+
+    }
+    
+    private void listChecksumAlgorithms() throws IOException, ServiceFailure,
+			NotImplemented, JiBXException {
+		logMetacat.debug("Entering listFormats()");
+
+		ChecksumAlgorithmList result = CNodeService.getInstance(request).listChecksumAlgorithms();
+
+		// get the response output stream
+		OutputStream out = response.getOutputStream();
+		response.setStatus(200);
+		response.setContentType("text/xml");
+
+		TypeMarshaller.marshalTypeToOutputStream(result, out);
+
+	}
+    
+    /**
+     * http://mule1.dataone.org/ArchitectureDocs-current/apis/CN_APIs.html#CNRead.describe
+     * @param pid
+     * @throws InvalidToken
+     * @throws ServiceFailure
+     * @throws NotAuthorized
+     * @throws NotFound
+     * @throws NotImplemented
+     * @throws InvalidRequest
+     */
+    private void describeObject(String pid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, InvalidRequest
+    {
+        response.setContentType("text/xml");
+        
+        Identifier id = new Identifier();
+        id.setValue(pid);
+        
+        DescribeResponse dr = null;
+        try {
+            dr = CNodeService.getInstance(request).describe(session, id);
+        } catch (BaseException e) {
+        	response.setStatus(e.getCode());
+        	response.addHeader("DataONE-Exception-Name", e.getClass().getName());
+            response.addHeader("DataONE-Exception-DetailCode", e.getDetail_code());
+            response.addHeader("DataONE-Exception-Description", e.getDescription());
+            response.addHeader("DataONE-Exception-PID", id.getValue());
+            return;
+		}
+        
+        response.setStatus(200);
+        //response.addHeader("pid", pid);
+        response.addHeader("DataONE-Checksum", dr.getDataONE_Checksum().getAlgorithm() + "," + dr.getDataONE_Checksum().getValue());
+        response.addHeader("Content-Length", dr.getContent_Length() + "");
+        response.addHeader("Last-Modified", DateTimeMarshaller.serializeDateToUTC(dr.getLast_Modified()));
+        response.addHeader("DataONE-ObjectFormat", dr.getDataONE_ObjectFormatIdentifier().getValue());
+        response.addHeader("DataONE-SerialVersion", dr.getSerialVersion().toString());
+
+    }
+    
+    /**
+     * Handle delete 
+     * @param pid ID of data object to be deleted
+     * @throws IOException
+     * @throws InvalidRequest 
+     * @throws NotImplemented 
+     * @throws NotFound 
+     * @throws NotAuthorized 
+     * @throws ServiceFailure 
+     * @throws InvalidToken 
+     * @throws JiBXException 
+     */
+    private void deleteObject(String pid) throws IOException, InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, InvalidRequest, JiBXException 
+    {
+
+        OutputStream out = response.getOutputStream();
+        response.setStatus(200);
+        response.setContentType("text/xml");
+
+        Identifier id = new Identifier();
+        id.setValue(pid);
+
+        logMetacat.debug("Calling delete for identifier " + pid);
+        CNodeService.getInstance(request).delete(session, id);
+        TypeMarshaller.marshalTypeToOutputStream(id, out);
+        
+    }
+    
+    /**
+     * Archives the given pid
+     * @param pid
+     * @throws InvalidToken
+     * @throws ServiceFailure
+     * @throws NotAuthorized
+     * @throws NotFound
+     * @throws NotImplemented
+     * @throws IOException
+     * @throws JiBXException
+     * @throws InvalidRequest 
+     */
+    private void archive(String pid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, IOException, JiBXException, InvalidRequest {
+
+        OutputStream out = response.getOutputStream();
+        response.setStatus(200);
+        response.setContentType("text/xml");
+
+        Identifier id = new Identifier();
+        id.setValue(pid);
+
+        logMetacat.debug("Calling archive");
+        CNodeService.getInstance(request).archive(session, id);
+        
+        TypeMarshaller.marshalTypeToOutputStream(id, out);
+        
+    }
+
+    /**
+     * Return the requested object format
+     * 
+     * @param fmtidStr
+     *            the requested format identifier as a string
+     * @throws NotImplemented
+     * @throws InsufficientResources
+     * @throws NotFound
+     * @throws ServiceFailure
+     * @throws InvalidRequest
+     * @throws IOException
+     * @throws JiBXException
+     */
+    private void getFormat(String fmtidStr) throws InvalidRequest,
+            ServiceFailure, NotFound, InsufficientResources, NotImplemented,
+            IOException, JiBXException {
+        logMetacat.debug("Entering listFormats()");
+
+        ObjectFormatIdentifier fmtid = new ObjectFormatIdentifier();
+        fmtid.setValue(fmtidStr);
+
+        // get the specified object format
+        ObjectFormat objectFormat = CNodeService.getInstance(request)
+                .getFormat(fmtid);
+
+        OutputStream out = response.getOutputStream();
+        response.setStatus(200);
+        response.setContentType("text/xml");
+
+        TypeMarshaller.marshalTypeToOutputStream(objectFormat, out);
+
+    }
+
+    /**
+     * Reserve the given Identifier
+     * 
+     * @throws InvalidToken
+     * @throws ServiceFailure
+     * @throws NotAuthorized
+     * @throws IdentifierNotUnique
+     * @throws NotImplemented
+     * @throws InvalidRequest
+     */
+    private void reserve() 
+        throws InvalidToken, ServiceFailure, NotAuthorized, IdentifierNotUnique, 
+        NotImplemented, InvalidRequest {
+        Identifier pid = null;
+        String scope = null;
+        String format = null;
+
+        // Parse the params out of the multipart form data
+        logMetacat.debug("Parsing reserve parameters from the mime multipart entity");
+        try {
+            collectMultipartParams();
+            
+        } catch (FileUploadException e1) {
+            String msg = "FileUploadException: Couldn't parse the mime multipart information: " +
+            e1.getMessage();
+            logMetacat.debug(msg);
+            throw new ServiceFailure("4210", msg);
+
+        } catch (IOException e1) {
+            String msg = "IOException: Couldn't parse the mime multipart information: " +
+            e1.getMessage();
+            logMetacat.debug(msg);
+            throw new ServiceFailure("4210", msg);
+        
+        } catch (Exception e1) {
+            String msg = "Exception: Couldn't parse the mime multipart information: " +
+            e1.getMessage();
+            logMetacat.debug(msg);
+            throw new ServiceFailure("4210", msg);
+
+        }
+        
+        // gather the params
+        try {
+            String id = multipartparams.get("pid").get(0);
+            pid = new Identifier();
+            pid.setValue(id);
+            
+        } catch (NullPointerException e) {
+            String msg = "The 'pid' must be provided as a parameter and was not.";
+            logMetacat.error(msg);
+            throw new InvalidRequest("4200", msg);
+ 
+        }
+        
+        // call the implementation
+        try {
+            Identifier resultPid = CNodeService.getInstance(request).reserveIdentifier(session, pid);
+            OutputStream out = response.getOutputStream();
+            response.setStatus(200);
+            response.setContentType("text/xml");
+            // send back the reserved pid
+            TypeMarshaller.marshalTypeToOutputStream(resultPid, out);
+            
+        } catch (IOException e) {
+            String msg = "Couldn't write the identifier to the response output stream: " +
+                e.getMessage();
+            logMetacat.debug(msg);
+            throw new ServiceFailure("4210", msg);
+        
+        } catch (JiBXException e) {
+            String msg = "Couldn't marshall the identifier to the response output stream: " +
+            e.getMessage();
+            logMetacat.debug(msg);
+            throw new ServiceFailure("4210", msg);
+            
+        }
+    }
+
+    /**
+     * 
+     * @param id
+     * @throws InvalidRequest
+     * @throws InvalidToken
+     * @throws ServiceFailure
+     * @throws NotAuthorized
+     * @throws NotFound
+     * @throws NotImplemented
+     * @throws IOException
+     * @throws JiBXException
+     */
+    private void resolve(String id) throws InvalidRequest, InvalidToken,
+            ServiceFailure, NotAuthorized, NotFound, NotImplemented,
+            IOException, JiBXException {
+        Identifier pid = new Identifier();
+        pid.setValue(id);
+        ObjectLocationList locationList = CNodeService.getInstance(request)
+                .resolve(session, pid);
+        OutputStream out = response.getOutputStream();
+        response.setStatus(200);
+        response.setContentType("text/xml");
+        TypeMarshaller.marshalTypeToOutputStream(locationList, out);
+
+    }
+
+    /**
+     * Set the owner of a resource
+     * 
+     * @param id
+     * @throws InvalidToken
+     * @throws ServiceFailure
+     * @throws NotFound
+     * @throws NotAuthorized
+     * @throws NotImplemented
+     * @throws InvalidRequest
+     * @throws IllegalAccessException
+     * @throws InstantiationException
+     * @throws VersionMismatch 
+     */
+    private void owner(String id) 
+        throws InvalidToken, ServiceFailure, NotFound, NotAuthorized, 
+        NotImplemented, InvalidRequest, InstantiationException, 
+        IllegalAccessException, VersionMismatch {
+
+        Identifier pid = new Identifier();
+        pid.setValue(id);
+
+        long serialVersion = 0L;
+        String serialVersionStr = null;
+        String userIdStr = null;
+        Subject userId = null;
+        
+        // Parse the params out of the multipart form data
+        // Read the incoming data from its Mime Multipart encoding
+        logMetacat.debug("Parsing rights holder parameters from the mime multipart entity");
+        try {
+            collectMultipartParams();
+            
+        } catch (FileUploadException e1) {
+            String msg = "FileUploadException: Couldn't parse the mime multipart information: " +
+            e1.getMessage();
+            logMetacat.debug(msg);
+            throw new ServiceFailure("4490", msg);
+
+        } catch (IOException e1) {
+            String msg = "IOException: Couldn't parse the mime multipart information: " +
+            e1.getMessage();
+            logMetacat.debug(msg);
+            throw new ServiceFailure("4490", msg);
+        
+        } catch (Exception e1) {
+            String msg = "Exception: Couldn't parse the mime multipart information: " +
+            e1.getMessage();
+            logMetacat.debug(msg);
+            throw new ServiceFailure("4490", msg);
+
+        }
+        
+        // get the serialVersion
+        try {
+            serialVersionStr = multipartparams.get("serialVersion").get(0);
+            serialVersion = new Long(serialVersionStr).longValue();
+            
+        } catch (NumberFormatException nfe) {
+            String msg = "The 'serialVersion' must be provided as a positive integer and was not.";
+            logMetacat.error(msg);
+            throw new InvalidRequest("4442", msg);
+                        
+        } catch (NullPointerException e) {
+            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
+            logMetacat.error(msg);
+            throw new InvalidRequest("4442", msg);
+            
+        }
+
+        // get the subject userId that will become the rights holder
+        try {
+            userIdStr = multipartparams.get("userId").get(0);
+            userId = new Subject();
+            userId.setValue(userIdStr);
+                                    
+        } catch (NullPointerException e) {
+            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
+            logMetacat.error(msg);
+            throw new InvalidRequest("4442", msg);
+            
+        }
+
+        // set the rights holder
+        Identifier retPid = CNodeService.getInstance(request).setRightsHolder(session, pid, userId, serialVersion);
+        
+        try {
+            OutputStream out = response.getOutputStream();
+            response.setStatus(200);
+            response.setContentType("text/xml");
+            TypeMarshaller.marshalTypeToOutputStream(retPid, out);
+            
+        } catch (IOException e) {
+            String msg = "Couldn't write the identifier to the response output stream: " +
+                e.getMessage();
+            logMetacat.debug(msg);
+            throw new ServiceFailure("4490", msg);
+        
+        } catch (JiBXException e) {
+            String msg = "Couldn't marshall the identifier to the response output stream: " +
+            e.getMessage();
+            logMetacat.debug(msg);
+            throw new ServiceFailure("4490", msg);
+            
+        }
+    }
+
+    /**
+     * Processes the authorization check for given id
+     * 
+     * @param id
+     * @return
+     * @throws ServiceFailure
+     * @throws InvalidToken
+     * @throws NotFound
+     * @throws NotAuthorized
+     * @throws NotImplemented
+     * @throws InvalidRequest
+     */
+    private boolean isAuthorized(String id) throws ServiceFailure,
+            InvalidToken, NotFound, NotAuthorized, NotImplemented,
+            InvalidRequest {
+        Identifier pid = new Identifier();
+        pid.setValue(id);
+        String permission = params.get("action")[0];
+        boolean result = CNodeService.getInstance(request).isAuthorized(
+                session, pid, Permission.convert(permission));
+        response.setStatus(200);
+        response.setContentType("text/xml");
+        return result;
+    }
+
+    /**
+     * Register System Metadata without data or metadata object
+     * 
+     * @param pid
+     *            identifier for System Metadata entry
+     * @throws JiBXException
+     * @throws FileUploadException
+     * @throws IOException
+     * @throws InvalidRequest
+     * @throws ServiceFailure
+     * @throws InvalidSystemMetadata
+     * @throws NotAuthorized
+     * @throws NotImplemented
+     * @throws IllegalAccessException
+     * @throws InstantiationException
+     * @throws InvalidToken 
+     */
+    protected void registerSystemMetadata()
+            throws ServiceFailure, InvalidRequest, IOException,
+            FileUploadException, JiBXException, NotImplemented, NotAuthorized,
+            InvalidSystemMetadata, InstantiationException,
+            IllegalAccessException, InvalidToken {
+    	
+    	// Read the incoming data from its Mime Multipart encoding
+        Map<String, File> files = collectMultipartFiles();
+        
+    	// get the encoded pid string from the body and make the object
+        String pidString = multipartparams.get("pid").get(0);
+        Identifier pid = new Identifier();
+        pid.setValue(pidString);
+        
+        logMetacat.debug("registerSystemMetadata: " + pid);
+
+        // get the system metadata from the request
+        File smFile = files.get("sysmeta");
+        FileInputStream sysmeta = new FileInputStream(smFile);
+        SystemMetadata systemMetadata = TypeMarshaller.unmarshalTypeFromStream(SystemMetadata.class, sysmeta);
+
+        logMetacat.debug("registering system metadata with pid " + pid.getValue());
+        Identifier retGuid = CNodeService.getInstance(request).registerSystemMetadata(session, pid, systemMetadata);
+
+        OutputStream out = response.getOutputStream();
+        response.setStatus(200);
+        response.setContentType("text/xml");
+        
+        TypeMarshaller.marshalTypeToOutputStream(retGuid, out);
+
+    }
+
+    /**
+     * set the access perms on a document
+     * 
+     * @throws JiBXException
+     * @throws InvalidRequest
+     * @throws NotImplemented
+     * @throws NotAuthorized
+     * @throws NotFound
+     * @throws ServiceFailure
+     * @throws InvalidToken
+     * @throws IllegalAccessException
+     * @throws InstantiationException
+     * @throws IOException
+     * @throws SAXException
+     * @throws ParserConfigurationException
+     * @throws VersionMismatch 
+     */
+    protected void setAccess(String pid) throws JiBXException, InvalidToken,
+            ServiceFailure, NotFound, NotAuthorized, NotImplemented,
+            InvalidRequest, IOException, InstantiationException,
+            IllegalAccessException, ParserConfigurationException, SAXException, VersionMismatch {
+
+        long serialVersion = 0L;
+        String serialVersionStr = null;
+        
+        // parse the accessPolicy
+        Map<String, File> files = collectMultipartFiles();        
+        AccessPolicy accessPolicy = TypeMarshaller.unmarshalTypeFromFile(AccessPolicy.class, files.get("accessPolicy"));;
+
+        // get the serialVersion
+        try {
+            serialVersionStr = multipartparams.get("serialVersion").get(0);
+            serialVersion = new Long(serialVersionStr).longValue();
+
+        } catch (NumberFormatException nfe) {
+            String msg = "The 'serialVersion' must be provided as a positive integer and was not.";
+            logMetacat.error(msg);
+            throw new InvalidRequest("4402", msg);
+            
+        } catch (NullPointerException e) {
+            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
+            logMetacat.error(msg);
+            throw new InvalidRequest("4402", msg);
+
+        }
+
+        Identifier id = new Identifier();
+        id.setValue(pid);
+
+        CNodeService.getInstance(request).setAccessPolicy(session, id,
+                accessPolicy, serialVersion);
+
+    }
+
+    /**
+     * List the objects
+     * 
+     * @throws NotImplemented
+     * @throws InvalidRequest
+     * @throws NotAuthorized
+     * @throws ServiceFailure
+     * @throws InvalidToken
+     * @throws NotFound
+     * @throws IOException
+     * @throws JiBXException
+     * @throws Exception
+     */
+    private void listObjects() throws InvalidToken, ServiceFailure,
+            NotAuthorized, InvalidRequest, NotImplemented, NotFound,
+            IOException, JiBXException {
+
+        Date startTime = null;
+        Date endTime = null;
+        ObjectFormatIdentifier formatId = null;
+        boolean replicaStatus = true;
+        int start = 0;
+        int count = 1000;
+        Enumeration<String> paramlist = request.getParameterNames();
+        while (paramlist.hasMoreElements()) {
+            // parse the params and make the call
+            String name = paramlist.nextElement();
+            String[] values = request.getParameterValues(name);
+            String value = null;
+            if (values != null && values.length > 0) {
+            	value = values[0];
+            	value = EncodingUtilities.decodeString(value);
+            }
+
+            if (name.equals("fromDate") && value != null) {
+                try {
+                    startTime = DateTimeMarshaller.deserializeDateToUTC(value);
+                } catch (Exception e) {
+                    // if we can't parse it, just don't use the startTime param
+                    logMetacat.warn("Could not parse fromDate: " + value);
+                    startTime = null;
+                }
+            } else if (name.equals("toDate") && value != null) {
+                try {
+                    endTime = DateTimeMarshaller.deserializeDateToUTC(value);
+                } catch (Exception e) {
+                    // if we can't parse it, just don't use the endTime param
+                    logMetacat.warn("Could not parse toDate: " + value);
+                    endTime = null;
+                }
+            } else if (name.equals("formatId") && value != null) {
+            	formatId = new ObjectFormatIdentifier();
+            	formatId.setValue(value);
+            } else if (name.equals("replicaStatus") && value != null) {
+                replicaStatus = Boolean.parseBoolean(value);
+            } else if (name.equals("start") && value != null) {
+                start = Integer.valueOf(value);
+            } else if (name.equals("count") && value != null) {
+                count = Integer.valueOf(value);
+            }
+        }
+        // make the call
+        logMetacat.debug("session: " + session + " fromDate: " + startTime
+                + " toDate: " + endTime + " formatId: " + formatId
+                + " replicaStatus: " + replicaStatus + " start: " + start
+                + " count: " + count);        
+
+        // get the list
+        ObjectList ol = CNodeService.getInstance(request).listObjects(session,
+                startTime, endTime, formatId, replicaStatus, start, count);
+
+        // send it
+        OutputStream out = response.getOutputStream();
+        response.setStatus(200);
+        response.setContentType("text/xml");
+
+        // style the object with a processing directive
+        String stylesheet = null;
+        try {
+            stylesheet = PropertyService.getProperty("dataone.types.xsl");
+        } catch (PropertyNotFoundException e) {
+            logMetacat.warn("Could not locate DataONE types XSLT: "
+                    + e.getMessage());
+        }
+
+        // Serialize and write it to the output stream
+        TypeMarshaller.marshalTypeToOutputStream(ol, out, stylesheet);
+    }
+
+    /**
+     * Pass the request to get node replication authorization to CNodeService
+     * 
+     * @param pid
+     *            the identifier of the object to get authorization to replicate
+     * 
+     * @throws NotImplemented
+     * @throws NotAuthorized
+     * @throws InvalidToken
+     * @throws ServiceFailure
+     * @throws NotFound
+     * @throws InvalidRequest
+     */
+    public boolean isNodeAuthorized(String pid) throws NotImplemented,
+            NotAuthorized, InvalidToken, ServiceFailure, NotFound,
+            InvalidRequest {
+
+        boolean result = false;
+        Subject targetNodeSubject = new Subject();
+        String nodeSubject = null;
+        String replPermission = null;
+
+        // get the pid
+        Identifier identifier = new Identifier();
+        identifier.setValue(pid);
+
+        // get the target node subject
+        try {
+            nodeSubject = params.get("targetNodeSubject")[0];
+            targetNodeSubject.setValue(nodeSubject);
+
+        } catch (NullPointerException e) {
+            String msg = "The 'targetNodeSubject' must be provided as a parameter and was not.";
+            logMetacat.error(msg);
+            throw new InvalidRequest("4873", msg);
+
+        }
+
+        result = CNodeService.getInstance(request).isNodeAuthorized(session, targetNodeSubject, identifier);
+
+        response.setStatus(200);
+        response.setContentType("text/xml");
+        return result;
+
+    }
+
+    /**
+     * Pass the request to set the replication policy to CNodeService
+     * 
+     * @param pid
+     *            the identifier of the object to set the replication policy on
+     * 
+     * @throws NotImplemented
+     * @throws NotFound
+     * @throws NotAuthorized
+     * @throws ServiceFailure
+     * @throws InvalidRequest
+     * @throws InvalidToken
+     * @throws IOException
+     * @throws InstantiationException
+     * @throws IllegalAccessException
+     * @throws JiBXException
+     * @throws VersionMismatch 
+     */
+    public boolean setReplicationPolicy(String pid) throws NotImplemented,
+            NotFound, NotAuthorized, ServiceFailure, InvalidRequest,
+            InvalidToken, IOException, InstantiationException,
+            IllegalAccessException, JiBXException, VersionMismatch {
+
+        boolean result = false;
+        long serialVersion = 0L;
+        String serialVersionStr = null;
+
+        Identifier identifier = new Identifier();
+        identifier.setValue(pid);
+
+        // parse the policy
+        Map<String, File> files = collectMultipartFiles();        
+        ReplicationPolicy policy = TypeMarshaller.unmarshalTypeFromFile(ReplicationPolicy.class, files.get("policy"));
+
+        // get the serialVersion
+        try {
+            serialVersionStr = multipartparams.get("serialVersion").get(0);
+            serialVersion = new Long(serialVersionStr).longValue();
+
+        } catch (NullPointerException e) {
+            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
+            logMetacat.error(msg);
+            throw new InvalidRequest("4883", msg);
+
+        }
+        result = CNodeService.getInstance(request).setReplicationPolicy(
+                session, identifier, policy, serialVersion);
+        response.setStatus(200);
+        response.setContentType("text/xml");
+        return result;
+
+    }
+    
+    /**
+     * Update the system metadata for a given pid, setting it to be obsoleted
+     * by the obsoletedByPid
+     *  
+     * @param pid
+     * @return
+     * @throws NotImplemented
+     * @throws NotFound
+     * @throws NotAuthorized
+     * @throws ServiceFailure
+     * @throws InvalidRequest
+     * @throws InvalidToken
+     * @throws InstantiationException
+     * @throws IllegalAccessException
+     * @throws VersionMismatch
+     */
+    public boolean setObsoletedBy(String pid) 
+        throws NotImplemented, NotFound, NotAuthorized, ServiceFailure, 
+        InvalidRequest, InvalidToken, InstantiationException, 
+        IllegalAccessException, VersionMismatch {
+
+        boolean result = false;
+        long serialVersion = 0L;
+        String serialVersionStr = null;
+
+        Identifier identifier = new Identifier();
+        identifier.setValue(pid);
+        String obsoletedByPidString = null;
+        Identifier obsoletedByPid = null;
+
+        // Parse the params out of the multipart form data
+        // Read the incoming data from its Mime Multipart encoding
+        logMetacat.debug("Parsing rights holder parameters from the mime multipart entity");
+        try {
+            collectMultipartParams();
+            
+        } catch (FileUploadException e1) {
+            String msg = "FileUploadException: Couldn't parse the mime multipart information: " +
+            e1.getMessage();
+            logMetacat.debug(msg);
+            throw new ServiceFailure("4941", msg);
+
+        } catch (IOException e1) {
+            String msg = "IOException: Couldn't parse the mime multipart information: " +
+            e1.getMessage();
+            logMetacat.debug(msg);
+            throw new ServiceFailure("4941", msg);
+        
+        } catch (Exception e1) {
+            String msg = "Exception: Couldn't parse the mime multipart information: " +
+            e1.getMessage();
+            logMetacat.debug(msg);
+            throw new ServiceFailure("4941", msg);
+
+        }
+
+        // get the obsoletedByPid
+        try {
+            obsoletedByPidString = multipartparams.get("obsoletedByPid").get(0);
+            obsoletedByPid = new Identifier();
+            obsoletedByPid.setValue(obsoletedByPidString);
+        } catch (NullPointerException e) {
+            String msg = "The 'obsoletedByPid' must be provided as a parameter and was not.";
+            logMetacat.error(msg);
+            throw new InvalidRequest("4883", msg);
+        }
+
+        // get the serialVersion
+        try {
+            serialVersionStr = multipartparams.get("serialVersion").get(0);
+            serialVersion = new Long(serialVersionStr).longValue();
+            
+        } catch (NumberFormatException nfe) {
+            String msg = "The 'serialVersion' must be provided as a positive integer and was not.";
+            logMetacat.error(msg);
+            throw new InvalidRequest("4942", msg);
+                        
+        } catch (NullPointerException e) {
+            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
+            logMetacat.error(msg);
+            throw new InvalidRequest("4942", msg);
+            
+        }
+        result = CNodeService.getInstance(request).setObsoletedBy(session,
+            identifier, obsoletedByPid, serialVersion);
+        response.setStatus(200);
+        response.setContentType("text/xml");
+        return result;
+
+    }
+    
+    /**
+     * Delete the replica entry with the given nodeId for the given pid
+     * 
+     * @param pid
+     * @return
+     * @throws NotImplemented
+     * @throws NotFound
+     * @throws NotAuthorized
+     * @throws ServiceFailure
+     * @throws InvalidRequest
+     * @throws InvalidToken
+     * @throws InstantiationException
+     * @throws IllegalAccessException
+     * @throws VersionMismatch
+     */
+    public boolean deleteReplica(String pid) 
+        throws NotImplemented, NotFound, NotAuthorized, ServiceFailure, 
+        InvalidRequest, InvalidToken, InstantiationException, 
+        IllegalAccessException, VersionMismatch {
+
+        boolean result = false;
+        long serialVersion = 0L;
+        String serialVersionStr = null;
+
+        Identifier identifier = new Identifier();
+        identifier.setValue(pid);
+
+        NodeReference nodeId = null;
+        
+        // Parse the params out of the multipart form data
+        // Read the incoming data from its Mime Multipart encoding
+        logMetacat.debug("Parsing delete replica parameters from the mime multipart entity");
+        try {
+            collectMultipartParams();
+            
+        } catch (FileUploadException e1) {
+            String msg = "FileUploadException: Couldn't parse the mime multipart information: " +
+            e1.getMessage();
+            logMetacat.debug(msg);
+            throw new ServiceFailure("4951", msg);
+
+        } catch (IOException e1) {
+            String msg = "IOException: Couldn't parse the mime multipart information: " +
+            e1.getMessage();
+            logMetacat.debug(msg);
+            throw new ServiceFailure("4951", msg);
+        
+        } catch (Exception e1) {
+            String msg = "Exception: Couldn't parse the mime multipart information: " +
+            e1.getMessage();
+            logMetacat.debug(msg);
+            throw new ServiceFailure("4951", msg);
+
+        }
+        
+        // get the nodeId param
+        try {
+            String nodeIdString = multipartparams.get("nodeId").get(0);
+            nodeId = new NodeReference();
+            nodeId.setValue(nodeIdString);
+            
+        } catch (NullPointerException e) {
+            String msg = "The 'nodeId' must be provided as a parameter and was not.";
+            logMetacat.error(msg);
+            throw new InvalidRequest("4952", msg);
+        }
+
+        // get the serialVersion
+        try {
+            serialVersionStr = multipartparams.get("serialVersion").get(0);
+            serialVersion = new Long(serialVersionStr).longValue();
+            
+        } catch (NumberFormatException nfe) {
+            String msg = "The 'serialVersion' must be provided as a positive integer and was not.";
+            logMetacat.error(msg);
+            throw new InvalidRequest("4952", msg);
+                        
+        } catch (NullPointerException e) {
+            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
+            logMetacat.error(msg);
+            throw new InvalidRequest("4952", msg);
+            
+        }
+        result = CNodeService.getInstance(request).deleteReplicationMetadata(
+                session, identifier, nodeId, serialVersion);
+        response.setStatus(200);
+        response.setContentType("text/xml");
+        return result;
+
+    }
+
+    /**
+     * Pass the request to set the replication status to CNodeService
+     * 
+     * @param pid
+     *            the identifier of the object to set the replication status on
+     * 
+     * @throws ServiceFailure
+     * @throws NotImplemented
+     * @throws InvalidToken
+     * @throws NotAuthorized
+     * @throws InvalidRequest
+     * @throws NotFound
+     * @throws JiBXException 
+     * @throws IllegalAccessException 
+     * @throws InstantiationException 
+     * @throws IOException 
+     */
+    public boolean setReplicationStatus(String pid) throws ServiceFailure,
+            NotImplemented, InvalidToken, NotAuthorized, InvalidRequest,
+            NotFound {
+        
+        boolean result = false;
+        Identifier identifier = new Identifier();
+        identifier.setValue(pid);
+        BaseException failure = null;
+        ReplicationStatus status = null;
+        String replicationStatus = null;
+        NodeReference targetNodeRef = null;
+        String targetNode = null;
+
+        // Parse the params out of the multipart form data
+        // Read the incoming data from its Mime Multipart encoding
+        logMetacat.debug("Parsing ReplicaStatus from the mime multipart entity");
+
+        try {
+        	// parse the policy
+            Map<String, File> files = collectMultipartFiles();        
+            failure = ExceptionHandler.deserializeXml(new FileInputStream(files.get("failure")), 
+                    "Replication failed for an unknown reason.");
+            
+        } catch (Exception e2) {
+            throw new ServiceFailure("4700", "Couldn't resolve the multipart request: " +
+                e2.getMessage());
+            
+        }
+        
+        // get the replication status param
+        try {
+            replicationStatus = multipartparams.get("status").get(0);
+            status = ReplicationStatus.convert(replicationStatus);
+
+        } catch (NullPointerException npe) {
+
+            logMetacat.debug("The 'status' parameter was not found in the "
+                    + "multipartparams map.  Trying the params map.");
+
+            try {
+                replicationStatus = params.get("status")[0];
+                status = ReplicationStatus.convert(replicationStatus
+                        .toLowerCase());
+
+            } catch (Exception e) {
+                String msg = "The 'status' must be provided as a parameter and was not.";
+                logMetacat.error(msg);
+                throw new InvalidRequest("4730", msg);
+
+            }
+
+        }
+
+        // get the target node reference param
+        try {
+            targetNode = multipartparams.get("nodeRef").get(0);
+            targetNodeRef = new NodeReference();
+            targetNodeRef.setValue(targetNode);
+
+        } catch (NullPointerException e) {
+            logMetacat.debug("The 'nodeRef' parameter was not found in the "
+                    + "multipartparams map.  Trying the params map.");
+
+            try {
+                targetNode = params.get("nodeRef")[0];
+                targetNodeRef = new NodeReference();
+                targetNodeRef.setValue(targetNode);
+
+            } catch (Exception e1) {
+                String msg = "The 'nodeRef' must be provided as a parameter and was not.";
+                logMetacat.error(msg);
+                throw new InvalidRequest("4730", msg);
+
+            }
+
+        }
+
+        result = CNodeService.getInstance(request).setReplicationStatus(
+                session, identifier, targetNodeRef, status, failure);
+        response.setStatus(200);
+        response.setContentType("text/xml");
+        return result;
+
+    }
+
+    /**
+     * Pass the request to update the replication metadata to CNodeService
+     * 
+     * @param pid
+     *            the identifier of the object to update the replication
+     *            metadata on
+     * 
+     * @throws ServiceFailure
+     * @throws NotImplemented
+     * @throws InvalidToken
+     * @throws NotAuthorized
+     * @throws InvalidRequest
+     * @throws NotFound
+     * @throws VersionMismatch 
+     * @throws JiBXException 
+     * @throws IOException 
+     * @throws IllegalAccessException 
+     * @throws InstantiationException 
+     */
+    public boolean updateReplicationMetadata(String pid) throws ServiceFailure,
+            NotImplemented, InvalidToken, NotAuthorized, InvalidRequest,
+            NotFound, VersionMismatch, InstantiationException, IllegalAccessException, IOException, JiBXException {
+
+        boolean result = false;
+        long serialVersion = 0L;
+        String serialVersionStr = null;
+        Identifier identifier = new Identifier();
+        identifier.setValue(pid);
+
+        // parse the replica
+        Map<String, File> files = collectMultipartFiles();        
+        Replica replica = TypeMarshaller.unmarshalTypeFromFile(Replica.class, files.get("replicaMetadata"));
+
+        // get the serialVersion
+        try {
+            serialVersionStr = multipartparams.get("serialVersion").get(0);
+            serialVersion = new Long(serialVersionStr).longValue();
+
+        } catch (NullPointerException e) {
+            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
+            logMetacat.error(msg);
+            throw new InvalidRequest("4853", msg);
+
+        }
+
+        result = CNodeService.getInstance(request).updateReplicationMetadata(
+                session, identifier, replica, serialVersion);
+        response.setStatus(200);
+        response.setContentType("text/xml");
+        return result;
+
+    }
+
+}

Property changes on: src/edu/ucsb/nceas/metacat/restservice/v1/CNResourceHandler.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property
Index: src/edu/ucsb/nceas/metacat/restservice/v1/MNRestServlet.java
===================================================================
--- src/edu/ucsb/nceas/metacat/restservice/v1/MNRestServlet.java	(nonexistent)
+++ src/edu/ucsb/nceas/metacat/restservice/v1/MNRestServlet.java	(revision 8810)
@@ -0,0 +1,50 @@
+/**
+ *  '$RCSfile$'
+ *  Copyright: 2000 Regents of the University of California and the
+ *              National Center for Ecological Analysis and Synthesis
+ *
+ *   '$Author$'
+ *     '$Date$'
+ *
+ * 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.v1;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import edu.ucsb.nceas.metacat.restservice.D1ResourceHandler;
+import edu.ucsb.nceas.metacat.restservice.D1RestServlet;
+
+
+/**
+ * Routes MN REST service requests to the appropriate handler
+ *  
+ */
+public class MNRestServlet extends D1RestServlet {
+    
+	/**
+	 * Provide an MNResourceHandler subclass of D1ResourceHandler
+	 */
+	@Override
+    protected D1ResourceHandler createHandler(HttpServletRequest request, HttpServletResponse response) 
+    	throws ServletException, IOException {
+        return new MNResourceHandler(getServletContext(), request, response);
+    }
+
+}

Property changes on: src/edu/ucsb/nceas/metacat/restservice/v1/MNRestServlet.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property
Index: src/edu/ucsb/nceas/metacat/restservice/v2/MNResourceHandler.java
===================================================================
--- src/edu/ucsb/nceas/metacat/restservice/v2/MNResourceHandler.java	(nonexistent)
+++ src/edu/ucsb/nceas/metacat/restservice/v2/MNResourceHandler.java	(revision 8810)
@@ -0,0 +1,1453 @@
+/**
+ *  '$RCSfile$'
+ *  Copyright: 2011 Regents of the University of California and the
+ *              National Center for Ecological Analysis and Synthesis
+ *
+ *   '$Author$'
+ *     '$Date$'
+ *
+ * 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.v2;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.commons.fileupload.FileUploadException;
+import org.apache.commons.io.IOUtils;
+import org.apache.log4j.Logger;
+import org.dataone.client.v2.formats.ObjectFormatInfo;
+import org.dataone.mimemultipart.MultipartRequest;
+import org.dataone.mimemultipart.MultipartRequestResolver;
+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.NotFound;
+import org.dataone.service.exceptions.NotImplemented;
+import org.dataone.service.exceptions.ServiceFailure;
+import org.dataone.service.exceptions.SynchronizationFailed;
+import org.dataone.service.exceptions.UnsupportedType;
+import org.dataone.service.types.v1.Checksum;
+import org.dataone.service.types.v1.DescribeResponse;
+import org.dataone.service.types.v1.Event;
+import org.dataone.service.types.v1.Identifier;
+import org.dataone.service.types.v2.Log;
+import org.dataone.service.types.v2.Node;
+import org.dataone.service.types.v1.NodeReference;
+import org.dataone.service.types.v1.ObjectFormatIdentifier;
+import org.dataone.service.types.v1.ObjectList;
+import org.dataone.service.types.v1.Permission;
+import org.dataone.service.types.v2.SystemMetadata;
+import org.dataone.service.types.v1_1.QueryEngineDescription;
+import org.dataone.service.types.v1_1.QueryEngineList;
+import org.dataone.service.util.Constants;
+import org.dataone.service.util.DateTimeMarshaller;
+import org.dataone.service.util.ExceptionHandler;
+import org.dataone.service.util.TypeMarshaller;
+import org.jibx.runtime.JiBXException;
+import org.xml.sax.SAXException;
+
+import edu.ucsb.nceas.metacat.common.query.stream.ContentTypeInputStream;
+import edu.ucsb.nceas.metacat.dataone.MNodeService;
+import edu.ucsb.nceas.metacat.properties.PropertyService;
+import edu.ucsb.nceas.metacat.restservice.D1ResourceHandler;
+import edu.ucsb.nceas.metacat.util.DeleteOnCloseFileInputStream;
+import edu.ucsb.nceas.utilities.PropertyNotFoundException;
+
+/**
+ * MN REST service implementation handler
+ * 
+ * ******************
+ * MNCore -- DONE
+ * 		ping() - GET /d1/mn/monitor/ping
+ * 		log() - GET /d1/mn/log
+ * 		**getObjectStatistics() - GET /d1/mn/monitor/object
+ * 		getOperationsStatistics - GET /d1/mn/monitor/event
+ * 		**getStatus - GET /d1/mn/monitor/status
+ * 		getCapabilities() - GET /d1/mn/ and /d1/mn/node
+ * 	
+ * 	MNRead -- DONE
+ * 		get() - GET /d1/mn/object/PID
+ * 		getSystemMetadata() - GET /d1/mn/meta/PID
+ * 		describe() - HEAD /d1/mn/object/PID
+ * 		getChecksum() - GET /d1/mn/checksum/PID
+ * 		listObjects() - GET /d1/mn/object
+ * 		synchronizationFailed() - POST /d1/mn/error
+ * 	
+ * 	MNAuthorization -- DONE
+ * 		isAuthorized() - GET /d1/mn/isAuthorized/PID
+ * 		setAccessPolicy() - PUT /d1/mn/accessRules/PID
+ * 		
+ * 	MNStorage - DONE
+ * 		create() - POST /d1/mn/object/PID
+ * 		update() - PUT /d1/mn/object/PID
+ * 		delete() - DELETE /d1/mn/object/PID
+ * 		archive() - PUT /d1/mn/archive/PID
+
+ *    systemMetadataChanged() - POST /dirtySystemMetadata/PID
+ * 	
+ * 	MNReplication
+ * 		replicate() - POST /d1/mn/replicate
+ *    getReplica() - GET /d1/mn/replica
+ * 
+ * ******************
+ * @author leinfelder
+ *
+ */
+public class MNResourceHandler extends D1ResourceHandler {
+
+    // MN-specific API Resources
+    protected static final String RESOURCE_MONITOR = "monitor";
+    protected static final String RESOURCE_REPLICATE = "replicate";
+    protected static final String RESOURCE_REPLICAS = "replica";
+    protected static final String RESOURCE_NODE = "node";
+    protected static final String RESOURCE_ERROR = "error";
+    protected static final String RESOURCE_META_CHANGED = "dirtySystemMetadata";
+    protected static final String RESOURCE_GENERATE_ID = "generate";
+    protected static final String RESOURCE_PUBLISH = "publish";
+    protected static final String RESOURCE_PACKAGE = "package";
+    protected static final String RESOURCE_VIEWS = "views";
+
+
+    
+    // shared executor
+	private static ExecutorService executor = null;
+
+	static {
+		// use a shared executor service with nThreads == one less than available processors
+    	int availableProcessors = Runtime.getRuntime().availableProcessors();
+        int nThreads = availableProcessors * 1;
+        nThreads--;
+        nThreads = Math.max(1, nThreads);
+    	executor = Executors.newFixedThreadPool(nThreads);	
+	}
+	
+    /**
+     * Initializes new instance by setting servlet context,request and response
+     * */
+    public MNResourceHandler(ServletContext servletContext,
+            HttpServletRequest request, HttpServletResponse response) {
+    	super(servletContext, request, response);
+        logMetacat = Logger.getLogger(MNResourceHandler.class);
+    }
+    
+    @Override
+    protected boolean isD1Enabled() {
+    	
+    	boolean enabled = false;
+    	try {
+			enabled = Boolean.parseBoolean(PropertyService.getProperty("dataone.mn.services.enabled"));
+		} catch (PropertyNotFoundException e) {
+			logMetacat.error("Could not check if DataONE is enabled: " + e.getMessage());
+		}
+    	
+    	return enabled;	
+    }
+
+    /**
+     * This function is called from REST API servlet and handles each request to the servlet 
+     * 
+     * @param httpVerb (GET, POST, PUT or DELETE)
+     */
+    @Override
+    public void handle(byte httpVerb) {
+    	// prepare the handler
+    	super.handle(httpVerb);
+    	
+        try {
+        	
+        	// only service requests if we have D1 configured
+        	if (!isD1Enabled()) {
+        		ServiceFailure se = new ServiceFailure("0000", "DataONE services are not enabled on this node");
+                serializeException(se, response.getOutputStream());
+                return;
+        	}
+        	
+        	// get the resource
+            String resource = request.getPathInfo();
+            resource = resource.substring(resource.indexOf("/") + 1);
+            
+            // default to node info
+            if (resource.equals("")) {
+                resource = RESOURCE_NODE;
+            }
+            
+            // get the rest of the path info
+            String extra = null;
+                        
+            logMetacat.debug("handling verb " + httpVerb + " request with resource '" + resource + "'");
+            logMetacat.debug("resource: '" + resource + "'");
+            boolean status = false;
+            
+            if (resource != null) {
+
+                if (resource.startsWith(RESOURCE_NODE)) {
+                    // node response
+                    node();
+                    status = true;
+                } else if (resource.startsWith(RESOURCE_IS_AUTHORIZED)) {
+                    if (httpVerb == GET) {
+                    	// after the command
+                        extra = parseTrailing(resource, RESOURCE_IS_AUTHORIZED);
+	                	// check the access rules
+	                    isAuthorized(extra);
+	                    status = true;
+	                    logMetacat.debug("done getting access");
+                    }
+                } else if (resource.startsWith(RESOURCE_META)) {
+                    logMetacat.debug("Using resource 'meta'");
+                    // get
+                    if (httpVerb == GET) {
+                    	// after the command
+                        extra = parseTrailing(resource, RESOURCE_META);
+                        getSystemMetadataObject(extra);
+                        status = true;
+                    }
+                    
+                } else if (resource.startsWith(RESOURCE_OBJECTS)) {
+                    logMetacat.debug("Using resource 'object'");
+                    // after the command
+                    extra = parseTrailing(resource, RESOURCE_OBJECTS);
+                    logMetacat.debug("objectId: " + extra);
+                    logMetacat.debug("verb:" + httpVerb);
+
+                    if (httpVerb == GET) {
+                        getObject(extra);
+                        status = true;
+                    } else if (httpVerb == POST) {
+                    	// part of the params, not the URL
+                        putObject(null, FUNCTION_NAME_INSERT);
+                        status = true;
+                    } else if (httpVerb == PUT) {
+                        putObject(extra, FUNCTION_NAME_UPDATE);
+                        status = true;
+                    } else if (httpVerb == DELETE) {
+                        deleteObject(extra);
+                        status = true;
+                    } else if (httpVerb == HEAD) {
+                        describeObject(extra);
+                        status = true;
+                    }
+                  
+                } else if (resource.startsWith(RESOURCE_LOG)) {
+                    logMetacat.debug("Using resource 'log'");
+                    // handle log events
+                    if (httpVerb == GET) {
+                        getLog();
+                        status = true;
+                    }
+                } else if (resource.startsWith(Constants.RESOURCE_ARCHIVE)) {
+                    logMetacat.debug("Using resource " + Constants.RESOURCE_ARCHIVE);
+                    // handle archive events
+                    if (httpVerb == PUT) {
+                        extra = parseTrailing(resource, Constants.RESOURCE_ARCHIVE);
+                        archive(extra);
+                        status = true;
+                    }
+                } else if (resource.startsWith(Constants.RESOURCE_CHECKSUM)) {
+                    logMetacat.debug("Using resource 'checksum'");
+                    // handle checksum requests
+                    if (httpVerb == GET) {
+                    	// after the command
+                        extra = parseTrailing(resource, Constants.RESOURCE_CHECKSUM);
+                        checksum(extra);
+                        status = true;
+                    }
+                } else if (resource.startsWith(RESOURCE_MONITOR)) {
+                    // there are various parts to monitoring
+                    if (httpVerb == GET) {
+                    	// after the command
+                        extra = parseTrailing(resource, RESOURCE_MONITOR);
+                        
+                        // ping
+                        if (extra.toLowerCase().equals("ping")) {
+                            logMetacat.debug("processing ping request");
+                            Date result = MNodeService.getInstance(request).ping();
+                            // TODO: send to output	
+                            status = true;
+                            
+                        }
+                        
+                    }
+                } else if (resource.startsWith(RESOURCE_REPLICATE)) {
+                	if (httpVerb == POST) {
+	                    logMetacat.debug("processing replicate request");
+	                    replicate();
+	                    status = true;
+                	}
+                } else if (resource.startsWith(RESOURCE_ERROR)) {
+	                // sync error
+	                if (httpVerb == POST) {
+	                    syncError();
+	                    status = true;
+	                }
+                } else if (resource.startsWith(RESOURCE_META_CHANGED)) {
+                    // system metadata changed
+                    if (httpVerb == POST) {
+                        systemMetadataChanged();
+                        status = true;
+                    }
+                } else if (resource.startsWith(RESOURCE_REPLICAS)) {
+                    // get replica
+                    if (httpVerb == GET) {
+                        extra = parseTrailing(resource, RESOURCE_REPLICAS);
+                        getReplica(extra);
+                        status = true;
+                    }
+                } else if (resource.startsWith(RESOURCE_QUERY)) {
+	                logMetacat.debug("Using resource " + RESOURCE_QUERY);
+	                // after the command
+	                extra = parseTrailing(resource, RESOURCE_QUERY);
+	                logMetacat.debug("query extra: " + extra);
+
+	                String engine = null;
+	                String query = null;
+
+	                if (extra != null) {
+		                // get the engine
+		                int engineIndex = extra.length();
+		                if (extra.indexOf("/") > -1) {
+		                	engineIndex = extra.indexOf("/");
+		                }
+		                engine = extra.substring(0, engineIndex);
+		                logMetacat.debug("query engine: " + engine);
+		                
+		                // get the query if it is there
+		                query = extra.substring(engineIndex, extra.length());
+		                if (query != null && query.length() == 0) {
+		                	query = null;
+		                } else {
+		                	if (query.startsWith("/")) {
+		                		query = query.substring(1);
+		                    }
+		                	// remove the query delimiter if it exists
+		                	if (query.startsWith("?")) {
+		                		query = query.substring(1);
+		                    }
+		                }
+		                logMetacat.debug("query: " + query);
+
+	                }
+	                logMetacat.debug("verb:" + httpVerb);
+	                if (httpVerb == GET) {
+	                    doQuery(engine, query);
+	                    status = true;
+	                }
+                } else if (resource.startsWith(RESOURCE_GENERATE_ID)) {
+                	// generate an id
+                    if (httpVerb == POST) {
+                        generateIdentifier();
+                        status = true;
+                    }
+                } else if (resource.startsWith(RESOURCE_PUBLISH)) {
+                    logMetacat.debug("Using resource: " + RESOURCE_PUBLISH);
+                    // PUT
+                    if (httpVerb == PUT) {
+                    	// after the command
+                        extra = parseTrailing(resource, RESOURCE_PUBLISH);
+                        publish(extra);
+                        status = true;
+                    }  
+                } else if (resource.startsWith(RESOURCE_PACKAGE)) {
+                    logMetacat.debug("Using resource: " + RESOURCE_PACKAGE);
+                    // after the command
+                    extra = parseTrailing(resource, RESOURCE_PACKAGE);
+                    
+                    String format = null;
+	                String pid = null;
+
+	                if (extra != null) {
+		                // get the format
+		                int formatIndex = extra.length();
+		                if (extra.indexOf("/") > -1) {
+		                	formatIndex = extra.indexOf("/");
+		                }
+		                format = extra.substring(0, formatIndex);
+		                logMetacat.debug("package format: " + format);
+		                
+		                // get the pid if it is there
+		                pid = extra.substring(formatIndex, extra.length());
+		                if (pid != null && pid.length() == 0) {
+		                	pid = null;
+		                } else {
+		                	if (pid.startsWith("/")) {
+		                		pid = pid.substring(1);
+		                    }
+		                }
+		                logMetacat.debug("pid: " + pid);
+
+	                }
+                    
+                    // get
+                    if (httpVerb == GET) {
+                        
+                        getPackage(format, pid);
+                        status = true;
+                    }  
+                } else if (resource.startsWith(RESOURCE_VIEWS)) {
+	                logMetacat.debug("Using resource " + RESOURCE_VIEWS);
+	                // after the command
+	                extra = parseTrailing(resource, RESOURCE_VIEWS);
+	                logMetacat.debug("view extra: " + extra);
+
+	                String format = null;
+	                String pid = null;
+
+	                if (extra != null) {
+		                // get the format
+		                int formatIndex = extra.length();
+		                if (extra.indexOf("/") > -1) {
+		                	formatIndex = extra.indexOf("/");
+		                }
+		                format = extra.substring(0, formatIndex);
+		                logMetacat.debug("view format: " + format);
+		                
+		                // get the pid if it is there
+		                pid = extra.substring(formatIndex, extra.length());
+		                if (pid != null && pid.length() == 0) {
+		                	pid = null;
+		                } else {
+		                	if (pid.startsWith("/")) {
+		                		pid = pid.substring(1);
+		                    }
+		                }
+		                logMetacat.debug("pid: " + pid);
+
+	                }
+	                logMetacat.debug("verb:" + httpVerb);
+	                if (httpVerb == GET) {
+	                    doViews(format, pid);
+	                    status = true;
+	                }
+                } 
+                
+                if (!status) {
+                	throw new ServiceFailure("0000", "Unknown error, status = " + status);
+                }
+            } else {
+            	throw new InvalidRequest("0000", "No resource matched for " + resource);
+            }
+        } catch (BaseException be) {
+        	// report Exceptions as clearly as possible
+        	OutputStream out = null;
+			try {
+				out = response.getOutputStream();
+			} catch (IOException e) {
+				logMetacat.error("Could not get output stream from response", e);
+			}
+            serializeException(be, out);
+        } catch (Exception e) {
+            // report Exceptions as clearly and generically as possible
+            logMetacat.error(e.getClass() + ": " + e.getMessage(), e);
+        	OutputStream out = null;
+			try {
+				out = response.getOutputStream();
+			} catch (IOException ioe) {
+				logMetacat.error("Could not get output stream from response", ioe);
+			}
+			ServiceFailure se = new ServiceFailure("0000", e.getMessage());
+            serializeException(se, out);
+        }
+    }
+    
+
+    private void doQuery(String engine, String query) {
+    	
+		OutputStream out = null;
+
+    	try {
+    		// NOTE: we set the session explicitly for the MNode instance since these methods do not provide a parameter			
+	    	if (engine == null) {
+	    		// just looking for list of engines
+	    		MNodeService mnode = MNodeService.getInstance(request);
+    			mnode.setSession(session);
+	    		QueryEngineList qel = mnode.listQueryEngines(session);
+	    		response.setContentType("text/xml");
+	            response.setStatus(200);
+	            out = response.getOutputStream();
+	            TypeMarshaller.marshalTypeToOutputStream(qel, out);
+	            return;
+	    	} else {
+	    		if (query != null) {
+	    			MNodeService mnode = MNodeService.getInstance(request);
+	    			mnode.setSession(session);
+	    			InputStream stream = mnode.query(session, engine, query);
+
+	    			// set the content-type if we have it from the implementation
+	    			if (stream instanceof ContentTypeInputStream) {
+		    			//response.setContentType("application/octet-stream");
+		    			//response.setContentType("text/xml");
+	    				response.setContentType(((ContentTypeInputStream) stream).getContentType());
+	    			}
+	                response.setStatus(200);
+	                out = response.getOutputStream();
+	                // write the results to the output stream
+	                IOUtils.copyLarge(stream, out);
+	                return;
+	    		} else {
+	    			MNodeService mnode = MNodeService.getInstance(request);
+	    			mnode.setSession(session);
+	    			QueryEngineDescription qed = mnode.getQueryEngineDescription(session, engine);
+	    			response.setContentType("text/xml");
+		            response.setStatus(200);
+		            out = response.getOutputStream();
+		            TypeMarshaller.marshalTypeToOutputStream(qed, out);
+		            return;
+	    		}
+	    	}
+	        
+	        
+    	} catch (BaseException be) {
+        	// report Exceptions as clearly as possible
+			try {
+				out = response.getOutputStream();
+			} catch (IOException e) {
+				logMetacat.error("Could not get output stream from response", e);
+			}
+            serializeException(be, out);
+        } catch (Exception e) {
+            // report Exceptions as clearly and generically as possible
+            logMetacat.error(e.getClass() + ": " + e.getMessage(), e);
+			try {
+				out = response.getOutputStream();
+			} catch (IOException ioe) {
+				logMetacat.error("Could not get output stream from response", ioe);
+			}
+			ServiceFailure se = new ServiceFailure("0000", e.getMessage());
+            serializeException(se, out);
+        }
+    }
+    
+    private void doViews(String format, String pid) {
+    	
+		OutputStream out = null;
+		MNodeService mnode = MNodeService.getInstance(request);
+
+    	try {
+    		// get a list of views
+    		if (pid != null) {
+    			Identifier identifier = new Identifier();
+    			identifier.setValue(pid);
+				InputStream stream = mnode.view(session, format, identifier);
+
+    			// set the content-type if we have it from the implementation
+    			if (stream instanceof ContentTypeInputStream) {
+    				response.setContentType(((ContentTypeInputStream) stream).getContentType());
+    			}
+                response.setStatus(200);
+                out = response.getOutputStream();
+                // write the results to the output stream
+                IOUtils.copyLarge(stream, out);
+                return;
+    		} else {
+    			// TODO: list the registered views
+                BaseException ni = new NotImplemented("9999", "MN.listViews() is not implemented at this node");
+				throw ni;
+    		}
+	    	
+	        
+    	} catch (BaseException be) {
+        	// report Exceptions as clearly as possible
+			try {
+				out = response.getOutputStream();
+			} catch (IOException e) {
+				logMetacat.error("Could not get output stream from response", e);
+			}
+            serializeException(be, out);
+        } catch (Exception e) {
+            // report Exceptions as clearly and generically as possible
+            logMetacat.error(e.getClass() + ": " + e.getMessage(), e);
+			try {
+				out = response.getOutputStream();
+			} catch (IOException ioe) {
+				logMetacat.error("Could not get output stream from response", ioe);
+			}
+			ServiceFailure se = new ServiceFailure("0000", e.getMessage());
+            serializeException(se, out);
+        }
+    }
+    
+    /**
+     * Handles notification of system metadata changes for the given identifier
+     * 
+     * @param id  the identifier for the object
+     * @throws InvalidToken 
+     * @throws InvalidRequest 
+     * @throws NotAuthorized 
+     * @throws ServiceFailure 
+     * @throws NotImplemented 
+     */
+    private void systemMetadataChanged() 
+        throws NotImplemented, ServiceFailure, NotAuthorized, InvalidRequest, 
+        InvalidToken {
+
+        long serialVersion = 0L;
+        String serialVersionStr = null;
+        Date dateSysMetaLastModified = null;
+        String dateSysMetaLastModifiedStr = null;
+        Identifier pid = null;
+        
+        // mkae sure we have the multipart params
+        try {
+			initMultipartParams();
+		} catch (Exception e1) {
+			throw new ServiceFailure("1333", "Could not collect the multipart params for the request");
+		}
+        
+        // get the pid
+        try {
+        	String id = multipartparams.get("pid").get(0);
+        	pid = new Identifier();
+            pid.setValue(id);            
+        } catch (NullPointerException e) {
+            String msg = "The 'pid' must be provided as a parameter and was not.";
+            logMetacat.error(msg);
+            throw new InvalidRequest("1334", msg);
+        }      
+        
+        // get the serialVersion
+        try {
+            serialVersionStr = multipartparams.get("serialVersion").get(0);
+            serialVersion = new Long(serialVersionStr).longValue();
+            
+        } catch (NullPointerException e) {
+            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
+            logMetacat.error(msg);
+            throw new InvalidRequest("1334", msg);
+            
+        }       
+        
+        // get the dateSysMetaLastModified
+        try {
+            dateSysMetaLastModifiedStr = multipartparams.get("dateSysMetaLastModified").get(0);
+            dateSysMetaLastModified = DateTimeMarshaller.deserializeDateToUTC(dateSysMetaLastModifiedStr);
+            
+        } catch (NullPointerException e) {
+            String msg = 
+                "The 'dateSysMetaLastModified' must be provided as a " + 
+                "parameter and was not, or was an invalid representation of the timestamp.";
+            logMetacat.error(msg);
+            throw new InvalidRequest("1334", msg);
+            
+        }       
+        
+        // call the service
+        MNodeService.getInstance(request).systemMetadataChanged(session, pid, serialVersion, dateSysMetaLastModified);
+        response.setStatus(200);
+    }
+    
+    /**
+     * Handles identifier generation calls
+     * 
+     * @throws InvalidRequest 
+     * @throws NotImplemented 
+     * @throws NotAuthorized 
+     * @throws ServiceFailure 
+     * @throws InvalidToken 
+     * @throws IOException 
+     * @throws JiBXException 
+     */
+    private void generateIdentifier() throws InvalidToken, ServiceFailure, NotAuthorized, NotImplemented, InvalidRequest, IOException, JiBXException {
+        
+        // make sure we have the multipart params
+        try {
+			initMultipartParams();
+		} catch (Exception e1) {
+			throw new ServiceFailure("1333", "Could not collect the multipart params for the request");
+		}
+        
+        // get the scheme
+		String scheme = null;
+        try {
+        	scheme = multipartparams.get("scheme").get(0);	           
+        } catch (NullPointerException e) {
+            String msg = "The 'scheme' parameter was not provided, using default";
+            logMetacat.warn(msg);
+        }
+        
+        // get the fragment
+		String fragment = null;
+        try {
+        	fragment = multipartparams.get("fragment").get(0);	           
+        } catch (NullPointerException e) {
+            String msg = "The 'fragment' parameter was not provided, using default";
+            logMetacat.warn(msg);
+        }
+
+        // call the service
+        Identifier identifier = MNodeService.getInstance(request).generateIdentifier(session, scheme, fragment);
+        response.setStatus(200);
+        response.setContentType("text/xml");
+        OutputStream out = response.getOutputStream();
+        TypeMarshaller.marshalTypeToOutputStream(identifier, out);
+    }
+
+    /**
+     * Checks the access policy
+     * @param id
+     * @return
+     * @throws ServiceFailure
+     * @throws InvalidToken
+     * @throws NotFound
+     * @throws NotAuthorized
+     * @throws NotImplemented
+     * @throws InvalidRequest
+     */
+    private boolean isAuthorized(String id) throws ServiceFailure, InvalidToken, NotFound, NotAuthorized, NotImplemented, InvalidRequest {
+		Identifier pid = new Identifier();
+		pid.setValue(id);
+		Permission permission = null;
+		try {
+			String perm = params.get("action")[0];
+			permission = Permission.convert(perm);
+		} catch (Exception e) {
+			logMetacat.warn("No permission specified");
+		}
+		boolean result = MNodeService.getInstance(request).isAuthorized(session, pid, permission);
+		response.setStatus(200);
+		response.setContentType("text/xml");
+		return result;
+    }
+    
+    /**
+     * Processes failed synchronization message
+     * @throws NotImplemented
+     * @throws ServiceFailure
+     * @throws NotAuthorized
+     * @throws InvalidRequest
+     * @throws JiBXException
+     * @throws IllegalAccessException 
+     * @throws InstantiationException 
+     * @throws IOException 
+     */
+    private void syncError() throws NotImplemented, ServiceFailure, NotAuthorized, InvalidRequest, JiBXException, IOException, InstantiationException, IllegalAccessException {
+    	SynchronizationFailed syncFailed = null;
+		try {
+			syncFailed = collectSynchronizationFailed();
+		} catch (ParserConfigurationException e) {
+			throw new ServiceFailure("2161", e.getMessage());
+		} catch (SAXException e) {
+			throw new ServiceFailure("2161", e.getMessage());
+		}
+		
+		MNodeService.getInstance(request).synchronizationFailed(session, syncFailed);
+    }
+
+	/**
+     * Calculate the checksum 
+     * @throws NotImplemented
+     * @throws JiBXException
+     * @throws IOException
+     * @throws InvalidToken
+     * @throws ServiceFailure
+     * @throws NotAuthorized
+     * @throws NotFound
+     * @throws InvalidRequest
+     */
+    private void checksum(String pid) throws NotImplemented, JiBXException, IOException, InvalidToken, ServiceFailure, NotAuthorized, NotFound, InvalidRequest {
+    	String checksumAlgorithm = "MD5";
+    	try {
+    		checksumAlgorithm = PropertyService.getProperty("dataone.checksumAlgorithm.default");
+        } catch(Exception e) {
+        	logMetacat.warn("Could not lookup configured default checksum algorithm, using: " + checksumAlgorithm);
+        }    
+        
+        Identifier pidid = new Identifier();
+        pidid.setValue(pid);
+        try {
+            checksumAlgorithm = params.get("checksumAlgorithm")[0];
+        } catch(Exception e) {
+            //do nothing.  use the default
+        	logMetacat.warn("No algorithm specified, using default: " + checksumAlgorithm);
+        }
+        logMetacat.debug("getting checksum for object " + pid + " with algorithm " + checksumAlgorithm);
+        
+        Checksum c = MNodeService.getInstance(request).getChecksum(session, pidid, checksumAlgorithm);
+        logMetacat.debug("got checksum " + c.getValue());
+        response.setStatus(200);
+        logMetacat.debug("serializing response");
+        TypeMarshaller.marshalTypeToOutputStream(c, response.getOutputStream());
+        logMetacat.debug("done serializing response.");
+        
+    }
+    
+	/**
+     * handle the replicate action for MN
+	 * @throws JiBXException 
+	 * @throws FileUploadException 
+	 * @throws IOException 
+	 * @throws InvalidRequest 
+	 * @throws ServiceFailure 
+	 * @throws UnsupportedType 
+	 * @throws InsufficientResources 
+	 * @throws NotAuthorized 
+	 * @throws NotImplemented 
+	 * @throws IllegalAccessException 
+	 * @throws InstantiationException 
+	 * @throws InvalidToken 
+     */
+    private void replicate() 
+        throws ServiceFailure, InvalidRequest, IOException, FileUploadException, 
+        JiBXException, NotImplemented, NotAuthorized, InsufficientResources, 
+        UnsupportedType, InstantiationException, IllegalAccessException, InvalidToken {
+
+        logMetacat.debug("in POST replicate()");
+        
+        // somewhat unorthodox, but the call is asynchronous and we'd like to return this info sooner
+        boolean allowed = false;
+        if (session == null) {
+        	String msg = "No session was provided.";
+            NotAuthorized failure = new NotAuthorized("2152", msg);
+        	throw failure;
+        } else {
+        	allowed = MNodeService.getInstance(request).isAdminAuthorized(session);
+        	if (!allowed) {
+        		String msg = "User is not an admin user";
+                NotAuthorized failure = new NotAuthorized("2152", msg);
+            	throw failure;
+        	}
+        }
+        
+        // parse the systemMetadata
+        Map<String, File> files = collectMultipartFiles();        
+        final SystemMetadata sysmeta = TypeMarshaller.unmarshalTypeFromFile(SystemMetadata.class, files.get("sysmeta"));
+        
+        String sn = multipartparams.get("sourceNode").get(0);
+        logMetacat.debug("sourceNode: " + sn);
+        final NodeReference sourceNode = new NodeReference();
+        sourceNode.setValue(sn);
+        
+        // run it in a thread to avoid connection timeout
+        Runnable runner = new Runnable() {
+			@Override
+			public void run() {
+				try {
+			        MNodeService.getInstance(request).replicate(session, sysmeta, sourceNode);
+				} catch (Exception e) {
+					logMetacat.error("Error running replication: " + e.getMessage(), e);
+					throw new RuntimeException(e.getMessage(), e);
+				}
+			}
+    	};
+    	// submit the task, and that's it
+    	executor.submit(runner);
+        
+    	// thread was started, so we return success
+        response.setStatus(200);
+        
+    }
+
+    /**
+     * Handle the getReplica action for the MN
+     * @param id  the identifier for the object
+     * @throws NotFound 
+     * @throws ServiceFailure 
+     * @throws NotImplemented 
+     * @throws NotAuthorized 
+     * @throws InvalidToken 
+     * @throws InvalidRequest 
+     */
+    private void getReplica(String id) 
+        throws InvalidRequest, InvalidToken, NotAuthorized, NotImplemented, 
+        ServiceFailure, NotFound {
+        
+        Identifier pid = new Identifier();
+        pid.setValue(id);
+        OutputStream out = null;
+        InputStream dataBytes = null;
+                
+        try {
+            // call the service
+            dataBytes = MNodeService.getInstance(request).getReplica(session, pid);
+
+            response.setContentType("application/octet-stream");
+            response.setStatus(200);
+            out = response.getOutputStream();
+            // write the object to the output stream
+            IOUtils.copyLarge(dataBytes, out);
+            
+        } catch (IOException e) {
+            String msg = "There was an error writing the output: " + e.getMessage();
+            logMetacat.error(msg);
+            throw new ServiceFailure("2181", msg);
+        
+        }
+
+    }
+
+    /**
+     * Get the Node information
+     * 
+     * @throws JiBXException
+     * @throws IOException
+     * @throws InvalidRequest 
+     * @throws ServiceFailure 
+     * @throws NotAuthorized 
+     * @throws NotImplemented 
+     */
+    private void node() 
+        throws JiBXException, IOException, NotImplemented, NotAuthorized, ServiceFailure, InvalidRequest {
+        
+        Node n = MNodeService.getInstance(request).getCapabilities();
+        
+        response.setContentType("text/xml");
+        response.setStatus(200);
+        TypeMarshaller.marshalTypeToOutputStream(n, response.getOutputStream());
+        
+    }
+    
+    /**
+     * MN_crud.describe()
+     * http://mule1.dataone.org/ArchitectureDocs/mn_api_crud.html#MN_crud.describe
+     * @param pid
+     * @throws InvalidRequest 
+     * @throws NotImplemented 
+     * @throws NotFound 
+     * @throws NotAuthorized 
+     * @throws ServiceFailure 
+     * @throws InvalidToken 
+     */
+    private void describeObject(String pid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, InvalidRequest
+    {
+        
+        response.setContentType("text/xml");
+
+        Identifier id = new Identifier();
+        id.setValue(pid);
+
+        DescribeResponse dr = null;
+        try {
+        	dr = MNodeService.getInstance(request).describe(session, id);
+        } catch (BaseException e) {
+        	response.setStatus(e.getCode());
+        	response.addHeader("DataONE-Exception-Name", e.getClass().getName());
+            response.addHeader("DataONE-Exception-DetailCode", e.getDetail_code());
+            response.addHeader("DataONE-Exception-Description", e.getDescription());
+            response.addHeader("DataONE-Exception-PID", id.getValue());
+            return;
+		}
+        
+        response.setStatus(200);
+        
+        //response.addHeader("pid", pid);
+        response.addHeader("DataONE-Checksum", dr.getDataONE_Checksum().getAlgorithm() + "," + dr.getDataONE_Checksum().getValue());
+        response.addHeader("Content-Length", dr.getContent_Length() + "");
+        response.addHeader("Last-Modified", DateTimeMarshaller.serializeDateToUTC(dr.getLast_Modified()));
+        response.addHeader("DataONE-ObjectFormat", dr.getDataONE_ObjectFormatIdentifier().getValue());
+        response.addHeader("DataONE-SerialVersion", dr.getSerialVersion().toString());
+
+        
+    }
+    
+    /**
+     * get the logs based on passed params.  Available 
+     * See http://mule1.dataone.org/ArchitectureDocs/mn_api_crud.html#MN_crud.getLogRecords
+     * for more info
+     * @throws NotImplemented 
+     * @throws InvalidRequest 
+     * @throws NotAuthorized 
+     * @throws ServiceFailure 
+     * @throws InvalidToken 
+     * @throws IOException 
+     * @throws JiBXException 
+     */
+    private void getLog() throws InvalidToken, ServiceFailure, NotAuthorized, InvalidRequest, NotImplemented, IOException, JiBXException
+    {
+            
+        Date fromDate = null;
+        Date toDate = null;
+        String event = null;
+        Integer start = null;
+        Integer count = null;
+        String pidFilter = null;
+        
+        try {
+        	String fromDateS = params.get("fromDate")[0];
+            logMetacat.debug("param fromDateS: " + fromDateS);
+            fromDate = DateTimeMarshaller.deserializeDateToUTC(fromDateS);
+        } catch (Exception e) {
+        	logMetacat.warn("Could not parse fromDate: " + e.getMessage());
+        }
+        try {
+        	String toDateS = params.get("toDate")[0];
+            logMetacat.debug("param toDateS: " + toDateS);
+            toDate = DateTimeMarshaller.deserializeDateToUTC(toDateS);
+        } catch (Exception e) {
+        	logMetacat.warn("Could not parse toDate: " + e.getMessage());
+		}
+        try {
+        	event = params.get("event")[0];
+        } catch (Exception e) {
+        	logMetacat.warn("Could not parse event: " + e.getMessage());
+		}
+        logMetacat.debug("fromDate: " + fromDate + " toDate: " + toDate);
+        
+        try {
+        	start =  Integer.parseInt(params.get("start")[0]);
+        } catch (Exception e) {
+			logMetacat.warn("Could not parse start: " + e.getMessage());
+		}
+        try {
+        	count =  Integer.parseInt(params.get("count")[0]);
+        } catch (Exception e) {
+			logMetacat.warn("Could not parse count: " + e.getMessage());
+		}
+        
+        try {
+            pidFilter = params.get("pidFilter")[0];
+        } catch (Exception e) {
+            logMetacat.warn("Could not parse pidFilter: " + e.getMessage());
+        }
+        
+        logMetacat.debug("calling getLogRecords");
+        Log log = MNodeService.getInstance(request).getLogRecords(session, fromDate, toDate, event, pidFilter, start, count);
+        
+        OutputStream out = response.getOutputStream();
+        response.setStatus(200);
+        response.setContentType("text/xml");
+        
+        TypeMarshaller.marshalTypeToOutputStream(log, out);
+        
+    }
+    
+    
+    
+    /**
+     * Implements REST version of DataONE CRUD API --> get
+     * @param pid ID of data object to be read
+     * @throws NotImplemented 
+     * @throws InvalidRequest 
+     * @throws NotFound 
+     * @throws NotAuthorized 
+     * @throws ServiceFailure 
+     * @throws InvalidToken 
+     * @throws IOException 
+     * @throws JiBXException 
+     */
+    protected void getObject(String pid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, InvalidRequest, NotImplemented, IOException, JiBXException {
+        OutputStream out = null;
+        
+        if (pid != null) { //get a specific document                
+            Identifier id = new Identifier();
+            id.setValue(pid);
+                
+            SystemMetadata sm = MNodeService.getInstance(request).getSystemMetadata(session, id);
+            
+            // set the headers for the content
+            String mimeType = ObjectFormatInfo.instance().getMimeType(sm.getFormatId().getValue());
+            if (mimeType == null) {
+            	mimeType = "application/octet-stream";
+            }
+            String extension = ObjectFormatInfo.instance().getExtension(sm.getFormatId().getValue());
+            String filename = id.getValue();
+            if (extension != null) {
+            	filename = id.getValue() + extension;
+            }
+            response.setContentType(mimeType);
+            response.setHeader("Content-Disposition", "inline; filename=" + filename);
+            
+            InputStream data = MNodeService.getInstance(request).get(session, id);
+
+            out = response.getOutputStream();  
+            IOUtils.copyLarge(data, out);
+            
+        }
+        else
+        { //call listObjects with specified params
+            Date startTime = null;
+            Date endTime = null;
+            ObjectFormatIdentifier formatId = null;
+            Identifier identifier = null;
+            boolean replicaStatus = true;
+            int start = 0;
+            //TODO: make the max count into a const
+            int count = 1000;
+            Enumeration paramlist = request.getParameterNames();
+            while (paramlist.hasMoreElements()) 
+            { //parse the params and make the crud call
+                String name = (String) paramlist.nextElement();
+                String[] value = (String[])request.getParameterValues(name);
+
+                if (name.equals("fromDate") && value != null)
+                {
+                    try
+                    {
+                      //startTime = dateFormat.parse(value[0]);
+                    	startTime = DateTimeMarshaller.deserializeDateToUTC(value[0]);
+                        //startTime = parseDateAndConvertToGMT(value[0]);
+                    }
+                    catch(Exception e)
+                    {  //if we can't parse it, just don't use the fromDate param
+                        logMetacat.warn("Could not parse fromDate: " + value[0]);
+                        startTime = null;
+                    }
+                }
+                else if(name.equals("toDate") && value != null)
+                {
+                    try
+                    {
+                    	endTime = DateTimeMarshaller.deserializeDateToUTC(value[0]);
+                    }
+                    catch(Exception e)
+                    {  //if we can't parse it, just don't use the toDate param
+                        logMetacat.warn("Could not parse toDate: " + value[0]);
+                        endTime = null;
+                    }
+                }
+                else if(name.equals("formatId") && value != null) 
+                {
+                	formatId = new ObjectFormatIdentifier();
+                	formatId.setValue(value[0]);
+                }
+                else if(name.equals("identifier") && value != null) 
+                {
+                	identifier = new Identifier();
+                	identifier.setValue(value[0]);
+                }
+                else if(name.equals("replicaStatus") && value != null)
+                {
+                    if(value != null && 
+                       value.length > 0 && 
+                       (value[0].equalsIgnoreCase("false") || value[0].equalsIgnoreCase("no")))
+                    {
+                        replicaStatus = false;
+                    }
+                }
+                else if(name.equals("start") && value != null)
+                {
+                    start = new Integer(value[0]).intValue();
+                }
+                else if(name.equals("count") && value != null)
+                {
+                    count = new Integer(value[0]).intValue();
+                }
+            }
+            //make the crud call
+            logMetacat.debug("session: " + session + " startTime: " + startTime +
+                    " endTime: " + endTime + " formatId: " + 
+                    formatId + " replicaStatus: " + replicaStatus + 
+                    " start: " + start + " count: " + count);
+           
+            ObjectList ol = 
+           	 MNodeService.getInstance(request).listObjects(session, startTime, endTime, 
+           			formatId, identifier, replicaStatus, start, count);
+           
+            out = response.getOutputStream();  
+            response.setStatus(200);
+            response.setContentType("text/xml");
+            // Serialize and write it to the output stream
+            TypeMarshaller.marshalTypeToOutputStream(ol, out);
+            
+        }
+        
+    }
+    
+
+    /**
+     * Retrieve data package as Bagit zip
+     * @param pid
+     * @throws NotImplemented 
+     * @throws NotFound 
+     * @throws NotAuthorized 
+     * @throws ServiceFailure 
+     * @throws InvalidToken 
+     * @throws IOException 
+     * @throws InvalidRequest 
+     */
+    protected void getPackage(String format, String pid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, IOException, InvalidRequest {
+
+        Identifier id = new Identifier();
+        id.setValue(pid);
+        ObjectFormatIdentifier formatId = null;
+        if (format != null) {
+        	formatId = new ObjectFormatIdentifier();
+        	formatId.setValue(format);
+        }
+		InputStream is = MNodeService.getInstance(request).getPackage(session, formatId , id);
+        
+        // use the provided filename
+        String filename = null;
+        if (is instanceof DeleteOnCloseFileInputStream) {
+            filename = ((DeleteOnCloseFileInputStream)is).getFile().getName();
+        } else {
+        	filename = "dataPackage-" + System.currentTimeMillis() + ".zip";
+        }
+        response.setHeader("Content-Disposition", "inline; filename=" + filename);
+        response.setContentType("application/zip");
+        response.setStatus(200);
+        OutputStream out = response.getOutputStream();
+        
+        // write it to the output stream
+        IOUtils.copyLarge(is, out);
+   }
+    
+	protected void publish(String pid) throws InvalidToken, ServiceFailure,
+			NotAuthorized, NotFound, NotImplemented, IOException,
+			JiBXException, InvalidRequest, IdentifierNotUnique,
+			UnsupportedType, InsufficientResources, InvalidSystemMetadata {
+
+		// publish the object
+		Identifier originalIdentifier = new Identifier();
+		originalIdentifier.setValue(pid);
+		Identifier newIdentifier = MNodeService.getInstance(request).publish(session, originalIdentifier);
+
+		response.setStatus(200);
+		response.setContentType("text/xml");
+		OutputStream out = response.getOutputStream();
+
+		// write new identifier to the output stream
+		TypeMarshaller.marshalTypeToOutputStream(newIdentifier, out);
+	}
+    
+    /**
+     * Retrieve System Metadata
+     * @param pid
+     * @throws InvalidToken
+     * @throws ServiceFailure
+     * @throws NotAuthorized
+     * @throws NotFound
+     * @throws InvalidRequest
+     * @throws NotImplemented
+     * @throws IOException
+     * @throws JiBXException
+     */
+    protected void getSystemMetadataObject(String pid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, InvalidRequest, NotImplemented, IOException, JiBXException {
+
+        Identifier id = new Identifier();
+        id.setValue(pid);
+        SystemMetadata sysmeta = MNodeService.getInstance(request).getSystemMetadata(session, id);
+        
+        response.setContentType("text/xml");
+        response.setStatus(200);
+        OutputStream out = response.getOutputStream();
+        
+        // Serialize and write it to the output stream
+        TypeMarshaller.marshalTypeToOutputStream(sysmeta, out);
+   }
+    
+    
+    /**
+     * Inserts or updates the object
+     * 
+     * @param pid - ID of data object to be inserted or updated.  If action is update, the pid
+     *               is the existing pid.  If insert, the pid is the new one
+     * @throws InvalidRequest 
+     * @throws ServiceFailure 
+     * @throws JiBXException 
+     * @throws NotImplemented 
+     * @throws InvalidSystemMetadata 
+     * @throws InsufficientResources 
+     * @throws UnsupportedType 
+     * @throws IdentifierNotUnique 
+     * @throws NotAuthorized 
+     * @throws InvalidToken 
+     * @throws NotFound 
+     * @throws IOException 
+     * @throws IllegalAccessException 
+     * @throws InstantiationException 
+     */
+    protected void putObject(String trailingPid, String action) throws ServiceFailure, InvalidRequest, JiBXException, InvalidToken, NotAuthorized, IdentifierNotUnique, UnsupportedType, InsufficientResources, InvalidSystemMetadata, NotImplemented, NotFound, IOException, InstantiationException, IllegalAccessException {
+       
+    	// Read the incoming data from its Mime Multipart encoding
+    	Map<String, File> files = collectMultipartFiles();
+               
+    	Identifier pid = new Identifier();
+        if (trailingPid == null) {
+	        // get the pid string from the body and set the value
+	        String pidString = multipartparams.get("pid").get(0);
+	        if (pidString != null) {
+            pid.setValue(pidString);
+            
+          } else {
+              throw new InvalidRequest("1102", "The pid param must be included and contain the identifier.");
+              
+          }
+        } else {
+        	// use the pid included in the URL
+        	pid.setValue(trailingPid);
+        }
+        logMetacat.debug("putObject with pid " + pid.getValue());
+        logMetacat.debug("Entering putObject: " + pid.getValue() + "/" + action);
+
+        InputStream object = null;
+        InputStream sysmeta = null;
+        File smFile = files.get("sysmeta");
+        sysmeta = new FileInputStream(smFile);
+        File objFile = files.get("object");
+        object = new FileInputStream(objFile);
+        
+        // ensure we have the object bytes
+        if  ( objFile == null ) {
+            throw new InvalidRequest("1102", "The object param must contain the object bytes.");
+            
+        }
+        
+        // ensure we have the system metadata
+        if  ( smFile == null ) {
+            throw new InvalidRequest("1102", "The sysmeta param must contain the system metadata document.");
+            
+        }
+        
+        response.setStatus(200);
+        response.setContentType("text/xml");
+        OutputStream out = response.getOutputStream();
+        
+        if (action.equals(FUNCTION_NAME_INSERT)) { 
+            // handle inserts
+            logMetacat.debug("Commence creation...");
+            SystemMetadata smd = TypeMarshaller.unmarshalTypeFromStream(SystemMetadata.class, sysmeta);
+
+            logMetacat.debug("creating object with pid " + pid.getValue());
+            Identifier rId = MNodeService.getInstance(request).create(session, pid, object, smd);
+            TypeMarshaller.marshalTypeToOutputStream(rId, out);
+            
+        } else if (action.equals(FUNCTION_NAME_UPDATE)) {
+        	// handle updates
+        	
+            // construct pids
+            Identifier newPid = null;
+            try {
+            	String newPidString = multipartparams.get("newPid").get(0);
+            	newPid = new Identifier();
+            	newPid.setValue(newPidString);
+            } catch (Exception e) {
+				logMetacat.error("Could not get newPid from request");
+			}
+            logMetacat.debug("Commence update...");
+            
+            // get the systemmetadata object
+            SystemMetadata smd = TypeMarshaller.unmarshalTypeFromStream(SystemMetadata.class, sysmeta);
+
+            Identifier rId = MNodeService.getInstance(request).update(session, pid, object, newPid, smd);
+            TypeMarshaller.marshalTypeToOutputStream(rId, out);
+        } else {
+            throw new InvalidRequest("1000", "Operation must be create or update.");
+        }
+   
+    }
+
+    /**
+     * Handle delete 
+     * @param pid ID of data object to be deleted
+     * @throws IOException
+     * @throws InvalidRequest 
+     * @throws NotImplemented 
+     * @throws NotFound 
+     * @throws NotAuthorized 
+     * @throws ServiceFailure 
+     * @throws InvalidToken 
+     * @throws JiBXException 
+     */
+    private void deleteObject(String pid) throws IOException, InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, InvalidRequest, JiBXException 
+    {
+
+        OutputStream out = response.getOutputStream();
+        response.setStatus(200);
+        response.setContentType("text/xml");
+
+        Identifier id = new Identifier();
+        id.setValue(pid);
+
+        logMetacat.debug("Calling delete");
+        MNodeService.getInstance(request).delete(session, id);
+        TypeMarshaller.marshalTypeToOutputStream(id, out);
+        
+    }
+    
+    /**
+     * Archives the given pid
+     * @param pid
+     * @throws InvalidToken
+     * @throws ServiceFailure
+     * @throws NotAuthorized
+     * @throws NotFound
+     * @throws NotImplemented
+     * @throws IOException
+     * @throws JiBXException
+     */
+    private void archive(String pid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, IOException, JiBXException {
+
+        OutputStream out = response.getOutputStream();
+        response.setStatus(200);
+        response.setContentType("text/xml");
+
+        Identifier id = new Identifier();
+        id.setValue(pid);
+
+        logMetacat.debug("Calling archive");
+        MNodeService.getInstance(request).archive(session, id);
+        
+        TypeMarshaller.marshalTypeToOutputStream(id, out);
+        
+    }
+
+	protected SynchronizationFailed collectSynchronizationFailed() throws IOException, ServiceFailure, InvalidRequest, JiBXException, InstantiationException, IllegalAccessException, ParserConfigurationException, SAXException  {
+		
+		// Read the incoming data from its Mime Multipart encoding
+		logMetacat.debug("Disassembling MIME multipart form");
+		InputStream sf = null;
+	
+		// handle MMP inputs
+		File tmpDir = getTempDirectory();
+		logMetacat.debug("temp dir: " + tmpDir.getAbsolutePath());
+		MultipartRequestResolver mrr = 
+			new MultipartRequestResolver(tmpDir.getAbsolutePath(), 1000000000, 0);
+		MultipartRequest mr = null;
+		try {
+			mr = mrr.resolveMultipart(request);
+		} catch (Exception e) {
+			throw new ServiceFailure("2161", 
+					"Could not resolve multipart: " + e.getMessage());
+		}
+		logMetacat.debug("resolved multipart request");
+		Map<String, File> files = mr.getMultipartFiles();
+		if (files == null || files.keySet() == null) {
+			throw new InvalidRequest("2163",
+					"must have multipart file with name 'message'");
+		}
+		logMetacat.debug("got multipart files");
+	
+		multipartparams = mr.getMultipartParameters();
+	
+		File sfFile = files.get("message");
+		if (sfFile == null) {
+			throw new InvalidRequest("2163",
+					"Missing the required file-part 'message' from the multipart request.");
+		}
+		logMetacat.debug("sfFile: " + sfFile.getAbsolutePath());
+		sf = new FileInputStream(sfFile);
+	
+		SynchronizationFailed syncFailed = (SynchronizationFailed) ExceptionHandler.deserializeXml(sf, "Error deserializing exception");
+		return syncFailed;
+	}
+
+}

Property changes on: src/edu/ucsb/nceas/metacat/restservice/v2/MNResourceHandler.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property
Index: src/edu/ucsb/nceas/metacat/restservice/v2/CNResourceHandler.java
===================================================================
--- src/edu/ucsb/nceas/metacat/restservice/v2/CNResourceHandler.java	(nonexistent)
+++ src/edu/ucsb/nceas/metacat/restservice/v2/CNResourceHandler.java	(revision 8810)
@@ -0,0 +1,1706 @@
+/**
+ *  '$RCSfile$'
+ *  Copyright: 2011 Regents of the University of California and the
+ *              National Center for Ecological Analysis and Synthesis
+ *
+ *   '$Author$'
+ *     '$Date$'
+ *
+ * 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.v2;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Map;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.commons.fileupload.FileUploadException;
+import org.apache.commons.io.IOUtils;
+import org.apache.log4j.Logger;
+import org.dataone.client.v2.formats.ObjectFormatInfo;
+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.NotFound;
+import org.dataone.service.exceptions.NotImplemented;
+import org.dataone.service.exceptions.ServiceFailure;
+import org.dataone.service.exceptions.UnsupportedType;
+import org.dataone.service.exceptions.VersionMismatch;
+import org.dataone.service.types.v1.AccessPolicy;
+import org.dataone.service.types.v1.Checksum;
+import org.dataone.service.types.v1.ChecksumAlgorithmList;
+import org.dataone.service.types.v1.DescribeResponse;
+import org.dataone.service.types.v1.Event;
+import org.dataone.service.types.v1.Identifier;
+import org.dataone.service.types.v2.Log;
+import org.dataone.service.types.v1.NodeReference;
+import org.dataone.service.types.v2.ObjectFormat;
+import org.dataone.service.types.v1.ObjectFormatIdentifier;
+import org.dataone.service.types.v2.ObjectFormatList;
+import org.dataone.service.types.v1.ObjectList;
+import org.dataone.service.types.v1.ObjectLocationList;
+import org.dataone.service.types.v1.Permission;
+import org.dataone.service.types.v1.Replica;
+import org.dataone.service.types.v1.ReplicationPolicy;
+import org.dataone.service.types.v1.ReplicationStatus;
+import org.dataone.service.types.v1.Subject;
+import org.dataone.service.types.v2.SystemMetadata;
+import org.dataone.service.util.Constants;
+import org.dataone.service.util.DateTimeMarshaller;
+import org.dataone.service.util.EncodingUtilities;
+import org.dataone.service.util.ExceptionHandler;
+import org.dataone.service.util.TypeMarshaller;
+import org.jibx.runtime.JiBXException;
+import org.xml.sax.SAXException;
+
+import edu.ucsb.nceas.metacat.dataone.CNodeService;
+import edu.ucsb.nceas.metacat.properties.PropertyService;
+import edu.ucsb.nceas.metacat.restservice.D1ResourceHandler;
+import edu.ucsb.nceas.utilities.PropertyNotFoundException;
+
+/**
+ * CN REST service implementation handler
+ * 
+ * ****************** CNCore -- DONE create() - POST /d1/cn/object/PID
+ * listFormats() - GET /d1/cn/formats getFormat() - GET /d1/cn/formats/FMTID
+ * getLogRecords - GET /d1/cn/log reserveIdentifier() - POST /d1/cn/reserve
+ * listNodes() - Not implemented registerSystemMetadata() - POST /d1/meta/PID
+ * 
+ * CNRead -- DONE get() - GET /d1/cn/object/PID getSystemMetadata() - GET
+ * /d1/cn/meta/PID resolve() - GET /d1/cn/resolve/PID assertRelation() - GET
+ * /d1/cn/assertRelation/PID getChecksum() - GET /d1/cn/checksum search() - Not
+ * implemented in Metacat
+ * 
+ * CNAuthorization setOwner() - PUT /d1/cn/owner/PID isAuthorized() - GET
+ * /d1/cn/isAuthorized/PID setAccessPolicy() - POST /d1/cn/accessRules
+ * 
+ * CNIdentity - not implemented at all on Metacat
+ * 
+ * CNReplication setReplicationStatus() - PUT /replicaNotifications/PID
+ * updateReplicationMetadata() - PUT /replicaMetadata/PID setReplicationPolicy()
+ * - PUT /replicaPolicies/PID isNodeAuthorized() - GET
+ * /replicaAuthorizations/PID
+ * 
+ * CNRegister -- not implemented at all in Metacat ******************
+ * 
+ * @author leinfelder
+ * 
+ */
+public class CNResourceHandler extends D1ResourceHandler {
+
+    /** CN-specific operations **/
+    protected static final String RESOURCE_RESERVE = "reserve";
+    protected static final String RESOURCE_FORMATS = "formats";
+    protected static final String RESOURCE_RESOLVE = "resolve";
+    protected static final String RESOURCE_OWNER = "owner";
+    protected static final String RESOURCE_REPLICATION_POLICY = "replicaPolicies";
+    protected static final String RESOURCE_REPLICATION_META = "replicaMetadata";
+    protected static final String RESOURCE_REPLICATION_AUTHORIZED = "replicaAuthorizations";
+    protected static final String RESOURCE_REPLICATION_NOTIFY = "replicaNotifications";
+
+    public CNResourceHandler(ServletContext servletContext,
+            HttpServletRequest request, HttpServletResponse response) {
+        super(servletContext, request, response);
+        logMetacat = Logger.getLogger(CNResourceHandler.class);
+    }
+
+    /**
+     * This function is called from REST API servlet and handles each request to
+     * the servlet
+     * 
+     * @param httpVerb
+     *            (GET, POST, PUT or DELETE)
+     */
+    @Override
+    public void handle(byte httpVerb) {
+        // prepare the handler
+        super.handle(httpVerb);
+
+        try {
+
+        	// only service requests if we have D1 configured
+        	if (!isD1Enabled()) {
+        		ServiceFailure se = new ServiceFailure("0000", "DataONE services are not enabled on this node");
+                serializeException(se, response.getOutputStream());
+                return;
+        	}
+        	
+            // get the resource
+            String resource = request.getPathInfo();
+            resource = resource.substring(resource.indexOf("/") + 1);
+
+            // for the rest of the resouce
+            String extra = null;
+
+            logMetacat.debug("handling verb " + httpVerb
+                    + " request with resource '" + resource + "'");
+            boolean status = false;
+
+            if (resource != null) {
+
+                if (resource.startsWith(RESOURCE_ACCESS_RULES)
+                        && httpVerb == PUT) {
+                    logMetacat.debug("Setting access policy");
+                    // after the command
+                    extra = parseTrailing(resource, RESOURCE_ACCESS_RULES);
+                    setAccess(extra);
+                    status = true;
+                    logMetacat.debug("done setting access");
+
+                } else if (resource.startsWith(RESOURCE_META)) {
+                    logMetacat.debug("Using resource: " + RESOURCE_META);
+
+                    // after the command
+                    extra = parseTrailing(resource, RESOURCE_META);
+
+                    // get
+                    if (httpVerb == GET) {
+                        getSystemMetadataObject(extra);
+                        status = true;
+                    }
+                    // post to register system metadata
+                    if (httpVerb == POST) {
+                        registerSystemMetadata();
+                        status = true;
+                    }
+
+                } else if (resource.startsWith(RESOURCE_RESERVE)) {
+                    // reserve the ID (in params)
+                    if (httpVerb == POST) {
+                        reserve();
+                        status = true;
+                    }
+                } else if (resource.startsWith(RESOURCE_RESOLVE)) {
+
+                    // after the command
+                    extra = parseTrailing(resource, RESOURCE_RESOLVE);
+
+                    // resolve the object location
+                    if (httpVerb == GET) {
+                        resolve(extra);
+                        status = true;
+                    }
+                } else if (resource.startsWith(RESOURCE_OWNER)) {
+
+                    // after the command
+                    extra = parseTrailing(resource, RESOURCE_OWNER);
+
+                    // set the owner
+                    if (httpVerb == PUT) {
+                        owner(extra);
+                        status = true;
+                    }
+                } else if (resource.startsWith(RESOURCE_IS_AUTHORIZED)) {
+
+                    // after the command
+                    extra = parseTrailing(resource, RESOURCE_IS_AUTHORIZED);
+
+                    // authorized?
+                    if (httpVerb == GET) {
+                        isAuthorized(extra);
+                        status = true;
+                    }
+                } else if (resource.startsWith(RESOURCE_OBJECTS)) {
+                    logMetacat.debug("Using resource 'object'");
+                    logMetacat
+                            .debug("D1 Rest: Starting resource processing...");
+
+                    // after the command
+                    extra = parseTrailing(resource, RESOURCE_OBJECTS);
+
+                    logMetacat.debug("objectId: " + extra);
+                    logMetacat.debug("verb:" + httpVerb);
+
+                    if (httpVerb == GET) {
+                        if (extra != null) {
+                            getObject(extra);
+                        } else {
+                            listObjects();
+                        }
+                        status = true;
+                    } else if (httpVerb == POST) {
+                        putObject(FUNCTION_NAME_INSERT);
+                        status = true;
+                    } else if (httpVerb == HEAD) {
+                        describeObject(extra);
+                        status = true;
+                    } else if (httpVerb == DELETE) {
+                        deleteObject(extra);
+                        status = true;
+                    } 
+
+                } else if (resource.startsWith(RESOURCE_FORMATS)) {
+                    logMetacat.debug("Using resource: " + RESOURCE_FORMATS);
+
+                    // after the command
+                    extra = parseTrailing(resource, RESOURCE_FORMATS);
+
+                    // handle each verb
+                    if (httpVerb == GET) {
+                        if (extra == null) {
+                            // list the formats collection
+                            listFormats();
+                        } else {
+                            // get the specified format
+                            getFormat(extra);
+                        }
+                        status = true;
+                    }
+
+                } else if (resource.startsWith(RESOURCE_LOG)) {
+                    logMetacat.debug("Using resource: " + RESOURCE_LOG);
+                    // handle log events
+                    if (httpVerb == GET) {
+                        getLog();
+                        status = true;
+                    }
+
+                } else if (resource.startsWith(Constants.RESOURCE_ARCHIVE)) {
+                    logMetacat.debug("Using resource " + Constants.RESOURCE_ARCHIVE);
+                    // handle archive events
+                    if (httpVerb == PUT) {
+                        extra = parseTrailing(resource, Constants.RESOURCE_ARCHIVE);
+                        archive(extra);
+                        status = true;
+                    }
+                } else if (resource.startsWith(Constants.RESOURCE_CHECKSUM)) {
+                    logMetacat.debug("Using resource: " + Constants.RESOURCE_CHECKSUM);
+
+                    // after the command
+                    extra = parseTrailing(resource, Constants.RESOURCE_CHECKSUM);
+
+                    // handle checksum requests
+                    if (httpVerb == GET) {
+
+                    	if (extra != null && extra.length() > 0) {
+	                        checksum(extra);
+	                        status = true;
+                    	} else {
+                    		listChecksumAlgorithms();
+                    		status = true;
+                    	}
+
+                    }
+
+                } else if (resource.startsWith(RESOURCE_REPLICATION_POLICY)
+                        && httpVerb == PUT) {
+
+                    logMetacat.debug("Using resource: "
+                            + RESOURCE_REPLICATION_POLICY);
+                    // get the trailing pid
+                    extra = parseTrailing(resource, RESOURCE_REPLICATION_POLICY);
+                    setReplicationPolicy(extra);
+                    status = true;
+
+                } else if (resource.startsWith(RESOURCE_REPLICATION_META)
+                        && httpVerb == PUT) {
+
+                    logMetacat.debug("Using resource: "
+                            + RESOURCE_REPLICATION_META);
+                    // get the trailing pid
+                    extra = parseTrailing(resource, RESOURCE_REPLICATION_META);
+                    updateReplicationMetadata(extra);
+                    status = true;
+
+                } else if (resource.startsWith(RESOURCE_REPLICATION_NOTIFY)
+                        && httpVerb == PUT) {
+
+                    logMetacat.debug("Using resource: "
+                            + RESOURCE_REPLICATION_NOTIFY);
+                    // get the trailing pid
+                    extra = parseTrailing(resource, RESOURCE_REPLICATION_NOTIFY);
+                    setReplicationStatus(extra);
+                    status = true;
+
+                } else if (resource.startsWith(RESOURCE_REPLICATION_AUTHORIZED)
+                        && httpVerb == GET) {
+
+                    logMetacat.debug("Using resource: "
+                            + RESOURCE_REPLICATION_AUTHORIZED);
+                    // get the trailing pid
+                    extra = parseTrailing(resource,
+                            RESOURCE_REPLICATION_AUTHORIZED);
+                    isNodeAuthorized(extra);
+                    status = true;
+
+                } else if (resource.startsWith(Constants.RESOURCE_MONITOR_PING)) {
+                    if (httpVerb == GET) {
+                    	// after the command
+                        extra = parseTrailing(resource, Constants.RESOURCE_MONITOR_PING);
+                        
+                        logMetacat.debug("processing ping request");
+                        Date result = CNodeService.getInstance(request).ping();
+                        // TODO: send to output	
+                        status = true;
+                    }
+                } else if (resource.startsWith(Constants.RESOURCE_META_OBSOLETEDBY)
+                        && httpVerb == PUT) {
+
+                    logMetacat.debug("Using resource: "
+                            + Constants.RESOURCE_META_OBSOLETEDBY);
+                    // get the trailing pid
+                    extra = parseTrailing(resource, Constants.RESOURCE_META_OBSOLETEDBY);
+                    setObsoletedBy(extra);
+                    status = true;
+                } else if (resource.startsWith(Constants.RESOURCE_REPLICATION_DELETE_REPLICA)
+                        && httpVerb == PUT) {
+
+                    logMetacat.debug("Using resource: "
+                            + Constants.RESOURCE_REPLICATION_DELETE_REPLICA);
+                    // get the trailing pid
+                    extra = parseTrailing(resource, Constants.RESOURCE_REPLICATION_DELETE_REPLICA);
+                    deleteReplica(extra);
+                    status = true;
+                }
+
+                if (!status) {
+                    throw new ServiceFailure("0000", "Unknown error, status = "
+                            + status);
+                }
+            } else {
+                throw new InvalidRequest("0000", "No resource matched for "
+                        + resource);
+            }
+        } catch (BaseException be) {
+            // report Exceptions as clearly and generically as possible
+            OutputStream out = null;
+            try {
+                out = response.getOutputStream();
+            } catch (IOException ioe) {
+                logMetacat.error("Could not get output stream from response",
+                        ioe);
+            }
+            serializeException(be, out);
+        } catch (Exception e) {
+            // report Exceptions as clearly and generically as possible
+            logMetacat.error(e.getClass() + ": " + e.getMessage(), e);
+            OutputStream out = null;
+            try {
+                out = response.getOutputStream();
+            } catch (IOException ioe) {
+                logMetacat.error("Could not get output stream from response",
+                        ioe);
+            }
+            ServiceFailure se = new ServiceFailure("0000", e.getMessage());
+            serializeException(se, out);
+        }
+    }
+
+    /**
+     * Get the checksum for the given guid
+     * 
+     * @param guid
+     * @throws NotImplemented
+     * @throws InvalidRequest
+     * @throws NotFound
+     * @throws NotAuthorized
+     * @throws ServiceFailure
+     * @throws InvalidToken
+     * @throws IOException
+     * @throws JiBXException
+     */
+    private void checksum(String guid) throws InvalidToken, ServiceFailure,
+            NotAuthorized, NotFound, InvalidRequest, NotImplemented,
+            JiBXException, IOException {
+        Identifier guidid = new Identifier();
+        guidid.setValue(guid);
+        logMetacat.debug("getting checksum for object " + guid);
+        Checksum c = CNodeService.getInstance(request).getChecksum(session,
+                guidid);
+        logMetacat.debug("got checksum " + c.getValue());
+        response.setStatus(200);
+        logMetacat.debug("serializing response");
+        TypeMarshaller.marshalTypeToOutputStream(c, response.getOutputStream());
+        logMetacat.debug("done serializing response.");
+
+    }
+
+    /**
+     * get the logs based on passed params. Available params are token,
+     * fromDate, toDate, event. See
+     * http://mule1.dataone.org/ArchitectureDocs/mn_api_crud
+     * .html#MN_crud.getLogRecords for more info
+     * 
+     * @throws NotImplemented
+     * @throws InvalidRequest
+     * @throws NotAuthorized
+     * @throws ServiceFailure
+     * @throws InvalidToken
+     * @throws IOException
+     * @throws JiBXException
+     */
+    private void getLog() throws InvalidToken, ServiceFailure, NotAuthorized,
+            InvalidRequest, NotImplemented, IOException, JiBXException {
+
+        Date fromDate = null;
+        Date toDate = null;
+        String event = null;
+        Integer start = null;
+        Integer count = null;
+        String pidFilter = null;
+
+        try {
+            String fromDateS = params.get("fromDate")[0];
+            logMetacat.debug("param fromDateS: " + fromDateS);
+            fromDate = DateTimeMarshaller.deserializeDateToUTC(fromDateS);
+        } catch (Exception e) {
+            logMetacat.warn("Could not parse fromDate: " + e.getMessage());
+        }
+        try {
+            String toDateS = params.get("toDate")[0];
+            logMetacat.debug("param toDateS: " + toDateS);
+            toDate = DateTimeMarshaller.deserializeDateToUTC(toDateS);
+        } catch (Exception e) {
+            logMetacat.warn("Could not parse toDate: " + e.getMessage());
+        }
+        try {
+            event = params.get("event")[0];
+        } catch (Exception e) {
+            logMetacat.warn("Could not parse event: " + e.getMessage());
+        }
+        logMetacat.debug("fromDate: " + fromDate + " toDate: " + toDate);
+
+        try {
+            start = Integer.parseInt(params.get("start")[0]);
+        } catch (Exception e) {
+            logMetacat.warn("Could not parse start: " + e.getMessage());
+        }
+        try {
+            count = Integer.parseInt(params.get("count")[0]);
+        } catch (Exception e) {
+            logMetacat.warn("Could not parse count: " + e.getMessage());
+        }
+
+        try {
+            pidFilter = params.get("pidFilter")[0];
+        } catch (Exception e) {
+            logMetacat.warn("Could not parse pidFilter: " + e.getMessage());
+        }
+        
+        logMetacat.debug("calling getLogRecords");
+        Log log = CNodeService.getInstance(request).getLogRecords(session,
+                fromDate, toDate, event, pidFilter, start, count);
+
+        OutputStream out = response.getOutputStream();
+        response.setStatus(200);
+        response.setContentType("text/xml");
+
+        TypeMarshaller.marshalTypeToOutputStream(log, out);
+
+    }
+
+    /**
+     * Implements REST version of DataONE CRUD API --> get
+     * 
+     * @param guid
+     *            ID of data object to be read
+     * @throws NotImplemented
+     * @throws InvalidRequest
+     * @throws NotFound
+     * @throws NotAuthorized
+     * @throws ServiceFailure
+     * @throws InvalidToken
+     * @throws IOException
+     */
+    protected void getObject(String guid) throws InvalidToken, ServiceFailure,
+            NotAuthorized, NotFound, InvalidRequest, NotImplemented,
+            IOException {
+
+        Identifier id = new Identifier();
+        id.setValue(guid);
+
+        SystemMetadata sm = CNodeService.getInstance(request)
+                .getSystemMetadata(session, id);
+
+        // set the headers for the content
+        String mimeType = ObjectFormatInfo.instance().getMimeType(sm.getFormatId().getValue());
+        if (mimeType == null) {
+        	mimeType = "application/octet-stream";
+        }
+        String extension = ObjectFormatInfo.instance().getExtension(sm.getFormatId().getValue());
+        String filename = id.getValue();
+        if (extension != null) {
+        	filename = id.getValue() + extension;
+        }
+        response.setContentType(mimeType);
+        response.setHeader("Content-Disposition", "inline; filename=" + filename);
+
+        InputStream data = CNodeService.getInstance(request).get(session, id);
+
+        OutputStream out = response.getOutputStream();
+        response.setStatus(200);
+        IOUtils.copyLarge(data, out);
+
+    }
+
+    /**
+     * Implements REST version of DataONE CRUD API --> getSystemMetadata
+     * 
+     * @param guid
+     *            ID of data object to be read
+     * @throws NotImplemented
+     * @throws InvalidRequest
+     * @throws NotFound
+     * @throws NotAuthorized
+     * @throws ServiceFailure
+     * @throws InvalidToken
+     * @throws IOException
+     * @throws JiBXException
+     */
+    protected void getSystemMetadataObject(String guid) throws InvalidToken,
+            ServiceFailure, NotAuthorized, NotFound, InvalidRequest,
+            NotImplemented, IOException, JiBXException {
+
+        Identifier id = new Identifier();
+        id.setValue(guid);
+        SystemMetadata sysmeta = CNodeService.getInstance(request)
+                .getSystemMetadata(session, id);
+
+        response.setContentType("text/xml");
+        response.setStatus(200);
+        OutputStream out = response.getOutputStream();
+
+        // Serialize and write it to the output stream
+        TypeMarshaller.marshalTypeToOutputStream(sysmeta, out);
+    }
+
+    /**
+     * Earthgrid API > Put Service >Put Function : calls MetacatHandler >
+     * handleInsertOrUpdateAction
+     * 
+     * @param guid
+     *            - ID of data object to be inserted or updated. If action is
+     *            update, the pid is the existing pid. If insert, the pid is the
+     *            new one
+     * @throws InvalidRequest
+     * @throws ServiceFailure
+     * @throws IdentifierNotUnique
+     * @throws JiBXException
+     * @throws NotImplemented
+     * @throws InvalidSystemMetadata
+     * @throws InsufficientResources
+     * @throws UnsupportedType
+     * @throws NotAuthorized
+     * @throws InvalidToken
+     * @throws IOException
+     * @throws IllegalAccessException
+     * @throws InstantiationException
+     */
+    protected void putObject(String action) throws ServiceFailure,
+            InvalidRequest, IdentifierNotUnique, JiBXException, InvalidToken,
+            NotAuthorized, UnsupportedType, InsufficientResources,
+            InvalidSystemMetadata, NotImplemented, IOException,
+            InstantiationException, IllegalAccessException {
+    	
+        // Read the incoming data from its Mime Multipart encoding
+        Map<String, File> files = collectMultipartFiles();
+        
+	    // get the encoded pid string from the body and make the object
+        String pidString = multipartparams.get("pid").get(0);
+        Identifier pid = new Identifier();
+        pid.setValue(pidString);
+        
+        logMetacat.debug("putObject: " + pid.getValue() + "/" + action);
+        
+        InputStream object = null;
+        InputStream sysmeta = null;
+
+        File smFile = files.get("sysmeta");
+        sysmeta = new FileInputStream(smFile);
+        File objFile = files.get("object");
+        object = new FileInputStream(objFile);
+
+        if (action.equals(FUNCTION_NAME_INSERT)) { // handle inserts
+
+            logMetacat.debug("Commence creation...");
+            SystemMetadata smd = TypeMarshaller.unmarshalTypeFromStream(
+                    SystemMetadata.class, sysmeta);
+
+           
+            logMetacat.debug("creating object with pid " + pid.getValue());
+            Identifier rId = CNodeService.getInstance(request).create(session, pid, object, smd);
+
+            OutputStream out = response.getOutputStream();
+            response.setStatus(200);
+            response.setContentType("text/xml");
+
+            TypeMarshaller.marshalTypeToOutputStream(rId, out);
+
+        } else {
+            throw new InvalidRequest("1000", "Operation must be create.");
+        }
+    }
+
+    /**
+     * List the object formats registered with the system
+     * 
+     * @throws NotImplemented
+     * @throws InsufficientResources
+     * @throws NotFound
+     * @throws ServiceFailure
+     * @throws InvalidRequest
+     * @throws IOException
+     * @throws JiBXException
+     */
+    private void listFormats() throws InvalidRequest, ServiceFailure, NotFound,
+            InsufficientResources, NotImplemented, IOException, JiBXException {
+        logMetacat.debug("Entering listFormats()");
+
+        ObjectFormatList objectFormatList = CNodeService.getInstance(request)
+                .listFormats();
+        // get the response output stream
+        OutputStream out = response.getOutputStream();
+        response.setStatus(200);
+        response.setContentType("text/xml");
+
+        // style the object with a processing directive
+        String stylesheet = null;
+        try {
+            stylesheet = PropertyService.getProperty("dataone.types.xsl");
+        } catch (PropertyNotFoundException e) {
+            logMetacat.warn("Could not locate DataONE types XSLT: "
+                    + e.getMessage());
+        }
+
+        TypeMarshaller.marshalTypeToOutputStream(objectFormatList, out,
+                stylesheet);
+
+    }
+    
+    private void listChecksumAlgorithms() throws IOException, ServiceFailure,
+			NotImplemented, JiBXException {
+		logMetacat.debug("Entering listFormats()");
+
+		ChecksumAlgorithmList result = CNodeService.getInstance(request).listChecksumAlgorithms();
+
+		// get the response output stream
+		OutputStream out = response.getOutputStream();
+		response.setStatus(200);
+		response.setContentType("text/xml");
+
+		TypeMarshaller.marshalTypeToOutputStream(result, out);
+
+	}
+    
+    /**
+     * http://mule1.dataone.org/ArchitectureDocs-current/apis/CN_APIs.html#CNRead.describe
+     * @param pid
+     * @throws InvalidToken
+     * @throws ServiceFailure
+     * @throws NotAuthorized
+     * @throws NotFound
+     * @throws NotImplemented
+     * @throws InvalidRequest
+     */
+    private void describeObject(String pid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, InvalidRequest
+    {
+        response.setContentType("text/xml");
+        
+        Identifier id = new Identifier();
+        id.setValue(pid);
+        
+        DescribeResponse dr = null;
+        try {
+            dr = CNodeService.getInstance(request).describe(session, id);
+        } catch (BaseException e) {
+        	response.setStatus(e.getCode());
+        	response.addHeader("DataONE-Exception-Name", e.getClass().getName());
+            response.addHeader("DataONE-Exception-DetailCode", e.getDetail_code());
+            response.addHeader("DataONE-Exception-Description", e.getDescription());
+            response.addHeader("DataONE-Exception-PID", id.getValue());
+            return;
+		}
+        
+        response.setStatus(200);
+        //response.addHeader("pid", pid);
+        response.addHeader("DataONE-Checksum", dr.getDataONE_Checksum().getAlgorithm() + "," + dr.getDataONE_Checksum().getValue());
+        response.addHeader("Content-Length", dr.getContent_Length() + "");
+        response.addHeader("Last-Modified", DateTimeMarshaller.serializeDateToUTC(dr.getLast_Modified()));
+        response.addHeader("DataONE-ObjectFormat", dr.getDataONE_ObjectFormatIdentifier().getValue());
+        response.addHeader("DataONE-SerialVersion", dr.getSerialVersion().toString());
+
+    }
+    
+    /**
+     * Handle delete 
+     * @param pid ID of data object to be deleted
+     * @throws IOException
+     * @throws InvalidRequest 
+     * @throws NotImplemented 
+     * @throws NotFound 
+     * @throws NotAuthorized 
+     * @throws ServiceFailure 
+     * @throws InvalidToken 
+     * @throws JiBXException 
+     */
+    private void deleteObject(String pid) throws IOException, InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, InvalidRequest, JiBXException 
+    {
+
+        OutputStream out = response.getOutputStream();
+        response.setStatus(200);
+        response.setContentType("text/xml");
+
+        Identifier id = new Identifier();
+        id.setValue(pid);
+
+        logMetacat.debug("Calling delete for identifier " + pid);
+        CNodeService.getInstance(request).delete(session, id);
+        TypeMarshaller.marshalTypeToOutputStream(id, out);
+        
+    }
+    
+    /**
+     * Archives the given pid
+     * @param pid
+     * @throws InvalidToken
+     * @throws ServiceFailure
+     * @throws NotAuthorized
+     * @throws NotFound
+     * @throws NotImplemented
+     * @throws IOException
+     * @throws JiBXException
+     */
+    private void archive(String pid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, IOException, JiBXException {
+
+        OutputStream out = response.getOutputStream();
+        response.setStatus(200);
+        response.setContentType("text/xml");
+
+        Identifier id = new Identifier();
+        id.setValue(pid);
+
+        logMetacat.debug("Calling archive");
+        CNodeService.getInstance(request).archive(session, id);
+        
+        TypeMarshaller.marshalTypeToOutputStream(id, out);
+        
+    }
+
+    /**
+     * Return the requested object format
+     * 
+     * @param fmtidStr
+     *            the requested format identifier as a string
+     * @throws NotImplemented
+     * @throws InsufficientResources
+     * @throws NotFound
+     * @throws ServiceFailure
+     * @throws InvalidRequest
+     * @throws IOException
+     * @throws JiBXException
+     */
+    private void getFormat(String fmtidStr) throws InvalidRequest,
+            ServiceFailure, NotFound, InsufficientResources, NotImplemented,
+            IOException, JiBXException {
+        logMetacat.debug("Entering listFormats()");
+
+        ObjectFormatIdentifier fmtid = new ObjectFormatIdentifier();
+        fmtid.setValue(fmtidStr);
+
+        // get the specified object format
+        ObjectFormat objectFormat = CNodeService.getInstance(request)
+                .getFormat(fmtid);
+
+        OutputStream out = response.getOutputStream();
+        response.setStatus(200);
+        response.setContentType("text/xml");
+
+        TypeMarshaller.marshalTypeToOutputStream(objectFormat, out);
+
+    }
+
+    /**
+     * Reserve the given Identifier
+     * 
+     * @throws InvalidToken
+     * @throws ServiceFailure
+     * @throws NotAuthorized
+     * @throws IdentifierNotUnique
+     * @throws NotImplemented
+     * @throws InvalidRequest
+     */
+    private void reserve() 
+        throws InvalidToken, ServiceFailure, NotAuthorized, IdentifierNotUnique, 
+        NotImplemented, InvalidRequest {
+        Identifier pid = null;
+        String scope = null;
+        String format = null;
+
+        // Parse the params out of the multipart form data
+        logMetacat.debug("Parsing reserve parameters from the mime multipart entity");
+        try {
+            collectMultipartParams();
+            
+        } catch (FileUploadException e1) {
+            String msg = "FileUploadException: Couldn't parse the mime multipart information: " +
+            e1.getMessage();
+            logMetacat.debug(msg);
+            throw new ServiceFailure("4210", msg);
+
+        } catch (IOException e1) {
+            String msg = "IOException: Couldn't parse the mime multipart information: " +
+            e1.getMessage();
+            logMetacat.debug(msg);
+            throw new ServiceFailure("4210", msg);
+        
+        } catch (Exception e1) {
+            String msg = "Exception: Couldn't parse the mime multipart information: " +
+            e1.getMessage();
+            logMetacat.debug(msg);
+            throw new ServiceFailure("4210", msg);
+
+        }
+        
+        // gather the params
+        try {
+            String id = multipartparams.get("pid").get(0);
+            pid = new Identifier();
+            pid.setValue(id);
+            
+        } catch (NullPointerException e) {
+            String msg = "The 'pid' must be provided as a parameter and was not.";
+            logMetacat.error(msg);
+            throw new InvalidRequest("4200", msg);
+ 
+        }
+        
+        // call the implementation
+        try {
+            Identifier resultPid = CNodeService.getInstance(request).reserveIdentifier(session, pid);
+            OutputStream out = response.getOutputStream();
+            response.setStatus(200);
+            response.setContentType("text/xml");
+            // send back the reserved pid
+            TypeMarshaller.marshalTypeToOutputStream(resultPid, out);
+            
+        } catch (IOException e) {
+            String msg = "Couldn't write the identifier to the response output stream: " +
+                e.getMessage();
+            logMetacat.debug(msg);
+            throw new ServiceFailure("4210", msg);
+        
+        } catch (JiBXException e) {
+            String msg = "Couldn't marshall the identifier to the response output stream: " +
+            e.getMessage();
+            logMetacat.debug(msg);
+            throw new ServiceFailure("4210", msg);
+            
+        }
+    }
+
+    /**
+     * 
+     * @param id
+     * @throws InvalidRequest
+     * @throws InvalidToken
+     * @throws ServiceFailure
+     * @throws NotAuthorized
+     * @throws NotFound
+     * @throws NotImplemented
+     * @throws IOException
+     * @throws JiBXException
+     */
+    private void resolve(String id) throws InvalidRequest, InvalidToken,
+            ServiceFailure, NotAuthorized, NotFound, NotImplemented,
+            IOException, JiBXException {
+        Identifier pid = new Identifier();
+        pid.setValue(id);
+        ObjectLocationList locationList = CNodeService.getInstance(request)
+                .resolve(session, pid);
+        OutputStream out = response.getOutputStream();
+        response.setStatus(200);
+        response.setContentType("text/xml");
+        TypeMarshaller.marshalTypeToOutputStream(locationList, out);
+
+    }
+
+    /**
+     * Set the owner of a resource
+     * 
+     * @param id
+     * @throws InvalidToken
+     * @throws ServiceFailure
+     * @throws NotFound
+     * @throws NotAuthorized
+     * @throws NotImplemented
+     * @throws InvalidRequest
+     * @throws IllegalAccessException
+     * @throws InstantiationException
+     * @throws VersionMismatch 
+     */
+    private void owner(String id) 
+        throws InvalidToken, ServiceFailure, NotFound, NotAuthorized, 
+        NotImplemented, InvalidRequest, InstantiationException, 
+        IllegalAccessException, VersionMismatch {
+
+        Identifier pid = new Identifier();
+        pid.setValue(id);
+
+        long serialVersion = 0L;
+        String serialVersionStr = null;
+        String userIdStr = null;
+        Subject userId = null;
+        
+        // Parse the params out of the multipart form data
+        // Read the incoming data from its Mime Multipart encoding
+        logMetacat.debug("Parsing rights holder parameters from the mime multipart entity");
+        try {
+            collectMultipartParams();
+            
+        } catch (FileUploadException e1) {
+            String msg = "FileUploadException: Couldn't parse the mime multipart information: " +
+            e1.getMessage();
+            logMetacat.debug(msg);
+            throw new ServiceFailure("4490", msg);
+
+        } catch (IOException e1) {
+            String msg = "IOException: Couldn't parse the mime multipart information: " +
+            e1.getMessage();
+            logMetacat.debug(msg);
+            throw new ServiceFailure("4490", msg);
+        
+        } catch (Exception e1) {
+            String msg = "Exception: Couldn't parse the mime multipart information: " +
+            e1.getMessage();
+            logMetacat.debug(msg);
+            throw new ServiceFailure("4490", msg);
+
+        }
+        
+        // get the serialVersion
+        try {
+            serialVersionStr = multipartparams.get("serialVersion").get(0);
+            serialVersion = new Long(serialVersionStr).longValue();
+            
+        } catch (NumberFormatException nfe) {
+            String msg = "The 'serialVersion' must be provided as a positive integer and was not.";
+            logMetacat.error(msg);
+            throw new InvalidRequest("4442", msg);
+                        
+        } catch (NullPointerException e) {
+            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
+            logMetacat.error(msg);
+            throw new InvalidRequest("4442", msg);
+            
+        }
+
+        // get the subject userId that will become the rights holder
+        try {
+            userIdStr = multipartparams.get("userId").get(0);
+            userId = new Subject();
+            userId.setValue(userIdStr);
+                                    
+        } catch (NullPointerException e) {
+            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
+            logMetacat.error(msg);
+            throw new InvalidRequest("4442", msg);
+            
+        }
+
+        // set the rights holder
+        Identifier retPid = CNodeService.getInstance(request).setRightsHolder(session, pid, userId, serialVersion);
+        
+        try {
+            OutputStream out = response.getOutputStream();
+            response.setStatus(200);
+            response.setContentType("text/xml");
+            TypeMarshaller.marshalTypeToOutputStream(retPid, out);
+            
+        } catch (IOException e) {
+            String msg = "Couldn't write the identifier to the response output stream: " +
+                e.getMessage();
+            logMetacat.debug(msg);
+            throw new ServiceFailure("4490", msg);
+        
+        } catch (JiBXException e) {
+            String msg = "Couldn't marshall the identifier to the response output stream: " +
+            e.getMessage();
+            logMetacat.debug(msg);
+            throw new ServiceFailure("4490", msg);
+            
+        }
+    }
+
+    /**
+     * Processes the authorization check for given id
+     * 
+     * @param id
+     * @return
+     * @throws ServiceFailure
+     * @throws InvalidToken
+     * @throws NotFound
+     * @throws NotAuthorized
+     * @throws NotImplemented
+     * @throws InvalidRequest
+     */
+    private boolean isAuthorized(String id) throws ServiceFailure,
+            InvalidToken, NotFound, NotAuthorized, NotImplemented,
+            InvalidRequest {
+        Identifier pid = new Identifier();
+        pid.setValue(id);
+        String permission = params.get("action")[0];
+        boolean result = CNodeService.getInstance(request).isAuthorized(
+                session, pid, Permission.convert(permission));
+        response.setStatus(200);
+        response.setContentType("text/xml");
+        return result;
+    }
+
+    /**
+     * Register System Metadata without data or metadata object
+     * 
+     * @param pid
+     *            identifier for System Metadata entry
+     * @throws JiBXException
+     * @throws FileUploadException
+     * @throws IOException
+     * @throws InvalidRequest
+     * @throws ServiceFailure
+     * @throws InvalidSystemMetadata
+     * @throws NotAuthorized
+     * @throws NotImplemented
+     * @throws IllegalAccessException
+     * @throws InstantiationException
+     */
+    protected void registerSystemMetadata()
+            throws ServiceFailure, InvalidRequest, IOException,
+            FileUploadException, JiBXException, NotImplemented, NotAuthorized,
+            InvalidSystemMetadata, InstantiationException,
+            IllegalAccessException {
+    	
+    	// Read the incoming data from its Mime Multipart encoding
+        Map<String, File> files = collectMultipartFiles();
+        
+    	// get the encoded pid string from the body and make the object
+        String pidString = multipartparams.get("pid").get(0);
+        Identifier pid = new Identifier();
+        pid.setValue(pidString);
+        
+        logMetacat.debug("registerSystemMetadata: " + pid);
+
+        // get the system metadata from the request
+        File smFile = files.get("sysmeta");
+        FileInputStream sysmeta = new FileInputStream(smFile);
+        SystemMetadata systemMetadata = TypeMarshaller.unmarshalTypeFromStream(SystemMetadata.class, sysmeta);
+
+        logMetacat.debug("registering system metadata with pid " + pid.getValue());
+        Identifier retGuid = CNodeService.getInstance(request).registerSystemMetadata(session, pid, systemMetadata);
+
+        OutputStream out = response.getOutputStream();
+        response.setStatus(200);
+        response.setContentType("text/xml");
+        
+        TypeMarshaller.marshalTypeToOutputStream(retGuid, out);
+
+    }
+
+    /**
+     * set the access perms on a document
+     * 
+     * @throws JiBXException
+     * @throws InvalidRequest
+     * @throws NotImplemented
+     * @throws NotAuthorized
+     * @throws NotFound
+     * @throws ServiceFailure
+     * @throws InvalidToken
+     * @throws IllegalAccessException
+     * @throws InstantiationException
+     * @throws IOException
+     * @throws SAXException
+     * @throws ParserConfigurationException
+     * @throws VersionMismatch 
+     */
+    protected void setAccess(String pid) throws JiBXException, InvalidToken,
+            ServiceFailure, NotFound, NotAuthorized, NotImplemented,
+            InvalidRequest, IOException, InstantiationException,
+            IllegalAccessException, ParserConfigurationException, SAXException, VersionMismatch {
+
+        long serialVersion = 0L;
+        String serialVersionStr = null;
+        
+        // parse the accessPolicy
+        Map<String, File> files = collectMultipartFiles();        
+        AccessPolicy accessPolicy = TypeMarshaller.unmarshalTypeFromFile(AccessPolicy.class, files.get("accessPolicy"));;
+
+        // get the serialVersion
+        try {
+            serialVersionStr = multipartparams.get("serialVersion").get(0);
+            serialVersion = new Long(serialVersionStr).longValue();
+
+        } catch (NumberFormatException nfe) {
+            String msg = "The 'serialVersion' must be provided as a positive integer and was not.";
+            logMetacat.error(msg);
+            throw new InvalidRequest("4402", msg);
+            
+        } catch (NullPointerException e) {
+            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
+            logMetacat.error(msg);
+            throw new InvalidRequest("4402", msg);
+
+        }
+
+        Identifier id = new Identifier();
+        id.setValue(pid);
+
+        CNodeService.getInstance(request).setAccessPolicy(session, id,
+                accessPolicy, serialVersion);
+
+    }
+
+    /**
+     * List the objects
+     * 
+     * @throws NotImplemented
+     * @throws InvalidRequest
+     * @throws NotAuthorized
+     * @throws ServiceFailure
+     * @throws InvalidToken
+     * @throws NotFound
+     * @throws IOException
+     * @throws JiBXException
+     * @throws Exception
+     */
+    private void listObjects() throws InvalidToken, ServiceFailure,
+            NotAuthorized, InvalidRequest, NotImplemented, NotFound,
+            IOException, JiBXException {
+
+        Date startTime = null;
+        Date endTime = null;
+        ObjectFormatIdentifier formatId = null;
+        Identifier identifier = null;
+        boolean replicaStatus = true;
+        int start = 0;
+        int count = 1000;
+        Enumeration<String> paramlist = request.getParameterNames();
+        while (paramlist.hasMoreElements()) {
+            // parse the params and make the call
+            String name = paramlist.nextElement();
+            String[] values = request.getParameterValues(name);
+            String value = null;
+            if (values != null && values.length > 0) {
+            	value = values[0];
+            	value = EncodingUtilities.decodeString(value);
+            }
+
+            if (name.equals("fromDate") && value != null) {
+                try {
+                    startTime = DateTimeMarshaller.deserializeDateToUTC(value);
+                } catch (Exception e) {
+                    // if we can't parse it, just don't use the startTime param
+                    logMetacat.warn("Could not parse fromDate: " + value);
+                    startTime = null;
+                }
+            } else if (name.equals("toDate") && value != null) {
+                try {
+                    endTime = DateTimeMarshaller.deserializeDateToUTC(value);
+                } catch (Exception e) {
+                    // if we can't parse it, just don't use the endTime param
+                    logMetacat.warn("Could not parse toDate: " + value);
+                    endTime = null;
+                }
+            } else if (name.equals("formatId") && value != null) {
+            	formatId = new ObjectFormatIdentifier();
+            	formatId.setValue(value);
+            } else if (name.equals("identifier") && value != null) {
+            	identifier = new Identifier();
+            	identifier.setValue(value);
+            } else if (name.equals("replicaStatus") && value != null) {
+                replicaStatus = Boolean.parseBoolean(value);
+            } else if (name.equals("start") && value != null) {
+                start = Integer.valueOf(value);
+            } else if (name.equals("count") && value != null) {
+                count = Integer.valueOf(value);
+            }
+        }
+        // make the call
+        logMetacat.debug("session: " + session + " fromDate: " + startTime
+                + " toDate: " + endTime + " formatId: " + formatId
+                + " replicaStatus: " + replicaStatus + " start: " + start
+                + " count: " + count);        
+
+        // get the list
+        ObjectList ol = CNodeService.getInstance(request).listObjects(session,
+                startTime, endTime, formatId, identifier, replicaStatus, start, count);
+
+        // send it
+        OutputStream out = response.getOutputStream();
+        response.setStatus(200);
+        response.setContentType("text/xml");
+
+        // style the object with a processing directive
+        String stylesheet = null;
+        try {
+            stylesheet = PropertyService.getProperty("dataone.types.xsl");
+        } catch (PropertyNotFoundException e) {
+            logMetacat.warn("Could not locate DataONE types XSLT: "
+                    + e.getMessage());
+        }
+
+        // Serialize and write it to the output stream
+        TypeMarshaller.marshalTypeToOutputStream(ol, out, stylesheet);
+    }
+
+    /**
+     * Pass the request to get node replication authorization to CNodeService
+     * 
+     * @param pid
+     *            the identifier of the object to get authorization to replicate
+     * 
+     * @throws NotImplemented
+     * @throws NotAuthorized
+     * @throws InvalidToken
+     * @throws ServiceFailure
+     * @throws NotFound
+     * @throws InvalidRequest
+     */
+    public boolean isNodeAuthorized(String pid) throws NotImplemented,
+            NotAuthorized, InvalidToken, ServiceFailure, NotFound,
+            InvalidRequest {
+
+        boolean result = false;
+        Subject targetNodeSubject = new Subject();
+        String nodeSubject = null;
+        String replPermission = null;
+
+        // get the pid
+        Identifier identifier = new Identifier();
+        identifier.setValue(pid);
+
+        // get the target node subject
+        try {
+            nodeSubject = params.get("targetNodeSubject")[0];
+            targetNodeSubject.setValue(nodeSubject);
+
+        } catch (NullPointerException e) {
+            String msg = "The 'targetNodeSubject' must be provided as a parameter and was not.";
+            logMetacat.error(msg);
+            throw new InvalidRequest("4873", msg);
+
+        }
+
+        result = CNodeService.getInstance(request).isNodeAuthorized(session, targetNodeSubject, identifier);
+
+        response.setStatus(200);
+        response.setContentType("text/xml");
+        return result;
+
+    }
+
+    /**
+     * Pass the request to set the replication policy to CNodeService
+     * 
+     * @param pid
+     *            the identifier of the object to set the replication policy on
+     * 
+     * @throws NotImplemented
+     * @throws NotFound
+     * @throws NotAuthorized
+     * @throws ServiceFailure
+     * @throws InvalidRequest
+     * @throws InvalidToken
+     * @throws IOException
+     * @throws InstantiationException
+     * @throws IllegalAccessException
+     * @throws JiBXException
+     * @throws VersionMismatch 
+     */
+    public boolean setReplicationPolicy(String pid) throws NotImplemented,
+            NotFound, NotAuthorized, ServiceFailure, InvalidRequest,
+            InvalidToken, IOException, InstantiationException,
+            IllegalAccessException, JiBXException, VersionMismatch {
+
+        boolean result = false;
+        long serialVersion = 0L;
+        String serialVersionStr = null;
+
+        Identifier identifier = new Identifier();
+        identifier.setValue(pid);
+
+        // parse the policy
+        Map<String, File> files = collectMultipartFiles();        
+        ReplicationPolicy policy = TypeMarshaller.unmarshalTypeFromFile(ReplicationPolicy.class, files.get("policy"));
+
+        // get the serialVersion
+        try {
+            serialVersionStr = multipartparams.get("serialVersion").get(0);
+            serialVersion = new Long(serialVersionStr).longValue();
+
+        } catch (NullPointerException e) {
+            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
+            logMetacat.error(msg);
+            throw new InvalidRequest("4883", msg);
+
+        }
+        result = CNodeService.getInstance(request).setReplicationPolicy(
+                session, identifier, policy, serialVersion);
+        response.setStatus(200);
+        response.setContentType("text/xml");
+        return result;
+
+    }
+    
+    /**
+     * Update the system metadata for a given pid, setting it to be obsoleted
+     * by the obsoletedByPid
+     *  
+     * @param pid
+     * @return
+     * @throws NotImplemented
+     * @throws NotFound
+     * @throws NotAuthorized
+     * @throws ServiceFailure
+     * @throws InvalidRequest
+     * @throws InvalidToken
+     * @throws InstantiationException
+     * @throws IllegalAccessException
+     * @throws VersionMismatch
+     */
+    public boolean setObsoletedBy(String pid) 
+        throws NotImplemented, NotFound, NotAuthorized, ServiceFailure, 
+        InvalidRequest, InvalidToken, InstantiationException, 
+        IllegalAccessException, VersionMismatch {
+
+        boolean result = false;
+        long serialVersion = 0L;
+        String serialVersionStr = null;
+
+        Identifier identifier = new Identifier();
+        identifier.setValue(pid);
+        String obsoletedByPidString = null;
+        Identifier obsoletedByPid = null;
+
+        // Parse the params out of the multipart form data
+        // Read the incoming data from its Mime Multipart encoding
+        logMetacat.debug("Parsing rights holder parameters from the mime multipart entity");
+        try {
+            collectMultipartParams();
+            
+        } catch (FileUploadException e1) {
+            String msg = "FileUploadException: Couldn't parse the mime multipart information: " +
+            e1.getMessage();
+            logMetacat.debug(msg);
+            throw new ServiceFailure("4941", msg);
+
+        } catch (IOException e1) {
+            String msg = "IOException: Couldn't parse the mime multipart information: " +
+            e1.getMessage();
+            logMetacat.debug(msg);
+            throw new ServiceFailure("4941", msg);
+        
+        } catch (Exception e1) {
+            String msg = "Exception: Couldn't parse the mime multipart information: " +
+            e1.getMessage();
+            logMetacat.debug(msg);
+            throw new ServiceFailure("4941", msg);
+
+        }
+
+        // get the obsoletedByPid
+        try {
+            obsoletedByPidString = multipartparams.get("obsoletedByPid").get(0);
+            obsoletedByPid = new Identifier();
+            obsoletedByPid.setValue(obsoletedByPidString);
+        } catch (NullPointerException e) {
+            String msg = "The 'obsoletedByPid' must be provided as a parameter and was not.";
+            logMetacat.error(msg);
+            throw new InvalidRequest("4883", msg);
+        }
+
+        // get the serialVersion
+        try {
+            serialVersionStr = multipartparams.get("serialVersion").get(0);
+            serialVersion = new Long(serialVersionStr).longValue();
+            
+        } catch (NumberFormatException nfe) {
+            String msg = "The 'serialVersion' must be provided as a positive integer and was not.";
+            logMetacat.error(msg);
+            throw new InvalidRequest("4942", msg);
+                        
+        } catch (NullPointerException e) {
+            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
+            logMetacat.error(msg);
+            throw new InvalidRequest("4942", msg);
+            
+        }
+        result = CNodeService.getInstance(request).setObsoletedBy(session,
+            identifier, obsoletedByPid, serialVersion);
+        response.setStatus(200);
+        response.setContentType("text/xml");
+        return result;
+
+    }
+    
+    /**
+     * Delete the replica entry with the given nodeId for the given pid
+     * 
+     * @param pid
+     * @return
+     * @throws NotImplemented
+     * @throws NotFound
+     * @throws NotAuthorized
+     * @throws ServiceFailure
+     * @throws InvalidRequest
+     * @throws InvalidToken
+     * @throws InstantiationException
+     * @throws IllegalAccessException
+     * @throws VersionMismatch
+     */
+    public boolean deleteReplica(String pid) 
+        throws NotImplemented, NotFound, NotAuthorized, ServiceFailure, 
+        InvalidRequest, InvalidToken, InstantiationException, 
+        IllegalAccessException, VersionMismatch {
+
+        boolean result = false;
+        long serialVersion = 0L;
+        String serialVersionStr = null;
+
+        Identifier identifier = new Identifier();
+        identifier.setValue(pid);
+
+        NodeReference nodeId = null;
+        
+        // Parse the params out of the multipart form data
+        // Read the incoming data from its Mime Multipart encoding
+        logMetacat.debug("Parsing delete replica parameters from the mime multipart entity");
+        try {
+            collectMultipartParams();
+            
+        } catch (FileUploadException e1) {
+            String msg = "FileUploadException: Couldn't parse the mime multipart information: " +
+            e1.getMessage();
+            logMetacat.debug(msg);
+            throw new ServiceFailure("4951", msg);
+
+        } catch (IOException e1) {
+            String msg = "IOException: Couldn't parse the mime multipart information: " +
+            e1.getMessage();
+            logMetacat.debug(msg);
+            throw new ServiceFailure("4951", msg);
+        
+        } catch (Exception e1) {
+            String msg = "Exception: Couldn't parse the mime multipart information: " +
+            e1.getMessage();
+            logMetacat.debug(msg);
+            throw new ServiceFailure("4951", msg);
+
+        }
+        
+        // get the nodeId param
+        try {
+            String nodeIdString = multipartparams.get("nodeId").get(0);
+            nodeId = new NodeReference();
+            nodeId.setValue(nodeIdString);
+            
+        } catch (NullPointerException e) {
+            String msg = "The 'nodeId' must be provided as a parameter and was not.";
+            logMetacat.error(msg);
+            throw new InvalidRequest("4952", msg);
+        }
+
+        // get the serialVersion
+        try {
+            serialVersionStr = multipartparams.get("serialVersion").get(0);
+            serialVersion = new Long(serialVersionStr).longValue();
+            
+        } catch (NumberFormatException nfe) {
+            String msg = "The 'serialVersion' must be provided as a positive integer and was not.";
+            logMetacat.error(msg);
+            throw new InvalidRequest("4952", msg);
+                        
+        } catch (NullPointerException e) {
+            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
+            logMetacat.error(msg);
+            throw new InvalidRequest("4952", msg);
+            
+        }
+        result = CNodeService.getInstance(request).deleteReplicationMetadata(
+                session, identifier, nodeId, serialVersion);
+        response.setStatus(200);
+        response.setContentType("text/xml");
+        return result;
+
+    }
+
+    /**
+     * Pass the request to set the replication status to CNodeService
+     * 
+     * @param pid
+     *            the identifier of the object to set the replication status on
+     * 
+     * @throws ServiceFailure
+     * @throws NotImplemented
+     * @throws InvalidToken
+     * @throws NotAuthorized
+     * @throws InvalidRequest
+     * @throws NotFound
+     * @throws JiBXException 
+     * @throws IllegalAccessException 
+     * @throws InstantiationException 
+     * @throws IOException 
+     */
+    public boolean setReplicationStatus(String pid) throws ServiceFailure,
+            NotImplemented, InvalidToken, NotAuthorized, InvalidRequest,
+            NotFound {
+        
+        boolean result = false;
+        Identifier identifier = new Identifier();
+        identifier.setValue(pid);
+        BaseException failure = null;
+        ReplicationStatus status = null;
+        String replicationStatus = null;
+        NodeReference targetNodeRef = null;
+        String targetNode = null;
+
+        // Parse the params out of the multipart form data
+        // Read the incoming data from its Mime Multipart encoding
+        logMetacat.debug("Parsing ReplicaStatus from the mime multipart entity");
+
+        try {
+        	// parse the policy
+            Map<String, File> files = collectMultipartFiles();        
+            failure = ExceptionHandler.deserializeXml(new FileInputStream(files.get("failure")), 
+                    "Replication failed for an unknown reason.");
+            
+        } catch (Exception e2) {
+            throw new ServiceFailure("4700", "Couldn't resolve the multipart request: " +
+                e2.getMessage());
+            
+        }
+        
+        // get the replication status param
+        try {
+            replicationStatus = multipartparams.get("status").get(0);
+            status = ReplicationStatus.convert(replicationStatus);
+
+        } catch (NullPointerException npe) {
+
+            logMetacat.debug("The 'status' parameter was not found in the "
+                    + "multipartparams map.  Trying the params map.");
+
+            try {
+                replicationStatus = params.get("status")[0];
+                status = ReplicationStatus.convert(replicationStatus
+                        .toLowerCase());
+
+            } catch (Exception e) {
+                String msg = "The 'status' must be provided as a parameter and was not.";
+                logMetacat.error(msg);
+                throw new InvalidRequest("4730", msg);
+
+            }
+
+        }
+
+        // get the target node reference param
+        try {
+            targetNode = multipartparams.get("nodeRef").get(0);
+            targetNodeRef = new NodeReference();
+            targetNodeRef.setValue(targetNode);
+
+        } catch (NullPointerException e) {
+            logMetacat.debug("The 'nodeRef' parameter was not found in the "
+                    + "multipartparams map.  Trying the params map.");
+
+            try {
+                targetNode = params.get("nodeRef")[0];
+                targetNodeRef = new NodeReference();
+                targetNodeRef.setValue(targetNode);
+
+            } catch (Exception e1) {
+                String msg = "The 'nodeRef' must be provided as a parameter and was not.";
+                logMetacat.error(msg);
+                throw new InvalidRequest("4730", msg);
+
+            }
+
+        }
+
+        result = CNodeService.getInstance(request).setReplicationStatus(
+                session, identifier, targetNodeRef, status, failure);
+        response.setStatus(200);
+        response.setContentType("text/xml");
+        return result;
+
+    }
+
+    /**
+     * Pass the request to update the replication metadata to CNodeService
+     * 
+     * @param pid
+     *            the identifier of the object to update the replication
+     *            metadata on
+     * 
+     * @throws ServiceFailure
+     * @throws NotImplemented
+     * @throws InvalidToken
+     * @throws NotAuthorized
+     * @throws InvalidRequest
+     * @throws NotFound
+     * @throws VersionMismatch 
+     * @throws JiBXException 
+     * @throws IOException 
+     * @throws IllegalAccessException 
+     * @throws InstantiationException 
+     */
+    public boolean updateReplicationMetadata(String pid) throws ServiceFailure,
+            NotImplemented, InvalidToken, NotAuthorized, InvalidRequest,
+            NotFound, VersionMismatch, InstantiationException, IllegalAccessException, IOException, JiBXException {
+
+        boolean result = false;
+        long serialVersion = 0L;
+        String serialVersionStr = null;
+        Identifier identifier = new Identifier();
+        identifier.setValue(pid);
+
+        // parse the replica
+        Map<String, File> files = collectMultipartFiles();        
+        Replica replica = TypeMarshaller.unmarshalTypeFromFile(Replica.class, files.get("replicaMetadata"));
+
+        // get the serialVersion
+        try {
+            serialVersionStr = multipartparams.get("serialVersion").get(0);
+            serialVersion = new Long(serialVersionStr).longValue();
+
+        } catch (NullPointerException e) {
+            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
+            logMetacat.error(msg);
+            throw new InvalidRequest("4853", msg);
+
+        }
+
+        result = CNodeService.getInstance(request).updateReplicationMetadata(
+                session, identifier, replica, serialVersion);
+        response.setStatus(200);
+        response.setContentType("text/xml");
+        return result;
+
+    }
+
+}

Property changes on: src/edu/ucsb/nceas/metacat/restservice/v2/CNResourceHandler.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property
Index: src/edu/ucsb/nceas/metacat/restservice/D1ResourceHandler.java
===================================================================
--- src/edu/ucsb/nceas/metacat/restservice/D1ResourceHandler.java	(revision 8809)
+++ src/edu/ucsb/nceas/metacat/restservice/D1ResourceHandler.java	(revision 8810)
@@ -23,8 +23,6 @@
 package edu.ucsb.nceas.metacat.restservice;
 
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -41,7 +39,6 @@
 import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import javax.xml.parsers.ParserConfigurationException;
 
 import org.apache.commons.fileupload.FileUploadException;
 import org.apache.commons.io.IOUtils;
@@ -53,19 +50,11 @@
 import org.dataone.service.exceptions.BaseException;
 import org.dataone.service.exceptions.InvalidRequest;
 import org.dataone.service.exceptions.ServiceFailure;
-import org.dataone.service.types.v1.AccessPolicy;
 import org.dataone.service.types.v1.Group;
 import org.dataone.service.types.v1.Person;
-import org.dataone.service.types.v1.Replica;
-import org.dataone.service.types.v1.ReplicationPolicy;
 import org.dataone.service.types.v1.Session;
 import org.dataone.service.types.v1.Subject;
 import org.dataone.service.types.v1.SubjectInfo;
-import org.dataone.service.types.v1.SystemMetadata;
-import org.dataone.service.util.ExceptionHandler;
-import org.dataone.service.util.TypeMarshaller;
-import org.jibx.runtime.JiBXException;
-import org.xml.sax.SAXException;
 
 import edu.ucsb.nceas.metacat.MetacatHandler;
 import edu.ucsb.nceas.metacat.properties.PropertyService;
@@ -249,88 +238,6 @@
     }
 
     /**
-     * Parse the BaseException information for replication status failures if any
-     * 
-     * @return failure  the BaseException failure, one of it's subclasses, or null
-     * @throws ServiceFailure
-     * @throws InvalidRequest
-     * @throws JiBXException 
-     * @throws IllegalAccessException 
-     * @throws InstantiationException 
-     * @throws IOException 
-     */
-    protected BaseException collectReplicationStatus() 
-        throws ServiceFailure, InvalidRequest, IOException, 
-        InstantiationException, IllegalAccessException, JiBXException {
-        
-        BaseException failure = null;
-        File tmpDir = getTempDirectory();
-        MultipartRequest mr = null;
-        Map<String, File> mmFileParts = null;
-        File exceptionFile = null;
-        InputStream exceptionFileStream = null;
-
-        // Read the incoming data from its Mime Multipart encoding
-        logMetacat.debug("Parsing BaseException from the mime multipart entity");
-
-        // handle MMP inputs
-        MultipartRequestResolver mrr = 
-            new MultipartRequestResolver(tmpDir.getAbsolutePath(),1000000000, 0);
-
-        try {
-            mr = mrr.resolveMultipart(request);
-            logMetacat.debug("Resolved the replication status BaseException multipart request.");
-            
-        } catch (IOException e) {
-            throw new ServiceFailure("4700", "Couldn't resolve the multipart request: " +
-                e.getMessage());
-            
-        } catch (FileUploadException e) {
-            throw new ServiceFailure("4700", "Couldn't resolve the multipart request: " +
-                e.getMessage());
-            
-        } catch (Exception e) {
-            throw new ServiceFailure("4700", "Couldn't resolve the multipart request: " +
-                e.getMessage());
-            
-        }
-
-        // get the map of file parts
-        mmFileParts = mr.getMultipartFiles();
-        
-        if ( mmFileParts == null || mmFileParts.keySet() == null) {
-            logMetacat.debug("BaseException for setReplicationStatus is null");            
-        }
-        
-        multipartparams = mr.getMultipartParameters();
-        exceptionFile = mmFileParts.get("failure");
-        
-        if ( exceptionFile != null && exceptionFile.length() > 0 ) {
-            
-            // deserialize the BaseException subclass
-            exceptionFileStream = new FileInputStream(exceptionFile);
-            try {
-                failure = ExceptionHandler.deserializeXml(exceptionFileStream, 
-                    "Replication failed for an unknown reason.");
-                
-            } catch (ParserConfigurationException e) {
-                throw new ServiceFailure("4700", "Couldn't parse the replication failure exception: " +
-                        e.getMessage());
-                
-            } catch (SAXException e) {
-                throw new ServiceFailure("4700", "Couldn't traverse the replication failure exception: " +
-                        e.getMessage());
-                
-            }
-                
-        }
-        
-        
-        return failure;
-        
-    }
-
-    /**
      * Parse string parameters from the mime multipart entity of the request.
      * Populates the multipartparams map
      * 
@@ -359,306 +266,7 @@
                 
     }
     
-
     /**
-     * Parse the replication policy document out of the mime-multipart form data
-     * 
-     * @return policy  the encoded policy
-     * @throws ServiceFailure
-     * @throws InvalidRequest
-     * @throws IOException
-     * @throws InstantiationException
-     * @throws IllegalAccessException
-     * @throws JiBXException
-     */
-    protected ReplicationPolicy collectReplicationPolicy() 
-        throws ServiceFailure, InvalidRequest, IOException, InstantiationException, 
-        IllegalAccessException, JiBXException {
-        
-        ReplicationPolicy policy = null;
-        File tmpDir = getTempDirectory();
-        MultipartRequest mr = null;
-        Map<String, File> mmFileParts = null;
-        File replPolicyFile = null;
-        InputStream replPolicyStream = null;
-        
-        // Read the incoming data from its Mime Multipart encoding
-        logMetacat.debug("Parsing ReplicationPolicy from the mime multipart entity");
-
-        // handle MMP inputs
-        MultipartRequestResolver mrr = 
-            new MultipartRequestResolver(tmpDir.getAbsolutePath(),1000000000, 0);
-        
-        try {
-            mr = mrr.resolveMultipart(request);
-            logMetacat.debug("Resolved the ReplicationPolicy multipart request.");
-            
-        } catch (IOException e) {
-            throw new ServiceFailure("4882", "Couldn't resolve the multipart request: " +
-                e.getMessage());
-            
-        } catch (FileUploadException e) {
-            throw new ServiceFailure("4882", "Couldn't resolve the multipart request: " +
-                e.getMessage());
-            
-        } catch (Exception e) {
-            throw new ServiceFailure("4882", "Couldn't resolve the multipart request: " +
-                e.getMessage());
-            
-        }
-        
-        // get the map of file parts
-        mmFileParts = mr.getMultipartFiles();
-        
-        if ( mmFileParts == null || mmFileParts.keySet() == null) {
-            throw new InvalidRequest("4883", "The multipart request must include " +
-                "a file with the name 'policy'.");
-            
-        }
-        
-        multipartparams = mr.getMultipartParameters();
-        replPolicyFile = mmFileParts.get("policy");
-        
-        if ( replPolicyFile == null ) {
-            throw new InvalidRequest("4883", "The multipart request must include " +
-            "a file with the name 'policy'.");
-            
-        }
-        
-        
-        // deserialize the ReplicationPolicy
-        replPolicyStream = new FileInputStream(replPolicyFile);
-        policy = TypeMarshaller.unmarshalTypeFromStream(ReplicationPolicy.class, replPolicyStream);
-        
-        return policy;
-        
-    }
-
-    /**
-     * Parse the replica metadata document out of the mime-multipart form data
-     * 
-     * @return replica  the encoded replica
-     * @throws ServiceFailure
-     * @throws InvalidRequest
-     * @throws IOException
-     * @throws InstantiationException
-     * @throws IllegalAccessException
-     * @throws JiBXException
-     */
-    protected Replica collectReplicaMetadata() 
-        throws ServiceFailure, InvalidRequest {
-        
-        Replica replica = null;
-        File tmpDir = getTempDirectory();
-        MultipartRequest mr = null;
-        Map<String, File> mmFileParts = null;
-        File replicaFile = null;
-        InputStream replicaStream = null;
-        
-        // Read the incoming data from its Mime Multipart encoding
-        logMetacat.debug("Parsing Replica from the mime multipart entity");
-
-        // handle MMP inputs
-        MultipartRequestResolver mrr = 
-            new MultipartRequestResolver(tmpDir.getAbsolutePath(),1000000000, 0);
-        
-        try {
-            mr = mrr.resolveMultipart(request);
-            logMetacat.debug("Resolved the Replica multipart request.");
-            
-        } catch (IOException e) {
-            throw new ServiceFailure("4852", "Couldn't resolve the multipart request: " +
-                e.getMessage());
-            
-        } catch (FileUploadException e) {
-            throw new ServiceFailure("4852", "Couldn't resolve the multipart request: " +
-                    e.getMessage());
-            
-        } catch (Exception e) {
-            throw new ServiceFailure("4852", "Couldn't resolve the multipart request: " +
-                    e.getMessage());
-            
-        }
-        
-        // get the map of file parts
-        mmFileParts = mr.getMultipartFiles();
-        
-        if ( mmFileParts == null || mmFileParts.keySet() == null) {
-            throw new InvalidRequest("4853", "The multipart request must include " +
-                "a file with the name 'replicaMetadata'.");
-            
-        }
-        
-        multipartparams = mr.getMultipartParameters();
-        replicaFile = mmFileParts.get("replicaMetadata");
-        
-        if ( replicaFile == null ) {
-            throw new InvalidRequest("4853", "The multipart request must include " +
-            "a file with the name 'replicaMetadata'.");
-            
-        }
-        
-        
-        // deserialize the ReplicationPolicy
-        try {
-            replicaStream = new FileInputStream(replicaFile);
-        } catch (FileNotFoundException e) {
-            throw new ServiceFailure("4852", "Couldn't find the multipart file: " +
-                    e.getMessage());
-            
-        }
-        
-        try {
-            replica = TypeMarshaller.unmarshalTypeFromStream(Replica.class, replicaStream);
-        } catch (IOException e) {
-            throw new ServiceFailure("4852", "Couldn't deserialize the replica document: " +
-                    e.getMessage());
-            
-        } catch (InstantiationException e) {
-            throw new ServiceFailure("4852", "Couldn't deserialize the replica document: " +
-                    e.getMessage());
-            
-        } catch (IllegalAccessException e) {
-            throw new ServiceFailure("4852", "Couldn't deserialize the replica document: " +
-                    e.getMessage());
-            
-        } catch (JiBXException e) {
-            throw new ServiceFailure("4852", "Couldn't deserialize the replica document: " +
-                    e.getMessage());
-            
-        }
-        
-        return replica;
-        
-    }
-    
-    protected AccessPolicy collectAccessPolicy() 
-        throws IOException, ServiceFailure, InvalidRequest, JiBXException, 
-        InstantiationException, IllegalAccessException, ParserConfigurationException, 
-        SAXException  {
-		
-		// Read the incoming data from its Mime Multipart encoding
-		logMetacat.debug("Disassembling MIME multipart form");
-		InputStream ap = null;
-
-		// handle MMP inputs
-		File tmpDir = getTempDirectory();
-		logMetacat.debug("temp dir: " + tmpDir.getAbsolutePath());
-		MultipartRequestResolver mrr = 
-			new MultipartRequestResolver(tmpDir.getAbsolutePath(), 1000000000, 0);
-		MultipartRequest mr = null;
-		try {
-			mr = mrr.resolveMultipart(request);
-		} catch (Exception e) {
-			throw new ServiceFailure("2161", 
-					"Could not resolve multipart: " + e.getMessage());
-		}
-		logMetacat.debug("resolved multipart request");
-		Map<String, File> files = mr.getMultipartFiles();
-		if (files == null || files.keySet() == null) {
-			throw new InvalidRequest("2163",
-					"must have multipart file with name 'accessPolicy'");
-		}
-		logMetacat.debug("got multipart files");
-
-		multipartparams = mr.getMultipartParameters();
-
-		File apFile = files.get("accessPolicy");
-		if (apFile == null) {
-			throw new InvalidRequest("2163",
-					"Missing the required file-part 'accessPolicy' from the multipart request.");
-		}
-		logMetacat.debug("apFile: " + apFile.getAbsolutePath());
-		ap = new FileInputStream(apFile);
-	
-		AccessPolicy accessPolicy = TypeMarshaller.unmarshalTypeFromStream(AccessPolicy.class, ap);
-		return accessPolicy;
-	}
-    
-    protected SystemMetadata collectSystemMetadata() 
-        throws IOException, FileUploadException, ServiceFailure, InvalidRequest, 
-        JiBXException, InstantiationException, IllegalAccessException  {
-		
-		// Read the incoming data from its Mime Multipart encoding
-		logMetacat.debug("Disassembling MIME multipart form");
-		InputStream sysmeta = null;
-
-		// handle MMP inputs
-		File tmpDir = getTempDirectory();
-		logMetacat.debug("temp dir: " + tmpDir.getAbsolutePath());
-		MultipartRequestResolver mrr = 
-			new MultipartRequestResolver(tmpDir.getAbsolutePath(), 1000000000, 0);
-		MultipartRequest mr = null;
-		try {
-			mr = mrr.resolveMultipart(request);
-			
-		} catch (Exception e) {
-		  if ( logMetacat.isDebugEnabled() ) {
-		      e.printStackTrace();
-		      
-		  }
-			throw new ServiceFailure("1202", 
-					"Could not resolve multipart: " + e.getMessage());
-			
-		}
-		logMetacat.debug("resolved multipart request");
-		Map<String, File> files = mr.getMultipartFiles();
-		if (files == null) {
-			throw new ServiceFailure("1202",
-					"register meta must have multipart file with name 'sysmeta'");
-		}
-		logMetacat.debug("got multipart files");
-
-		if (files.keySet() == null) {
-			logMetacat.error("No file keys in MMP request.");
-			throw new ServiceFailure(
-					"1202",
-					"No file keys found in MMP.  "
-							+ "register meta must have multipart file with name 'sysmeta'");
-		}
-
-		// for logging purposes, dump out the key-value pairs that
-		// constitute the request
-		// 3 types exist: request params, multipart params, and
-		// multipart files
-		Iterator it = files.keySet().iterator();
-		logMetacat.debug("iterating through request parts: " + it);
-		while (it.hasNext()) {
-			String key = (String) it.next();
-			logMetacat.debug("files key: " + key);
-			logMetacat.debug("files value: " + files.get(key));
-		}
-
-		multipartparams = mr.getMultipartParameters();
-		it = multipartparams.keySet().iterator();
-		while (it.hasNext()) {
-			String key = (String) it.next();
-			logMetacat.debug("multipartparams key: " + key);
-			logMetacat.debug("multipartparams value: " + multipartparams.get(key));
-		}
-
-		it = params.keySet().iterator();
-		while (it.hasNext()) {
-			String key = (String) it.next();
-			logMetacat.debug("param key: " + key);
-			logMetacat.debug("param value: " + params.get(key));
-		}
-		logMetacat.debug("done iterating the request...");
-
-		File smFile = files.get("sysmeta");
-		if (smFile == null) {
-			throw new InvalidRequest("1102",
-					"Missing the required file-part 'sysmeta' from the multipart request.");
-		}
-		logMetacat.debug("smFile: " + smFile.getAbsolutePath());
-		sysmeta = new FileInputStream(smFile);
-	
-		logMetacat.debug("Commence creation...");
-		SystemMetadata systemMetadata = TypeMarshaller.unmarshalTypeFromStream(SystemMetadata.class, sysmeta);
-		return systemMetadata;
-	}
-    
-    /**
      * Process the MMP request that includes files for each param
      * @return map of param key and the temp file that contains the encoded information
      * @throws ServiceFailure
Index: src/edu/ucsb/nceas/metacat/EventLog.java
===================================================================
--- src/edu/ucsb/nceas/metacat/EventLog.java	(revision 8809)
+++ src/edu/ucsb/nceas/metacat/EventLog.java	(revision 8810)
@@ -35,10 +35,10 @@
 import java.util.Vector;
 
 import org.apache.log4j.Logger;
+import org.dataone.service.types.v1.Identifier;
+import org.dataone.service.types.v2.Log;
+import org.dataone.service.types.v2.LogEntry;
 import org.dataone.service.types.v1.Event;
-import org.dataone.service.types.v1.Identifier;
-import org.dataone.service.types.v1.Log;
-import org.dataone.service.types.v1.LogEntry;
 import org.dataone.service.types.v1.NodeReference;
 import org.dataone.service.types.v1.Subject;
 import org.dataone.service.util.DateTimeMarshaller;
@@ -139,14 +139,13 @@
     	// update the search index for the event
         try {
         	
-        	Event d1Event = Event.convert(event);
-        	if (d1Event != null) {
+        	if (event != null) {
         		
-	        	String fieldName = d1Event.xmlValue() + "_count_i";
+	        	String fieldName = event + "_count_i";
 	        	int eventCount = 0;
 	        	
 	        	String docid = IdentifierManager.getInstance().getLocalId(pid.getValue());
-	        	Log eventLog = this.getD1Report(null, null, new String[] {docid}, d1Event, null, null, false, 0, 0);
+	        	Log eventLog = this.getD1Report(null, null, new String[] {docid}, event, null, null, false, 0, 0);
 	        	eventCount = eventLog.getTotal();
 	
 		        List<Object> values = new ArrayList<Object>();
@@ -371,7 +370,7 @@
     
     
     public Log getD1Report(String[] ipAddress, String[] principal, String[] docid,
-            Event event, Timestamp startDate, Timestamp endDate, boolean anonymous, Integer start, Integer count)
+            String event, Timestamp startDate, Timestamp endDate, boolean anonymous, Integer start, Integer count)
     {
         
         Log log = new Log();
@@ -459,8 +458,8 @@
             }
         	queryWhereClause.append("event in (");
     		queryWhereClause.append("?");
-    		String eventString = event.xmlValue();
-    		if (event.equals(Event.CREATE)) {
+    		String eventString = event;
+    		if (eventString.equals(Event.CREATE.xmlValue())) {
     			eventString = "insert";
     		}
     		paramValues.add(eventString);
@@ -467,26 +466,7 @@
         	queryWhereClause.append(") ");
             clauseAdded = true;
         }
-        else {
-	        if (clauseAdded) {
-	            queryWhereClause.append(" and ");
-	        }
-	    	queryWhereClause.append("event in (");
-	    	for (int i = 0; i < Event.values().length; i++) {
-	    		if (i > 0) {
-	        		queryWhereClause.append(", ");
-	    		}
-	    		queryWhereClause.append("?");
-	    		Event e = Event.values()[i];
-	    		String eventString = e.xmlValue();
-	    		if (e.equals(Event.CREATE)) {
-	    			eventString = "insert";
-	    		}
-	    		paramValues.add(eventString);
-	    	}
-	    	queryWhereClause.append(") ");
-	        clauseAdded = true;
-        }
+        
         if (startDate != null) {
             if (clauseAdded) {
                 queryWhereClause.append(" and ");
@@ -568,12 +548,7 @@
 					logEntry.setSubject(subject);
 					
 					String logEventString = rs.getString(6);
-					Event logEvent = Event.convert(logEventString );
-					if (logEvent == null) {
-						logMetacat.info("Skipping uknown DataONE Event type: " + logEventString);
-						continue;
-					}
-					logEntry.setEvent(logEvent);
+					logEntry.setEvent(logEventString);
 					logEntry.setDateLogged(rs.getTimestamp(7));
 					
 					logEntry.setNodeIdentifier(memberNode);
Index: src/edu/ucsb/nceas/metacat/MetacatHandler.java
===================================================================
--- src/edu/ucsb/nceas/metacat/MetacatHandler.java	(revision 8809)
+++ src/edu/ucsb/nceas/metacat/MetacatHandler.java	(revision 8810)
@@ -78,7 +78,7 @@
 import org.dataone.service.types.v1.Event;
 import org.dataone.service.types.v1.Identifier;
 import org.dataone.service.types.v1.Session;
-import org.dataone.service.types.v1.SystemMetadata;
+import org.dataone.service.types.v2.SystemMetadata;
 import org.ecoinformatics.eml.EMLParser;
 
 import au.com.bytecode.opencsv.CSVWriter;
Index: src/edu/ucsb/nceas/metacat/dataone/MNodeService.java
===================================================================
--- src/edu/ucsb/nceas/metacat/dataone/MNodeService.java	(revision 8809)
+++ src/edu/ucsb/nceas/metacat/dataone/MNodeService.java	(revision 8810)
@@ -55,12 +55,12 @@
 
 import org.apache.commons.io.IOUtils;
 import org.apache.log4j.Logger;
-import org.dataone.client.CNode;
-import org.dataone.client.D1Client;
-import org.dataone.client.MNode;
-import org.dataone.client.ObjectFormatCache;
+import org.dataone.client.v2.CNode;
+import org.dataone.client.v2.itk.D1Client;
+import org.dataone.client.v2.MNode;
+import org.dataone.client.v2.formats.ObjectFormatCache;
 import org.dataone.client.auth.CertificateManager;
-import org.dataone.client.formats.ObjectFormatInfo;
+import org.dataone.client.v2.formats.ObjectFormatInfo;
 import org.dataone.configuration.Settings;
 import org.dataone.ore.ResourceMapFactory;
 import org.dataone.service.exceptions.BaseException;
@@ -75,27 +75,30 @@
 import org.dataone.service.exceptions.ServiceFailure;
 import org.dataone.service.exceptions.SynchronizationFailed;
 import org.dataone.service.exceptions.UnsupportedType;
-import org.dataone.service.mn.tier1.v1.MNCore;
-import org.dataone.service.mn.tier1.v1.MNRead;
-import org.dataone.service.mn.tier2.v1.MNAuthorization;
-import org.dataone.service.mn.tier3.v1.MNStorage;
-import org.dataone.service.mn.tier4.v1.MNReplication;
-import org.dataone.service.mn.v1.MNQuery;
+import org.dataone.service.mn.tier1.v2.MNCore;
+import org.dataone.service.mn.tier1.v2.MNRead;
+import org.dataone.service.mn.tier2.v2.MNAuthorization;
+import org.dataone.service.mn.tier3.v2.MNStorage;
+import org.dataone.service.mn.tier4.v2.MNReplication;
+import org.dataone.service.mn.v2.MNPackage;
+import org.dataone.service.mn.v2.MNQuery;
+import org.dataone.service.mn.v2.MNView;
 import org.dataone.service.types.v1.AccessRule;
 import org.dataone.service.types.v1.Checksum;
 import org.dataone.service.types.v1.DescribeResponse;
 import org.dataone.service.types.v1.Event;
 import org.dataone.service.types.v1.Identifier;
-import org.dataone.service.types.v1.Log;
-import org.dataone.service.types.v1.LogEntry;
+import org.dataone.service.types.v2.Log;
+import org.dataone.service.types.v2.LogEntry;
+import org.dataone.service.types.v2.OptionList;
 import org.dataone.service.types.v1.MonitorInfo;
 import org.dataone.service.types.v1.MonitorList;
-import org.dataone.service.types.v1.Node;
-import org.dataone.service.types.v1.NodeList;
+import org.dataone.service.types.v2.Node;
+import org.dataone.service.types.v2.NodeList;
 import org.dataone.service.types.v1.NodeReference;
 import org.dataone.service.types.v1.NodeState;
 import org.dataone.service.types.v1.NodeType;
-import org.dataone.service.types.v1.ObjectFormat;
+import org.dataone.service.types.v2.ObjectFormat;
 import org.dataone.service.types.v1.ObjectFormatIdentifier;
 import org.dataone.service.types.v1.ObjectList;
 import org.dataone.service.types.v1.Permission;
@@ -107,7 +110,7 @@
 import org.dataone.service.types.v1.Session;
 import org.dataone.service.types.v1.Subject;
 import org.dataone.service.types.v1.Synchronization;
-import org.dataone.service.types.v1.SystemMetadata;
+import org.dataone.service.types.v2.SystemMetadata;
 import org.dataone.service.types.v1.util.AuthUtils;
 import org.dataone.service.types.v1.util.ChecksumUtil;
 import org.dataone.service.types.v1_1.QueryEngineDescription;
@@ -141,6 +144,7 @@
 import edu.ucsb.nceas.metacat.shared.MetacatUtilException;
 import edu.ucsb.nceas.metacat.util.DeleteOnCloseFileInputStream;
 import edu.ucsb.nceas.metacat.util.DocumentUtil;
+import edu.ucsb.nceas.metacat.util.SkinUtil;
 import edu.ucsb.nceas.metacat.util.SystemUtil;
 import edu.ucsb.nceas.utilities.PropertyNotFoundException;
 import edu.ucsb.nceas.utilities.XMLUtilities;
@@ -177,7 +181,7 @@
  * 
  */
 public class MNodeService extends D1NodeService 
-    implements MNAuthorization, MNCore, MNRead, MNReplication, MNStorage, MNQuery {
+    implements MNAuthorization, MNCore, MNRead, MNReplication, MNStorage, MNQuery, MNView, MNPackage {
 
     //private static final String PATHQUERY = "pathquery";
 	public static final String UUID_SCHEME = "UUID";
@@ -788,7 +792,7 @@
      * @throws NotImplemented
      */
     @Override
-    public ObjectList listObjects(Session session, Date startTime, Date endTime, ObjectFormatIdentifier objectFormatId, Boolean replicaStatus, Integer start,
+    public ObjectList listObjects(Session session, Date startTime, Date endTime, ObjectFormatIdentifier objectFormatId, Identifier identifier, Boolean replicaStatus, Integer start,
             Integer count) throws NotAuthorized, InvalidRequest, NotImplemented, ServiceFailure, InvalidToken {
 
         ObjectList objectList = null;
@@ -962,64 +966,8 @@
         }
     }
 
-    /**
-     * Returns the number of operations that have been serviced by the node 
-     * over time periods of one and 24 hours.
-     * 
-     * @param session - the Session object containing the credentials for the Subject
-     * @param period - An ISO8601 compatible DateTime range specifying the time 
-     *                 range for which to return operation statistics.
-     * @param requestor - Limit to operations performed by given requestor identity.
-     * @param event -  Enumerated value indicating the type of event being examined
-     * @param format - Limit to events involving objects of the specified format
-     * 
-     * @return the desired log records
-     * 
-     * @throws InvalidToken
-     * @throws ServiceFailure
-     * @throws NotAuthorized
-     * @throws InvalidRequest
-     * @throws NotImplemented
-     */
-    public MonitorList getOperationStatistics(Session session, Date startTime, 
-        Date endTime, Subject requestor, Event event, ObjectFormatIdentifier formatId)
-        throws NotImplemented, ServiceFailure, NotAuthorized, InsufficientResources, UnsupportedType {
+    
 
-        MonitorList monitorList = new MonitorList();
-
-        try {
-
-            // get log records first
-            Log logs = getLogRecords(session, startTime, endTime, event, null, 0, null);
-
-            // TODO: aggregate by day or hour -- needs clarification
-            int count = 1;
-            for (LogEntry logEntry : logs.getLogEntryList()) {
-                Identifier pid = logEntry.getIdentifier();
-                Date logDate = logEntry.getDateLogged();
-                // if we are filtering by format
-                if (formatId != null) {
-                    SystemMetadata sysmeta = HazelcastService.getInstance().getSystemMetadataMap().get(pid);
-                    if (!sysmeta.getFormatId().getValue().equals(formatId.getValue())) {
-                        // does not match
-                        continue;
-                    }
-                }
-                MonitorInfo item = new MonitorInfo();
-                item.setCount(count);
-                item.setDate(new java.sql.Date(logDate.getTime()));
-                monitorList.addMonitorInfo(item);
-
-            }
-        } catch (Exception e) {
-            e.printStackTrace();
-            throw new ServiceFailure("2081", "Could not retrieve statistics: " + e.getMessage());
-        }
-
-        return monitorList;
-
-    }
-
     /**
      * A callback method used by a CN to indicate to a MN that it cannot 
      * complete synchronization of the science metadata identified by pid.  Log
@@ -1398,132 +1346,12 @@
 		return identifier;
 	}
 
-	@Override
-	public boolean isAuthorized(Identifier pid, Permission permission)
-			throws ServiceFailure, InvalidRequest, InvalidToken, NotFound,
-			NotAuthorized, NotImplemented {
+	
 
-		return isAuthorized(null, pid, permission);
-	}
-
 	@Override
-	public boolean systemMetadataChanged(Identifier pid, long serialVersion, Date dateSysMetaLastModified)
+	public QueryEngineDescription getQueryEngineDescription(Session session, String engine)
 			throws InvalidToken, ServiceFailure, NotAuthorized, NotImplemented,
-			InvalidRequest {
-
-		return systemMetadataChanged(null, pid, serialVersion, dateSysMetaLastModified);
-	}
-
-	@Override
-	public Log getLogRecords(Date fromDate, Date toDate, Event event, String pidFilter,
-			Integer start, Integer count) throws InvalidRequest, InvalidToken,
-			NotAuthorized, NotImplemented, ServiceFailure {
-
-		return getLogRecords(null, fromDate, toDate, event, pidFilter, start, count);
-	}
-
-	@Override
-	public DescribeResponse describe(Identifier pid) throws InvalidToken,
-			NotAuthorized, NotImplemented, ServiceFailure, NotFound {
-
-		return describe(null, pid);
-	}
-
-	@Override
-	public InputStream get(Identifier pid) throws InvalidToken, NotAuthorized,
-			NotImplemented, ServiceFailure, NotFound, InsufficientResources {
-
-		return get(null, pid);
-	}
-
-	@Override
-	public Checksum getChecksum(Identifier pid, String algorithm)
-			throws InvalidRequest, InvalidToken, NotAuthorized, NotImplemented,
-			ServiceFailure, NotFound {
-
-		return getChecksum(null, pid, algorithm);
-	}
-
-	@Override
-	public SystemMetadata getSystemMetadata(Identifier pid)
-			throws InvalidToken, NotAuthorized, NotImplemented, ServiceFailure,
 			NotFound {
-
-		return getSystemMetadata(null, pid);
-	}
-
-	@Override
-	public ObjectList listObjects(Date startTime, Date endTime,
-			ObjectFormatIdentifier objectFormatId, Boolean replicaStatus, Integer start,
-			Integer count) throws InvalidRequest, InvalidToken, NotAuthorized,
-			NotImplemented, ServiceFailure {
-
-		return listObjects(null, startTime, endTime, objectFormatId, replicaStatus, start, count);
-	}
-
-	@Override
-	public boolean synchronizationFailed(SynchronizationFailed syncFailed)
-			throws InvalidToken, NotAuthorized, NotImplemented, ServiceFailure {
-
-		return synchronizationFailed(null, syncFailed);
-	}
-
-	@Override
-	public InputStream getReplica(Identifier pid) throws InvalidToken,
-			NotAuthorized, NotImplemented, ServiceFailure, NotFound,
-			InsufficientResources {
-
-		return getReplica(null, pid);
-	}
-
-	@Override
-	public boolean replicate(SystemMetadata sysmeta, NodeReference sourceNode)
-			throws NotImplemented, ServiceFailure, NotAuthorized,
-			InvalidRequest, InvalidToken, InsufficientResources,
-			UnsupportedType {
-
-		return replicate(null, sysmeta, sourceNode);
-	}
-
-	@Override
-	public Identifier create(Identifier pid, InputStream object,
-			SystemMetadata sysmeta) throws IdentifierNotUnique,
-			InsufficientResources, InvalidRequest, InvalidSystemMetadata,
-			InvalidToken, NotAuthorized, NotImplemented, ServiceFailure,
-			UnsupportedType {
-
-		return create(null, pid, object, sysmeta);
-	}
-
-	@Override
-	public Identifier delete(Identifier pid) throws InvalidToken,
-			ServiceFailure, NotAuthorized, NotFound, NotImplemented {
-
-		return delete(null, pid);
-	}
-
-	@Override
-	public Identifier generateIdentifier(String scheme, String fragment)
-			throws InvalidToken, ServiceFailure, NotAuthorized, NotImplemented,
-			InvalidRequest {
-
-		return generateIdentifier(null, scheme, fragment);
-	}
-
-	@Override
-	public Identifier update(Identifier pid, InputStream object,
-			Identifier newPid, SystemMetadata sysmeta) throws IdentifierNotUnique,
-			InsufficientResources, InvalidRequest, InvalidSystemMetadata,
-			InvalidToken, NotAuthorized, NotImplemented, ServiceFailure,
-			UnsupportedType, NotFound {
-
-		return update(null, pid, object, newPid, sysmeta);
-	}
-
-	@Override
-	public QueryEngineDescription getQueryEngineDescription(String engine)
-			throws InvalidToken, ServiceFailure, NotAuthorized, NotImplemented,
-			NotFound {
 	    if(engine != null && engine.equals(EnabledQueryEngines.PATHQUERYENGINE)) {
 	        if(!EnabledQueryEngines.getInstance().isEnabled(EnabledQueryEngines.PATHQUERYENGINE)) {
                 throw new NotImplemented("0000", "MNodeService.query - the query engine "+engine +" hasn't been implemented or has been disabled.");
@@ -1569,7 +1397,7 @@
 	}
 
 	@Override
-	public QueryEngineList listQueryEngines() throws InvalidToken,
+	public QueryEngineList listQueryEngines(Session session) throws InvalidToken,
 			ServiceFailure, NotAuthorized, NotImplemented {
 		QueryEngineList qel = new QueryEngineList();
 		//qel.addQueryEngine(EnabledQueryEngines.PATHQUERYENGINE);
@@ -1582,7 +1410,7 @@
 	}
 
 	@Override
-	public InputStream query(String engine, String query) throws InvalidToken,
+	public InputStream query(Session session, String engine, String query) throws InvalidToken,
 			ServiceFailure, NotAuthorized, InvalidRequest, NotImplemented,
 			NotFound {
 	    String user = Constants.SUBJECT_PUBLIC;
@@ -1855,7 +1683,7 @@
 				query = "fl=id,resourceMap&wt=xml&q=resourceMap:[* TO *]+id:\"" + pid + "\"";
 			}
 			
-			InputStream results = this.query("solr", query);
+			InputStream results = this.query(null, "solr", query);
 			org.w3c.dom.Node rootNode = XMLUtilities.getXMLReaderAsDOMTreeRootNode(new InputStreamReader(results, "UTF-8"));
 			//String resultString = XMLUtilities.getDOMTreeAsString(rootNode);
 			org.w3c.dom.NodeList nodeList = XMLUtilities.getNodeListWithXPath(rootNode, "//arr[@name=\"resourceMap\"]/str");
@@ -1875,17 +1703,11 @@
 		return retList;
 	}
 	
-	/**
-	 * Packages the given package in a Bagit collection for download
-	 * @param pid
-	 * @throws NotImplemented 
-	 * @throws NotFound 
-	 * @throws NotAuthorized 
-	 * @throws ServiceFailure 
-	 * @throws InvalidToken 
-	 */
-	public InputStream getPackage(Session session, Identifier pid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented {
-		
+
+	@Override
+	public InputStream getPackage(Session session, ObjectFormatIdentifier formatId,
+			Identifier pid) throws InvalidToken, ServiceFailure,
+			NotAuthorized, InvalidRequest, NotImplemented, NotFound {
 		InputStream bagInputStream = null;
 		BagFactory bagFactory = new BagFactory();
 		Bag bag = bagFactory.createBag();
@@ -2145,24 +1967,28 @@
 		}
 		
 		return bagInputStream;
+	}
 
+	@Override
+	public OptionList listViews(Session arg0) throws InvalidToken,
+			ServiceFailure, NotAuthorized, InvalidRequest, NotImplemented {
+		OptionList views = new OptionList();
+		Vector<String> skinNames = null;
+		try {
+			skinNames = SkinUtil.getSkinNames();
+		} catch (PropertyNotFoundException e) {
+			throw new ServiceFailure("2841", e.getMessage());
+		}
+		for (String skinName: skinNames) {
+			views.addOption(skinName);
+		}
+		return views;
 	}
-	
-	/**
-	 * Get a rendered view of the object identified by pid.
-	 * Uses the registered format given by the format parameter.
-	 * Typically, this is structured HTML that can be styled with CSS.
-	 * @param session
-	 * @param pid
-	 * @param format
-	 * @return
-	 * @throws InvalidToken
-	 * @throws ServiceFailure
-	 * @throws NotAuthorized
-	 * @throws NotFound
-	 * @throws NotImplemented
-	 */
-	public InputStream getView(Session session, Identifier pid, String format) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented {
+
+	@Override
+	public InputStream view(Session session, String format, Identifier pid)
+			throws InvalidToken, ServiceFailure, NotAuthorized, InvalidRequest,
+			NotImplemented, NotFound {
 		InputStream resultInputStream = null;
 		
 		SystemMetadata sysMeta = this.getSystemMetadata(session, pid);
@@ -2231,7 +2057,6 @@
 		}
 		
 		return resultInputStream;
-		
 	}	
     
 }
Index: src/edu/ucsb/nceas/metacat/dataone/CNodeService.java
===================================================================
--- src/edu/ucsb/nceas/metacat/dataone/CNodeService.java	(revision 8809)
+++ src/edu/ucsb/nceas/metacat/dataone/CNodeService.java	(revision 8810)
@@ -34,13 +34,13 @@
 import javax.servlet.http.HttpServletRequest;
 
 import org.apache.log4j.Logger;
-import org.dataone.client.CNode;
-import org.dataone.client.D1Client;
-import org.dataone.client.MNode;
-import org.dataone.service.cn.v1.CNAuthorization;
-import org.dataone.service.cn.v1.CNCore;
-import org.dataone.service.cn.v1.CNRead;
-import org.dataone.service.cn.v1.CNReplication;
+import org.dataone.client.v2.CNode;
+import org.dataone.client.v2.itk.D1Client;
+import org.dataone.client.v2.MNode;
+import org.dataone.service.cn.v2.CNAuthorization;
+import org.dataone.service.cn.v2.CNCore;
+import org.dataone.service.cn.v2.CNRead;
+import org.dataone.service.cn.v2.CNReplication;
 import org.dataone.service.exceptions.BaseException;
 import org.dataone.service.exceptions.IdentifierNotUnique;
 import org.dataone.service.exceptions.InsufficientResources;
@@ -59,14 +59,14 @@
 import org.dataone.service.types.v1.DescribeResponse;
 import org.dataone.service.types.v1.Event;
 import org.dataone.service.types.v1.Identifier;
-import org.dataone.service.types.v1.Log;
-import org.dataone.service.types.v1.Node;
-import org.dataone.service.types.v1.NodeList;
+import org.dataone.service.types.v2.Log;
+import org.dataone.service.types.v2.Node;
+import org.dataone.service.types.v2.NodeList;
 import org.dataone.service.types.v1.NodeReference;
 import org.dataone.service.types.v1.NodeType;
-import org.dataone.service.types.v1.ObjectFormat;
+import org.dataone.service.types.v2.ObjectFormat;
 import org.dataone.service.types.v1.ObjectFormatIdentifier;
-import org.dataone.service.types.v1.ObjectFormatList;
+import org.dataone.service.types.v2.ObjectFormatList;
 import org.dataone.service.types.v1.ObjectList;
 import org.dataone.service.types.v1.ObjectLocationList;
 import org.dataone.service.types.v1.Permission;
@@ -75,8 +75,8 @@
 import org.dataone.service.types.v1.ReplicationStatus;
 import org.dataone.service.types.v1.Session;
 import org.dataone.service.types.v1.Subject;
-import org.dataone.service.types.v1.SystemMetadata;
-import org.dataone.service.types.v1.util.ServiceMethodRestrictionUtil;
+import org.dataone.service.types.v2.SystemMetadata;
+import org.dataone.service.types.v2.util.ServiceMethodRestrictionUtil;
 import org.dataone.service.types.v1_1.QueryEngineDescription;
 import org.dataone.service.types.v1_1.QueryEngineList;
 
@@ -84,6 +84,7 @@
 import edu.ucsb.nceas.metacat.IdentifierManager;
 import edu.ucsb.nceas.metacat.McdbDocNotFoundException;
 import edu.ucsb.nceas.metacat.dataone.hazelcast.HazelcastService;
+import edu.ucsb.nceas.metacat.index.MetacatSolrIndex;
 
 /**
  * Represents Metacat's implementation of the DataONE Coordinating Node 
@@ -1729,7 +1730,7 @@
    */
   @Override
   public ObjectList listObjects(Session session, Date startTime, 
-      Date endTime, ObjectFormatIdentifier formatid, Boolean replicaStatus,
+      Date endTime, ObjectFormatIdentifier formatid, Identifier identifier, Boolean replicaStatus,
       Integer start, Integer count)
       throws InvalidRequest, InvalidToken, NotAuthorized, NotImplemented,
       ServiceFailure {
@@ -1834,203 +1835,132 @@
   }
 
 	@Override
-	public boolean isAuthorized(Identifier pid, Permission permission)
-			throws ServiceFailure, InvalidToken, NotFound, NotAuthorized,
-			NotImplemented, InvalidRequest {
-		
-		return isAuthorized(null, pid, permission);
-	}
-	
-	@Override
-	public boolean setAccessPolicy(Identifier pid, AccessPolicy accessPolicy, long serialVersion)
-			throws InvalidToken, NotFound, NotImplemented, NotAuthorized,
-			ServiceFailure, InvalidRequest, VersionMismatch {
-		
-		return setAccessPolicy(null, pid, accessPolicy, serialVersion);
-	}
-	
-	@Override
-	public Identifier setRightsHolder(Identifier pid, Subject userId, long serialVersion)
-			throws InvalidToken, ServiceFailure, NotFound, NotAuthorized,
-			NotImplemented, InvalidRequest, VersionMismatch {
-		
-		return setRightsHolder(null, pid, userId, serialVersion);
-	}
-	
-	@Override
-	public Identifier create(Identifier pid, InputStream object, SystemMetadata sysmeta)
-			throws InvalidToken, ServiceFailure, NotAuthorized,
-			IdentifierNotUnique, UnsupportedType, InsufficientResources,
-			InvalidSystemMetadata, NotImplemented, InvalidRequest {
+	public QueryEngineDescription getQueryEngineDescription(Session session,
+			String queryEngine) throws InvalidToken, ServiceFailure, NotAuthorized,
+			NotImplemented, NotFound {
+		throw new NotImplemented("0000", "CN query services are not implemented in Metacat.");
 
-		return create(null, pid, object, sysmeta);
 	}
 	
 	@Override
-	public Identifier delete(Identifier pid) throws InvalidToken, ServiceFailure,
-			NotAuthorized, NotFound, NotImplemented {
+	public QueryEngineList listQueryEngines(Session session) throws InvalidToken,
+			ServiceFailure, NotAuthorized, NotImplemented {
+		throw new NotImplemented("0000", "CN query services are not implemented in Metacat.");
 
-		return delete(null, pid);
 	}
 	
 	@Override
-	public Identifier generateIdentifier(String scheme, String fragment)
-			throws InvalidToken, ServiceFailure, NotAuthorized, NotImplemented,
-			InvalidRequest {
+	public InputStream query(Session session, String queryEngine, String query)
+			throws InvalidToken, ServiceFailure, NotAuthorized, InvalidRequest,
+			NotImplemented, NotFound {
+		throw new NotImplemented("0000", "CN query services are not implemented in Metacat.");
 
-		return generateIdentifier(null, scheme, fragment);
 	}
 	
 	@Override
-	public Log getLogRecords(Date fromDate, Date toDate, Event event, String pidFilter,
-			Integer start, Integer count) throws InvalidToken, InvalidRequest,
-			ServiceFailure, NotAuthorized, NotImplemented, InsufficientResources {
-
-		return getLogRecords(null, fromDate, toDate, event, pidFilter, start, count);
+	public Node getCapabilities() throws NotImplemented, ServiceFailure {
+		throw new NotImplemented("0000", "The CN capabilities are not stored in Metacat.");
 	}
 	
+	/**
+     * A method to notify the Coordinating Node that the authoritative copy of 
+     * system metadata on the Authoritative Member Node has changed.
+     * 
+     * @param session   Session information that contains the identity of the 
+     *                  calling user as retrieved from the X.509 certificate 
+     *                  which must be traceable to the CILogon service.
+     * @param serialVersion   The serialVersion of the system metadata
+     * @param dateSysMetaLastModified  The time stamp for when the system metadata was changed
+     * @throws NotImplemented
+     * @throws ServiceFailure
+     * @throws NotAuthorized
+     * @throws InvalidRequest
+     * @throws InvalidToken
+     */
 	@Override
-	public boolean hasReservation(Subject subject, Identifier pid)
-			throws InvalidToken, ServiceFailure, NotFound, NotAuthorized,
-			NotImplemented, InvalidRequest, IdentifierNotUnique {
+    public boolean systemMetadataChanged(Session session, Identifier pid,
+        long serialVersion, Date dateSysMetaLastModified) 
+        throws NotImplemented, ServiceFailure, NotAuthorized, InvalidRequest,
+        InvalidToken {
+        
+        // cannot be called by public
+        if (session == null) {
+        	throw new InvalidToken("2183", "No session was provided.");
+        }
 
-		return hasReservation(null, subject, pid);
-	}
-	
-	@Override
-	public Identifier registerSystemMetadata(Identifier pid, SystemMetadata sysmeta)
-			throws NotImplemented, NotAuthorized, ServiceFailure, InvalidRequest,
-			InvalidSystemMetadata, InvalidToken {
+        SystemMetadata currentLocalSysMeta = null;
+        SystemMetadata newSysMeta = null;
+        boolean allowed = false;
+        
+        // are we allowed to call this?
+        allowed = super.isAuthoritativeMNodeAdmin(session, pid);
+        
+        if (!allowed ) {
+            String msg = "The subject identified by " + session.getSubject().getValue() +
+              " is not authorized to call this service.";
+            throw new NotAuthorized("1331", msg);
+            
+        }
+        
+        // compare what we have locally to what is sent in the change notification
+        try {
+            currentLocalSysMeta = HazelcastService.getInstance().getSystemMetadataMap().get(pid);
+             
+        } catch (RuntimeException e) {
+            String msg = "SystemMetadata for pid " + pid.getValue() +
+              " couldn't be updated because it couldn't be found locally: " +
+              e.getMessage();
+            logMetacat.error(msg);
+            ServiceFailure sf = new ServiceFailure("1333", msg);
+            sf.initCause(e);
+            throw sf; 
+        }
+        
+        if (currentLocalSysMeta.getSerialVersion().longValue() < serialVersion ) {
+            try {
+            	
+                MNode mn = D1Client.getMN(currentLocalSysMeta.getAuthoritativeMemberNode());
+				newSysMeta = mn .getSystemMetadata(null, pid);
+            } catch (NotFound e) {
+                // huh? you just said you had it
+            	String msg = "On updating the local copy of system metadata " + 
+                "for pid " + pid.getValue() +", the AuthMN reports it is not found." +
+                " The error message was: " + e.getMessage();
+                logMetacat.error(msg);
+                ServiceFailure sf = new ServiceFailure("1333", msg);
+                sf.initCause(e);
+                throw sf;
+            }
+            
+            // update the local copy of system metadata for the pid
+            try {
+                HazelcastService.getInstance().getSystemMetadataMap().put(newSysMeta.getIdentifier(), newSysMeta);
+                logMetacat.info("Updated local copy of system metadata for pid " +
+                    pid.getValue() + " after change notification from the CN.");
+                
+                // TODO: consider inspecting the change for archive
+                // see: https://projects.ecoinformatics.org/ecoinfo/issues/6417
 
-		return registerSystemMetadata(null, pid, sysmeta);
-	}
+            } catch (RuntimeException e) {
+                String msg = "SystemMetadata for pid " + pid.getValue() +
+                  " couldn't be updated: " +
+                  e.getMessage();
+                logMetacat.error(msg);
+                ServiceFailure sf = new ServiceFailure("1333", msg);
+                sf.initCause(e);
+                throw sf;
+            }
+            
+            // submit for indexing
+            try {
+				MetacatSolrIndex.getInstance().submit(newSysMeta.getIdentifier(), newSysMeta, null, true);
+			} catch (Exception e) {
+                logMetacat.error("Could not submit changed systemMetadata for indexing, pid: " + newSysMeta.getIdentifier().getValue(), e);
+			}
+        }
+        
+        return true;
+        
+    }
 	
-	@Override
-	public Identifier reserveIdentifier(Identifier pid) throws InvalidToken,
-			ServiceFailure, NotAuthorized, IdentifierNotUnique, NotImplemented,
-			InvalidRequest {
-
-		return reserveIdentifier(null, pid);
-	}
-	
-	@Override
-	public boolean setObsoletedBy(Identifier pid, Identifier obsoletedByPid, long serialVersion)
-			throws NotImplemented, NotFound, NotAuthorized, ServiceFailure,
-			InvalidRequest, InvalidToken, VersionMismatch {
-
-		return setObsoletedBy(null, pid, obsoletedByPid, serialVersion);
-	}
-	
-	@Override
-	public DescribeResponse describe(Identifier pid) throws InvalidToken,
-			NotAuthorized, NotImplemented, ServiceFailure, NotFound {
-
-		return describe(null, pid);
-	}
-	
-	@Override
-	public InputStream get(Identifier pid) throws InvalidToken, ServiceFailure,
-			NotAuthorized, NotFound, NotImplemented {
-
-		return get(null, pid);
-	}
-	
-	@Override
-	public Checksum getChecksum(Identifier pid) throws InvalidToken,
-			ServiceFailure, NotAuthorized, NotFound, NotImplemented {
-
-		return getChecksum(null, pid);
-	}
-	
-	@Override
-	public SystemMetadata getSystemMetadata(Identifier pid) throws InvalidToken,
-			ServiceFailure, NotAuthorized, NotFound, NotImplemented {
-
-		return getSystemMetadata(null, pid);
-	}
-	
-	@Override
-	public ObjectList listObjects(Date startTime, Date endTime,
-			ObjectFormatIdentifier formatid, Boolean replicaStatus, Integer start, Integer count)
-			throws InvalidRequest, InvalidToken, NotAuthorized, NotImplemented,
-			ServiceFailure {
-
-		return listObjects(null, startTime, endTime, formatid, replicaStatus, start, count);
-	}
-	
-	@Override
-	public ObjectLocationList resolve(Identifier pid) throws InvalidToken,
-			ServiceFailure, NotAuthorized, NotFound, NotImplemented {
-
-		return resolve(null, pid);
-	}
-	
-	@Override
-	public ObjectList search(String queryType, String query) throws InvalidToken,
-			ServiceFailure, NotAuthorized, InvalidRequest, NotImplemented {
-
-		return search(null, queryType, query);
-	}
-	
-	@Override
-	public boolean deleteReplicationMetadata(Identifier pid, NodeReference nodeId,
-			long serialVersion) throws InvalidToken, InvalidRequest, ServiceFailure,
-			NotAuthorized, NotFound, NotImplemented, VersionMismatch {
-
-		return deleteReplicationMetadata(null, pid, nodeId, serialVersion);
-	}
-	
-	@Override
-	public boolean isNodeAuthorized(Subject targetNodeSubject, Identifier pid)
-			throws NotImplemented, NotAuthorized, InvalidToken, ServiceFailure,
-			NotFound, InvalidRequest {
-
-		return isNodeAuthorized(null, targetNodeSubject, pid);
-	}
-	
-	@Override
-	public boolean setReplicationPolicy(Identifier pid, ReplicationPolicy policy,
-			long serialVersion) throws NotImplemented, NotFound, NotAuthorized,
-			ServiceFailure, InvalidRequest, InvalidToken, VersionMismatch {
-
-		return setReplicationPolicy(null, pid, policy, serialVersion);
-	}
-	
-	@Override
-	public boolean setReplicationStatus(Identifier pid, NodeReference targetNode,
-			ReplicationStatus status, BaseException failure) throws ServiceFailure,
-			NotImplemented, InvalidToken, NotAuthorized, InvalidRequest, NotFound {
-
-		return setReplicationStatus(null, pid, targetNode, status, failure);
-	}
-	
-	@Override
-	public boolean updateReplicationMetadata(Identifier pid, Replica replica,
-			long serialVersion) throws NotImplemented, NotAuthorized, ServiceFailure,
-			NotFound, InvalidRequest, InvalidToken, VersionMismatch {
-
-		return updateReplicationMetadata(null, pid, replica, serialVersion);
-	}
-
-  @Override
-  public QueryEngineDescription getQueryEngineDescription(String arg0)
-          throws InvalidToken, ServiceFailure, NotAuthorized, NotImplemented,
-          NotFound {
-      throw new NotImplemented("4410", "getQueryEngineDescription not implemented");
-      
-  }
-
-  @Override
-  public QueryEngineList listQueryEngines() throws InvalidToken, ServiceFailure,
-          NotAuthorized, NotImplemented {
-      throw new NotImplemented("4420", "listQueryEngines not implemented");
-      
-  }
-
-  @Override
-  public InputStream query(String arg0, String arg1) throws InvalidToken,
-          ServiceFailure, NotAuthorized, InvalidRequest, NotImplemented, NotFound {
-      throw new NotImplemented("4324", "query not implemented");
-      
-  }
 }
Index: src/edu/ucsb/nceas/metacat/dataone/SystemMetadataFactory.java
===================================================================
--- src/edu/ucsb/nceas/metacat/dataone/SystemMetadataFactory.java	(revision 8809)
+++ src/edu/ucsb/nceas/metacat/dataone/SystemMetadataFactory.java	(revision 8810)
@@ -49,7 +49,7 @@
 import org.apache.commons.io.IOUtils;
 import org.apache.log4j.Logger;
 import org.apache.wicket.protocol.http.mock.MockHttpServletRequest;
-import org.dataone.client.ObjectFormatCache;
+import org.dataone.client.v2.formats.ObjectFormatCache;
 import org.dataone.eml.DataoneEMLParser;
 import org.dataone.eml.EMLDocument;
 import org.dataone.eml.EMLDocument.DistributionMetadata;
@@ -65,7 +65,7 @@
 import org.dataone.service.types.v1.ReplicationPolicy;
 import org.dataone.service.types.v1.Session;
 import org.dataone.service.types.v1.Subject;
-import org.dataone.service.types.v1.SystemMetadata;
+import org.dataone.service.types.v2.SystemMetadata;
 import org.dataone.service.types.v1.util.ChecksumUtil;
 import org.dataone.service.util.DateTimeMarshaller;
 import org.dspace.foresite.ResourceMap;
Index: src/edu/ucsb/nceas/metacat/dataone/hazelcast/SystemMetadataMap.java
===================================================================
--- src/edu/ucsb/nceas/metacat/dataone/hazelcast/SystemMetadataMap.java	(revision 8809)
+++ src/edu/ucsb/nceas/metacat/dataone/hazelcast/SystemMetadataMap.java	(revision 8810)
@@ -9,7 +9,7 @@
 import org.apache.log4j.Logger;
 import org.dataone.service.exceptions.InvalidSystemMetadata;
 import org.dataone.service.types.v1.Identifier;
-import org.dataone.service.types.v1.SystemMetadata;
+import org.dataone.service.types.v2.SystemMetadata;
 
 import com.hazelcast.core.MapLoader;
 import com.hazelcast.core.MapStore;
Index: src/edu/ucsb/nceas/metacat/restservice/v2/CNRestServlet.java
===================================================================
--- src/edu/ucsb/nceas/metacat/restservice/v2/CNRestServlet.java	(nonexistent)
+++ src/edu/ucsb/nceas/metacat/restservice/v2/CNRestServlet.java	(revision 8810)
@@ -0,0 +1,50 @@
+/**
+ *  '$RCSfile$'
+ *  Copyright: 2000 Regents of the University of California and the
+ *              National Center for Ecological Analysis and Synthesis
+ *
+ *   '$Author$'
+ *     '$Date$'
+ *
+ * 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.v2;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import edu.ucsb.nceas.metacat.restservice.D1ResourceHandler;
+import edu.ucsb.nceas.metacat.restservice.D1RestServlet;
+
+
+/**
+ * Routes CN REST service requests to the appropriate handler
+ *  
+ */
+public class CNRestServlet extends D1RestServlet {
+    
+	/**
+	 * Provide a CNResourceHandler subclass of D1ResourceHandler
+	 */
+	@Override
+    protected D1ResourceHandler createHandler(HttpServletRequest request, HttpServletResponse response) 
+    	throws ServletException, IOException {
+        return new CNResourceHandler(getServletContext(), request, response);
+    }
+
+}

Property changes on: src/edu/ucsb/nceas/metacat/restservice/v2/CNRestServlet.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property
Index: src/edu/ucsb/nceas/metacat/restservice/v2/MNRestServlet.java
===================================================================
--- src/edu/ucsb/nceas/metacat/restservice/v2/MNRestServlet.java	(nonexistent)
+++ src/edu/ucsb/nceas/metacat/restservice/v2/MNRestServlet.java	(revision 8810)
@@ -0,0 +1,50 @@
+/**
+ *  '$RCSfile$'
+ *  Copyright: 2000 Regents of the University of California and the
+ *              National Center for Ecological Analysis and Synthesis
+ *
+ *   '$Author$'
+ *     '$Date$'
+ *
+ * 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.v2;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import edu.ucsb.nceas.metacat.restservice.D1ResourceHandler;
+import edu.ucsb.nceas.metacat.restservice.D1RestServlet;
+
+
+/**
+ * Routes MN REST service requests to the appropriate handler
+ *  
+ */
+public class MNRestServlet extends D1RestServlet {
+    
+	/**
+	 * Provide an MNResourceHandler subclass of D1ResourceHandler
+	 */
+	@Override
+    protected D1ResourceHandler createHandler(HttpServletRequest request, HttpServletResponse response) 
+    	throws ServletException, IOException {
+        return new MNResourceHandler(getServletContext(), request, response);
+    }
+
+}

Property changes on: src/edu/ucsb/nceas/metacat/restservice/v2/MNRestServlet.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property
Index: src/edu/ucsb/nceas/metacat/restservice/D1HttpRequest.java
===================================================================
--- src/edu/ucsb/nceas/metacat/restservice/D1HttpRequest.java	(revision 8809)
+++ src/edu/ucsb/nceas/metacat/restservice/D1HttpRequest.java	(revision 8810)
@@ -25,12 +25,10 @@
 
 import java.io.UnsupportedEncodingException;
 import java.net.URLDecoder;
-import java.util.Enumeration;
-import java.util.Map;
-import java.util.StringTokenizer;
 
 import javax.servlet.ServletRequest;
-import javax.servlet.http.*;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
 
 /**
  * @author berkley
Index: src/edu/ucsb/nceas/metacat/DocumentImpl.java
===================================================================
--- src/edu/ucsb/nceas/metacat/DocumentImpl.java	(revision 8809)
+++ src/edu/ucsb/nceas/metacat/DocumentImpl.java	(revision 8810)
@@ -89,7 +89,7 @@
 import org.apache.commons.io.input.XmlStreamReader;
 import org.apache.log4j.Logger;
 import org.dataone.service.types.v1.Identifier;
-import org.dataone.service.types.v1.SystemMetadata;
+import org.dataone.service.types.v2.SystemMetadata;
 import org.xml.sax.ContentHandler;
 import org.xml.sax.DTDHandler;
 import org.xml.sax.EntityResolver;
Index: src/edu/ucsb/nceas/metacat/util/MetacatPopulator.java
===================================================================
--- src/edu/ucsb/nceas/metacat/util/MetacatPopulator.java	(revision 8809)
+++ src/edu/ucsb/nceas/metacat/util/MetacatPopulator.java	(revision 8810)
@@ -39,9 +39,9 @@
 import java.util.Vector;
 
 import org.apache.commons.io.IOUtils;
-import org.dataone.client.D1Client;
-import org.dataone.client.MNode;
-import org.dataone.client.ObjectFormatCache;
+import org.dataone.client.v2.itk.D1Client;
+import org.dataone.client.v2.MNode;
+import org.dataone.client.v2.formats.ObjectFormatCache;
 import org.dataone.client.auth.CertificateManager;
 import org.dataone.ore.ResourceMapFactory;
 import org.dataone.service.exceptions.NotFound;
@@ -54,7 +54,7 @@
 import org.dataone.service.types.v1.Permission;
 import org.dataone.service.types.v1.Session;
 import org.dataone.service.types.v1.Subject;
-import org.dataone.service.types.v1.SystemMetadata;
+import org.dataone.service.types.v2.SystemMetadata;
 import org.dataone.service.types.v1.util.ChecksumUtil;
 import org.dataone.service.util.Constants;
 import org.dspace.foresite.ResourceMap;
Index: src/edu/ucsb/nceas/metacat/dataone/v1/MNodeService.java
===================================================================
--- src/edu/ucsb/nceas/metacat/dataone/v1/MNodeService.java	(nonexistent)
+++ src/edu/ucsb/nceas/metacat/dataone/v1/MNodeService.java	(revision 8810)
@@ -0,0 +1,461 @@
+/**
+ *  '$RCSfile$'
+ *  Copyright: 2000-2011 Regents of the University of California and the
+ *              National Center for Ecological Analysis and Synthesis
+ *
+ *   '$Author$'
+ *     '$Date$'
+ *
+ * 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.dataone.v1;
+
+import java.io.InputStream;
+import java.util.Date;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.log4j.Logger;
+import org.dataone.service.exceptions.IdentifierNotUnique;
+import org.dataone.service.exceptions.InsufficientResources;
+import org.dataone.service.exceptions.InvalidRequest;
+import org.dataone.service.exceptions.InvalidSystemMetadata;
+import org.dataone.service.exceptions.InvalidToken;
+import org.dataone.service.exceptions.NotAuthorized;
+import org.dataone.service.exceptions.NotFound;
+import org.dataone.service.exceptions.NotImplemented;
+import org.dataone.service.exceptions.ServiceFailure;
+import org.dataone.service.exceptions.SynchronizationFailed;
+import org.dataone.service.exceptions.UnsupportedType;
+import org.dataone.service.mn.tier1.v1.MNCore;
+import org.dataone.service.mn.tier1.v1.MNRead;
+import org.dataone.service.mn.tier2.v1.MNAuthorization;
+import org.dataone.service.mn.tier3.v1.MNStorage;
+import org.dataone.service.mn.tier4.v1.MNReplication;
+import org.dataone.service.mn.v1.MNQuery;
+import org.dataone.service.types.v1.Checksum;
+import org.dataone.service.types.v1.DescribeResponse;
+import org.dataone.service.types.v1.Event;
+import org.dataone.service.types.v1.Identifier;
+import org.dataone.service.types.v1.Log;
+import org.dataone.service.types.v1.Node;
+import org.dataone.service.types.v1.NodeReference;
+import org.dataone.service.types.v1.ObjectFormatIdentifier;
+import org.dataone.service.types.v1.ObjectList;
+import org.dataone.service.types.v1.Permission;
+import org.dataone.service.types.v1.Session;
+import org.dataone.service.types.v1.SystemMetadata;
+import org.dataone.service.types.v1_1.QueryEngineDescription;
+import org.dataone.service.types.v1_1.QueryEngineList;
+import org.dataone.service.util.TypeMarshaller;
+
+/**
+ * Represents Metacat's implementation of the DataONE Member Node 
+ * service API, v1. Methods typically pass through to the current 
+ * version implementation performing type conversion as needed.
+ * 
+ */
+public class MNodeService 
+    implements MNAuthorization, MNCore, MNRead, MNReplication, MNStorage, MNQuery {
+
+	/**
+	 * current version implementation
+	 */
+	edu.ucsb.nceas.metacat.dataone.MNodeService impl = null;
+	
+	/* the logger instance */
+    private Logger logMetacat = null;
+
+    /**
+     * Singleton accessor to get an instance of MNodeService.
+     * 
+     * @return instance - the instance of MNodeService
+     */
+    public static MNodeService getInstance(HttpServletRequest request) {
+        return new MNodeService(request);
+    }
+
+    /**
+     * Constructor, private for singleton access
+     */
+    private MNodeService(HttpServletRequest request) {
+        logMetacat = Logger.getLogger(MNodeService.class);
+        impl = edu.ucsb.nceas.metacat.dataone.MNodeService.getInstance(request);
+    }
+    
+    public void setSession(Session session) {
+    	impl.setSession(session);
+    }
+    
+    public boolean isAdminAuthorized(Session session) throws ServiceFailure, InvalidToken, NotAuthorized, NotImplemented {
+    	return impl.isAdminAuthorized(session);
+    }
+
+	@Override
+	public QueryEngineDescription getQueryEngineDescription(String engine)
+			throws InvalidToken, ServiceFailure, NotAuthorized, NotImplemented,
+			NotFound {
+		return impl.getQueryEngineDescription(null, engine);
+	}
+
+	@Override
+	public QueryEngineList listQueryEngines() throws InvalidToken,
+			ServiceFailure, NotAuthorized, NotImplemented {
+		return impl.listQueryEngines(null);
+	}
+
+	@Override
+	public InputStream query(String engine, String query) throws InvalidToken,
+			ServiceFailure, NotAuthorized, InvalidRequest, NotImplemented,
+			NotFound {
+		return impl.query(null, engine, query);
+	}
+
+	@Override
+	public Identifier archive(Identifier pid) throws InvalidToken,
+			ServiceFailure, NotAuthorized, NotFound, NotImplemented {
+		return impl.archive(null, pid);
+	}
+
+	@Override
+	@Deprecated
+	public Identifier archive(Session session, Identifier pid)
+			throws InvalidToken, ServiceFailure, NotAuthorized, NotFound,
+			NotImplemented {
+		return impl.archive(session, pid);
+	}
+
+	@Override
+	public Identifier create(Identifier pid, InputStream object,
+			SystemMetadata sysmeta) throws IdentifierNotUnique,
+			InsufficientResources, InvalidRequest, InvalidSystemMetadata,
+			InvalidToken, NotAuthorized, NotImplemented, ServiceFailure,
+			UnsupportedType {
+		return this.create(null, pid, object, sysmeta);
+	}
+
+	@Override
+	@Deprecated
+	public Identifier create(Session session, Identifier pid, InputStream object,
+			SystemMetadata sysmeta) throws IdentifierNotUnique,
+			InsufficientResources, InvalidRequest, InvalidSystemMetadata,
+			InvalidToken, NotAuthorized, NotImplemented, ServiceFailure,
+			UnsupportedType {
+		//convert sysmeta to newer version
+		org.dataone.service.types.v2.SystemMetadata v2Sysmeta = null;
+		try {
+			v2Sysmeta = TypeMarshaller.convertTypeFromType(sysmeta, org.dataone.service.types.v2.SystemMetadata.class);
+		} catch (Exception e) {
+			// report as service failure
+			ServiceFailure sf = new ServiceFailure("1190", e.getMessage());
+			sf.initCause(e);
+			throw sf;
+		}
+		
+		return impl.create(session, pid, object, v2Sysmeta);
+	}
+
+	@Override
+	public Identifier delete(Identifier pid) throws InvalidToken,
+			ServiceFailure, NotAuthorized, NotFound, NotImplemented {
+		return impl.delete(null, pid);
+	}
+
+	@Override
+	@Deprecated
+	public Identifier delete(Session session, Identifier pid)
+			throws InvalidToken, ServiceFailure, NotAuthorized, NotFound,
+			NotImplemented {
+		return impl.delete(session, pid);
+	}
+
+	@Override
+	public Identifier generateIdentifier(String scheme, String fragment)
+			throws InvalidToken, ServiceFailure, NotAuthorized, NotImplemented,
+			InvalidRequest {
+		return impl.generateIdentifier(null, scheme, fragment);
+	}
+
+	@Override
+	@Deprecated
+	public Identifier generateIdentifier(Session session, String scheme, String fragment)
+			throws InvalidToken, ServiceFailure, NotAuthorized, NotImplemented,
+			InvalidRequest {
+		return impl.generateIdentifier(session, scheme, fragment);
+	}
+
+	@Override
+	public Identifier update(Identifier pid, InputStream object,
+			Identifier newPid, SystemMetadata sysmeta) throws IdentifierNotUnique,
+			InsufficientResources, InvalidRequest, InvalidSystemMetadata,
+			InvalidToken, NotAuthorized, NotImplemented, ServiceFailure,
+			UnsupportedType, NotFound {
+		return this.update(null, pid, object, newPid, sysmeta);
+	}
+
+	@Override
+	@Deprecated
+	public Identifier update(Session session, Identifier pid, InputStream object,
+			Identifier newPid, SystemMetadata sysmeta) throws IdentifierNotUnique,
+			InsufficientResources, InvalidRequest, InvalidSystemMetadata,
+			InvalidToken, NotAuthorized, NotImplemented, ServiceFailure,
+			UnsupportedType, NotFound {
+		//convert sysmeta to newer version
+		org.dataone.service.types.v2.SystemMetadata v2Sysmeta = null;
+		try {
+			v2Sysmeta = TypeMarshaller.convertTypeFromType(sysmeta, org.dataone.service.types.v2.SystemMetadata.class);
+		} catch (Exception e) {
+			// report as service failure
+			ServiceFailure sf = new ServiceFailure("1030", e.getMessage());
+			sf.initCause(e);
+			throw sf;
+		}
+		return impl.update(session, pid, object, newPid, v2Sysmeta);
+	}
+
+	@Override
+	public boolean replicate(SystemMetadata sysmeta, NodeReference sourceNode)
+			throws NotImplemented, ServiceFailure, NotAuthorized,
+			InvalidRequest, InvalidToken, InsufficientResources,
+			UnsupportedType {
+		return this.replicate(null, sysmeta, sourceNode);
+	}
+
+	@Override
+	@Deprecated
+	public boolean replicate(Session session, SystemMetadata sysmeta,
+			NodeReference sourceNode) throws NotImplemented, ServiceFailure,
+			NotAuthorized, InvalidRequest, InvalidToken, InsufficientResources,
+			UnsupportedType {
+		//convert sysmeta to newer version
+		org.dataone.service.types.v2.SystemMetadata v2Sysmeta = null;
+		try {
+			v2Sysmeta = TypeMarshaller.convertTypeFromType(sysmeta, org.dataone.service.types.v2.SystemMetadata.class);
+		} catch (Exception e) {
+			// report as service failure
+			ServiceFailure sf = new ServiceFailure("1030", e.getMessage());
+			sf.initCause(e);
+			throw sf;
+		}
+		return impl.replicate(session, v2Sysmeta, sourceNode);
+	}
+
+	@Override
+	public DescribeResponse describe(Identifier pid) throws InvalidToken,
+			NotAuthorized, NotImplemented, ServiceFailure, NotFound {
+		return impl.describe(null, pid);
+	}
+
+	@Override
+	@Deprecated
+	public DescribeResponse describe(Session session, Identifier pid)
+			throws InvalidToken, NotAuthorized, NotImplemented, ServiceFailure,
+			NotFound {
+		return impl.describe(session, pid);
+	}
+
+	@Override
+	public InputStream get(Identifier pid) throws InvalidToken, NotAuthorized,
+			NotImplemented, ServiceFailure, NotFound, InsufficientResources {
+		return impl.get(null, pid);
+	}
+
+	@Override
+	@Deprecated
+	public InputStream get(Session session, Identifier pid) throws InvalidToken,
+			NotAuthorized, NotImplemented, ServiceFailure, NotFound,
+			InsufficientResources {
+		return impl.get(session, pid);
+	}
+
+	@Override
+	public Checksum getChecksum(Identifier pid, String algorithm)
+			throws InvalidRequest, InvalidToken, NotAuthorized, NotImplemented,
+			ServiceFailure, NotFound {
+		return impl.getChecksum(null, pid, algorithm);
+	}
+
+	@Override
+	@Deprecated
+	public Checksum getChecksum(Session session, Identifier pid, String algorithm)
+			throws InvalidRequest, InvalidToken, NotAuthorized, NotImplemented,
+			ServiceFailure, NotFound {
+		return impl.getChecksum(session, pid, algorithm);
+	}
+
+	@Override
+	public InputStream getReplica(Identifier pid) throws InvalidToken,
+			NotAuthorized, NotImplemented, ServiceFailure, NotFound,
+			InsufficientResources {
+		return impl.getReplica(null, pid);
+	}
+
+	@Override
+	@Deprecated
+	public InputStream getReplica(Session session, Identifier pid)
+			throws InvalidToken, NotAuthorized, NotImplemented, ServiceFailure,
+			NotFound, InsufficientResources {
+		return impl.get(session, pid);
+	}
+
+	@Override
+	public SystemMetadata getSystemMetadata(Identifier pid)
+			throws InvalidToken, NotAuthorized, NotImplemented, ServiceFailure,
+			NotFound {
+		return impl.getSystemMetadata(null, pid);
+	}
+
+	@Override
+	@Deprecated
+	public SystemMetadata getSystemMetadata(Session session, Identifier pid)
+			throws InvalidToken, NotAuthorized, NotImplemented, ServiceFailure,
+			NotFound {
+		return impl.getSystemMetadata(session, pid);
+	}
+
+	@Override
+	public ObjectList listObjects(Date startTime, Date endTime,
+			ObjectFormatIdentifier objectFormatId, Boolean replicaStatus, Integer start,
+			Integer count) throws InvalidRequest, InvalidToken, NotAuthorized,
+			NotImplemented, ServiceFailure {
+		return this.listObjects(null, startTime, endTime, objectFormatId, replicaStatus, start, count);
+	}
+
+	@Override
+	@Deprecated
+	public ObjectList listObjects(Session session, Date startTime, Date endTime,
+			ObjectFormatIdentifier objectFormatId, Boolean replicaStatus, Integer start,
+			Integer count) throws InvalidRequest, InvalidToken, NotAuthorized,
+			NotImplemented, ServiceFailure {
+		return impl.listObjects(session, startTime, endTime, objectFormatId, null, replicaStatus, start, count);
+	}
+
+	@Override
+	public boolean synchronizationFailed(SynchronizationFailed syncFailed)
+			throws InvalidToken, NotAuthorized, NotImplemented, ServiceFailure {
+		return impl.synchronizationFailed(null, syncFailed);
+	}
+
+	@Override
+	@Deprecated
+	public boolean synchronizationFailed(Session session,
+			SynchronizationFailed syncFailed) throws InvalidToken, NotAuthorized,
+			NotImplemented, ServiceFailure {
+		return impl.synchronizationFailed(session, syncFailed);
+	}
+
+	@Override
+	public Node getCapabilities() throws NotImplemented, ServiceFailure {
+		org.dataone.service.types.v2.Node node = impl.getCapabilities();
+		Node retNode = null;
+		try {
+			retNode = TypeMarshaller.convertTypeFromType(node, Node.class);
+		} catch (Exception e) {
+			// report as service failure
+			ServiceFailure sf = new ServiceFailure("4801", e.getMessage());
+			sf.initCause(e);
+			throw sf;
+		}
+		return retNode;
+	}
+
+	@Override
+	public Log getLogRecords(Date fromDate, Date toDate, Event event,
+			String pidFilter, Integer start, Integer count) throws InvalidRequest, InvalidToken,
+			NotAuthorized, NotImplemented, ServiceFailure {
+		return this.getLogRecords(null, fromDate, toDate, event, pidFilter, start, count);
+	}
+
+	@Override
+	@Deprecated
+	public Log getLogRecords(Session session, Date fromDate, Date toDate, Event event,
+			String pidFilter, Integer start, Integer count) throws InvalidRequest, InvalidToken,
+			NotAuthorized, NotImplemented, ServiceFailure {
+		org.dataone.service.types.v2.Log log = impl.getLogRecords(session, fromDate, toDate, event.xmlValue(), pidFilter, start, count);
+		Log retLog = null;
+		try {
+			retLog = TypeMarshaller.convertTypeFromType(log, Log.class);
+		} catch (Exception e) {
+			// report as service failure
+			ServiceFailure sf = new ServiceFailure("1490", e.getMessage());
+			sf.initCause(e);
+			throw sf;
+		}
+		return retLog;
+	}
+
+	@Override
+	public Date ping() throws NotImplemented, ServiceFailure,
+			InsufficientResources {
+		return impl.ping();
+	}
+
+	@Override
+	public boolean isAuthorized(Identifier pid, Permission permission)
+			throws ServiceFailure, InvalidRequest, InvalidToken, NotFound,
+			NotAuthorized, NotImplemented {
+		return impl.isAuthorized(null, pid, permission);
+	}
+
+	@Override
+	@Deprecated
+	public boolean isAuthorized(Session session, Identifier pid, Permission permission)
+			throws ServiceFailure, InvalidRequest, InvalidToken, NotFound,
+			NotAuthorized, NotImplemented {
+		return impl.isAuthorized(session, pid, permission);
+	}
+
+	@Override
+	public boolean systemMetadataChanged(Identifier pid, long serialVersion, Date dateSysMetaLastModified)
+			throws InvalidToken, ServiceFailure, NotAuthorized, NotImplemented,
+			InvalidRequest {
+		return impl.systemMetadataChanged(null, pid, serialVersion, dateSysMetaLastModified);
+
+	}
+
+	@Override
+	@Deprecated
+	public boolean systemMetadataChanged(Session session, Identifier pid,
+			long serialVersion, Date dateSysMetaLastModified) throws InvalidToken, ServiceFailure,
+			NotAuthorized, NotImplemented, InvalidRequest {
+		return impl.systemMetadataChanged(session, pid, serialVersion, dateSysMetaLastModified);
+	}
+    
+	// methods not defined in v1, but implemented in metacat pre-v2 release
+	
+	public Identifier publish(Session session, Identifier originalIdentifier) 
+			throws InvalidToken, ServiceFailure, NotAuthorized, NotImplemented, InvalidRequest, NotFound, IdentifierNotUnique, UnsupportedType, InsufficientResources, InvalidSystemMetadata {
+		return impl.publish(session, originalIdentifier);
+		
+	}
+	
+	public InputStream view(Session session, String format, Identifier pid)
+			throws InvalidToken, ServiceFailure, NotAuthorized, InvalidRequest,
+			NotImplemented, NotFound {
+		
+		return impl.view(session, format, pid);
+	}
+	
+	public InputStream getPackage(Session session, ObjectFormatIdentifier formatId,
+			Identifier pid) throws InvalidToken, ServiceFailure,
+			NotAuthorized, InvalidRequest, NotImplemented, NotFound {
+		return impl.getPackage(session, formatId, pid);
+	}
+	
+    
+
+   
+}

Property changes on: src/edu/ucsb/nceas/metacat/dataone/v1/MNodeService.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property
Index: src/edu/ucsb/nceas/metacat/dataone/D1NodeService.java
===================================================================
--- src/edu/ucsb/nceas/metacat/dataone/D1NodeService.java	(revision 8809)
+++ src/edu/ucsb/nceas/metacat/dataone/D1NodeService.java	(revision 8810)
@@ -37,14 +37,15 @@
 import java.util.List;
 import java.util.Set;
 import java.util.Timer;
+import java.util.concurrent.locks.Lock;
 
 import javax.servlet.http.HttpServletRequest;
 
 import org.apache.commons.io.IOUtils;
 import org.apache.log4j.Logger;
-import org.dataone.client.CNode;
-import org.dataone.client.D1Client;
-import org.dataone.client.ObjectFormatCache;
+import org.dataone.client.v2.CNode;
+import org.dataone.client.v2.itk.D1Client;
+import org.dataone.client.v2.formats.ObjectFormatCache;
 import org.dataone.service.exceptions.BaseException;
 import org.dataone.service.exceptions.IdentifierNotUnique;
 import org.dataone.service.exceptions.InsufficientResources;
@@ -58,19 +59,19 @@
 import org.dataone.service.exceptions.UnsupportedType;
 import org.dataone.service.types.v1.AccessRule;
 import org.dataone.service.types.v1.DescribeResponse;
-import org.dataone.service.types.v1.Event;
 import org.dataone.service.types.v1.Group;
 import org.dataone.service.types.v1.Identifier;
-import org.dataone.service.types.v1.Log;
-import org.dataone.service.types.v1.Node;
+import org.dataone.service.types.v2.Log;
+import org.dataone.service.types.v2.Node;
+import org.dataone.service.types.v1.Event;
 import org.dataone.service.types.v1.NodeReference;
 import org.dataone.service.types.v1.NodeType;
-import org.dataone.service.types.v1.ObjectFormat;
+import org.dataone.service.types.v2.ObjectFormat;
 import org.dataone.service.types.v1.Permission;
 import org.dataone.service.types.v1.Replica;
 import org.dataone.service.types.v1.Session;
 import org.dataone.service.types.v1.Subject;
-import org.dataone.service.types.v1.SystemMetadata;
+import org.dataone.service.types.v2.SystemMetadata;
 import org.dataone.service.types.v1.util.AuthUtils;
 import org.dataone.service.types.v1.util.ChecksumUtil;
 import org.dataone.service.util.Constants;
@@ -470,7 +471,7 @@
    * @throws NotImplemented
    */
   public Log getLogRecords(Session session, Date fromDate, Date toDate, 
-      Event event, String pidFilter, Integer start, Integer count) throws InvalidToken, ServiceFailure,
+      String event, String pidFilter, Integer start, Integer count) throws InvalidToken, ServiceFailure,
       NotAuthorized, InvalidRequest, NotImplemented {
 
 	  // only admin access to this method
@@ -750,7 +751,7 @@
                         CNode cn = null;
                         try {
                             cn = D1Client.getCN();
-                        } catch (ServiceFailure e) {
+                        } catch (BaseException e) {
                             logMetacat.error("D1NodeService.isAuthoritativeMNodeAdmin - couldn't connect to the CN since "+
                                             e.getDescription()+ ". The false value will be returned for the AuthoritativeMNodeAdmin.");
                             return allowed;
@@ -1353,6 +1354,48 @@
         }
 
     }
+    
+	public boolean updateSystemMetadata(Session session, Identifier pid,
+			SystemMetadata sysmeta) throws NotImplemented, NotAuthorized,
+			ServiceFailure, InvalidRequest, InvalidSystemMetadata, InvalidToken {
+		
+		// The lock to be used for this identifier
+      Lock lock = null;
+
+      // TODO: control who can call this?
+      if (session == null) {
+          //TODO: many of the thrown exceptions do not use the correct error codes
+          //check these against the docs and correct them
+          throw new NotAuthorized("4861", "No Session - could not authorize for registration." +
+                  "  If you are not logged in, please do so and retry the request.");
+      }
+      
+      // verify that guid == SystemMetadata.getIdentifier()
+      logMetacat.debug("Comparing guid|sysmeta_guid: " + pid.getValue() + 
+          "|" + sysmeta.getIdentifier().getValue());
+      
+      if (!pid.getValue().equals(sysmeta.getIdentifier().getValue())) {
+          throw new InvalidRequest("4863", 
+              "The identifier in method call (" + pid.getValue() + 
+              ") does not match identifier in system metadata (" +
+              sysmeta.getIdentifier().getValue() + ").");
+      }
+
+      // do the actual update
+      this.updateSystemMetadata(sysmeta);
+      
+      try {
+    	  String localId = IdentifierManager.getInstance().getLocalId(pid.getValue());
+    	  EventLog.getInstance().log(request.getRemoteAddr(), 
+    	          request.getHeader("User-Agent"), session.getSubject().getValue(), 
+    	          localId, "updateSystemMetadata");
+      } catch (McdbDocNotFoundException e) {
+    	  // do nothing, no localId to log with
+    	  logMetacat.warn("Could not log 'updateSystemMetadata' event because no localId was found for pid: " + pid.getValue());
+      }
+      
+      return true;
+	}
   
   /**
    * Given a Permission, returns a list of all permissions that it encompasses
@@ -1544,10 +1587,6 @@
 
       return pid;
   }
-  
-  public Identifier archive(Identifier pid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented {
-	  return archive(null, pid);
-  }
 
 
 }
Index: src/edu/ucsb/nceas/metacat/dataone/SyncAccessPolicy.java
===================================================================
--- src/edu/ucsb/nceas/metacat/dataone/SyncAccessPolicy.java	(revision 8809)
+++ src/edu/ucsb/nceas/metacat/dataone/SyncAccessPolicy.java	(revision 8810)
@@ -40,8 +40,8 @@
 import java.util.concurrent.Executors;
 
 import org.apache.log4j.Logger;
-import org.dataone.client.CNode;
-import org.dataone.client.D1Client;
+import org.dataone.client.v2.CNode;
+import org.dataone.client.v2.itk.D1Client;
 import org.dataone.service.exceptions.InvalidRequest;
 import org.dataone.service.exceptions.InvalidToken;
 import org.dataone.service.exceptions.NotAuthorized;
@@ -58,7 +58,7 @@
 import org.dataone.service.types.v1.Permission;
 import org.dataone.service.types.v1.Session;
 import org.dataone.service.types.v1.Subject;
-import org.dataone.service.types.v1.SystemMetadata;
+import org.dataone.service.types.v2.SystemMetadata;
 
 import edu.ucsb.nceas.metacat.AccessionNumberException;
 import edu.ucsb.nceas.metacat.IdentifierManager;
@@ -149,7 +149,7 @@
 
 			// Get sm, access policy for requested pid from the CN
 			try {
-				cnSysMeta = cn.getSystemMetadata(pid);
+				cnSysMeta = cn.getSystemMetadata(null, pid);
 			} catch (Exception e) {
 				logMetacat.error("Error getting system metadata for pid: "
 						+ pid.getValue() + " from cn: " + e.getMessage());
Index: src/edu/ucsb/nceas/metacat/admin/upgrade/dataone/GenerateORE.java
===================================================================
--- src/edu/ucsb/nceas/metacat/admin/upgrade/dataone/GenerateORE.java	(revision 8809)
+++ src/edu/ucsb/nceas/metacat/admin/upgrade/dataone/GenerateORE.java	(revision 8810)
@@ -39,9 +39,9 @@
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.dataone.client.D1Client;
-import org.dataone.client.MNode;
-import org.dataone.client.ObjectFormatCache;
+import org.dataone.client.v2.itk.D1Client;
+import org.dataone.client.v2.MNode;
+import org.dataone.client.v2.formats.ObjectFormatCache;
 import org.dataone.ore.ResourceMapFactory;
 import org.dataone.service.types.v1.Checksum;
 import org.dataone.service.types.v1.Identifier;
@@ -48,7 +48,7 @@
 import org.dataone.service.types.v1.ObjectFormatIdentifier;
 import org.dataone.service.types.v1.ObjectInfo;
 import org.dataone.service.types.v1.ObjectList;
-import org.dataone.service.types.v1.SystemMetadata;
+import org.dataone.service.types.v2.SystemMetadata;
 import org.dataone.service.types.v1.util.ChecksumUtil;
 import org.dspace.foresite.ResourceMap;
 
@@ -169,7 +169,7 @@
 	        formatId = ObjectFormatCache.getInstance().getFormat("http://www.openarchives.org/ore/terms").getFormatId();
 	        
 	        // get the objects that match
-			ObjectList objectList = mn.listObjects(null, null, null, formatId , null, 0, Integer.MAX_VALUE);
+			ObjectList objectList = mn.listObjects(null, null, null, formatId, null, null, 0, Integer.MAX_VALUE);
 			pids = new ArrayList<Identifier>();
 			for (ObjectInfo o: objectList.getObjectInfoList()) {
 				pids.add(o.getIdentifier());
@@ -214,7 +214,7 @@
 				log.debug("processing ORE pid: " + orePid.getValue());
 
 				// get original SystemMetadata
-				SystemMetadata originalOreSysMeta = mn.getSystemMetadata(orePid);
+				SystemMetadata originalOreSysMeta = mn.getSystemMetadata(null, orePid);
 				
 				// only update the CURRENT revision of the ORE
 				if (originalOreSysMeta.getObsoletedBy() != null || (originalOreSysMeta.getArchived() != null && originalOreSysMeta.getArchived())) {
@@ -223,7 +223,7 @@
 				}
 				
 				// get the original ORE map
-				InputStream originalOreStream = mn.get(orePid);
+				InputStream originalOreStream = mn.get(null, orePid);
 				Map<Identifier, Map<Identifier, List<Identifier>>> originalOre = ResourceMapFactory.getInstance().parseResourceMap(originalOreStream);
 
 				// generate the updated ORE map, in this case we aren't changing any values, just altering the serialization using a newer foresite library
Index: src/edu/ucsb/nceas/metacat/replication/ForceReplicationHandler.java
===================================================================
--- src/edu/ucsb/nceas/metacat/replication/ForceReplicationHandler.java	(revision 8809)
+++ src/edu/ucsb/nceas/metacat/replication/ForceReplicationHandler.java	(revision 8810)
@@ -336,9 +336,9 @@
 				logReplication.error("ForceReplicationHandler.run - URL error in ForceReplicationHandler.run for server "
 						+ server + " : " + mue.getMessage());
 //				mue.printStackTrace();
-			} catch (IOException io) {
+			} catch (Exception io) {
 		    	logMetacat.error("ForceReplicationHandler.run - " + ReplicationService.METACAT_REPL_ERROR_MSG);
-				logReplication.error("ForceReplicationHandler.run - I/O error in ForceReplicationHandler.run for server "
+				logReplication.error("ForceReplicationHandler.run - Error in ForceReplicationHandler.run for server "
 						+ server + " : " + io.getMessage());
 			}
 		}//for
Index: build.properties
===================================================================
--- build.properties	(revision 8809)
+++ build.properties	(revision 8810)
@@ -2,7 +2,7 @@
 
 #Version of this build.  This needs to be a dotted numeric version.  For
 #instance 1.9.1 is okay.  1.9.1_rc1 is not.
-metacat.version=2.4.1
+metacat.version=2.5.0
 
 #This is for packaging purposes.  leave it blank for final production release.
 metacat.releaseCandidate=
Index: src/edu/ucsb/nceas/metacat/IdentifierManager.java
===================================================================
--- src/edu/ucsb/nceas/metacat/IdentifierManager.java	(revision 8809)
+++ src/edu/ucsb/nceas/metacat/IdentifierManager.java	(revision 8810)
@@ -36,7 +36,7 @@
 import java.util.Vector;
 
 import org.apache.log4j.Logger;
-import org.dataone.client.ObjectFormatCache;
+import org.dataone.client.v2.formats.ObjectFormatCache;
 import org.dataone.service.exceptions.BaseException;
 import org.dataone.service.exceptions.InvalidSystemMetadata;
 import org.dataone.service.types.v1.AccessPolicy;
@@ -52,7 +52,7 @@
 import org.dataone.service.types.v1.ReplicationPolicy;
 import org.dataone.service.types.v1.ReplicationStatus;
 import org.dataone.service.types.v1.Subject;
-import org.dataone.service.types.v1.SystemMetadata;
+import org.dataone.service.types.v2.SystemMetadata;
 
 import edu.ucsb.nceas.metacat.accesscontrol.XMLAccessAccess;
 import edu.ucsb.nceas.metacat.database.DBConnection;
@@ -1054,7 +1054,7 @@
         String authoritativeMemberNode, long modifiedDate, String submitter, 
         String guid, String objectFormat, BigInteger size, boolean archived,
         boolean replicationAllowed, int numberReplicas, String obsoletes,
-        String obsoletedBy, BigInteger serialVersion, DBConnection dbConn) throws SQLException  {
+        String obsoletedBy, BigInteger serialVersion, String seriesId, DBConnection dbConn) throws SQLException  {
   
         // Execute the insert statement
         String query = "update " + TYPE_SYSTEM_METADATA + 
@@ -1061,8 +1061,8 @@
             " set (date_uploaded, rights_holder, checksum, checksum_algorithm, " +
             "origin_member_node, authoritive_member_node, date_modified, " +
             "submitter, object_format, size, archived, replication_allowed, number_replicas, " +
-            "obsoletes, obsoleted_by, serial_version) " +
-            "= (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) where guid = ?";
+            "obsoletes, obsoleted_by, serial_version, series_id) " +
+            "= (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) where guid = ?";
         PreparedStatement stmt = dbConn.prepareStatement(query);
         
         //data values
@@ -1082,9 +1082,11 @@
         stmt.setString(14, obsoletes);
         stmt.setString(15, obsoletedBy);
         stmt.setString(16, serialVersion.toString());
+        stmt.setString(17, seriesId);
 
+
         //where clause
-        stmt.setString(17, guid);
+        stmt.setString(18, guid);
         logMetacat.debug("stmt: " + stmt.toString());
         //execute
         int rows = stmt.executeUpdate();
@@ -1207,6 +1209,7 @@
 		    sm.getObsoletes() == null ? null:sm.getObsoletes().getValue(),
 		    sm.getObsoletedBy() == null ? null: sm.getObsoletedBy().getValue(),
 		    sm.getSerialVersion(),
+		    sm.getSeriesId() == null ? null: sm.getSeriesId().getValue(),
 		    dbConn
         );
         
Index: src/edu/ucsb/nceas/metacat/annotation/OrcidService.java
===================================================================
--- src/edu/ucsb/nceas/metacat/annotation/OrcidService.java	(revision 8809)
+++ src/edu/ucsb/nceas/metacat/annotation/OrcidService.java	(revision 8810)
@@ -106,7 +106,7 @@
 			}
 			
 			MockHttpServletRequest request = new MockHttpServletRequest(null, null, null);
-			InputStream results = MNodeService.getInstance(request ).query("solr", query);
+			InputStream results = MNodeService.getInstance(request ).query(null, "solr", query);
 			Node rootNode = XMLUtilities.getXMLReaderAsDOMTreeRootNode(new InputStreamReader(results, "UTF-8"));
 			//String resultString = XMLUtilities.getDOMTreeAsString(rootNode);
 			NodeList nodeList = XMLUtilities.getNodeListWithXPath(rootNode, "//lst[@name=\"origin\"]/int/@name");
Index: src/edu/ucsb/nceas/metacat/admin/D1Admin.java
===================================================================
--- src/edu/ucsb/nceas/metacat/admin/D1Admin.java	(revision 8809)
+++ src/edu/ucsb/nceas/metacat/admin/D1Admin.java	(revision 8810)
@@ -31,19 +31,17 @@
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.log4j.Logger;
-import org.dataone.client.CNode;
-import org.dataone.client.D1Client;
+import org.dataone.client.v2.CNode;
+import org.dataone.client.v2.itk.D1Client;
 import org.dataone.client.auth.CertificateManager;
 import org.dataone.configuration.Settings;
 import org.dataone.service.exceptions.BaseException;
-import org.dataone.service.types.v1.Node;
-import org.dataone.service.types.v1.NodeList;
+import org.dataone.service.types.v2.Node;
+import org.dataone.service.types.v2.NodeList;
 import org.dataone.service.types.v1.NodeReference;
 import org.dataone.service.types.v1.Session;
 
 import edu.ucsb.nceas.metacat.IdentifierManager;
-import edu.ucsb.nceas.metacat.admin.upgrade.dataone.GenerateORE;
-import edu.ucsb.nceas.metacat.admin.upgrade.dataone.GenerateSystemMetadata;
 import edu.ucsb.nceas.metacat.dataone.MNodeService;
 import edu.ucsb.nceas.metacat.properties.PropertyService;
 import edu.ucsb.nceas.metacat.shared.MetacatUtilException;
Index: src/edu/ucsb/nceas/metacat/replication/ReplicationService.java
===================================================================
--- src/edu/ucsb/nceas/metacat/replication/ReplicationService.java	(revision 8809)
+++ src/edu/ucsb/nceas/metacat/replication/ReplicationService.java	(revision 8810)
@@ -65,10 +65,11 @@
 import org.apache.http.conn.scheme.Scheme;
 import org.apache.http.conn.ssl.SSLSocketFactory;
 import org.apache.log4j.Logger;
-import org.dataone.client.RestClient;
+import org.dataone.client.rest.DefaultHttpMultipartRestClient;
+import org.dataone.client.rest.RestClient;
 import org.dataone.client.auth.CertificateManager;
 import org.dataone.service.types.v1.Identifier;
-import org.dataone.service.types.v1.SystemMetadata;
+import org.dataone.service.types.v2.SystemMetadata;
 import org.dataone.service.util.DateTimeMarshaller;
 import org.dataone.service.util.TypeMarshaller;
 import org.jibx.runtime.JiBXException;
@@ -1468,6 +1469,15 @@
 							+ me.getMessage());
 			// e.printStackTrace(System.out);
 			errorMsg = me.getMessage();
+		} catch (Exception e) {
+			logReplication
+			.error("ReplicationService.handleGetDocumentRequest - General exception encountered."
+					+ "handlGetDocumentRequest for file: "
+					+ documentPath
+					+ " : "
+					+ e.getMessage());
+			// e.printStackTrace(System.out);
+			errorMsg = e.getMessage();
 		} finally {
             IOUtils.closeQuietly(fos);
             IOUtils.closeQuietly(is);
@@ -2259,7 +2269,7 @@
 	 * @return a string representing the content of the url
 	 * @throws java.io.IOException
 	 */
-	public static String getURLContent(URL u) throws java.io.IOException {
+	public static String getURLContent(URL u) throws Exception {
 		char istreamChar;
 		int istreamInt;
 		// get the response content
@@ -2283,14 +2293,13 @@
 	 * @return a InputStream representing the content of the url
 	 * @throws java.io.IOException
 	 */
-	public static InputStream getURLStream(URL u) throws java.io.IOException {
+	public static InputStream getURLStream(URL u) throws Exception {
 	    logReplication.info("Getting url stream from " + u.toString());
 		logReplication.info("ReplicationService.getURLStream - Before sending request to: " + u.toString());
 		// use httpclient to set up SSL
-		RestClient client = getSSLClient();
-		HttpResponse response = client.doGetRequest(u.toString());
+		DefaultHttpMultipartRestClient client = getSSLClient();
 		// get the response content
-		InputStream input = response.getEntity().getContent();
+		InputStream input = client.doGetRequest(u.toString(), CLIENTTIMEOUT);
 		logReplication.info("ReplicationService.getURLStream - After getting response from: " + u.toString());
 		
 		return input;		
@@ -2301,8 +2310,8 @@
 	 * Sends client certificate to the server when doing the request.
 	 * @return
 	 */
-	private static RestClient getSSLClient() {
-		RestClient client = new RestClient();
+	private static DefaultHttpMultipartRestClient getSSLClient() {
+		DefaultHttpMultipartRestClient client = new DefaultHttpMultipartRestClient();
 		
 		// set up this server's client identity
 		String subject = null;
@@ -2321,7 +2330,7 @@
 		}
 		
 		// set the configured timeout
-		client.setTimeouts(CLIENTTIMEOUT);
+		//client.setTimeouts(CLIENTTIMEOUT);
 
 		SSLSocketFactory socketFactory = null;
 		try {
Index: README
===================================================================
--- README	(revision 8809)
+++ README	(revision 8810)
@@ -8,7 +8,7 @@
 Metacat: XML Metadata and Data Management System
 ------------------------------------------------                      
 
-Version: 2.4.1 Release
+Version: 2.5.0 Release
 
 Send feedback and bugs to: metacat-dev@ecoinformatics.org
                            http://bugzilla.ecoinformatics.org
@@ -54,6 +54,12 @@
 See the file "docs/install.html" for detailed instructions
 for your OS.
 
+Release Notes for 2.5.0:
+------------------------
+This major release adds DataONE V2 API support
+as well as:
+* ......
+
 Release Notes for 2.4.1:
 ------------------------
 This is a patch release that addresses the following:
Index: src/edu/ucsb/nceas/metacat/replication/ReplicationHandler.java
===================================================================
--- src/edu/ucsb/nceas/metacat/replication/ReplicationHandler.java	(revision 8809)
+++ src/edu/ucsb/nceas/metacat/replication/ReplicationHandler.java	(revision 8810)
@@ -44,7 +44,7 @@
 import java.util.Vector;
 
 import org.apache.log4j.Logger;
-import org.dataone.service.types.v1.SystemMetadata;
+import org.dataone.service.types.v2.SystemMetadata;
 import org.dataone.service.util.DateTimeMarshaller;
 import org.dataone.service.util.TypeMarshaller;
 import org.xml.sax.ContentHandler;
Index: pom.xml
===================================================================
--- pom.xml	(revision 8809)
+++ pom.xml	(revision 8810)
@@ -4,15 +4,15 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>org.ecoinformatics</groupId>
     <artifactId>metacat</artifactId>
-    <version>2.4.2-SNAPSHOT</version>
+    <version>2.5.0-SNAPSHOT</version>
     <name>metacat</name>
     <packaging>war</packaging>
     <url>http://maven.apache.org</url>
     <properties>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-        <d1_libclient_version>1.4.0-SNAPSHOT</d1_libclient_version>
-        <d1_portal_version>1.3.0-SNAPSHOT</d1_portal_version>
-        <metacat_common_version>2.4.2-SNAPSHOT</metacat_common_version>            
+        <d1_libclient_version>2.0.0-SNAPSHOT</d1_libclient_version>
+        <d1_portal_version>2.0.0-SNAPSHOT</d1_portal_version>
+        <metacat_common_version>2.5.0-SNAPSHOT</metacat_common_version>            
     </properties>
     <repositories>
         <repository>
