| author | haftmann | 
| Fri, 18 Oct 2019 18:41:33 +0000 | |
| changeset 70901 | 94a0c47b8553 | 
| parent 69901 | 20b32ade0024 | 
| child 71163 | b5822f4c3fde | 
| permissions | -rw-r--r-- | 
| 
56501
 
5fda9e5c5874
basic URL operations (with Isabelle/Scala error handling);
 
wenzelm 
parents:  
diff
changeset
 | 
1  | 
/* Title: Pure/General/url.scala  | 
| 
 
5fda9e5c5874
basic URL operations (with Isabelle/Scala error handling);
 
wenzelm 
parents:  
diff
changeset
 | 
2  | 
Author: Makarius  | 
| 
 
5fda9e5c5874
basic URL operations (with Isabelle/Scala error handling);
 
wenzelm 
parents:  
diff
changeset
 | 
3  | 
|
| 
 
5fda9e5c5874
basic URL operations (with Isabelle/Scala error handling);
 
wenzelm 
parents:  
diff
changeset
 | 
4  | 
Basic URL operations.  | 
| 
 
5fda9e5c5874
basic URL operations (with Isabelle/Scala error handling);
 
wenzelm 
parents:  
diff
changeset
 | 
5  | 
*/  | 
| 
 
5fda9e5c5874
basic URL operations (with Isabelle/Scala error handling);
 
wenzelm 
parents:  
diff
changeset
 | 
6  | 
|
| 
 
5fda9e5c5874
basic URL operations (with Isabelle/Scala error handling);
 
wenzelm 
parents:  
diff
changeset
 | 
7  | 
package isabelle  | 
| 
 
5fda9e5c5874
basic URL operations (with Isabelle/Scala error handling);
 
wenzelm 
parents:  
diff
changeset
 | 
8  | 
|
| 
 
5fda9e5c5874
basic URL operations (with Isabelle/Scala error handling);
 
wenzelm 
parents:  
diff
changeset
 | 
9  | 
|
| 64729 | 10  | 
import java.io.{File => JFile}
 | 
| 65188 | 11  | 
import java.nio.file.{Paths, FileSystemNotFoundException}
 | 
| 67245 | 12  | 
import java.net.{URI, URISyntaxException, URL, MalformedURLException, URLDecoder, URLEncoder}
 | 
| 69901 | 13  | 
import java.util.Locale  | 
| 63642 | 14  | 
import java.util.zip.GZIPInputStream  | 
| 
56501
 
5fda9e5c5874
basic URL operations (with Isabelle/Scala error handling);
 
wenzelm 
parents:  
diff
changeset
 | 
15  | 
|
| 
 
5fda9e5c5874
basic URL operations (with Isabelle/Scala error handling);
 
wenzelm 
parents:  
diff
changeset
 | 
16  | 
|
| 
 
5fda9e5c5874
basic URL operations (with Isabelle/Scala error handling);
 
wenzelm 
parents:  
diff
changeset
 | 
17  | 
object Url  | 
| 
 
5fda9e5c5874
basic URL operations (with Isabelle/Scala error handling);
 
wenzelm 
parents:  
diff
changeset
 | 
