org.dataone.proto.trove.mn.service.v1.impl.MNReadImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.dataone.proto.trove.mn.service.v1.impl.MNReadImpl.java

Source

/*
 * This work was created by participants in the DataONE project, and is
 * jointly copyrighted by participating institutions in DataONE. For
 * more information on DataONE, see our web site at http://dataone.org.
 * 
 * Copyright 2014
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 */
package org.dataone.proto.trove.mn.service.v1.impl;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.Properties;
import javax.inject.Named;

import org.apache.log4j.Logger;
import org.dataone.proto.trove.mn.service.v1.SolrIndex;
import org.dataone.service.exceptions.InsufficientResources;

import org.dataone.service.exceptions.InvalidRequest;
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.mn.tier1.v1.MNRead;
import org.dataone.service.types.v1.Checksum;
import org.dataone.service.types.v1.DescribeResponse;
import org.dataone.service.types.v1.Identifier;
import org.dataone.service.types.v1.ObjectFormatIdentifier;
import org.dataone.service.types.v1.ObjectList;
import org.dataone.service.types.v1.Session;
import org.dataone.service.types.v1.SystemMetadata;
import org.dataone.service.types.v1.util.ChecksumUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import org.dataone.proto.trove.util.MapDBIndexMap;

/**
 *
 * @author waltz
 */

@Named("mnReadImpl")
public class MNReadImpl implements MNRead {
    Logger logger = Logger.getLogger(MNReadImpl.class.getName());

    @Autowired
    @Qualifier("mapDBObjectSolrIndexMap")
    private MapDBIndexMap dataoneDataObjectDirectory;

    @Autowired
    @Qualifier("dataoneSystemMetadataDirectory")
    private MapDBIndexMap dataoneSystemMetadataDirectory;

