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.camel; 019 020import static org.fcrepo.camel.FcrepoConstants.COMMIT; 021import static org.fcrepo.camel.FcrepoConstants.ROLLBACK; 022import static org.fcrepo.camel.FcrepoConstants.TRANSACTION; 023import static org.fcrepo.client.FcrepoClient.client; 024import static org.slf4j.LoggerFactory.getLogger; 025 026import java.io.InputStream; 027import java.net.URI; 028 029import org.fcrepo.client.FcrepoClient; 030import org.fcrepo.client.FcrepoOperationFailedException; 031import org.fcrepo.client.FcrepoResponse; 032import org.slf4j.Logger; 033import org.springframework.transaction.CannotCreateTransactionException; 034import org.springframework.transaction.TransactionDefinition; 035import org.springframework.transaction.TransactionSystemException; 036import org.springframework.transaction.support.AbstractPlatformTransactionManager; 037import org.springframework.transaction.support.DefaultTransactionStatus; 038 039/** 040 * A Transaction Manager for interacting with fedora-based transactions 041 * 042 * @author Aaron Coburn 043 * @since Feb 16, 2015 044 */ 045public class FcrepoTransactionManager extends AbstractPlatformTransactionManager { 046 047 private FcrepoClient fcrepoClient; 048 049 private String baseUrl; 050 051 private String authUsername; 052 053 private String authPassword; 054 055 private String authHost; 056 057 private static final Logger LOGGER = getLogger(FcrepoTransactionManager.class); 058 059 /** 060 * Create a FcrepoTransactionManager 061 */ 062 public FcrepoTransactionManager() { 063 super(); 064 setNestedTransactionAllowed(false); 065 } 066 067 /** 068 * Set the baseUrl for the transaction manager. 069 * 070 * @param baseUrl the fcrepo base url 071 */ 072 public void setBaseUrl(final String baseUrl) { 073 this.baseUrl = baseUrl; 074 } 075 076 /** 077 * Get the base url for the transaction manager. 078 * 079 * @return the fcrepo base url 080 */ 081 public String getBaseUrl() { 082 return baseUrl; 083 } 084 085 /** 086 * Set the authUsername for the transaction manager. 087 * 088 * @param authUsername the username for authentication 089 */ 090 public void setAuthUsername(final String authUsername) { 091 this.authUsername = authUsername; 092 } 093 094 /** 095 * Get the authUsername for the transaction manager. 096 * 097 * @return the username for authentication 098 */ 099 public String getAuthUsername() { 100 return authUsername; 101 } 102 103 /** 104 * Set the authPassword for the transaction manager. 105 * 106 * @param authPassword the password used for authentication 107 */ 108 public void setAuthPassword(final String authPassword) { 109 this.authPassword = authPassword; 110 } 111 112 /** 113 * Get the authPassword for the transaction manager. 114 * 115 * @return the password used for authentication 116 */ 117 public String getAuthPassword() { 118 return authPassword; 119 } 120 121 /** 122 * Set the authHost for the transaction manager. 123 * 124 * @param authHost the host realm used for authentication 125 */ 126 public void setAuthHost(final String authHost) { 127 this.authHost = authHost; 128 } 129 130 /** 131 * Get the authHost for the transaction manager. 132 * 133 * @return the host realm used for authentication 134 */ 135 public String getAuthHost() { 136 return authHost; 137 } 138 139 @Override 140 protected void doBegin(final Object transaction, final TransactionDefinition definition) { 141 final FcrepoResponse response; 142 final InputStream is = null; 143 final String contentType = null; 144 final FcrepoTransactionObject tx = (FcrepoTransactionObject)transaction; 145 146 if (tx.getSessionId() == null) { 147 try { 148 response = getClient().post(URI.create(baseUrl + TRANSACTION)) 149 .body(is, contentType).perform(); 150 } catch (final FcrepoOperationFailedException ex) { 151 LOGGER.debug("HTTP Operation failed: ", ex); 152 throw new CannotCreateTransactionException("Could not create fcrepo transaction"); 153 } 154 155 if (response != null && response.getLocation() != null) { 156 tx.setSessionId(response.getLocation().toString().substring(baseUrl.length() + 1)); 157 } else { 158 throw new CannotCreateTransactionException("Invalid response while creating transaction"); 159 } 160 } 161 } 162 163 @Override 164 protected void doCommit(final DefaultTransactionStatus status) { 165 final FcrepoTransactionObject tx = (FcrepoTransactionObject)status.getTransaction(); 166 final InputStream is = null; 167 final String contentType = null; 168 169 try { 170 getClient().post(URI.create(baseUrl + "/" + tx.getSessionId() + COMMIT)) 171 .body(is, contentType).perform(); 172 } catch (final FcrepoOperationFailedException ex) { 173 LOGGER.debug("Transaction commit failed: ", ex); 174 throw new TransactionSystemException("Could not commit fcrepo transaction"); 175 } finally { 176 tx.setSessionId(null); 177 } 178 } 179 180 @Override 181 protected void doRollback(final DefaultTransactionStatus status) { 182 final FcrepoTransactionObject tx = (FcrepoTransactionObject)status.getTransaction(); 183 184 try { 185 getClient().post(URI.create(baseUrl + "/" + tx.getSessionId() + ROLLBACK)).perform(); 186 } catch (final FcrepoOperationFailedException ex) { 187 LOGGER.debug("Transaction rollback failed: ", ex); 188 throw new TransactionSystemException("Could not rollback fcrepo transaction"); 189 } finally { 190 tx.setSessionId(null); 191 } 192 } 193 194 @Override 195 protected Object doGetTransaction() { 196 return new FcrepoTransactionObject(); 197 } 198 199 private FcrepoClient getClient() { 200 if (fcrepoClient == null) { 201 return client().credentials(authUsername, authPassword).authScope(authHost) 202 .throwExceptionOnFailure().build(); 203 } 204 return fcrepoClient; 205 } 206}