001/* 002 * The contents of this file are subject to the license and copyright 003 * detailed in the LICENSE and NOTICE files at the root of the source 004 * tree. 005 */ 006package org.fcrepo.camel.ldpath; 007 008import static org.slf4j.LoggerFactory.getLogger; 009 010import org.apache.marmotta.ldclient.api.endpoint.Endpoint; 011import org.apache.marmotta.ldclient.provider.rdf.LinkedDataProvider; 012import org.fcrepo.client.FcrepoHttpClientBuilder; 013import org.fcrepo.client.FcrepoLink; 014 015import java.io.IOException; 016import java.io.UncheckedIOException; 017import java.util.Collections; 018import java.util.List; 019import java.util.Objects; 020import java.util.Optional; 021 022import org.apache.http.client.HttpClient; 023import org.apache.http.client.methods.HttpHead; 024import org.apache.http.Header; 025import org.apache.http.HttpResponse; 026import org.slf4j.Logger; 027 028 029/** 030 * An extension Linked Data provider to support Binary nodes in Fedora. 031 * 032 * @author Mohamed Mohideen Abdul Rasheed 033 */ 034public class FedoraProvider extends LinkedDataProvider { 035 036 private static final Logger LOGGER = getLogger(FedoraProvider.class); 037 038 public static final String PROVIDER_NAME = "Fedora"; 039 040 private final HttpClient httpClient; 041 042 private final String NON_RDF_SOURCE_URI = "http://www.w3.org/ns/ldp#NonRDFSource"; 043 044 /** 045 * FedoraProvider 046 * @param builder FcrepoHttpClientBuilder for building HttpClient 047 */ 048 public FedoraProvider(final FcrepoHttpClientBuilder builder) { 049 Objects.requireNonNull(builder); 050 httpClient = builder.build(); 051 } 052 053 /* 054 * Return the name of this data provider. To be used e.g. in the configuration and in log messages. 055 */ 056 @Override 057 public String getName() { 058 return PROVIDER_NAME; 059 } 060 061 /* 062 * Return the describedBy URL for NonRdfSource resources. Return the resourseUri otherwise. 063 */ 064 @Override 065 public List<String> buildRequestUrl(final String resourceUri, final Endpoint endpoint) { 066 LOGGER.debug("Processing: " + resourceUri); 067 Objects.requireNonNull(resourceUri); 068 try { 069 final Optional<String> nonRdfSourceDescUri = 070 getNonRDFSourceDescribedByUri(resourceUri); 071 if ( nonRdfSourceDescUri.isPresent() ) { 072 return Collections.singletonList(nonRdfSourceDescUri.get()); 073 } 074 } catch (final IOException ex) { 075 throw new UncheckedIOException(ex); 076 } 077 return Collections.singletonList(resourceUri); 078 } 079 080 /* 081 * Get the describedBy Uri if the resource has a NON_RDF_SOURCE_URI link header. 082 */ 083 private Optional<String> getNonRDFSourceDescribedByUri(final String resourceUri) throws IOException { 084 Optional<String> nonRdfSourceDescUri = Optional.empty(); 085 final Header[] links = getLinkHeaders(resourceUri); 086 if ( links != null ) { 087 String descriptionUri = null; 088 boolean isNonRDFSource = false; 089 for ( final Header h : links ) { 090 final FcrepoLink link = new FcrepoLink(h.getValue()); 091 if ( link.getRel().equals("describedby") ) { 092 descriptionUri = link.getUri().toString(); 093 } else if ( link.getUri().toString().contains(NON_RDF_SOURCE_URI)) { 094 isNonRDFSource = true; 095 } 096 } 097 LOGGER.debug("isNonRDFSource: " + isNonRDFSource); 098 if (isNonRDFSource && descriptionUri != null) { 099 nonRdfSourceDescUri = Optional.of(descriptionUri); 100 } 101 } 102 return nonRdfSourceDescUri; 103 } 104 105 /* 106 * Get the link headers for the resource at the given Uri. 107 */ 108 private Header[] getLinkHeaders(final String resourceUri) throws IOException { 109 final HttpHead request = new HttpHead(resourceUri); 110 final HttpResponse response = httpClient.execute(request); 111 LOGGER.debug("Got: " + response.getStatusLine().getStatusCode() + " for HEAD " + resourceUri); 112 return response.getHeaders("Link"); 113 } 114 115}