001/**
002 * Copyright 2014 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 abstract class NamespaceTools {
038
039    /**
040     * We need the Modeshape NamespaceRegistry, because it allows us to register
041     * anonymous namespaces.
042     */
043    public static Function<Node, NamespaceRegistry> getNamespaceRegistry = new Function<Node, NamespaceRegistry>() {
044        @Override
045        public NamespaceRegistry apply(final Node n) {
046            try {
047                checkNotNull(n, "null has no Namespace Registry associated with it!");
048                return (org.modeshape.jcr.api.NamespaceRegistry)n.getSession().getWorkspace().getNamespaceRegistry();
049            } catch (final RepositoryException e) {
050                throw new IllegalStateException(e);
051            }
052        }
053
054    };
055
056    /**
057     * Return the javax.jcr.NamespaceRegistry associated with the arg session.
058     *
059     * @param session containing the NamespaceRegistry
060     * @return NamespaceRegistry
061     */
062    public static javax.jcr.NamespaceRegistry getNamespaceRegistry(final Session session) {
063        final javax.jcr.NamespaceRegistry namespaceRegistry;
064        try {
065            namespaceRegistry =
066                    session.getWorkspace().getNamespaceRegistry();
067            checkNotNull(namespaceRegistry,
068                    "Couldn't find namespace registry in repository!");
069            return namespaceRegistry;
070        } catch (final RepositoryException e) {
071            throw new RepositoryRuntimeException(e);
072        }
073    }
074
075    /**
076     * Validate resource path for unregistered namespace prefixes
077     *
078     * @param session the JCR session to use
079     * @param path the absolute path to the object
080     * @throws org.fcrepo.kernel.exception.FedoraInvalidNamespaceException on unregistered namespaces
081     * @throws org.fcrepo.kernel.exception.RepositoryRuntimeException
082     */
083    public static void validatePath(final Session session, final String path) {
084
085        final javax.jcr.NamespaceRegistry namespaceRegistry = getNamespaceRegistry(session);
086
087        final String relPath = path.replaceAll("^/+", "").replaceAll("/+$", "");
088        final String[] pathSegments = relPath.split("/");
089        for (final String segment : pathSegments) {
090            if (segment.length() > 0 && segment.contains(":") &&
091                    !segment.substring(0, segment.indexOf(":")).equals("fedora")) {
092                final String prefix = segment.substring(0, segment.indexOf(":"));
093                if (prefix.length() == 0) {
094                    throw new FedoraInvalidNamespaceException(
095                            String.format("Unable to identify namespace for (%s)", segment));
096                }
097                try {
098                    namespaceRegistry.getURI(prefix);
099                } catch (final NamespaceException e) {
100                    throw new FedoraInvalidNamespaceException(
101                            String.format("The namespace prefix (%s) has not been registered", prefix), e);
102                } catch (final RepositoryException e) {
103                    throw new RepositoryRuntimeException(e);
104                }
105            }
106        }
107    }
108}