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 if (!prefix.equals("fedora")) { 089 if (prefix.length() == 0) { 090 throw new FedoraInvalidNamespaceException("Empty namespace in " + segment); 091 } 092 try { 093 namespaceRegistry.getURI(prefix); 094 } catch (final NamespaceException e) { 095 throw new FedoraInvalidNamespaceException("Prefix " + prefix + " has not been registered", e); 096 } catch (final RepositoryException e) { 097 throw new RepositoryRuntimeException(e); 098 } 099 } 100 } 101 } 102 } 103 104 /** 105 * Retrieve the namespaces as a Map 106 * 107 * @param session the JCR session to use 108 * @return a mapping of the prefix to URI 109 */ 110 public static Map<String, String> getNamespaces(final Session session) { 111 final NamespaceRegistry registry = getNamespaceRegistry(session); 112 final Map<String, String> namespaces = new HashMap<>(); 113 114 try { 115 stream(registry.getPrefixes()).filter(internalPrefix.negate()).forEach(x -> { 116 try { 117 namespaces.put(x, registry.getURI(x)); 118 } catch (final RepositoryException e) { 119 throw new RepositoryRuntimeException(e); 120 } 121 }); 122 } catch (final RepositoryException e) { 123 throw new RepositoryRuntimeException(e); 124 } 125 return namespaces; 126 } 127 128 private static Predicate<String> internalPrefix = INTERNAL_PREFIXES::contains; 129}