001/** 002 * Copyright 2015 DuraSpace, Inc. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.fcrepo.client.impl; 017 018import com.hp.hpl.jena.graph.Triple; 019 020import org.apache.http.HttpResponse; 021import org.apache.http.StatusLine; 022import org.apache.http.client.HttpClient; 023import org.apache.http.client.methods.HttpHead; 024import org.apache.http.client.methods.HttpPost; 025import org.apache.http.client.methods.HttpPut; 026import org.fcrepo.client.AlreadyExistsException; 027import org.fcrepo.client.FedoraContent; 028import org.fcrepo.client.FedoraDatastream; 029import org.fcrepo.client.FedoraException; 030import org.fcrepo.client.FedoraObject; 031import org.fcrepo.client.FedoraRepository; 032import org.fcrepo.client.ForbiddenException; 033import org.fcrepo.client.NotFoundException; 034import org.fcrepo.client.ReadOnlyException; 035import org.fcrepo.client.utils.HttpHelper; 036import org.slf4j.Logger; 037 038import java.io.InputStream; 039import java.util.Iterator; 040import java.util.Map; 041 042import static org.apache.http.HttpStatus.SC_CONFLICT; 043import static org.apache.http.HttpStatus.SC_CREATED; 044import static org.apache.http.HttpStatus.SC_FORBIDDEN; 045import static org.apache.http.HttpStatus.SC_NOT_FOUND; 046import static org.apache.http.HttpStatus.SC_OK; 047import static org.slf4j.LoggerFactory.getLogger; 048 049/** 050 * FedoraRepositoryImpl manage httpclient instance to run requests 051 * 052 * @author lsitu 053 * @author escowles 054 * @since 2014-08-11 055 */ 056public class FedoraRepositoryImpl implements FedoraRepository { 057 private static final Logger LOGGER = getLogger(FedoraRepositoryImpl.class); 058 059 protected HttpHelper httpHelper; 060 protected String repositoryURL; 061 062 protected FedoraRepositoryImpl() { 063 // for subclasses 064 } 065 066 /** 067 * Constructor that takes the repository url 068 * 069 * @param repositoryURL Fedora base URL. 070 */ 071 public FedoraRepositoryImpl(final String repositoryURL) { 072 this(repositoryURL, null, null); 073 } 074 075 /** 076 * Constructor 077 * 078 * @param repositoryURL Repository base URL 079 * @param username Repository username 080 * @param password Repository password 081 */ 082 public FedoraRepositoryImpl(final String repositoryURL, final String username, final String password) { 083 this.repositoryURL = repositoryURL; 084 this.httpHelper = new HttpHelper(repositoryURL, username, password, false); 085 } 086 087 /** 088 * Constructor that takes the pre-configured HttpClient 089 * 090 * @param repositoryURL Repository baseURL 091 * @param httpClient Pre-configured httpClient 092 */ 093 public FedoraRepositoryImpl(final String repositoryURL, final HttpClient httpClient) { 094 this.repositoryURL = repositoryURL; 095 this.httpHelper = new HttpHelper(repositoryURL, httpClient, false); 096 } 097 098 @Override 099 public boolean exists(final String path) throws FedoraException, ForbiddenException { 100 final HttpHead head = httpHelper.createHeadMethod(path); 101 try { 102 final HttpResponse response = httpHelper.execute(head); 103 final StatusLine status = response.getStatusLine(); 104 final int statusCode = status.getStatusCode(); 105 final String uri = head.getURI().toString(); 106 if (statusCode == SC_OK) { 107 return true; 108 } else if (statusCode == SC_NOT_FOUND) { 109 return false; 110 } else if (statusCode == SC_FORBIDDEN) { 111 LOGGER.error("request for resource {} is not authorized.", uri); 112 throw new ForbiddenException("request for resource " + uri + " is not authorized."); 113 } else { 114 LOGGER.error("error checking resource {}: {} {}", uri, statusCode, status.getReasonPhrase()); 115 throw new FedoraException("error checking resource " + uri + ": " + statusCode + " " + 116 status.getReasonPhrase()); 117 } 118 } catch (final Exception e) { 119 LOGGER.error("could not encode URI parameter", e); 120 throw new FedoraException(e); 121 } finally { 122 head.releaseConnection(); 123 } 124 } 125 126 @Override 127 public FedoraDatastream getDatastream(final String path) throws FedoraException { 128 return (FedoraDatastream)httpHelper.loadProperties(new FedoraDatastreamImpl(this, httpHelper, path)); 129 } 130 131 @Override 132 public FedoraObject getObject(final String path) throws FedoraException { 133 return (FedoraObject)httpHelper.loadProperties(new FedoraObjectImpl(this, httpHelper, path)); 134 } 135 136 @Override 137 public FedoraDatastream createDatastream(final String path, final FedoraContent content) throws FedoraException { 138 final HttpPut put = httpHelper.createContentPutMethod(path, null, content); 139 try { 140 final HttpResponse response = httpHelper.execute(put); 141 final String uri = put.getURI().toString(); 142 final StatusLine status = response.getStatusLine(); 143 final int statusCode = status.getStatusCode(); 144 145 if (statusCode == SC_CREATED) { 146 return getDatastream(path); 147 } else if (statusCode == SC_FORBIDDEN) { 148 LOGGER.error("request to create resource {} is not authorized.", uri); 149 throw new ForbiddenException("request to create resource " + uri + " is not authorized."); 150 } else if (statusCode == SC_CONFLICT) { 151 LOGGER.error("resource {} already exists", uri); 152 throw new AlreadyExistsException("resource " + uri + " already exists"); 153 } else { 154 LOGGER.error("error creating resource {}: {} {}", uri, statusCode, status.getReasonPhrase()); 155 throw new FedoraException("error retrieving resource " + uri + ": " + statusCode + " " + 156 status.getReasonPhrase()); 157 } 158 } catch (final Exception e) { 159 LOGGER.error("could not encode URI parameter", e); 160 throw new FedoraException(e); 161 } finally { 162 put.releaseConnection(); 163 } 164 } 165 166 @Override 167 public FedoraDatastream createOrUpdateRedirectDatastream(final String path, final String url) 168 throws FedoraException { 169 final HttpPut put = httpHelper.createContentPutMethod(path, null, null); 170 try { 171 put.setHeader("Content-Type", "message/external-body; access-type=URL; URL=\"" + url + "\""); 172 final HttpResponse response = httpHelper.execute(put); 173 final String uri = put.getURI().toString(); 174 final StatusLine status = response.getStatusLine(); 175 final int statusCode = status.getStatusCode(); 176 177 if (statusCode == SC_CREATED) { 178 return getDatastream(path); 179 } else if (statusCode == SC_FORBIDDEN) { 180 LOGGER.error("request to create resource {} is not authorized.", uri); 181 throw new ForbiddenException("request to create resource " + uri + " is not authorized."); 182 } else { 183 LOGGER.error("error creating resource {}: {} {}", uri, statusCode, status.getReasonPhrase()); 184 throw new FedoraException("error creating resource " + uri + ": " + statusCode + " " + 185 status.getReasonPhrase()); 186 } 187 } catch (final Exception e) { 188 LOGGER.error("Error making or building PUT request.", e); 189 throw new FedoraException(e); 190 } finally { 191 put.releaseConnection(); 192 } 193 } 194 195 @Override 196 public FedoraObject createObject(final String path) throws FedoraException { 197 final HttpPut put = httpHelper.createPutMethod(path, null); 198 try { 199 final HttpResponse response = httpHelper.execute(put); 200 final String uri = put.getURI().toString(); 201 final StatusLine status = response.getStatusLine(); 202 final int statusCode = status.getStatusCode(); 203 204 if (statusCode == SC_CREATED) { 205 return getObject(path); 206 } else if (statusCode == SC_FORBIDDEN) { 207 LOGGER.error("request to create resource {} is not authorized.", uri); 208 throw new ForbiddenException("request to create resource " + uri + " is not authorized."); 209 } else if (statusCode == SC_CONFLICT) { 210 LOGGER.error("resource {} already exists", uri); 211 throw new AlreadyExistsException("resource " + uri + " already exists"); 212 } else { 213 LOGGER.error("error creating resource {}: {} {}", uri, statusCode, status.getReasonPhrase()); 214 throw new FedoraException("error retrieving resource " + uri + ": " + statusCode + " " + 215 status.getReasonPhrase()); 216 } 217 } catch (final Exception e) { 218 LOGGER.error("could not encode URI parameter", e); 219 throw new FedoraException(e); 220 } finally { 221 put.releaseConnection(); 222 } 223 } 224 225 @Override 226 public FedoraObject createResource(final String containerPath) throws FedoraException { 227 final HttpPost post = httpHelper.createPostMethod(containerPath == null ? "" : containerPath, null); 228 try { 229 final HttpResponse response = httpHelper.execute(post); 230 final String uri = post.getURI().toString(); 231 final StatusLine status = response.getStatusLine(); 232 final int statusCode = status.getStatusCode(); 233 234 if (statusCode == SC_CREATED) { 235 return getObject(response.getFirstHeader("Location").getValue().substring(repositoryURL.length())); 236 } else if (statusCode == SC_FORBIDDEN) { 237 LOGGER.error("request to create resource {} is not authorized.", uri); 238 throw new ForbiddenException("request to create resource " + uri + " is not authorized."); 239 } else { 240 LOGGER.error("error creating resource {}: {} {}", uri, statusCode, status.getReasonPhrase()); 241 throw new FedoraException("error creating resource " + uri + ": " + statusCode + " " + 242 status.getReasonPhrase()); 243 } 244 } catch (final Exception e) { 245 LOGGER.error("could not encode URI parameter", e); 246 throw new FedoraException(e); 247 } finally { 248 post.releaseConnection(); 249 } 250 } 251 252 @Override 253 public FedoraDatastream findOrCreateDatastream(final String path) throws FedoraException { 254 try { 255 return getDatastream(path); 256 } catch ( NotFoundException ex ) { 257 return createDatastream(path, null); 258 } 259 } 260 261 @Override 262 public FedoraObject findOrCreateObject(final String path) throws FedoraException { 263 try { 264 return getObject(path); 265 } catch ( NotFoundException ex ) { 266 return createObject(path); 267 } 268 } 269 270 @Override 271 public Iterator<Triple> getNodeTypes() { 272 // TODO Auto-generated method stub 273 return null; 274 } 275 276 @Override 277 public void registerNodeTypes(final InputStream cndStream) throws ReadOnlyException { 278 // TODO Auto-generated method stub 279 280 } 281 282 @Override 283 public Map<String, String> getRepositoryNamespaces() { 284 // TODO Auto-generated method stub 285 return null; 286 } 287 288 @Override 289 public void addNamespace(final String prefix, final String uri) throws ReadOnlyException { 290 // TODO Auto-generated method stub 291 292 } 293 294 @Override 295 public void removeNamespace(final String prefix) throws ReadOnlyException { 296 // TODO Auto-generated method stub 297 298 } 299 300 @Override 301 public Long getRepositoryObjectCount() { 302 // TODO Auto-generated method stub 303 return null; 304 } 305 306 @Override 307 public Long getRepositorySize() { 308 // TODO Auto-generated method stub 309 return null; 310 } 311 312 @Override 313 public boolean isWritable() { 314 return true; 315 } 316 317 @Override 318 public String getRepositoryUrl() { 319 return repositoryURL; 320 } 321 322}