• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*******************************************************************************
2  * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  *    Marc R. Hoffmann - initial API and implementation
10  *
11  *******************************************************************************/
12 package org.jacoco.report.internal;
13 
14 import java.util.BitSet;
15 import java.util.HashMap;
16 import java.util.HashSet;
17 import java.util.Locale;
18 import java.util.Map;
19 import java.util.Set;
20 
21 /**
22  * Internal utility to create normalized file names from string ids. The file
23  * names generated by an instance of this class have the following properties:
24  *
25  * <ul>
26  * <li>The same input id is mapped to the same file name.</li>
27  * <li>Different ids are mapped to different file names.</li>
28  * <li>For safe characters the file name corresponds to the input id, other
29  * characters are replaced by <code>_</code> (underscore).</li>
30  * <li>File names are case aware, i.e. the same file name but with different
31  * upper/lower case characters is not possible.</li>
32  * <li>If unique filenames can't directly created from the ids, additional
33  * suffixes are appended.</li>
34  * </ul>
35  */
36 class NormalizedFileNames {
37 
38 	private static final BitSet LEGAL_CHARS = new BitSet();
39 
40 	static {
41 		final String legal = "abcdefghijklmnopqrstuvwxyz"
42 				+ "ABCDEFGHIJKLMNOPQRSTUVWYXZ0123456789$-._";
43 		for (final char c : legal.toCharArray()) {
44 			LEGAL_CHARS.set(c);
45 		}
46 	}
47 
48 	private final Map<String, String> mapping = new HashMap<String, String>();
49 
50 	private final Set<String> usedNames = new HashSet<String>();
51 
getFileName(final String id)52 	public String getFileName(final String id) {
53 		String name = mapping.get(id);
54 		if (name != null) {
55 			return name;
56 		}
57 		name = replaceIllegalChars(id);
58 		name = ensureUniqueness(name);
59 		mapping.put(id, name);
60 		return name;
61 	}
62 
replaceIllegalChars(final String s)63 	private String replaceIllegalChars(final String s) {
64 		final StringBuilder sb = new StringBuilder(s.length());
65 		boolean modified = false;
66 		for (int i = 0; i < s.length(); i++) {
67 			final char c = s.charAt(i);
68 			if (LEGAL_CHARS.get(c)) {
69 				sb.append(c);
70 			} else {
71 				sb.append('_');
72 				modified = true;
73 			}
74 		}
75 		return modified ? sb.toString() : s;
76 	}
77 
ensureUniqueness(final String s)78 	private String ensureUniqueness(final String s) {
79 		String unique = s;
80 		String lower = unique.toLowerCase(Locale.ENGLISH);
81 		int idx = 1;
82 		while (usedNames.contains(lower)) {
83 			unique = s + '~' + idx++;
84 			lower = unique.toLowerCase(Locale.ENGLISH);
85 		}
86 		usedNames.add(lower);
87 		return unique;
88 	}
89 
90 }
91