001/* 002 * Licensed to DuraSpace under one or more contributor license agreements. 003 * See the NOTICE file distributed with this work for additional information 004 * regarding copyright ownership. 005 * 006 * DuraSpace licenses this file to you under the Apache License, 007 * Version 2.0 (the "License"); you may not use this file except in 008 * compliance with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.fcrepo.kernel.impl.services; 019 020import org.fcrepo.kernel.api.exception.RepositoryRuntimeException; 021import org.fcrepo.kernel.api.identifiers.FedoraId; 022import org.fcrepo.kernel.api.models.ExternalContent; 023import org.fcrepo.kernel.api.operations.NonRdfSourceOperationBuilder; 024import org.fcrepo.kernel.api.operations.NonRdfSourceOperationFactory; 025import org.fcrepo.kernel.api.services.ReplaceBinariesService; 026import org.fcrepo.persistence.api.PersistentStorageSession; 027import org.fcrepo.persistence.api.PersistentStorageSessionManager; 028import org.fcrepo.persistence.api.exceptions.PersistentStorageException; 029import org.fcrepo.persistence.common.MultiDigestInputStreamWrapper; 030import org.slf4j.Logger; 031import org.springframework.stereotype.Component; 032 033import javax.inject.Inject; 034import java.io.InputStream; 035import java.net.URI; 036import java.util.Collection; 037import java.util.Collections; 038 039import static java.lang.String.format; 040import static org.slf4j.LoggerFactory.getLogger; 041 042/** 043 * Implementation of a service for replacing/updating binary resources 044 * 045 * @author bbpennel 046 */ 047@Component 048public class ReplaceBinariesServiceImpl extends AbstractService implements ReplaceBinariesService { 049 050 private static final Logger LOGGER = getLogger(ReplaceBinariesServiceImpl.class); 051 052 @Inject 053 private PersistentStorageSessionManager psManager; 054 055 @Inject 056 private NonRdfSourceOperationFactory factory; 057 058 @Override 059 public void perform(final String txId, 060 final String userPrincipal, 061 final FedoraId fedoraId, 062 final String filename, 063 final String contentType, 064 final Collection<URI> digests, 065 final InputStream contentBody, 066 final long contentSize, 067 final ExternalContent externalContent) { 068 try { 069 final PersistentStorageSession pSession = this.psManager.getSession(txId); 070 071 String mimeType = contentType; 072 long size = contentSize; 073 final NonRdfSourceOperationBuilder builder; 074 if (externalContent == null || externalContent.isCopy()) { 075 var contentInputStream = contentBody; 076 if (externalContent != null) { 077 LOGGER.debug("External content COPY '{}', '{}'", fedoraId, externalContent.getURL()); 078 contentInputStream = externalContent.fetchExternalContent(); 079 } 080 081 builder = factory.updateInternalBinaryBuilder(fedoraId, contentInputStream); 082 } else { 083 builder = factory.updateExternalBinaryBuilder(fedoraId, 084 externalContent.getHandling(), 085 externalContent.getURI()); 086 087 if (contentSize == -1L) { 088 size = externalContent.getContentSize(); 089 } 090 if (!digests.isEmpty()) { 091 final var multiDigestWrapper = new MultiDigestInputStreamWrapper( 092 externalContent.fetchExternalContent(), 093 digests, 094 Collections.emptyList()); 095 multiDigestWrapper.checkFixity(); 096 } 097 } 098 099 if (externalContent != null && externalContent.getContentType() != null) { 100 mimeType = externalContent.getContentType(); 101 } 102 103 builder.mimeType(mimeType) 104 .contentSize(size) 105 .filename(filename) 106 .contentDigests(digests) 107 .userPrincipal(userPrincipal); 108 final var replaceOp = builder.build(); 109 110 pSession.persist(replaceOp); 111 recordEvent(txId, fedoraId, replaceOp); 112 } catch (final PersistentStorageException ex) { 113 throw new RepositoryRuntimeException(format("failed to replace binary %s", 114 fedoraId), ex); 115 } 116 } 117 118}