001
002/*
003 * Licensed to DuraSpace under one or more contributor license agreements.
004 * See the NOTICE file distributed with this work for additional information
005 * regarding copyright ownership.
006 *
007 * DuraSpace licenses this file to you under the Apache License,
008 * Version 2.0 (the "License"); you may not use this file except in
009 * compliance with the License.  You may obtain a copy of the License at
010 *
011 *     http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 */
019package org.fcrepo.kernel.impl.services;
020
021import static org.fcrepo.kernel.api.RdfCollectors.toModel;
022
023import java.util.Optional;
024
025import javax.inject.Inject;
026
027import org.fcrepo.kernel.api.Transaction;
028import org.fcrepo.kernel.api.auth.ACLHandle;
029import org.fcrepo.kernel.api.exception.AccessDeniedException;
030import org.fcrepo.kernel.api.exception.ItemNotFoundException;
031import org.fcrepo.kernel.api.exception.MalformedRdfException;
032import org.fcrepo.kernel.api.exception.RepositoryRuntimeException;
033import org.fcrepo.kernel.api.identifiers.FedoraId;
034import org.fcrepo.kernel.api.services.ReplacePropertiesService;
035import org.fcrepo.kernel.api.services.UpdatePropertiesService;
036import org.fcrepo.persistence.api.PersistentStorageSessionManager;
037import org.fcrepo.persistence.api.exceptions.PersistentItemNotFoundException;
038import org.fcrepo.persistence.api.exceptions.PersistentStorageException;
039import org.springframework.stereotype.Component;
040
041import org.apache.jena.rdf.model.Model;
042import org.apache.jena.update.UpdateAction;
043import org.apache.jena.update.UpdateFactory;
044import org.apache.jena.update.UpdateRequest;
045
046import com.github.benmanes.caffeine.cache.Cache;
047
048/**
049 * This class implements the update properties operation.
050 *
051 * @author dbernstein
052 */
053@Component
054public class UpdatePropertiesServiceImpl extends AbstractService implements UpdatePropertiesService {
055
056    @Inject
057    private ReplacePropertiesService replacePropertiesService;
058
059    @Inject
060    private PersistentStorageSessionManager persistentStorageSessionManager;
061
062    @Inject
063    private Cache<String, Optional<ACLHandle>> authHandleCache;
064
065    @Override
066    public void updateProperties(final Transaction tx, final String userPrincipal,
067                                 final FedoraId fedoraId, final String sparqlUpdateStatement)
068            throws MalformedRdfException, AccessDeniedException {
069        try {
070            final var psession = persistentStorageSessionManager.getSession(tx);
071            final var triples = psession.getTriples(fedoraId, null);
072            final Model model = triples.collect(toModel());
073            final UpdateRequest request = UpdateFactory.create(sparqlUpdateStatement, fedoraId.getFullId());
074            UpdateAction.execute(request, model);
075            replacePropertiesService.perform(tx, userPrincipal, fedoraId, model);
076            if (fedoraId.isAcl()) {
077                // Flush ACL cache on any ACL creation/update/deletion.
078                authHandleCache.invalidateAll();
079            }
080        } catch (final PersistentItemNotFoundException ex) {
081            throw new ItemNotFoundException(ex.getMessage(), ex);
082        } catch (final PersistentStorageException ex) {
083            throw new RepositoryRuntimeException(ex.getMessage(), ex);
084        }
085
086    }
087}