<!--
  - Authors:
  -   Denys Duchier     <duchier@ps.uni-sb.de>
  -   Leif Kornstaedt <kornstae@ps.uni-sb.de>
  -   Christian Schulte <schulte@ps.uni-sb.de>
  -
  - Copyright:
  -   Denys Duchier, 1998
  -   Leif Kornstaedt, 1998
  -   Christian Schulte, 1998
  -
  - Last change:
  -   $Date: 2001/01/26 14:54:12 $ by $Author: duchier $
  -   $Revision: 1.8 $
  -
  - This file is part of Mozart, an implementation
  - of Oz 3
  -    http://www.mozart-oz.org
  -
  - See the file "LICENSE" or
  -    http://www.mozart-oz.org/LICENSE.html
  - for information on usage and redistribution
  - of this file, and for a DISCLAIMER OF ALL
  - WARRANTIES.
  -
  -->

<Chapter id="Chapter.Resolve">
  <Title/Resolving URLs: <<Resolve>>/
  <p>The <code/Resolve/ module generalizes the idea of a <em/search
path/ and simplifies read-oriented operations on arbitrary files and
urls.  The reader should be warned that this module has not yet reached
full maturity.</p> 
  <section proglang=sh>
    <title/From search paths to search methods/
    <p>A search path is a list of directores sequentially searched
to resolve a relative pathname.  On <name type="OS"/Unix/ a search
path is traditionally specified by an environment variable whose value
is of the form:
<code display/Dir1:Dir2:...:DirN/
On <name type="OS"/Windows/, the colons <samp/:/ would be replaced by
semi-colons <samp/;/.  In the age of the <em/World Wide Web/, the
classical notion of a search path is too limited: we want to search
for arbitrary urls in arbitrary networked locations, and not simply
for relative pathnames in local directories.  For this reason, the
notion of a directory to be searched is replaced by that of a method
to be applied.  A sequence of search methods can be specified by an
environment variable whose value is of the form:
<code display/Meth1:Meth2:...:MethN/
where each <code/MethK/ is of the form <code/KIND=ARG/.  <code/KIND/
selects the method to be applied and <code/ARG/ is its parameters.  On
<name type="OS"/Windows/, the colons might be replaced by semi-colons,
we support both notations on all platforms.  The idea is of course
that each method should be tried until one of them succeeds in
locating the desired resource.
  <section proglang=sh>
    <title/Syntax of methods/
    <p>We now describe the syntax of <code/KIND=ARG/ for the
supported methods.  For each one, we use a concrete example.
<code/ARG/ can normally be indifferently a directory or a url.
    <p>Any character of <code/ARG/ can be escaped by preceding it with
a backslash <samp/\/: this is useful &eg; to prevent an occurrence of
a colon in a url to be interpreted as a method separator.  However, it
means that, if you insist on using <samp/\/ as a path component
separator (à la Windows) instead of <samp>/</samp> (à la Unix), then
you will have to escape them in <code/ARG/.  Furthermore, <samp/\/ is
also an escape character for the shell, which means that you will
normally have to double each escape character.</p>
<p>
<list>
	<entry><code>all=/usr/local/oz/share</code></entry>
	<item>The last component in the input url is extracted and
looked up in the location supplied as the methods argument.  If the
input url is
<file>http://www.mozart-oz.org/home/share/Foo.ozf</file>, then we
try to look up  <file>/usr/local/oz/share/Foo.ozf</file> instead.
	<entry><code>root=~/lib/oz</code></entry>
	<item>This applies only to a relative pathname: it is
resolved relative to the base url or directory supplied as argument to
the method.  If the input url is
<file>share/Foo.ozf</file> then <file>~/lib/oz/share/Foo.ozf</file> is
looked up instead. For convenience, and to be compatible with search
path notation, you can omit <code/root=/ and simply write this method
as <code>~/lib/oz</code>
	<entry><code>cache=/usr/local/oz/cache</code></entry>
	<item>Applies only to a full url: it is transformed into a
relative pathname and looked up in the specified location.  If the
input url is:
<file>http://www.mozart-oz.org/home/share/Foo.ozf</file>, then
<file>/usr/local/oz/cache/http/www.mozart-oz.org/home/share/Foo.ozf</file>
is looked up instead.  This method is typically used to permit local
caching of often used functors.  The cache location could also be the
url of some sort of mirroring server.
	<entry><code>prefix=http://www.mozart-oz.org/home/=~/oz/</code></entry>
	<item>This method has the form <code/prefix=LOC1=LOC2/.
