src/Pure/General/url.scala
changeset 79510 d8330439823a
parent 79045 24d04dd5bf01
child 79511 57ceacd4a17b
equal deleted inserted replaced
79509:e82448aacf48 79510:d8330439823a
     1 /*  Title:      Pure/General/url.scala
     1 /*  Title:      Pure/General/url.scala
     2     Author:     Makarius
     2     Author:     Makarius
     3 
     3 
     4 Basic URL operations.
     4 Basic URL/URI operations.
     5 */
     5 */
     6 
     6 
     7 package isabelle
     7 package isabelle
     8 
     8 
     9 
     9 
    10 import java.io.{File => JFile}
    10 import java.io.{File => JFile, InputStream}
    11 import java.nio.file.{Paths, FileSystemNotFoundException}
    11 import java.nio.file.{Paths, FileSystemNotFoundException}
    12 import java.net.{URI, URISyntaxException, URL, MalformedURLException, URLDecoder, URLEncoder}
    12 import java.net.{URI, URISyntaxException, MalformedURLException, URLDecoder, URLEncoder,
       
    13   URLConnection}
    13 import java.util.Locale
    14 import java.util.Locale
    14 import java.util.zip.GZIPInputStream
    15 import java.util.zip.GZIPInputStream
    15 
    16 
    16 
    17 
    17 object Url {
    18 object Url {
    34   def is_malformed(exn: Throwable): Boolean =
    35   def is_malformed(exn: Throwable): Boolean =
    35     exn.isInstanceOf[MalformedURLException] ||
    36     exn.isInstanceOf[MalformedURLException] ||
    36     exn.isInstanceOf[URISyntaxException] ||
    37     exn.isInstanceOf[URISyntaxException] ||
    37     exn.isInstanceOf[IllegalArgumentException]
    38     exn.isInstanceOf[IllegalArgumentException]
    38 
    39 
    39   def apply(name: String): URL =
    40   def apply(uri: URI): Url = new Url(uri)
    40     try { new URI(name).toURL }
       
    41     catch {
       
    42       case exn: Throwable if is_malformed(exn) => error("Malformed URL " + quote(name))
       
    43     }
       
    44 
    41 
    45   def resolve(url: URL, route: String): URL =
    42   def apply(name: String): Url = {
    46     if (route.isEmpty) url else url.toURI.resolve(route).toURL
    43     val uri =
       
    44       try { new URI(name) }
       
    45       catch {
       
    46         case exn: Throwable if is_malformed(exn) => error("Malformed URL " + quote(name))
       
    47       }
       
    48     Url(uri)
       
    49   }
    47 
    50 
    48   def is_wellformed(name: String): Boolean =
    51   def is_wellformed(name: String): Boolean =
    49     try { Url(name); true }
    52     try { Url(name); true }
    50     catch { case ERROR(_) => false }
    53     catch { case ERROR(_) => false }
    51 
    54 
    52   def is_readable(name: String): Boolean =
    55   def is_readable(name: String): Boolean =
    53     try { Url(name).openStream.close(); true }
    56     try { Url(name).open_stream().close(); true }
    54     catch { case ERROR(_) => false }
    57     catch { case ERROR(_) => false }
    55 
    58 
    56 
    59 
    57   /* file name */
    60   /* file name */
    58 
    61 
    59   def file_name(url: URL): String =
    62   def file_name(url: Url): String =
    60     Library.take_suffix[Char](c => c != '/' && c != '\\', url.getFile.toString.toList)._2.mkString
    63     Library.take_suffix[Char](c => c != '/' && c != '\\',
       
    64       url.java_url.getFile.toString.toList)._2.mkString
    61 
    65 
    62   def trim_index(url: URL): URL = {
    66   def trim_index(url: Url): Url = {
    63     Library.try_unprefix("/index.html", url.toString) match {
    67     Library.try_unprefix("/index.html", url.toString) match {
    64       case Some(u) => Url(u)
    68       case Some(u) => Url(u)
    65       case None =>
    69       case None =>
    66         Library.try_unprefix("/index.php", url.toString) match {
    70         Library.try_unprefix("/index.php", url.toString) match {
    67           case Some(u) => Url(u)
    71           case Some(u) => Url(u)
    77   def encode(s: String): String = URLEncoder.encode(s, UTF8.charset)
    81   def encode(s: String): String = URLEncoder.encode(s, UTF8.charset)
    78 
    82 
    79 
    83 
    80   /* read */
    84   /* read */
    81 
    85 
    82   private def read(url: URL, gzip: Boolean): String =
    86   private def read(url: Url, gzip: Boolean): String =
    83     using(url.openStream)(stream =>
    87     using(url.open_stream())(stream =>
    84       File.read_stream(if (gzip) new GZIPInputStream(stream) else stream))
    88       File.read_stream(if (gzip) new GZIPInputStream(stream) else stream))
    85 
    89 
    86   def read(url: URL): String = read(url, false)
    90   def read(url: Url): String = read(url, false)
    87   def read_gzip(url: URL): String = read(url, true)
    91   def read_gzip(url: Url): String = read(url, true)
    88 
    92 
    89   def read(name: String): String = read(Url(name), false)
    93   def read(name: String): String = read(Url(name), false)
    90   def read_gzip(name: String): String = read(Url(name), true)
    94   def read_gzip(name: String): String = read(Url(name), true)
    91 
    95 
    92 
    96 
   144     }
   148     }
   145     else prefix + "/" + suffix
   149     else prefix + "/" + suffix
   146 
   150 
   147   def direct_path(prefix: String): String = append_path(prefix, ".")
   151   def direct_path(prefix: String): String = append_path(prefix, ".")
   148 }
   152 }
       
   153 
       
   154 final class Url private(val uri: URI) {
       
   155   override def toString: String = uri.toString
       
   156 
       
   157   override def hashCode: Int = uri.hashCode
       
   158   override def equals(obj: Any): Boolean =
       
   159     obj match {
       
   160       case other: Url => uri == other.uri
       
   161       case _ => false
       
   162     }
       
   163 
       
   164   def resolve(route: String): Url =
       
   165     if (route.isEmpty) this else new Url(uri.resolve(route))
       
   166 
       
   167   def java_url: java.net.URL = uri.toURL
       
   168   def open_stream(): InputStream = java_url.openStream()
       
   169   def open_connection(): URLConnection = java_url.openConnection()
       
   170 }