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