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