Whenever the input url begins with the string <code/LOC1/, this prefix
is replaced by <code/LOC2/ and the result is looked for instead.
Thus, if the input url is
<file>http://www.mozart-oz.org/home/share/Foo.ozf</file>, we would
look for <file>~/oz/share/Foo.ozf</file>.
	<entry><code>pattern=http://www.&qmrk;{x}/home/&qmrk;{y}=ftp://ftp.&qmrk;{x}/oz/&qmrk;{y}</code></entry>
	<item>The <code/pattern/ method is more general than the
<code/prefix/ method.  <code/LOC1/ can contain match variables, such
as <code/&qmrk;{x}/ and <code/&qmrk;{y}/ that should match arbitrary
sequences of characters, and <code/LOC2/ can also mention these
variables to denote the value they have been assigned by the match.
Thus, if the input url is
<file>http://www.mozart-oz.org/home/share/Foo.ozf</file>, we would
look for <file>ftp://ftp.mozart-oz.org/oz/share/Foo.ozf</file>.
	<entry/<code/=//
	<item>Normally, the default handler is implicitly appended
to your search methods.  This is the handler that simply looks up the
input url itself, when all previous methods have failed.  Sometimes it
is desirable to disallow this default: for example this is the case
when building the mozart distribution; the build process should be
self contained and should not attempt to access resources over the
network.  You can disallow the default by appending <code/=/ as the
very last of your search methods.  Thus
<code display>.:all=~/oz/bazar:=</code>
would first try to resolve relative pathnames with respect to the
current directory, then all urls by looking up their final component
in directory <file>~/oz/bazar</file>, and that's it.  If neither of
these two methods succeeds, the resolution would simply raise an
exception, but it would not attempt to retrieve the input url from the
net.
      </list>
  <section proglang=oz>
    <title/Interface of <code/Resolve/ Module/
    <p>A resolver is a module that encapsulates and exports the
resolving services of a sequence of search methods.  For different
purposes, you may need to apply different resolution strategies.  For
this reason, you may create arbitrarily many resolvers, each
implementing an arbitrary resolution strategy.
<list>
	<entry/<code/Resolve.make/<index/<code/Resolve/<and><code/make///
	<synopsis/<code/{Resolve.make ?+{VS} ?+{Spec} ??{R}}//
	<item>Creates a new resolver ?_{R}, identified by virtual
string ?_{VS} in trace messages, and whose strategy is initialized
according to ?_{Spec} which is one of:
<list>
	      <entry/<code/init(L)//
	      <item>where <code/L/ is a list of handlers (see
later).
	      <entry/<code/env(V)//
	      <item>where <code/V/ names an environment variable
whose value provides the search methods.  If it is not set, the
initial strategy simply looks up the input url itself.
	      <entry/<code/env(V S)//
	      <item>same as above, but, if the environment variable
is not set, then use <code/S/ as its value.
	      <entry/<code/vs(S)//
	      <item>simply get the search methods from virtual
string <code/S/.
	    </list>
	<entry/<code/Resolve.trace.get/
<index/<code/Resolve/<and><code/trace/<and><code/get///
	<entry/<code/Resolve.trace.set/
<index/<code/Resolve/<and><code/trace/<and><code/set///
	<synopsis/<code/{Resolve.trace.get ??{Bool}}//
	<synopsis/<code/{Resolve.trace.set ?+{Bool}}//
	<item>Obtain or set the trace flag.  When tracing is
enabled, every resolve method that is attempted prints an informative
message.  Furthermore, all messages are prefixed by the virtual string
identifying the resolver in which these methods are being invoked.
	<entry/<code/Resolve.expand/
<index/<code/Resolve/<and><code/expand///
	<synopsis/<code/{Resolve.expand ?+{Url1} ??{Url2}}//
	<item>Takes a Url or virtual string as input and returns a Url
with <code/"~"/ expanded to the full user's home directory path,
<code/"~john"/ expanded to <code/john/'s home directory, <code/"."/ and
<code/".."/ expanded to the current directory and parent directory.  This
functionality really belongs in the <code/URL/ module, but is put here
instead to keep module <code/URL/ stateless.
	<entry/<code/Resolve.handler/
<index/<code/Resolve/<and><code/handler///
	<item>You don't have to specify your methods as virtual
