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.http.commons.domain; 019 020import com.google.common.annotations.VisibleForTesting; 021 022import org.fcrepo.kernel.api.services.ExternalContentService; 023 024import javax.inject.Inject; 025import javax.ws.rs.WebApplicationException; 026import javax.ws.rs.core.MediaType; 027import javax.ws.rs.core.MultivaluedMap; 028import javax.ws.rs.ext.MessageBodyReader; 029import javax.ws.rs.ext.Provider; 030 031import java.io.IOException; 032import java.io.InputStream; 033import java.lang.annotation.Annotation; 034import java.lang.reflect.Type; 035import java.net.URI; 036import java.net.URISyntaxException; 037import static java.util.Arrays.stream; 038import static javax.ws.rs.core.Response.Status.BAD_REQUEST; 039 040/** 041 * Provide an InputStream either from the POST/PUT body, or by resolving a Content-Location URI 042 * @author cabeer 043 */ 044@Provider 045public class ContentLocationMessageBodyReader implements MessageBodyReader<InputStream> { 046 047 /** 048 * The fcrepo node service 049 */ 050 @Inject 051 private ExternalContentService contentService; 052 053 private static final Class<ContentLocation> contentLocationClass = ContentLocation.class; 054 055 @Override 056 public boolean isReadable(final Class<?> type, 057 final Type genericType, 058 final Annotation[] annotations, 059 final MediaType mediaType) { 060 return InputStream.class.isAssignableFrom(type) && 061 stream(annotations).map(Annotation::annotationType).anyMatch(contentLocationClass::equals); 062 } 063 064 @Override 065 public InputStream readFrom(final Class<InputStream> type, 066 final Type genericType, 067 final Annotation[] annotations, 068 final MediaType mediaType, 069 final MultivaluedMap<String, String> httpHeaders, 070 final InputStream entityStream) throws IOException { 071 072 if (httpHeaders.containsKey("Content-Location")) { 073 final String location = httpHeaders.getFirst("Content-Location"); 074 075 try { 076 return contentService.retrieveExternalContent(new URI(location)); 077 } catch (final URISyntaxException e) { 078 throw new WebApplicationException(e, BAD_REQUEST); 079 } 080 081 } 082 return entityStream; 083 } 084 085 @VisibleForTesting 086 protected void setContentService(final ExternalContentService externalContentService) { 087 this.contentService = externalContentService; 088 } 089}