blob: 4d50c2d686c6bbd6fba13ccc2a0a351dd0dd0546 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sling.jcr.resource.internal.helper.jcr;
import java.util.ArrayList;
import java.util.List;
import org.osgi.framework.Constants;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.osgi.service.metatype.annotations.Designate;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@code PathMapper} allows to
* - map path from the JCR resource tree to resource paths
* - hide JCR nodes; however this is not a security feature
* @deprecated
*/
@Deprecated
@Designate(ocd = PathMapper.Config.class)
@Component(service = PathMapper.class,
property = {
Constants.SERVICE_VENDOR + "=The Apache Software Foundation"
})
public class PathMapper {
@ObjectClassDefinition(name = "Apache Sling JCR Resource Provider Path Mapper",
description = "This service provides path mappings for JCR nodes.")
public @interface Config {
@AttributeDefinition(name = "Path Mapping",
description = "Defines an obtional path mapping for a path." +
"Each mapping entry is expressed as follow: <JCRPath>:<resourcePath>. As an example: /foo:/libs, " +
"this maps the JCR node /foo to the resource /libs. If the resource path is specified as '.', " +
" the JCR tree is not visible in the resource tree. This should not be considered a security feature " +
" as the nodes are still accessible through the JCR api. Mapping a JCR path to the root is not allowed. " +
"The mappings are evaluated as ordered in the configuration.")
String[] path_mapping();
}
/** Logger */
private final Logger log = LoggerFactory.getLogger(getClass());
/** The mappings. */
private final List<Mapping> mappings = new ArrayList<Mapping>();
private static final class Mapping {
public final String jcrPath;
public final String resourcePath;
public final String jcrPathPrefix;
public final String resourcePathPrefix;
public Mapping(final String path, final String mappedPath) {
this.jcrPath = path;
this.jcrPathPrefix = path.concat("/");
if ( mappedPath.equals(".") ) {
this.resourcePath = null;
this.resourcePathPrefix = null;
} else {
this.resourcePath = mappedPath;
this.resourcePathPrefix = mappedPath.concat("/");
}
}
}
@Activate
private void activate(final Config configObj) {
mappings.clear();
final String[] config = configObj.path_mapping();
if ( config != null ) {
log.warn("The Apache Sling JCR Path Mapper is deprecated.");
for (final String mapping : config) {
boolean valid = false;
final String[] parts = mapping.split(":");
if (parts.length == 2) {
parts[0] = parts[0].trim();
parts[1] = parts[1].trim();
if ( parts[0].startsWith("/") && (parts[1].startsWith("/") || parts[1].equals(".")) ) {
if ( parts[0].endsWith("/") ) {
parts[0] = parts[0].substring(0, parts[1].length() - 1);
}
if ( parts[1].endsWith("/") ) {
parts[1] = parts[1].substring(0, parts[1].length() - 1);
}
if ( parts[0].length() > 1 && (parts[1].length() > 1 || parts[1].equals(".")) ) {
mappings.add(new Mapping(parts[0], parts[1]));
valid = true;
}
}
}
if ( !valid ) {
log.warn("Invalid mapping configuration (skipping): {}", mapping);
}
}
}
}
/**
* Map a resource path to a JCR path
* @param resourcePath The resource path
* @return The JCR path or {@code null}
*/
public String mapResourcePathToJCRPath(final String resourcePath) {
String jcrPath = resourcePath;
if (resourcePath != null && !mappings.isEmpty()) {
for (final Mapping mapping : mappings) {
if ( mapping.resourcePath == null ) {
if ( resourcePath.equals(mapping.jcrPath) || resourcePath.startsWith(mapping.jcrPathPrefix) ) {
jcrPath = null;
break;
}
} else {
if (resourcePath.equals(mapping.resourcePath)) {
jcrPath = mapping.jcrPath;
break;
} else if (resourcePath.startsWith(mapping.resourcePathPrefix)) {
jcrPath = mapping.jcrPathPrefix.concat(resourcePath.substring(mapping.resourcePathPrefix.length()));
break;
}
}
}
}
return jcrPath;
}
/**
* Map a JCR path to a resource path
* @param jcrPath The JCR path
* @return The resource path or {@code null}
*/
public String mapJCRPathToResourcePath(final String jcrPath) {
String resourcePath = jcrPath;
if (jcrPath != null && !mappings.isEmpty()) {
for (final Mapping mapping : mappings) {
if (mapping.resourcePath != null && (jcrPath.equals(mapping.resourcePath) || jcrPath.startsWith(mapping.resourcePathPrefix)) ) {
resourcePath = null;
break;
} else if (jcrPath.equals(mapping.jcrPath)) {
resourcePath = mapping.resourcePath;
break;
} else if (jcrPath.startsWith(mapping.jcrPathPrefix)) {
if ( mapping.resourcePath == null ) {
resourcePath = null;
} else {
resourcePath = mapping.resourcePathPrefix.concat(jcrPath.substring(mapping.jcrPathPrefix.length()));
}
break;
}
}
}
return resourcePath;
}
}