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.modeshape.services; 019 020import org.fcrepo.kernel.api.FedoraSession; 021import org.fcrepo.kernel.api.exception.RepositoryRuntimeException; 022import org.fcrepo.kernel.api.exception.ResourceTypeException; 023import org.fcrepo.kernel.api.models.FedoraBinary; 024import org.fcrepo.kernel.api.models.NonRdfSourceDescription; 025import org.fcrepo.kernel.api.services.BinaryService; 026import org.fcrepo.kernel.modeshape.FedoraBinaryImpl; 027import org.fcrepo.kernel.modeshape.NonRdfSourceDescriptionImpl; 028import org.slf4j.Logger; 029import org.springframework.stereotype.Component; 030 031import javax.jcr.Node; 032import javax.jcr.RepositoryException; 033 034import static org.fcrepo.kernel.api.FedoraTypes.FEDORA_BINARY; 035import static org.fcrepo.kernel.api.FedoraTypes.FEDORA_NON_RDF_SOURCE_DESCRIPTION; 036import static org.fcrepo.kernel.api.FedoraTypes.FEDORA_RESOURCE; 037import static org.fcrepo.kernel.api.RdfLexicon.FEDORA_DESCRIPTION; 038import static org.fcrepo.kernel.api.RdfLexicon.NT_LEAF_NODE; 039import static org.fcrepo.kernel.api.RdfLexicon.NT_VERSION_FILE; 040import static org.fcrepo.kernel.modeshape.utils.FedoraTypesUtils.getContainingNode; 041import static org.fcrepo.kernel.modeshape.utils.FedoraTypesUtils.getJcrNode; 042import static org.fcrepo.kernel.modeshape.utils.FedoraTypesUtils.touch; 043import static org.fcrepo.kernel.modeshape.utils.FedoraTypesUtils.touchLdpMembershipResource; 044import static org.slf4j.LoggerFactory.getLogger; 045 046/** 047 * @author cabeer 048 * @author ajs6f 049 * @since 10/10/14 050 */ 051@Component 052public class BinaryServiceImpl extends AbstractService implements BinaryService { 053 054 private static final Logger LOGGER = getLogger(BinaryServiceImpl.class); 055 056 /** 057 * {@inheritDoc} 058 */ 059 @Override 060 public FedoraBinary findOrCreate(final FedoraSession session, final String path) { 061 try { 062 final FedoraBinary binary = findOrCreateBinary(session, path); 063 064 final Node dsNode = getJcrNode(binary); 065 if (dsNode.isNew()) { 066 final String descPath = dsNode.getPath() + "/" + FEDORA_DESCRIPTION; 067 findOrCreateDescription(session, descPath); 068 } 069 070 return binary; 071 } catch (final RepositoryException e) { 072 throw new RepositoryRuntimeException(e); 073 } 074 } 075 076 /** 077 * {@inheritDoc} 078 */ 079 @Override 080 public FedoraBinary findOrCreateBinary(final FedoraSession session, final String path) { 081 try { 082 final Node dsNode = findOrCreateNode(session, path, NT_VERSION_FILE); 083 084 if (dsNode.isNew()) { 085 initializeNewBinaryProperties(dsNode); 086 087 getContainingNode(dsNode).ifPresent(parent -> { 088 touch(parent); 089 touchLdpMembershipResource(dsNode); 090 }); 091 } 092 093 final FedoraBinaryImpl binary = new FedoraBinaryImpl(dsNode); 094 095 if (dsNode.isNew()) { 096 touch(binary.getNode()); 097 } 098 099 return binary; 100 } catch (final RepositoryException e) { 101 throw new RepositoryRuntimeException(e); 102 } 103 } 104 105 /** 106 * {@inheritDoc} 107 */ 108 @Override 109 public NonRdfSourceDescription findOrCreateDescription(final FedoraSession session, final String path) { 110 try { 111 final Node descNode = findOrCreateNode(session, path, NT_LEAF_NODE); 112 113 initializeNewDescriptionProperties(descNode); 114 115 return new NonRdfSourceDescriptionImpl(descNode); 116 } catch (final RepositoryException e) { 117 throw new RepositoryRuntimeException(e); 118 } 119 } 120 121 /** 122 * Retrieve a Datastream instance by pid and dsid 123 * 124 * @param path jcr path to the datastream 125 * @return datastream 126 */ 127 @Override 128 public FedoraBinary find(final FedoraSession session, final String path) { 129 return cast(findNode(session, path)); 130 } 131 132 private static void initializeNewBinaryProperties(final Node node) { 133 try { 134 135 if (node.canAddMixin(FEDORA_RESOURCE)) { 136 node.addMixin(FEDORA_RESOURCE); 137 } 138 if (node.canAddMixin(FEDORA_BINARY)) { 139 node.addMixin(FEDORA_BINARY); 140 } 141 } catch (final RepositoryException e) { 142 LOGGER.warn("Could not decorate {} with binary properties: {}", node, e); 143 } 144 } 145 146 private static void initializeNewDescriptionProperties(final Node descNode) { 147 try { 148 if (descNode.canAddMixin(FEDORA_NON_RDF_SOURCE_DESCRIPTION)) { 149 descNode.addMixin(FEDORA_NON_RDF_SOURCE_DESCRIPTION); 150 } 151 152 if (descNode.canAddMixin(FEDORA_BINARY)) { 153 descNode.addMixin(FEDORA_BINARY); 154 } 155 } catch (final RepositoryException e) { 156 LOGGER.warn("Could not decorate {} with description properties: {}", descNode, e); 157 } 158 } 159 160 /** 161 * Retrieve a Datastream instance by pid and dsid 162 * 163 * @param node datastream node 164 * @return node as datastream 165 */ 166 private FedoraBinary cast(final Node node) { 167 assertIsType(node); 168 return new FedoraBinaryImpl(node); 169 } 170 171 private static void assertIsType(final Node node) { 172 if (!FedoraBinaryImpl.hasMixin(node)) { 173 throw new ResourceTypeException(node + " can not be used as a binary"); 174 } 175 } 176 177 178}