strings, instead you can directly construct them using the following
procedures:
<list>
	      <entry/<code/Resolve.handler.default/
<index/<code/Resolve/<and><code/handler/<and><code/default///
	      <item>This is the default handler that simply looks up
the given url as is.
	      <entry/<code/Resolve.handler.all/
<index/<code/Resolve/<and><code/handler/<and><code/all///
	      <synopsis/<code/{Resolve.handler.all ?+{LOC} ??{Handler}}//
	      <item>This creates a handler that implements the
<code/all/ method for location ?_{LOC}.  The final component in the
input url is looked up in ?_{LOC}.
	      <entry/<code/Resolve.handler.root/
<index/<code/Resolve/<and><code/handler/<and><code/root///
	      <synopsis/<code/{Resolve.handler.root ?+{LOC} ??{Handler}}//
	      <item>This creates a handler that implements the
<code/root/ method for location ?_{LOC}.  A relative pathname is
resolved relative to ?_{LOC}.
	      <entry/<code/Resolve.handler.cache/
<index/<code/Resolve/<and><code/handler/<and><code/cache///
	      <synopsis/<code/{Resolve.handler.cache ?+{LOC} ??{Handler}}//
	      <item>This creates a handler that implements the
<code/cache/ method for location ?_{LOC}.  A full url is transformed
into a relative pathname and resolved relative to ?_{LOC}.
	      <entry/<code/Resolve.handler.prefix/
<index/<code/Resolve/<and><code/handler/<and><code/prefix///
	      <synopsis/<code/{Resolve.handler.prefix ?+{Prefix} ?+{Subst} ??{Handler}}//
	      <item>This creates a handler that implements the
<code/prefix/ method.  If the input url begins with string ?_{Prefix},
then this is replaced by ?_{Subst} and looked up instead.
	      <entry/<code/Resolve.handler.pattern/
<index/<code/Resolve/<and><code/handler/<and><code/pattern///
	      <synopsis/<code/{Resolve.handler.prefix ?+{Pattern} ?+{Subst} ??{Handler}}//
	      <item>This creates a handler that implements the
<code/pattern/ method.  If the input url matches the string pattern
?_{Pattern}, then this is replaced by the corresponding instantiation
of ?_{Subst} and looked up instead.
	    </list>
      </list></p>
  </section>
  <section>
    <title/Interface of a Resolver/
    <p>Each resolver <code/R/ exports the following methods
<list>
	<entry/<code/R.getHandlers/<index/getHandlers//
	<synopsis/<code/{R.getHandlers ??{L}}//
	<item>obtains <code/R/'s current list of handlers.
	<entry/<code/R.setHandlers/<index/setHandlers//
	<synopsis/<code/{R.setHandlers ?+{L}}//
	<item>install's ?_{L} as <code/R/'s current list of
handlers.
	<entry/<code/R.addHandler/<index/addHandler//
	<synopsis/<code/{R.addHandler front(H)}
{R.addHandler back(H)}//
	<item>adds <code/H/ at the front (resp.&nbsp;at the back) of
<code/R/'s list of handlers.
	<entry/<code/R.localize/<index/localize//
	<synopsis/<code/{R.localize ?+{Url} ??{Rec}}/<index/localize//
	<item>the return value ?_{Rec} is <code/old(Filename)/ if
?_{Url} resolves to local file <code/Filename/, else it is
<code/new(Filename)/ where <code/Filename/ is a new local file created
by retrieving the data at ?_{Url}.
	<entry/<code/R.open/<index/open//
	<synopsis/<code/{R.open ?+{Url} ??{FdI}}//
	<item>returns ?_{FdI}, which is an integer file descriptor
open for read on the data available from ?_{Url}.
	<entry/<code/R.load/<index/load//
	<synopsis/<code/{R.load ?+{Url} ??{V}}//
	<item>returns the value ?_{V} obtained from the pickle
available at ?_{Url}.
	<entry/<code/R.native/<index/native//
	<synopsis/<code/{R.native ?+{Url} ??{M}}//
	<item>returns the native module ?_{M} obtained by dynamically
linking the native functor available in file ?_{Url}.
      </list>
  </section>
</Chapter>

<!--
Local Variables:
mode: sgml
mode: auto-fill
sgml-default-dtd-file: "chapter.ced"
sgml-auto-activate-dtd: t
adaptive-fill-mode: nil
End:
-->
