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.sword.provider; 017 018import org.apache.abdera.Abdera; 019import org.apache.abdera.model.Service; 020import org.fcrepo.http.commons.session.SessionFactory; 021import org.fcrepo.kernel.api.RdfLexicon; 022import org.fcrepo.kernel.api.models.Container; 023import org.fcrepo.kernel.api.services.ContainerService; 024import org.fcrepo.kernel.api.services.NodeService; 025import org.fcrepo.kernel.api.utils.NamespaceTools; 026import org.fcrepo.sword.protocol.SWORDServiceDocumentBuilder; 027import org.slf4j.Logger; 028import org.slf4j.LoggerFactory; 029import org.springframework.beans.factory.annotation.Autowired; 030import org.springframework.stereotype.Component; 031 032import javax.annotation.PostConstruct; 033import javax.jcr.NamespaceRegistry; 034import javax.jcr.RepositoryException; 035import javax.jcr.Session; 036import java.util.Map; 037 038import static com.hp.hpl.jena.rdf.model.ResourceFactory.createProperty; 039import static java.util.Collections.emptyMap; 040import static org.fcrepo.kernel.modeshape.rdf.converters.PropertyConverter.getPropertyNameFromPredicate; 041import static org.fcrepo.sword.protocol.SWORDProtocol.SWORD_NAMESPACE; 042 043/** 044 * Implements all protocol related methods to be executed via {@link org.fcrepo.sword.http.SWORDWebResource} 045 * 046 * @author claussni 047 */ 048@Component 049public class SWORDServiceProvider { 050 051 public static final String SWORD_ROOT_PATH = "/sword"; 052 public static final String SWORD_COLLECTIONS_PATH = SWORD_ROOT_PATH + "/collections"; 053 public static final String SWORD_WORKSPACES_PATH = SWORD_ROOT_PATH + "/workspaces"; 054 055 private static final String RDF_PREFIX = "sword"; 056 private static final String SWORD_ROOT_LABEL = "SWORD root"; 057 private static final Integer SWORD_MAX_UPLOAD_SIZE_KB = Integer.MAX_VALUE; 058 059 private static final Logger log = LoggerFactory.getLogger(SWORDServiceProvider.class); 060 private final Abdera abdera = new Abdera(); 061 062 @Autowired 063 private SessionFactory sessionFactory; 064 065 @Autowired 066 private NodeService nodeService; 067 068 @Autowired 069 private ContainerService containerService; 070 071 private Container workspaces; 072 073 /** 074 * Build and return a SWORD service document 075 * 076 * @return SWORD service document 077 */ 078 public Service serviceDocument() { 079 final SWORDServiceDocumentBuilder sb = new SWORDServiceDocumentBuilder(abdera, log) 080 .maxUploadSize(SWORD_MAX_UPLOAD_SIZE_KB) 081 .workspacesContainer(workspaces); 082 return sb.serviceDocument(); 083 } 084 085 @PostConstruct 086 private void init() { 087 final Session session = sessionFactory.getInternalSession(); 088 final NamespaceRegistry namespaceRegistry = NamespaceTools.getNamespaceRegistry(session); 089 090 ensureSwordNamespaceRegistration(namespaceRegistry); 091 092 final Container root = getContainer(session, SWORD_ROOT_PATH, SWORD_ROOT_LABEL); 093 ensureProperty(namespaceRegistry, root, 094 RdfLexicon.FEDORA_CONFIG_NAMESPACE + "maxUploadSizeInKb", SWORD_MAX_UPLOAD_SIZE_KB); 095 096 workspaces = getContainer(session, SWORD_WORKSPACES_PATH, "SWORD workspaces"); 097 getContainer(session, SWORD_COLLECTIONS_PATH, "SWORD collections"); 098 } 099 100 private void ensureSwordNamespaceRegistration(final NamespaceRegistry namespaceRegistry) { 101 try { 102 namespaceRegistry.registerNamespace(RDF_PREFIX, SWORD_NAMESPACE); 103 } catch (RepositoryException e) { 104 throw new RuntimeException( 105 String.format("Failed to register namespace %s:%s", RDF_PREFIX, SWORD_NAMESPACE), e); 106 } 107 } 108 109 private Container getContainer(final Session session, final String path, final String label) { 110 try { 111 if (!nodeService.exists(session, path)) { 112 log.info("Initializing container `{}` at `{}`", label, path); 113 final Container c = containerService.findOrCreate(session, path); 114 session.save(); 115 return c; 116 } 117 } catch (RepositoryException e) { 118 throw new RuntimeException("Failed to initialize container " + label, e); 119 } 120 return null; 121 } 122 123 private void ensureProperty( 124 final NamespaceRegistry namespaceRegistry, 125 final Container container, 126 final String name, 127 final Object defaultValue) { 128 try { 129 final Map<String, String> namespaceMapping = emptyMap(); 130 final String propertyName = getPropertyNameFromPredicate( 131 (org.modeshape.jcr.api.NamespaceRegistry) namespaceRegistry, 132 createProperty(name), 133 namespaceMapping); 134 if (!container.getNode().hasProperty(propertyName)) { 135 container.getNode().setProperty(propertyName, String.valueOf(defaultValue)); 136 } 137 } catch (RepositoryException e) { 138 throw new RuntimeException("Failed to initialize property " + name, e); 139 } 140 } 141 142}