1 package org.daisy.pipeline.file;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.io.Reader;
6 import java.io.StringReader;
7 import java.net.URI;
8 import java.net.URISyntaxException;
9 import java.nio.file.FileSystems;
10 import java.nio.file.Path;
11 import java.nio.file.ProviderNotFoundException;
12 import java.util.Optional;
13
14 import org.daisy.common.file.URLs;
15
16
17
18
19 public final class FileUtils {
20
21 private FileUtils() {}
22
23
24
25
26
27
28
29 public static Reader cResultDocument(String text) {
30 StringBuilder sb = new StringBuilder();
31 sb.append("<c:result xmlns:c=\"http://www.w3.org/ns/xproc-step\">")
32 .append(text)
33 .append("</c:result>");
34 return new StringReader(sb.toString());
35 }
36
37
38
39
40
41
42
43
44 public static Path asPath(URI uri) throws IllegalArgumentException, URISyntaxException {
45 if (!uri.isAbsolute())
46 throw new IllegalArgumentException("expected absolute URI");
47 String protocol = uri.getScheme();
48 if (!"file".equals(protocol))
49 throw new IllegalArgumentException("expected file URI");
50 String query = uri.getQuery();
51 if (query != null && !query.isEmpty())
52 throw new IllegalArgumentException("expected URI without query");
53 String fragment = uri.getFragment();
54 if (fragment != null && !fragment.isEmpty())
55 throw new IllegalArgumentException("expected URI without fragment");
56 String path = uri.getPath();
57 String zipPath = null;
58 if (path.contains("!/")) {
59
60 zipPath = path.substring(path.indexOf("!/")+1);
61 path = path.substring(0, path.indexOf("!/"));
62 }
63 File file = new File(new URI(protocol, null, path, null, null));
64 if (file.exists() && zipPath != null)
65 try {
66 return FileSystems.newFileSystem(file.toPath(), null).getPath(zipPath);
67 } catch (ProviderNotFoundException e) {
68 throw new RuntimeException(e);
69 } catch (IOException e) {
70 throw new RuntimeException(e);
71 }
72 else
73 return file.toPath();
74 }
75
76
77
78
79
80
81
82
83 public static URI relativizeURI(URI uri, URI base) {
84 try {
85 if (base.isOpaque() || uri.isOpaque()
86 || !Optional.ofNullable(base.getScheme()).orElse("").equalsIgnoreCase(Optional.ofNullable(uri.getScheme()).orElse(""))
87 || !Optional.ofNullable(base.getAuthority()).equals(Optional.ofNullable(uri.getAuthority())))
88 return uri;
89 else {
90 String up = uri.normalize().getPath();
91 String bp = base.normalize().getPath();
92 String relativizedPath;
93 if (up.startsWith("/")) {
94 String[] upSegments = up.split("/", -1);
95 String[] bpSegments = bp.split("/", -1);
96 int i = bpSegments.length - 1;
97 int j = 0;
98 while (i > 0) {
99 if (bpSegments[j].equals(upSegments[j])) {
100 i--;
101 j++; }
102 else
103 break; }
104 relativizedPath = "";
105 while (i > 0) {
106 relativizedPath += "../";
107 i--; }
108 while (j < upSegments.length) {
109 relativizedPath += upSegments[j] + "/";
110 j++; }
111 relativizedPath = relativizedPath.substring(0, relativizedPath.length() - 1); }
112 else
113 relativizedPath = up;
114 if (relativizedPath.isEmpty())
115 relativizedPath = "./";
116 return new URI(null, null, relativizedPath, uri.getQuery(), uri.getFragment()); }
117 } catch (URISyntaxException e) {
118 throw new RuntimeException(e);
119 }
120 }
121
122 public static URI normalizeURI(URI uri) {
123 return normalizeURI(uri, false);
124 }
125
126 public static URI normalizeURI(URI uri, boolean dropFragment) {
127 try {
128 if (uri.isOpaque())
129 return uri;
130 if ("jar".equals(uri.getScheme()))
131 return URLs.asURI("jar:" + normalizeURI(URLs.asURI(uri.toASCIIString().substring(4))).toASCIIString());
132 uri = uri.normalize();
133 String scheme = uri.getScheme();
134 if (scheme != null) scheme = scheme.toLowerCase();
135 String authority = uri.getAuthority();
136 if (authority != null) authority = authority.toLowerCase();
137 if (authority != null && "http".equals(scheme) && authority.endsWith(":80"))
138 authority = authority.substring(0, authority.length() - 3);
139 uri = new URI(scheme, authority, uri.getPath(), uri.getQuery(), dropFragment ? null : uri.getFragment());
140
141 String path = uri.getPath(); {
142
143 path = path.replaceAll("(^|/)\\.\\.$", "$1../");
144
145 path = path.replaceAll("^/(\\.\\./)+", "/");
146 }
147 uri = new URI(uri.getScheme(), uri.getAuthority(), path, uri.getQuery(), uri.getFragment());
148 uri = expand83(uri);
149 return uri;
150 } catch (URISyntaxException e) {
151 throw new RuntimeException(e);
152 } catch (IOException e) {
153 throw new RuntimeException(e);
154 }
155 }
156
157
158
159
160
161
162
163 public static String expand83(String uri) throws URISyntaxException, IOException {
164 if (uri == null || !uri.startsWith("file:/")) {
165 return uri;
166 }
167 return expand83(URLs.asURI(uri)).toASCIIString();
168 }
169
170 private static URI expand83(URI uri) throws URISyntaxException, IOException {
171 if (uri == null || !"file".equals(uri.getScheme())) {
172 return uri;
173 }
174 String protocol = "file";
175 String path = uri.getPath();
176 String zipPath = null;
177 if (path.contains("!/")) {
178
179 zipPath = path.substring(path.indexOf("!/")+1);
180 path = path.substring(0, path.indexOf("!/"));
181 }
182 String query = uri.getQuery();
183 String fragment = uri.getFragment();
184 File file = new File(new URI(protocol, null, path, null, null));
185 URI expandedUri = expand83(file, path.endsWith("/"));
186 if (expandedUri == null) {
187 return uri;
188 } else {
189 path = expandedUri.getPath();
190 if (zipPath != null)
191 path = path + "!" + new URI(null, null, zipPath, null, null).getPath();
192 return new URI(protocol, null, path, query, fragment);
193 }
194 }
195
196 public static URI expand83(File file) throws URISyntaxException, IOException {
197 return expand83(file, false);
198 }
199
200 private static URI expand83(File file, boolean isDir) throws URISyntaxException, IOException {
201 if (file.exists()) {
202 return URLs.asURI(file.getCanonicalFile());
203 } else {
204
205 String relPath = file.getName();
206 if (isDir)
207 relPath += "/";
208 File dir = file.getParentFile();
209 while (dir != null) {
210 if (dir.exists())
211 return URLs.resolve(URLs.asURI(dir.getCanonicalFile()), new URI(null, null, relPath, null, null));
212 relPath = dir.getName() + "/" + relPath;
213 dir = dir.getParentFile();
214 }
215 return URLs.asURI(file);
216 }
217 }
218 }