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; 019 020import org.apache.jena.rdf.model.Resource; 021import org.fcrepo.kernel.api.exception.InvalidChecksumException; 022import org.fcrepo.kernel.api.exception.RepositoryRuntimeException; 023import org.fcrepo.kernel.api.exception.UnsupportedAlgorithmException; 024import org.fcrepo.kernel.api.identifiers.IdentifierConverter; 025import org.fcrepo.kernel.api.models.FedoraBinary; 026import org.fcrepo.kernel.api.models.FedoraResource; 027import org.fcrepo.kernel.api.RdfStream; 028import org.fcrepo.kernel.api.services.policy.StoragePolicyDecisionPoint; 029import org.fcrepo.kernel.api.TripleCategory; 030 031import static org.fcrepo.kernel.modeshape.utils.FedoraTypesUtils.isFedoraBinary; 032 033import javax.jcr.Node; 034import javax.jcr.RepositoryException; 035 036import java.io.InputStream; 037import java.net.URI; 038import java.util.Collection; 039import java.util.Set; 040 041/** 042 * @author cabeer 043 * @since 9/19/14 044 */ 045public class FedoraBinaryImpl extends AbstractFedoraBinary { 046 047 private static final String LOCAL_FILE_ACCESS_TYPE = "file"; 048 049 private static final String URL_ACCESS_TYPE = "http"; 050 051 private FedoraBinary wrappedBinary; 052 053 /** 054 * Wrap an existing Node as a Fedora Binary 055 * @param node the node 056 */ 057 public FedoraBinaryImpl(final Node node) { 058 super(node); 059 } 060 061 /** 062 * Get the proxied binary content object wrapped by this object 063 * 064 * @return the fedora binary 065 */ 066 private FedoraBinary getBinary() { 067 return getBinary(null); 068 } 069 070 /** 071 * Get the proxied binary content object wrapped by this object 072 * 073 * @return the fedora binary 074 */ 075 private FedoraBinary getBinary(final String extUrl) { 076 if (wrappedBinary == null) { 077 wrappedBinary = getBinaryImplementation(extUrl); 078 } 079 return wrappedBinary; 080 } 081 082 /** 083 * Return the proper object that can handle this type of binary 084 * @param extUrl URL of external binary, else null if it's internal to modeshape. 085 * @return the fedora binary, of the proper kind based on the URL or lack there of 086 */ 087 private FedoraBinary getBinaryImplementation(final String extUrl) { 088 String url = extUrl; 089 if (url == null || url.isEmpty()) { 090 url = getURLInfo(); 091 } 092 093 if (url != null) { 094 if (url.toLowerCase().startsWith(LOCAL_FILE_ACCESS_TYPE)) { 095 return new LocalFileBinary(getNode()); 096 } else if (url.toLowerCase().startsWith(URL_ACCESS_TYPE)) { 097 return new UrlBinary(getNode()); 098 } 099 } 100 101 return new InternalFedoraBinary(getNode()); 102 } 103 104 /** 105 * Fetch the URL of the external binary 106 * @return String containing the URL location of external binary, else null if it's an internal binary 107 */ 108 private String getURLInfo() { 109 try { 110 if (hasProperty(PROXY_FOR)) { 111 return getNode().getProperty(PROXY_FOR).getValue().getString(); 112 } else if (hasProperty(REDIRECTS_TO)) { 113 return getNode().getProperty(REDIRECTS_TO).getValue().getString(); 114 } 115 } catch (RepositoryException e) { 116 throw new RepositoryRuntimeException(e); 117 } 118 119 return null; 120 } 121 122 /* 123 * (non-Javadoc) 124 * @see org.fcrepo.kernel.api.models.FedoraBinary#getContent() 125 */ 126 @Override 127 public InputStream getContent() { 128 return getBinary().getContent(); 129 } 130 131 @Override 132 public void setExternalContent(final String contentType, 133 final Collection<URI> checksums, final String originalFileName, 134 final String externalHandling, final String externalUrl) 135 throws InvalidChecksumException { 136 137 // Clear the wrapped binary object prior to setting the content 138 wrappedBinary = null; 139 getBinary(externalUrl).setExternalContent(contentType, checksums, originalFileName, 140 externalHandling, externalUrl); 141 } 142 143 /* 144 * (non-Javadoc) 145 * @see org.fcrepo.kernel.api.models.FedoraBinary#setContent(java.io.InputStream, 146 * java.lang.String, java.net.URI, java.lang.String, 147 * org.fcrepo.kernel.api.services.policy.StoragePolicyDecisionPoint) 148 */ 149 @Override 150 public void setContent(final InputStream content, final String contentType, 151 final Collection<URI> checksums, final String originalFileName, 152 final StoragePolicyDecisionPoint storagePolicyDecisionPoint) 153 throws InvalidChecksumException { 154 155 // Clear the wrapped binary object prior to setting the content 156 wrappedBinary = null; 157 // Need to pass the new filename to get the correct implementation. 158 getBinary().setContent(content, contentType, checksums, originalFileName, 159 storagePolicyDecisionPoint); 160 } 161 162 /* 163 * (non-Javadoc) 164 * @see org.fcrepo.kernel.api.models.FedoraBinary#getContentSize() 165 */ 166 @Override 167 public long getContentSize() { 168 return getBinary().getContentSize(); 169 } 170 171 /* 172 * (non-Javadoc) 173 * @see org.fcrepo.kernel.api.models.FedoraBinary#getContentDigest() 174 */ 175 @Override 176 public URI getContentDigest() { 177 return getBinary().getContentDigest(); 178 } 179 180 /* 181 * (non-Javadoc) 182 * @see org.fcrepo.kernel.api.models.FedoraBinary#getMimeType() 183 */ 184 @Override 185 public String getMimeType() { 186 return getBinary().getMimeType(); 187 } 188 189 /* 190 * (non-Javadoc) 191 * @see org.fcrepo.kernel.api.models.FedoraBinary#getFilename() 192 */ 193 @Override 194 public String getFilename() { 195 return getBinary().getFilename(); 196 } 197 198 @Override 199 public RdfStream getFixity(final IdentifierConverter<Resource, FedoraResource> idTranslator) { 200 return getBinary().getFixity(idTranslator); 201 } 202 203 @Override 204 public RdfStream getFixity(final IdentifierConverter<Resource, FedoraResource> idTranslator, 205 final URI digestUri, 206 final long size) { 207 208 return getBinary().getFixity(idTranslator, digestUri, size); 209 } 210 211 @Override 212 public Collection<URI> checkFixity( final IdentifierConverter<Resource, FedoraResource> idTranslator, 213 final Collection<String> algorithms) 214 throws UnsupportedAlgorithmException { 215 216 return getBinary().checkFixity(idTranslator, algorithms); 217 } 218 219 /** 220 * When deleting the binary, we also need to clean up the description document. 221 */ 222 @Override 223 public void delete() { 224 getBinary().delete(); 225 } 226 227 @Override 228 protected boolean hasDescriptionProperty(final String relPath) { 229 try { 230 final Node descNode = getDescriptionNodeOrNull(); 231 if (descNode == null) { 232 return false; 233 } 234 return descNode.hasProperty(relPath); 235 } catch (final RepositoryException e) { 236 throw new RepositoryRuntimeException(e); 237 } 238 } 239 240 @Override 241 public RdfStream getTriples(final IdentifierConverter<Resource, FedoraResource> idTranslator, 242 final Set<? extends TripleCategory> contexts) { 243 return getDescription().getTriples(idTranslator, contexts); 244 } 245 246 /** 247 * Check if the given node is a Fedora binary 248 * 249 * @param node the given node 250 * @return whether the given node is a Fedora binary 251 */ 252 public static boolean hasMixin(final Node node) { 253 return isFedoraBinary.test(node); 254 } 255}