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; 019 020import org.fcrepo.common.db.DbTransactionExecutor; 021import org.fcrepo.http.commons.AbstractResource; 022import org.fcrepo.http.commons.api.rdf.HttpIdentifierConverter; 023import org.fcrepo.http.commons.session.TransactionProvider; 024import org.fcrepo.kernel.api.Transaction; 025import org.fcrepo.kernel.api.TransactionManager; 026import org.fcrepo.kernel.api.exception.PathNotFoundException; 027import org.fcrepo.kernel.api.identifiers.FedoraId; 028import org.fcrepo.kernel.api.models.FedoraResource; 029import org.fcrepo.kernel.api.models.ResourceFactory; 030import org.fcrepo.kernel.api.models.ResourceHelper; 031import org.slf4j.Logger; 032 033import javax.inject.Inject; 034import javax.servlet.http.HttpServletRequest; 035import javax.ws.rs.core.Context; 036import javax.ws.rs.core.SecurityContext; 037import java.security.Principal; 038 039import static org.slf4j.LoggerFactory.getLogger; 040 041/** 042 * @author cabeer 043 * @since 10/5/14 044 */ 045abstract public class FedoraBaseResource extends AbstractResource { 046 047 private static final Logger LOGGER = getLogger(FedoraBaseResource.class); 048 049 @Context 050 protected SecurityContext securityContext; 051 052 @Inject 053 protected ResourceFactory resourceFactory; 054 055 @Inject 056 protected ResourceHelper resourceHelper; 057 058 @Context protected HttpServletRequest servletRequest; 059 060 @Inject 061 protected TransactionManager txManager; 062 063 @Inject 064 protected DbTransactionExecutor dbTransactionExecutor; 065 066 private TransactionProvider txProvider; 067 068 private Transaction transaction; 069 070 protected HttpIdentifierConverter identifierConverter; 071 072 protected HttpIdentifierConverter identifierConverter() { 073 if (identifierConverter == null) { 074 identifierConverter = new HttpIdentifierConverter( 075 uriInfo.getBaseUriBuilder().clone().path(FedoraLdp.class)); 076 } 077 078 return identifierConverter; 079 } 080 081 /** 082 * Gets a fedora resource by id. Uses the provided transaction if it is uncommitted, 083 * or uses a new transaction. 084 * 085 * @param transaction the fedora transaction 086 * @param fedoraId identifier of the resource 087 * @return the requested FedoraResource 088 */ 089 protected FedoraResource getFedoraResource(final Transaction transaction, final FedoraId fedoraId) 090 throws PathNotFoundException { 091 return resourceFactory.getResource(transaction, fedoraId); 092 } 093 094 /** 095 * @param transaction the transaction in which to check 096 * @param fedoraId identifier of the object to check 097 * @param includeDeleted Whether to check for deleted resources too. 098 * @return Returns true if an object with the provided id exists 099 */ 100 protected boolean doesResourceExist(final Transaction transaction, final FedoraId fedoraId, 101 final boolean includeDeleted) { 102 return resourceHelper.doesResourceExist(transaction, fedoraId, includeDeleted); 103 } 104 105 /** 106 * 107 * @param transaction the transaction in which to check 108 * @param fedoraId identifier of the object to check 109 * @return Returns true if object does not exist but whose ID starts other resources that do exist. 110 */ 111 protected boolean isGhostNode(final Transaction transaction, final FedoraId fedoraId) { 112 return resourceHelper.isGhostNode(transaction, fedoraId); 113 } 114 115 protected String getUserPrincipal() { 116 final Principal p = securityContext.getUserPrincipal(); 117 return p == null ? null : p.getName(); 118 } 119 120 protected Transaction transaction() { 121 if (transaction == null) { 122 txProvider = new TransactionProvider(txManager, servletRequest, 123 uriInfo.getBaseUri(), fedoraPropsConfig.getJmsBaseUrl()); 124 transaction = txProvider.provide(); 125 } 126 return transaction; 127 } 128 129 /** 130 * Executes the runnable within a DB transaction that will retry entire block on MySQL deadlock exceptions. 131 * If the runnable throws an exception, after completing any retires, then the Fedora transaction is marked 132 * as failed. 133 * 134 * @param action the code to execute 135 */ 136 protected void doInDbTxWithRetry(final Runnable action) { 137 try { 138 dbTransactionExecutor.doInTxWithRetry(action); 139 } catch (RuntimeException e) { 140 transaction().fail(); 141 throw e; 142 } 143 } 144 145 /** 146 * Executes the runnable within a DB transaction. The block is NOT retried on MySQL deadlock exceptions. 147 * If the runnable throws an exception, then the Fedora transaction is marked as failed. 148 * 149 * @param action the code to execute 150 */ 151 protected void doInDbTx(final Runnable action) { 152 try { 153 dbTransactionExecutor.doInTx(action); 154 } catch (RuntimeException e) { 155 transaction().fail(); 156 throw e; 157 } 158 } 159 160}