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.utils;
017
018import static com.google.common.base.Preconditions.checkNotNull;
019
020import javax.jcr.NamespaceException;
021import javax.jcr.Node;
022import javax.jcr.RepositoryException;
023import javax.jcr.Session;
024
025import org.fcrepo.kernel.exception.FedoraInvalidNamespaceException;
026import org.fcrepo.kernel.exception.RepositoryRuntimeException;
027import org.modeshape.jcr.api.NamespaceRegistry;
028
029import com.google.common.base.Function;
030
031/**
032 * Tools for working with the JCR Namespace Registry
033 * (wrapping some non-standard Modeshape machinery)
034 * @author Benjamin Armintor
035 * @since May 13, 2013
036 */
037public final class NamespaceTools {
038
039    private NamespaceTools() {
040    }
041
042    /**
043     * We need the Modeshape NamespaceRegistry, because it allows us to register
044     * anonymous namespaces.
045     */
046    public static Function<Node, NamespaceRegistry> getNamespaceRegistry = new Function<Node, NamespaceRegistry>() {
047        @Override
048        public NamespaceRegistry apply(final Node n) {
049            try {
050                checkNotNull(n, "null has no Namespace Registry associated with it!");
051                return (org.modeshape.jcr.api.NamespaceRegistry)n.getSession().getWorkspace().getNamespaceRegistry();
052            } catch (final RepositoryException e) {
053                throw new IllegalStateException(e);
054            }
055        }
056
057    };
058
059    /**
060     * Return the javax.jcr.NamespaceRegistry associated with the arg session.
061     *
062     * @param session containing the NamespaceRegistry
063     * @return NamespaceRegistry
064     */
065    public static javax.jcr.NamespaceRegistry getNamespaceRegistry(final Session session) {
066        final javax.jcr.NamespaceRegistry namespaceRegistry;
067        try {
068            namespaceRegistry =
069                    session.getWorkspace().getNamespaceRegistry();
070            checkNotNull(namespaceRegistry,
071                    "Couldn't find namespace registry in repository!");
072            return namespaceRegistry;
073        } catch (final RepositoryException e) {
074            throw new RepositoryRuntimeException(e);
075        }
076    }
077
078    /**
079     * Validate resource path for unregistered namespace prefixes
080     *
081     * @param session the JCR session to use
082     * @param path the absolute path to the object
083     * @throws org.fcrepo.kernel.exception.FedoraInvalidNamespaceException on unregistered namespaces
084     * @throws org.fcrepo.kernel.exception.RepositoryRuntimeException if repository runtime exception occurred
085     */
086    public static void validatePath(final Session session, final String path) {
087
088        final javax.jcr.NamespaceRegistry namespaceRegistry = getNamespaceRegistry(session);
089
090        final String relPath = path.replaceAll("^/+", "").replaceAll("/+$", "");
091        final String[] pathSegments = relPath.split("/");
092        for (final String segment : pathSegments) {
093            if (segment.length() > 0 && segment.contains(":") &&
094                    !segment.substring(0, segment.indexOf(':')).equals("fedora")) {
095                final String prefix = segment.substring(0, segment.indexOf(':'));
096                if (prefix.length() == 0) {
097                    throw new FedoraInvalidNamespaceException(
098                            String.format("Unable to identify namespace for (%s)", segment));
099                }
100                try {
101                    namespaceRegistry.getURI(prefix);
102                } catch (final NamespaceException e) {
103                    throw new FedoraInvalidNamespaceException(
104                            String.format("The namespace prefix (%s) has not been registered", prefix), e);
105                } catch (final RepositoryException e) {
106                    throw new RepositoryRuntimeException(e);
107                }
108            }
109        }
110    }
111
112}