View Javadoc
1   /*
2    * Copyright 2014 Jin Kwon <jinahya_at_gmail.com>.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  
18  package com.github.jinahya.simple.file.back;
19  
20  
21  import java.nio.ByteBuffer;
22  import java.security.MessageDigest;
23  import java.security.NoSuchAlgorithmException;
24  import java.util.Formatter;
25  import java.util.stream.Collectors;
26  import java.util.stream.IntStream;
27  import java.util.stream.Stream;
28  
29  
30  /**
31   * A utility class for file back implementations.
32   * @author Jin Kwon <jinahya_at_gmail.com>
33   */
34  public final class FileBackUtilities {
35  
36  
37      /**
38       * Converts given file key to a path name.
39       *
40       * @param fileKey the file key to convert
41       * @param digestAlgorithm a message digest algorithm to hash.
42       * @param tokenLength the number of characters to split.
43       * @param tokenDelimiter the delimiter string used when joining split
44       * tokens.
45       *
46       * @return a path name.
47       *
48       * @throws NoSuchAlgorithmException if {@code digestAlgorithm} is unknown.
49       */
50      public static String fileKeyToPathName(final ByteBuffer fileKey,
51                                             final String digestAlgorithm,
52                                             final int tokenLength,
53                                             final String tokenDelimiter)
54          throws NoSuchAlgorithmException {
55  
56          if (fileKey == null) {
57              throw new NullPointerException("null fileKey");
58          }
59  
60          if (fileKey.remaining() == 0) {
61              throw new IllegalArgumentException("keyBuffer.remaining == 0");
62          }
63  
64          if (digestAlgorithm == null) {
65              throw new NullPointerException("null digestAlgorithm");
66          }
67  
68          if (tokenLength <= 0) {
69              throw new IllegalArgumentException(
70                  "tokenLength(" + tokenLength + ") <= 0");
71          }
72  
73          if (tokenDelimiter == null) {
74              throw new NullPointerException("null tokenDelimiter");
75          }
76  
77          final MessageDigest digest = MessageDigest.getInstance(digestAlgorithm);
78          digest.update(fileKey.asReadOnlyBuffer());
79          final byte[] digested = digest.digest();
80  
81          final String hexed = IntStream.range(0, digested.length)
82              .collect(() -> new StringBuilder(digested.length * 2),
83                       (b, i) -> new Formatter(b).format(
84                           "%02x", digested[i] & 0xFF),
85                       StringBuilder::append)
86              .toString();
87  
88          final String joined = Stream
89              .of(hexed.split("(?<=\\G.{" + tokenLength + "})"))
90              .collect(Collectors.joining(tokenDelimiter));
91  
92          return joined;
93      }
94  
95  
96      private FileBackUtilities() {
97  
98          super();
99      }
100 
101 
102 }
103