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.api.repository; 019 020import static com.google.common.io.Files.createTempDir; 021import static java.util.stream.Collectors.joining; 022import static javax.ws.rs.core.Response.serverError; 023import static org.slf4j.LoggerFactory.getLogger; 024 025import java.io.File; 026import java.io.IOException; 027import java.io.InputStream; 028import java.util.Collection; 029 030import javax.inject.Inject; 031import javax.jcr.Session; 032import javax.ws.rs.POST; 033import javax.ws.rs.Path; 034import javax.ws.rs.WebApplicationException; 035 036import org.apache.commons.io.IOUtils; 037import org.fcrepo.http.commons.AbstractResource; 038import org.fcrepo.kernel.api.services.RepositoryService; 039import org.slf4j.Logger; 040import org.springframework.context.annotation.Scope; 041 042/** 043 * Repository-wide backup endpoint 044 * 045 * @author cbeer 046 */ 047@Scope("prototype") 048@Path("/fcr:backup") 049public class FedoraRepositoryBackup extends AbstractResource { 050 051 private static final Logger LOGGER = getLogger(FedoraRepositoryBackup.class); 052 053 @Inject 054 protected Session session; 055 056 /** 057 * The fcrepo repository service 058 */ 059 @Inject 060 protected RepositoryService repositoryService; 061 062 /** 063 * This method runs a repository backup. 064 * 065 * @param bodyStream the input body stream 066 * @return path to the backup 067 * @throws IOException if IO exception occurred 068 */ 069 @POST 070 public String runBackup(final InputStream bodyStream) throws IOException { 071 072 File backupDirectory; 073 if (null != bodyStream) { 074 final String body = IOUtils.toString(bodyStream).trim(); 075 076 backupDirectory = new File(body.trim()); 077 if (body.isEmpty()) { 078 // Backup to a temp directory 079 backupDirectory = createTempDir(); 080 081 } else if (!backupDirectory.exists() || !backupDirectory.canWrite()) { 082 throw new WebApplicationException( 083 serverError().entity( 084 "Backup directory does not exist or is not writable: " + 085 backupDirectory.getAbsolutePath()) 086 .build()); 087 } 088 089 } else { 090 // Backup to a temp directory 091 backupDirectory = createTempDir(); 092 } 093 094 LOGGER.debug("Backing up to: {}", backupDirectory.getAbsolutePath()); 095 final Collection<Throwable> problems = repositoryService.backupRepository(session, backupDirectory); 096 097 if (!problems.isEmpty()) { 098 LOGGER.error("Problems backing up the repository:"); 099 100 // Report the problems (we'll just print them out) ... 101 final String output = problems.stream().map(Throwable::getMessage).peek(LOGGER::error) 102 .collect(joining("\n")); 103 104 throw new WebApplicationException(serverError().entity(output).build()); 105 106 } 107 return backupDirectory.getCanonicalPath(); 108 } 109}