    /**
     * MNRead.listObjects(session[, fromDate][, toDate][, formatId][, replicaStatus][, start=0][, count=1000]) 
     * ObjectList
     *
     * Retrieve the list of objects present on the MN that match the calling parameters. This method is required to
     * support the process of Member Node synchronization. At a minimum, this method MUST be able to return a list of
     * objects that match:
     *
     * fromDate < SystemMetadata.dateSysMetadataModified
     *
     * but is expected to also support date range (by also specifying toDate), and should also support slicing of the
     * matching set of records by indicating the starting index of the response (where 0 is the index of the first item)
     * and the count of elements to be returned.
     *
     * Note that date time precision is limited to one millisecond. If no timezone information is provided, the UTC will
     * be assumed.
     *
     * Access control for this method MUST be configured to allow calling by Coordinating Nodes and MAY be configured to
     * allow more general access. Use Cases:        *
     * UC06, UC16 Rest URL:        *
     * GET /object[?fromDate={fromDate}&toDate={toDate} &formatId={formatId}&replicaStatus={replicaStatus}
     * &start={start}&count={count}] Parameters:        *
     * session (Types.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. The subject of the session defaults to the
     * public user if the certificate was not provided with the request. Transmitted as part of the SSL handshake
     * process. fromDate (Types.DateTime)  Entries with SystemMetadata.dateSysMetadataModified greater than or equal to
     * (>=) fromDate must be returned. Transmitted as a URL query parameter, and so must be escaped accordingly. toDate
     * (Types.DateTime)  Entries with SystemMetadata.dateSysMetadataModified less than (<) toDate must be returned.
     * Transmitted as a URL query parameter, and so must be escaped accordingly. formatId (Types.ObjectFormatIdentifier)
     *  Restrict results to the specified object format identifier. Transmitted as a URL query parameter, and so must
     * be escaped accordingly. replicaStatus (boolean)  Indicates if replicated objects should be returned in the list
     * (i.e. any entries present in the SystemMetadata.replica, objects that have been replicated to this member node).
     * If false, then no objects that have been replicated should be returned. If true, then any objects can be
     * returned, regardless of replication status. If not present, then the replicaStatus filter should be ignored.
     * Transmitted as a URL query parameter, and so must be escaped accordingly. start=0 (integer)  The zero-based
     * index of the first value, relative to the first record of the resultset that matches the parameters. Transmitted
     * as a URL query parameter, and so must be escaped accordingly. count=1000 (integer)  The maximum number of
     * entries that should be returned in the response. The Member Node may return fewer and the caller should check the
     * total in the response to determine if further pages may be retrieved. Transmitted as a URL query parameter, and
     * so must be escaped accordingly.
     *
     * Returns:        *
     * The list of PIDs that match the query criteria. If none match, an empty list is returned.
     *
     *
     * @param startTime
     * @param endTime
     * @param objectFormatId
     * @param replicaStatus
     * @param start
     * @param count
     * @return ObjectList
     * @throws InvalidRequest
     * @throws InvalidToken
     * @throws NotAuthorized
     * @throws NotImplemented
     * @throws ServiceFailure
     */
    @Override
    public ObjectList listObjects(Date startTime, Date endTime, ObjectFormatIdentifier objectFormatId,
            Boolean replicaStatus, Integer start, Integer count)
            throws InvalidRequest, InvalidToken, NotAuthorized, NotImplemented, ServiceFailure {
        int total = 0;
        // Send a properties file? as a string, until we come up with a query syntax to support by default.
        Properties searchProperties = new Properties();
        if (startTime != null) {
            searchProperties.setProperty("startTime", startTime.toString());
        }
        if (endTime != null) {
            searchProperties.setProperty("endTime", endTime.toString());
        }
        if (objectFormatId != null) {
            searchProperties.setProperty("objectFormatId", objectFormatId.getValue());
        }
        if (replicaStatus != null) {
            searchProperties.setProperty("replicaStatus", Boolean.toString(replicaStatus.booleanValue()));
        }
        if (start != null) {
            searchProperties.setProperty("start", Integer.toString(start));
        } else {
            searchProperties.setProperty("start", "0");
        }

        if (count != null) {
            searchProperties.setProperty("count", Integer.toString(count));
        } else {
            searchProperties.setProperty("count", "1000");
        }

        ObjectList objectList;
        try {
            objectList = (ObjectList) dataoneDataObjectDirectory.search(searchProperties);
        } catch (Exception ex) {
            ex.printStackTrace();
            throw new ServiceFailure("2312", "SolrIndex failed-" + ex.getMessage());
        }

        return objectList;

        /*        File[] fileList = null;
         File dir = new File(dataoneCacheDirectory + File.separator + "object");
            
         if (startTime == null && endTime == null) {
         fileList = dir.listFiles();
         } else {
         DateTime startDate = new DateTime(startTime);
         DateTime endDate = new DateTime(endTime);
         FileFilterByDateTime fileFilter = new FileFilterByDateTime(startDate, endDate);
         fileList = dir.listFiles(fileFilter);
         }
            
         total = fileList.length;
         ObjectList objectList = new ObjectList();
         objectList.setTotal(total);
         int i = 0;
         for (i = 0; i < count && ((i + start) < fileList.length); i++) {
            
         String fileName = fileList[i + start].getName();
         String filePath = dataoneCacheDirectory + File.separator + "meta" + File.separator + fileName;
         logger.info(filePath);
         ObjectInfo objectInfo = new ObjectInfo();
         try {
            
         SystemMetadata systemMetadata = TypeMarshaller.unmarshalTypeFromFile(SystemMetadata.class, filePath);
         if (objectFormatId != null && !(systemMetadata.getFormatId().getValue().contentEquals(objectFormatId.getValue()))) {
         continue;
         }
         objectInfo.setIdentifier(systemMetadata.getIdentifier());
         objectInfo.setChecksum(systemMetadata.getChecksum());
         objectInfo.setSize(systemMetadata.getSize());
            
         objectInfo.setDateSysMetadataModified(systemMetadata.getDateSysMetadataModified());
            
         objectInfo.setFormatId(systemMetadata.getFormatId());
         objectList.addObjectInfo(objectInfo);
         } catch (Exception ex) {
         logger.error(ex.getMessage());
         InvalidRequest exception = new InvalidRequest("002", ex.getMessage());
         throw exception;
         }
         }
         objectList.setCount(i);
         objectList.setStart(start);
         */
    }

    @Override
    public InputStream get(Identifier pid)
            throws InvalidToken, NotAuthorized, NotImplemented, ServiceFailure, NotFound, InsufficientResources {

        InputStream inputStream = null;
        try {
            ObjectList objectList = new ObjectList();
            inputStream = (InputStream) dataoneDataObjectDirectory.get(pid);

            //            logger.info("get filepath: " + filePath);
            //            inputStream = new FileInputStream(new File(filePath));
            logger.debug("is it available? " + inputStream.available());
        } catch (FileNotFoundException ex) {
            logger.warn(ex);
            NotFound exception = new NotFound("000", ex.getMessage());
            throw exception;
        } catch (IOException ex) {
            logger.warn(ex);
            ServiceFailure exception = new ServiceFailure("001", ex.getMessage());
            throw exception;
        }
        return inputStream;
    }

    @Override
    public SystemMetadata getSystemMetadata(Identifier pid)
            throws InvalidToken, NotAuthorized, NotImplemented, ServiceFailure, NotFound {
        SystemMetadata systemMetadata = new SystemMetadata();

        InputStream inputStream = null;
        try {
            systemMetadata = (SystemMetadata) dataoneSystemMetadataDirectory.get(pid);
            logger.info("\n");
            logger.info(systemMetadata.getIdentifier());
            logger.info("\n");
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (IOException ex) {
                logger.warn(ex);
            }
        }

        return systemMetadata;
    }

