Java tutorial
/* * 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); } }