001/* 002 * (C) Copyright 2019 Nuxeo (http://nuxeo.com/) and others. 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 * 016 * Contributors: 017 * Florent Guillaume 018 */ 019package org.nuxeo.ecm.core.blob; 020 021import java.nio.file.Path; 022import java.util.regex.Pattern; 023 024import org.nuxeo.ecm.core.api.NuxeoException; 025 026/** 027 * Stores a file in a nested subdirectory based on the initial characters of the key, in groups of 2. The key is 028 * restricted the a safe subset of characters to use as filenames. 029 * <p> 030 * For instance for a depth of 3 and a key of 1234567890abcd the path will be 12/34/56/1234567890abcd. 031 * 032 * @since 11.1 033 */ 034public class PathStrategySubDirs extends PathStrategy { 035 036 /** Allowed key pattern, used as file path. */ 037 protected static final Pattern PATTERN = Pattern.compile("[a-zA-Z0-9]+"); 038 039 protected final int depth; 040 041 public PathStrategySubDirs(Path dir, int depth) { 042 super(dir); 043 this.depth = depth; 044 } 045 046 @Override 047 public Path getPathForKey(String key) { 048 if (!PATTERN.matcher(key).matches()) { 049 throw new NuxeoException("Invalid key: " + key); 050 } 051 if (key.length() < 2 * depth) { 052 // store short keys under a special 000 directory 053 return dir.resolve("000").resolve(key); 054 } 055 Path current = dir; 056 for (int i = 0; i < depth; i++) { 057 current = current.resolve(key.substring(2 * i, 2 * i + 2)); 058 } 059 return current.resolve(key); 060 } 061 062}