• 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.io.IOException;
15 import java.io.OutputStream;
16 import java.util.HashMap;
17 import java.util.Map;
18 
19 import org.jacoco.report.IMultiReportOutput;
20 
21 /**
22  * Logical representation of a folder in the output structure. This utility
23  * ensures valid and unique file names and helps to create relative links.
24  */
25 public class ReportOutputFolder {
26 
27 	private final IMultiReportOutput output;
28 
29 	private final ReportOutputFolder parent;
30 
31 	private final String path;
32 
33 	/** Cached sub-folder instances to guarantee stable normalization */
34 	private final Map<String, ReportOutputFolder> subFolders = new HashMap<String, ReportOutputFolder>();
35 
36 	private final NormalizedFileNames fileNames;
37 
38 	/**
39 	 * Creates a new root folder for the given output.
40 	 *
41 	 * @param output
42 	 *            output for generated files
43 	 */
ReportOutputFolder(final IMultiReportOutput output)44 	public ReportOutputFolder(final IMultiReportOutput output) {
45 		this(output, null, "");
46 	}
47 
48 	/**
49 	 * Creates a new root folder for the given output.
50 	 *
51 	 * @param output
52 	 *            output for generated files
53 	 */
ReportOutputFolder(final IMultiReportOutput output, final ReportOutputFolder parent, final String path)54 	private ReportOutputFolder(final IMultiReportOutput output,
55 			final ReportOutputFolder parent, final String path) {
56 		this.output = output;
57 		this.parent = parent;
58 		this.path = path;
59 		fileNames = new NormalizedFileNames();
60 	}
61 
62 	/**
63 	 * Creates a sub-folder with the given name.
64 	 *
65 	 * @param name
66 	 *            name of the sub-folder
67 	 * @return handle for output into the sub-folder
68 	 */
subFolder(final String name)69 	public ReportOutputFolder subFolder(final String name) {
70 		final String normalizedName = normalize(name);
71 		ReportOutputFolder folder = subFolders.get(normalizedName);
72 		if (folder != null) {
73 			return folder;
74 		}
75 		folder = new ReportOutputFolder(output, this, path + normalizedName
76 				+ "/");
77 		subFolders.put(normalizedName, folder);
78 		return folder;
79 	}
80 
81 	/**
82 	 * Creates a new file in this folder with the given local name.
83 	 *
84 	 * @param name
85 	 *            name of the sub-folder
86 	 * @return handle for output into the sub-folder
87 	 * @throws IOException
88 	 *             if the file creation fails
89 	 */
createFile(final String name)90 	public OutputStream createFile(final String name) throws IOException {
91 		return output.createFile(path + normalize(name));
92 	}
93 
94 	/**
95 	 * Returns a link relative to a given base to a resource within this folder.
96 	 *
97 	 * @param base
98 	 *            base to create the relative link from
99 	 * @param name
100 	 *            name of the file or folder in this folder
101 	 * @return relative link
102 	 * @throws IllegalArgumentException
103 	 *             if this folder and the base do not have the same root
104 	 */
getLink(final ReportOutputFolder base, final String name)105 	public String getLink(final ReportOutputFolder base, final String name) {
106 		if (base.isAncestorOf(this)) {
107 			return this.path.substring(base.path.length()) + normalize(name);
108 		}
109 		if (base.parent == null) {
110 			throw new IllegalArgumentException("Folders with different roots.");
111 		}
112 		return "../" + this.getLink(base.parent, name);
113 	}
114 
isAncestorOf(final ReportOutputFolder folder)115 	private boolean isAncestorOf(final ReportOutputFolder folder) {
116 		if (this == folder) {
117 			return true;
118 		}
119 		return folder.parent == null ? false : isAncestorOf(folder.parent);
120 	}
121 
normalize(final String name)122 	private String normalize(final String name) {
123 		return fileNames.getFileName(name);
124 	}
125 
126 }
127