| /* |
| * 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.jackrabbit.vault.util; |
| |
| import org.apache.jackrabbit.util.Text; |
| /** |
| * Implements a repository to platform name formatter. |
| * |
| * <p>Illegal characters a |
| * generally escaped using the url escaping format, i.e. replacing the char |
| * by a '%' hex(char) sequence. Special treatment is used for the ':' char |
| * since it's used quite often as namespace prefix separator. The |
| * PREFIX ':' NAME sequence is replaced by '_' PREFIX '_' NAME. Item names |
| * that would generate the same pattern are escaped with an extra leading '_'. |
| * |
| * <p>Examples: |
| * |
| * <pre> |
| * +-------------------+----------------------+----+----+ |
| * | repository name | platform name | pp | sp | |
| * +-------------------+----------------------+----+----+ |
| * | test.jpg | test.jpg | -1 | -1 | |
| * | cq:content | _cq_content | 2 | -1 | |
| * | cq:test_image.jpg | _cq_test_image.jpg | 2 | 7 | |
| * | test_image.jpg | test_image.jpg | -1 | 4 | |
| * | _testimage.jpg | _testimage.jpg | -1 | 0 | |
| * | _test_image.jpg | __test_image.jpg | -1 | 0 | |
| * +-------------------+----------------------+----+----+ |
| * | cq:test:image.jpg | _cq_test%3aimage.jpg | 2 | -1 | |
| * | _cq_:test.jpg | __cq_%3atest.jpg | 4 | 0 | |
| * | _cq:test.jpg | __cq%3atest.jpg | 3 | 0 | |
| * | cq_:test.jpg | cq_%3atest.jpg | 3 | 2 | |
| * +-------------------+----------------------+----+----+ |
| * </pre> |
| * |
| * Note for the 2nd set of examples the cases are very rare and justify the |
| * ugly '%' escaping. |
| * |
| */ |
| public class PlatformNameFormat { |
| |
| /** |
| * Returns the platform name for a given repository name. Unsupported |
| * characters are URL escaped (i.e. %xx). |
| * |
| * Note: Forward slashes '/' are not escaped since they never occur in a |
| * jcr name. so this method can also be used to encode paths. |
| * |
| * @param repositoryName the repository name |
| * @return the (escaped) platform name. |
| */ |
| public static String getPlatformName(String repositoryName) { |
| StringBuilder buf = new StringBuilder("_"); |
| boolean escapeColon = false; |
| boolean useUnderscore = false; |
| int numUnderscore = 0; |
| for (int i=0; i<repositoryName.length(); i++) { |
| char c = repositoryName.charAt(i); |
| switch (c) { |
| case':': |
| if (!escapeColon && i>0) { |
| // pure prefix |
| escapeColon = true; |
| useUnderscore = true; |
| numUnderscore = 2; |
| buf.append('_'); |
| } else { |
| buf.append("%3a"); |
| escapeColon = true; |
| } |
| break; |
| case '_': |
| if (i==0) { |
| useUnderscore = true; |
| } |
| numUnderscore++; |
| escapeColon=true; |
| buf.append(c); |
| break; |
| case'\\': |
| case'<': |
| case'>': |
| case'|': |
| case'\"': |
| case '/': |
| case'?': |
| case'%': |
| addEscapedCharacter(buf, c); |
| break; |
| default: |
| buf.append(c); |
| } |
| } |
| if (useUnderscore && numUnderscore > 1) { |
| return buf.toString(); |
| } else { |
| return buf.substring(1); |
| } |
| } |
| |
| public static void addEscapedCharacter(StringBuilder buf, char c) { |
| buf.append('%'); |
| buf.append(Character.forDigit(c / 16, 16)); |
| buf.append(Character.forDigit(c % 16, 16)); |
| } |
| |
| /** |
| * Returns the platform path for the given repository one. |
| * @param repoPath the repository path |
| * @return the platform path |
| */ |
| public static String getPlatformPath(String repoPath) { |
| String[] elems = Text.explode(repoPath, '/', true); |
| for (int i=0; i<elems.length; i++) { |
| if (elems[i].length() > 0) { |
| elems[i] = getPlatformName(elems[i]); |
| } |
| } |
| return Text.implode(elems, "/"); |
| } |
| |
| /** |
| * Returns the repository name for a given platform name. |
| * |
| * @param platformName the platform name |
| * @return the (unescaped) repository name. |
| */ |
| public static String getRepositoryName(String platformName) { |
| StringBuilder buffer = new StringBuilder("_"); |
| boolean firstUnderscore = false; |
| for (int i=0; i<platformName.length(); i++) { |
| char c = platformName.charAt(i); |
| if (c == '%') { |
| if (platformName.length() > i+2) { |
| int a = Character.digit(platformName.charAt(++i), 16); |
| int b = Character.digit(platformName.charAt(++i), 16); |
| c = (char) (a * 16 + b); |
| } |
| } else if (c == '_') { |
| if (i==0) { |
| firstUnderscore = true; |
| if (platformName.length()>1) { |
| c = platformName.charAt(++i); |
| if (c == '_') { |
| buffer.append('_'); |
| firstUnderscore = false; |
| } else { |
| buffer.append(c); |
| } |
| } |
| continue; |
| } else if (firstUnderscore) { |
| c = ':'; |
| firstUnderscore = false; |
| } |
| } |
| buffer.append(c); |
| } |
| if (firstUnderscore) { |
| // pending underscore |
| return buffer.toString(); |
| } else { |
| return buffer.substring(1); |
| } |
| } |
| |
| /** |
| * Returns the repository path for the given platform one. |
| * @param path the platform path |
| * @return the repository path |
| */ |
| public static String getRepositoryPath(String path) { |
| String[] elems = Text.explode(path, '/', true); |
| for (int i=0; i<elems.length; i++) { |
| if (elems[i].length() > 0) { |
| elems[i] = getRepositoryName(elems[i]); |
| } |
| } |
| return Text.implode(elems, "/"); |
| } |
| |
| /** |
| * Returns the repository path for the given platform one. |
| * @param path the platform path |
| * @param respectDotDir if {@code true}, all ".dir" are removed. |
| * @return the repository path |
| */ |
| public static String getRepositoryPath(String path, boolean respectDotDir) { |
| String[] elems = Text.explode(path, '/', true); |
| for (int i=0; i<elems.length; i++) { |
| if (elems[i].length() > 0) { |
| if (respectDotDir && elems[i].endsWith(".dir")) { |
| elems[i] = getRepositoryName(elems[i].substring(0, elems[i].length() - 4)); |
| } else { |
| elems[i] = getRepositoryName(elems[i]); |
| } |
| } |
| } |
| return Text.implode(elems, "/"); |
| } |
| |
| |
| } |