18  | 
{
 | 
| 69901 | 19  | 
/* special characters */  | 
20  | 
||
21  | 
def escape_special(c: Char): String =  | 
|
22  | 
    if ("!#$&'()*+,/:;=?@[]".contains(c)) String.format(Locale.ROOT, "%%%02X", new Integer(c.toInt))
 | 
|
23  | 
else c.toString  | 
|
24  | 
||
25  | 
def escape_special(s: String): String = s.iterator.map(escape_special(_)).mkString  | 
|
26  | 
||
27  | 
def escape_name(name: String): String =  | 
|
28  | 
    name.iterator.map({ case '\'' => "%27" case c => c.toString }).mkString
 | 
|
29  | 
||
30  | 
||
31  | 
/* make and check URLs */  | 
|
| 62248 | 32  | 
|
| 
56501
 
5fda9e5c5874
basic URL operations (with Isabelle/Scala error handling);
 
wenzelm 
parents:  
diff
changeset
 | 
33  | 
def apply(name: String): URL =  | 
| 
 
5fda9e5c5874
basic URL operations (with Isabelle/Scala error handling);
 
wenzelm 
parents:  
diff
changeset
 | 
34  | 
  {
 | 
| 
 
5fda9e5c5874
basic URL operations (with Isabelle/Scala error handling);
 
wenzelm 
parents:  
diff
changeset
 | 
35  | 
    try { new URL(name) }
 | 
| 
 
5fda9e5c5874
basic URL operations (with Isabelle/Scala error handling);
 
wenzelm 
parents:  
diff
changeset
 | 
36  | 
    catch { case _: MalformedURLException => error("Malformed URL " + quote(name)) }
 | 
| 
 
5fda9e5c5874
basic URL operations (with Isabelle/Scala error handling);
 
wenzelm 
parents:  
diff
changeset
 | 
37  | 
}  | 
| 
 
5fda9e5c5874
basic URL operations (with Isabelle/Scala error handling);
 
wenzelm 
parents:  
diff
changeset
 | 
38  | 
|
| 
 
5fda9e5c5874
basic URL operations (with Isabelle/Scala error handling);
 
wenzelm 
parents:  
diff
changeset
 | 
39  | 
def is_wellformed(name: String): Boolean =  | 
| 
 
5fda9e5c5874
basic URL operations (with Isabelle/Scala error handling);
 
wenzelm 
parents:  
diff
changeset
 | 
40  | 
    try { Url(name); true }
 | 
| 
 
5fda9e5c5874
basic URL operations (with Isabelle/Scala error handling);
 
wenzelm 
parents:  
diff
changeset
 | 
41  | 
    catch { case ERROR(_) => false }
 | 
| 
 
5fda9e5c5874
basic URL operations (with Isabelle/Scala error handling);
 
wenzelm 
parents:  
diff
changeset
 | 
42  | 
|
| 
 
5fda9e5c5874
basic URL operations (with Isabelle/Scala error handling);
 
wenzelm 
parents:  
diff
changeset
 | 
43  | 
def is_readable(name: String): Boolean =  | 
| 
 
5fda9e5c5874
basic URL operations (with Isabelle/Scala error handling);
 
wenzelm 
parents:  
diff
changeset
 | 
44  | 
    try { Url(name).openStream.close; true }
 | 
| 
 
5fda9e5c5874
basic URL operations (with Isabelle/Scala error handling);
 
wenzelm 
parents:  
diff
changeset
 | 
45  | 
    catch { case ERROR(_) => false }
 | 
| 
 
5fda9e5c5874
basic URL operations (with Isabelle/Scala error handling);
 
wenzelm 
parents:  
diff
changeset
 | 
46  | 
|
| 63642 | 47  | 
|
| 67245 | 48  | 
/* strings */  | 
49  | 
||
50  | 
def decode(s: String): String = URLDecoder.decode(s, UTF8.charset_name)  | 
|
51  | 
def encode(s: String): String = URLEncoder.encode(s, UTF8.charset_name)  | 
|
52  | 
||
53  | 
||
| 63642 | 54  | 
/* read */  | 
55  | 
||
| 63645 | 56  | 
private def read(url: URL, gzip: Boolean): String =  | 
| 65069 | 57  | 
using(url.openStream)(stream =>  | 
58  | 
File.read_stream(if (gzip) new GZIPInputStream(stream) else stream))  | 
|
| 63642 | 59  | 
|
| 63645 | 60  | 
def read(url: URL): String = read(url, false)  | 
61  | 
def read_gzip(url: URL): String = read(url, true)  | 
|
62  | 
||
63  | 
def read(name: String): String = read(Url(name), false)  | 
|
64  | 
def read_gzip(name: String): String = read(Url(name), true)  | 
|
| 64729 | 65  | 
|
| 69394 | 66  | 
def read_bytes(url: URL): Bytes =  | 
67  | 
  {
 | 
|
68  | 
val connection = url.openConnection  | 
|
69  | 
val length = connection.getContentLength  | 
|
70  | 
using(connection.getInputStream)(Bytes.read_stream(_, hint = length))  | 
|
71  | 
}  | 
|
72  | 
||
| 64729 | 73  | 
|
74  | 
/* file URIs */  | 
|
75  | 
||
| 66234 | 76  | 
def print_file(file: JFile): String = File.absolute(file).toPath.toUri.toString  | 
| 
64777
 
ca09695eb43c
clarified Document.Node.Name (again): canonical platform file;
 
wenzelm 
parents: 
64775 
diff
changeset
 | 
77  | 
def print_file_name(name: String): String = print_file(new JFile(name))  | 
| 64775 | 78  | 
|
79  | 
def parse_file(uri: String): JFile = Paths.get(new URI(uri)).toFile  | 
|
| 64729 | 80  | 
|
81  | 
def is_wellformed_file(uri: String): Boolean =  | 
|
| 64775 | 82  | 
    try { parse_file(uri); true }
 | 
| 65188 | 83  | 
    catch {
 | 
84  | 
case _: URISyntaxException | _: IllegalArgumentException | _: FileSystemNotFoundException =>  | 
|
85  | 
false  | 
|
86  | 
}  | 
|
| 64730 | 87  | 
|
| 
66235
 
d4fa51e7c4ff
retain symlinks in file names from VSCode: relevant for proper file locations in decorations etc.;
 
wenzelm 
parents: 
66234 
diff
changeset
 | 
88  | 
def absolute_file(uri: String): JFile = File.absolute(parse_file(uri))  | 
| 
 
d4fa51e7c4ff
retain symlinks in file names from VSCode: relevant for proper file locations in decorations etc.;
 
wenzelm 
parents: 
66234 
diff
changeset
 | 
89  | 
def absolute_file_name(uri: String): String = absolute_file(uri).getPath  | 
| 
 
d4fa51e7c4ff
retain symlinks in file names from VSCode: relevant for proper file locations in decorations etc.;
 
wenzelm 
parents: 
66234 
diff
changeset
 | 
90  | 
|
| 66234 | 91  | 
def canonical_file(uri: String): JFile = File.canonical(parse_file(uri))  | 
| 
64777
 
ca09695eb43c
clarified Document.Node.Name (again): canonical platform file;
 
wenzelm 
parents: 
64775 
diff
changeset
 | 
92  | 
def canonical_file_name(uri: String): String = canonical_file(uri).getPath  | 
| 
56501
 
5fda9e5c5874
basic URL operations (with Isabelle/Scala error handling);
 
wenzelm 
parents:  
diff
changeset
 | 
93  | 
}  |