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