    @Override
    public DescribeResponse describe(Identifier pid)
            throws InvalidToken, NotAuthorized, NotImplemented, ServiceFailure, NotFound {
        SystemMetadata systemMetadata = this.getSystemMetadata(pid);
        DescribeResponse describeResponse = new DescribeResponse(systemMetadata.getFormatId(),
                systemMetadata.getSize(), systemMetadata.getDateSysMetadataModified(), systemMetadata.getChecksum(),
                systemMetadata.getSerialVersion());
        return describeResponse;
    }

    @Override
    public Checksum getChecksum(Identifier pid, String checksumAlgorithm)
            throws InvalidRequest, InvalidToken, NotAuthorized, NotImplemented, ServiceFailure, NotFound {
        // on a membernode it would be more appropriate to calculate the checksum for the object itself
        // based on the checksum algorithm. if it is provided... otherwise pull from systemmetadata
        SystemMetadata systemMetadata = this.getSystemMetadata(pid);
        if ((checksumAlgorithm == null)
                || systemMetadata.getChecksum().getAlgorithm().equalsIgnoreCase(checksumAlgorithm)) {
            return systemMetadata.getChecksum();
        } else {
            InputStream inputStream = null;
            try {

                inputStream = this.get(pid); //new FileInputStream(new File(filePath));
                //
                // possible XXX here...
                // thread pool it  or something with ServiceFailure if too many concurrent threads
                //
                return ChecksumUtil.checksum(inputStream, checksumAlgorithm);
            } catch (NoSuchAlgorithmException ex) {
                logger.warn(ex.getMessage());
                throw new InvalidRequest("1402", ex.getMessage());
            } catch (FileNotFoundException ex) {
                logger.warn(ex.getMessage());
                throw new NotFound("1420", ex.getMessage());
            } catch (IOException ex) {
                logger.warn(ex.getMessage());
                throw new ServiceFailure("1410", ex.getMessage());
            } catch (InsufficientResources ex) {
                logger.warn(ex.getMessage());
                throw new ServiceFailure("1410", ex.getMessage());
            } finally {
                try {
                    inputStream.close();
                } catch (IOException ex) {
                    logger.warn(ex.getMessage());
                    throw new ServiceFailure("1410", ex.getMessage());
                }
            }
        }
    }

    @Override
    public boolean synchronizationFailed(SynchronizationFailed message)
            throws InvalidToken, NotAuthorized, NotImplemented, ServiceFailure {
        // business rule for reporting and acting upon synchronized failed events (inactivate the object)

        // something more than just logging the error please?
        logger.error(message);

        // oh geez...
        return true;

    }

    @Override
    public InputStream getReplica(Identifier pid)
            throws InvalidToken, NotAuthorized, NotImplemented, ServiceFailure, NotFound, InsufficientResources {

        return this.get(pid);
    }

    @Override
    public boolean synchronizationFailed(Session session, SynchronizationFailed message)
            throws InvalidToken, NotAuthorized, NotImplemented, ServiceFailure {
        return this.synchronizationFailed(message);
    }

    @Override
    public InputStream getReplica(Session session, Identifier pid)
            throws InvalidToken, NotAuthorized, NotImplemented, ServiceFailure, NotFound, InsufficientResources {

        return this.getReplica(pid);
    }

    @Override
    public InputStream get(Session session, Identifier pid)
            throws InvalidToken, NotAuthorized, NotImplemented, ServiceFailure, NotFound, InsufficientResources {
        return this.get(pid);
    }

    @Override
    public SystemMetadata getSystemMetadata(Session session, Identifier pid)
            throws InvalidToken, NotAuthorized, NotImplemented, ServiceFailure, NotFound {
        return getSystemMetadata(pid);
    }

    @Override
    public DescribeResponse describe(Session session, Identifier pid)
            throws InvalidToken, NotAuthorized, NotImplemented, ServiceFailure, NotFound {
        return this.describe(pid);
    }

    @Override
    public Checksum getChecksum(Session session, Identifier pid, String checksumAlgorithm)
            throws InvalidRequest, InvalidToken, NotAuthorized, NotImplemented, ServiceFailure, NotFound {
        return this.getChecksum(pid, checksumAlgorithm);
    }

    @Override
    public ObjectList listObjects(Session session, Date fromDate, Date toDate, ObjectFormatIdentifier formatid,
            Boolean replicaStatus, Integer start, Integer count)
            throws InvalidRequest, InvalidToken, NotAuthorized, NotImplemented, ServiceFailure {
        return this.listObjects(toDate, toDate, formatid, replicaStatus, start, count);
    }
}