View Javadoc

1   ////////////////////////////////////////////////////////////////////////////////
2   // MillScript: an Open Spice interpreter and batch website creation tool
3   // Copyright (C) 2005 Kevin Rogers
4   //
5   // This file is part of MillScript.
6   //
7   // MillScript is free software; you can redistribute it and/or modify it under
8   // the terms of the GNU General Public License as published by the Free
9   // Software Foundation; either version 2 of the License, or (at your option)
10  // any later version.
11  //
12  // MillScript is distributed in the hope that it will be useful, but WITHOUT
13  // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
15  // more details.
16  //
17  // You should have received a copy of the GNU General Public License along with
18  // MillScript; if not, write to the Free Software Foundation, Inc., 59 Temple
19  // Place, Suite 330, Boston, MA  02111-1307  USA
20  ////////////////////////////////////////////////////////////////////////////////
21  package org.millscript.commons.vfs.util;
22  
23  import org.millscript.commons.vfs.VFile;
24  import org.millscript.commons.vfs.VFolder;
25  import org.millscript.commons.vfs.VVolume;
26  import org.millscript.commons.vfs.mime.MIMETypeHandler;
27  
28  /**
29   * A utility class providing URI path resolution methods for the virtual
30   * filesystem.
31   */
32  public final class Resolver {
33  
34      /**
35       * Hidden constructor.
36       */
37      private Resolver() {
38      }
39  
40      /**
41       * Resolves the specified path to a virtual file against the specified
42       * folder. The new file may have different parent folders.
43       *
44       * @param base  the virtual folder to resolve the path against
45       * @param path   the path to get a virtual file for
46       * @return  a VFile for the specified relative URI
47       */
48      public static VFile resolveAsFile( final VFolder base, final String path ) {
49          // First get the index of the first slash
50          int n1 = path.indexOf( '/', 0 );
51          if ( n1 < 0 ) {
52              // The path doesn't contain a slash, so get it as a file
53              return base.checkVFile( path );
54          } else if ( n1 == 0 ) {
55              // It begins with a slash so it's an absolute path
56              // We need to get to the root and resolve against that
57              if ( base.getParent() == null ) {
58                  // We're at the root object, so strip the leading slash and
59                  // resolve as a relative path
60                  return resolveAsFile( base, path.substring( 1 ) );
61              } else {
62                  // Not at the root yet. Jump up to the parent and try again
63                  return resolveAsFile( base.getParent(), path );
64              }
65          } else if ( n1 == path.length() - 1 ) {
66              // The slash is at the end of the path so remove it and resolve
67              return resolveAsFile( base, path.substring( 0, n1 ) );
68          } else {
69              // It's a relative path
70              // Get the first segment as a folder. NOTE - the increment on n1 is
71              // there so we include the slash at the end of the segment
72              final VFolder folder = resolveAsFolder( base, path.substring( 0, ++n1 ) );
73              // Resolve the remaining path on the folder
74              return resolveAsFile( folder, path.substring( n1 ) );
75          }
76      }
77  
78      /**
79       * Resolves the specified path to a virtual folder against the specified
80       * folder. The new folder may have different parent folders.
81       *
82       * @param base  the virtual folder to resolve the path against
83       * @param path   the path to get a virtual folder for
84       * @return  a VFile for the specified relative URI
85       */
86      public static VFolder resolveAsFolder( final VFolder base, final String path ) {
87          // First get the index of the first slash
88          int n1 = path.indexOf( '/', 0 );
89          if ( n1 < 0 ) {
90              // The path doesn't contain a slash, so get it as a folder
91              // This step requires a MIME type check. If the path is a
92              // recognised VFS MIME type then we have to handle it as
93              // appropriate
94              // First check it's MIME type
95              final String type = base.getMIMEType( path );
96              // Do we have a handler for this type
97              final MIMETypeHandler handler = base.getMIMETypeHandler( type );
98              if ( handler == null ) {
99                  // It's nothing special, so make a normal folder for it
100                 return base.getVFolder( path );
101             } else {
102                 // Oooo. We've got something special
103                 // We treat this segment like a file
104                 final VFile file = resolveAsFile( base, path );
105                 // And now use the handler to turn it into a folder
106                 return handler.resolveAsFolder( file );
107             }
108         } else if ( n1 == 0 ) {
109             // It begins with a slash so it's an absolute path
110             // We need to get to the root and resolve against that
111             if ( base.getParent() == null ) {
112                 // We're at the root object, so strip the leading slash and
113                 // resolve as a relative path
114                 return resolveAsFolder( base, path.substring( 1 ) );
115             } else {
116                 // Not at the root yet. Jump up to the parent and try again
117                 return resolveAsFolder( base.getParent(), path );
118             }
119         } else if ( n1 == path.length() - 1 ) {
120             // The slash is at the end of the path so remove it and resolve
121             return resolveAsFolder( base, path.substring( 0, n1 ) );
122         } else {
123             // It's a relative path
124             // Get the first segment as a folder. NOTE - the increment on n1 is
125             // there so we include the slash at the end of the segment
126             final VFolder folder = resolveAsFolder( base, path.substring( 0, ++n1 ) );
127             // Resolve the remaining path on the folder
128             return resolveAsFolder( folder, path.substring( n1 ) );
129         }
130     }
131 
132     /**
133      * Resolves the specified path to a new virtual volume against the
134      * specified folder, with the volumes root at the resolved path. For this
135      * to work it must be possible to resolve the specified path as a folder.
136      *
137      * @param base  the virtual folder to resolve the path against
138      * @param path   the path to get a virtual volume for
139      * @return  a VVolume for the specified relative URI
140      */
141     public static VVolume resolveAsVolume( final VFolder base, final String path ) {
142         // Get the path as a folder and return it as a new volume
143         return resolveAsFolder( base, path ).toVolume();
144     }
145 
146 }