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.kernel.modeshape.utils; 019 020import static com.google.common.collect.ImmutableSet.of; 021import static java.util.Objects.requireNonNull; 022import static java.util.Arrays.stream; 023import static javax.jcr.NamespaceRegistry.PREFIX_EMPTY; 024import static javax.jcr.NamespaceRegistry.PREFIX_JCR; 025import static javax.jcr.NamespaceRegistry.PREFIX_MIX; 026import static javax.jcr.NamespaceRegistry.PREFIX_NT; 027 028import java.util.HashMap; 029import java.util.Map; 030import java.util.Set; 031import java.util.function.Predicate; 032 033import javax.jcr.NamespaceException; 034import javax.jcr.NamespaceRegistry; 035import javax.jcr.RepositoryException; 036import javax.jcr.Session; 037 038import org.fcrepo.kernel.api.exception.FedoraInvalidNamespaceException; 039import org.fcrepo.kernel.api.exception.RepositoryRuntimeException; 040 041/** 042 * Tools for working with the JCR Namespace Registry 043 * @author Benjamin Armintor 044 * @author acoburn 045 * @author ajs6f 046 * @since May 13, 2013 047 */ 048public final class NamespaceTools { 049 050 private NamespaceTools() { 051 } 052 053 // Internal namespaces defined in the modeshape CND file 054 private static final Set<String> INTERNAL_PREFIXES = of(PREFIX_EMPTY, PREFIX_JCR, PREFIX_MIX, PREFIX_NT, 055 "mode", "sv", "image"); 056 057 /** 058 * Return the {@link NamespaceRegistry} associated with the arg session. 059 * 060 * @param session containing the NamespaceRegistry 061 * @return NamespaceRegistry 062 */ 063 public static NamespaceRegistry getNamespaceRegistry(final Session session) { 064 try { 065 return requireNonNull(session.getWorkspace().getNamespaceRegistry(), 066 "Couldn't find namespace registry in repository!"); 067 } catch (final RepositoryException e) { 068 throw new RepositoryRuntimeException(e); 069 } 070 } 071 072 /** 073 * Validate resource path for unregistered namespace prefixes 074 * 075 * @param session the JCR session to use 076 * @param path the absolute path to the object 077 * @throws org.fcrepo.kernel.api.exception.FedoraInvalidNamespaceException on unregistered namespaces 078 * @throws org.fcrepo.kernel.api.exception.RepositoryRuntimeException if repository runtime exception occurred 079 */ 080 public static void validatePath(final Session session, final String path) { 081 082 final NamespaceRegistry namespaceRegistry = getNamespaceRegistry(session); 083 final String[] pathSegments = path.replaceAll("^/+", "").replaceAll("/+$", "").split("/"); 084 for (final String segment : pathSegments) { 085 final int colonPosition = segment.indexOf(':'); 086 if (segment.length() > 0 && colonPosition > -1) { 087 final String prefix = segment.substring(0, colonPosition); 088 089 // Skip the fcr namespace registration check to avoid the FedoraInvalidNamespaceException, 090 // which will happen when it fails to retrieve the memento from Modeshape. 091 if (!prefix.equals("fedora") && !prefix.equals("fcr")) { 092 if (prefix.length() == 0) { 093 throw new FedoraInvalidNamespaceException("Empty namespace in " + segment); 094 } 095 try { 096 namespaceRegistry.getURI(prefix); 097 } catch (final NamespaceException e) { 098 throw new FedoraInvalidNamespaceException("Prefix " + prefix + " has not been registered", e); 099 } catch (final RepositoryException e) { 100 throw new RepositoryRuntimeException(e); 101 } 102 } 103 } 104 } 105 } 106 107 /** 108 * Retrieve the namespaces as a Map 109 * 110 * @param session the JCR session to use 111 * @return a mapping of the prefix to URI 112 */ 113 public static Map<String, String> getNamespaces(final Session session) { 114 final NamespaceRegistry registry = getNamespaceRegistry(session); 115 final Map<String, String> namespaces = new HashMap<>(); 116 117 try { 118 stream(registry.getPrefixes()).filter(internalPrefix.negate()).forEach(x -> { 119 try { 120 namespaces.put(x, registry.getURI(x)); 121 } catch (final RepositoryException e) { 122 throw new RepositoryRuntimeException(e); 123 } 124 }); 125 } catch (final RepositoryException e) { 126 throw new RepositoryRuntimeException(e); 127 } 128 return namespaces; 129 } 130 131 private static final Predicate<String> internalPrefix = INTERNAL_PREFIXES::contains; 132}