You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ar...@locus.apache.org on 2000/10/11 02:24:46 UTC

cvs commit: jakarta-tomcat/src/share/org/apache/tomcat/util FileUtil.java

arieh       00/10/10 17:24:46

  Modified:    src/share/org/apache/tomcat/core Tag: tomcat_32 Context.java
               src/share/org/apache/tomcat/request Tag: tomcat_32
                        StaticInterceptor.java
               src/share/org/apache/tomcat/util Tag: tomcat_32
                        FileUtil.java
  Log:
  Add support for searching for Localized versions of static files.
  
  In Context, add 'String getRealPath(String, Locale, Locale)' method
  to allow to look for a locale-specific real path.
  
  In StaticInterceptor, add constants (static final String) to identify the
  localization property name and the valid values.
  Define 'void setLocalization (String)' method to allow setting the
  localization based on the "localization" property set in the server.xml
  entry for the StaticInterceptor.
  Define 'String getLocalization()' to the the value selected.
  Define 'String getWelcomeFile (Context, String, Locale, Locale)' method
  to allow for locale-sensitive search of welcome files.
  Modify 'requestMap' to perform localized resource lookup if configured
  with the Interceptor, behave as before if not.
  Also, modify the logic of getting the welcome files, to allow to invoke
  the locale-sensitive version of 'getWelcomeFile'.
  
  In FileUtil, add methods to support locale-sensitive lookup of
  resources. The algorithm used is similar to the one specified in
  java.util.ResourceBundle.
  
  Revision  Changes    Path
  No                   revision
  
  
  No                   revision
  
  
  1.100.2.3 +62 -0     jakarta-tomcat/src/share/org/apache/tomcat/core/Context.java
  
  Index: Context.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/Context.java,v
  retrieving revision 1.100.2.2
  retrieving revision 1.100.2.3
  diff -u -r1.100.2.2 -r1.100.2.3
  --- Context.java	2000/08/16 22:24:25	1.100.2.2
  +++ Context.java	2000/10/11 00:24:44	1.100.2.3
  @@ -96,6 +96,7 @@
    * @author Harish Prabandham
    * @author costin@dnt.ro
    * @author Gal Shachor shachor@il.ibm.com
  + * @author Arieh Markel [arieh.markel@sun.com]
    */
   public class Context {
       private static StringManager sm =StringManager.getManager("org.apache.tomcat.core");
  @@ -792,6 +793,67 @@
   	    log("Get real path " + path + " " + realPath + " " + base );
   	}
   	return realPath;
  +    }
  +
  +    /**  method to return the Localized version of the file whose
  +     *   name is passed as an argument.
  +     *
  +     *  The method performs a resource lookup in a manner similar to the
  +     *  one specified by java.util.ResourceBundle.
  +     *
  +     *  In the case of 'typed' files (files whose name is [file].[ftype])
  +     *  search for localized versions of the file are looked for:
  +     *
  +     *   file + "_" + language1 + "_" + country1 + "_" + variant1 + "." + ftype
  +     *   file + "_" + language1 + "_" + country1 + "." + ftype
  +     *   file + "_" + language1 + "." + ftype
  +     *   file + "_" + language2 + "_" + country2 + "_" + variant2 "." + ftype
  +     *   file + "_" + language2 + "_" + country2 "." + ftype
  +     *   file + "_" + language2 + "." + ftype
  +     *   file + "." + ftype
  +     *
  +     *  Where language1, country1, variant1 are associated with the Locale
  +     *  passed as an argument and language2, country2, variant are associated
  +     *  with the default Locale passed as argument.
  +     *
  +     *  For example, if the preferred Locale is <CODE>es_AR_POSIX</CODE> and 
  +     *  the default Locale passed is <CODE>fr_CA_WIN</CODE>, and the requested
  +     *  pathname is <CODE>/foo/bar/index.html</CODE>, then a search for
  +     *  the following localized versions of that file will be done, in order:
  +     *<UL>
  +     *<LI>/foo/bar/index_es_AR_POSIX.html</LI>
  +     *<LI>/foo/bar/index_es_AR.html</LI>
  +     *<LI>/foo/bar/index_es.html</LI>
  +     *<LI>/foo/bar/index_fr_CA_WIN.html</LI>
  +     *<LI>/foo/bar/index_fr.html</LI>
  +     *<LI>/foo/bar/index.html</LI>
  +     *</UL>
  +     *
  +     *  If the resource passed has no 'ftype' component, then the same
  +     *  rules above apply, with the exception that '.' + ftype are not
  +     *  concatenated.
  +     *
  +     *  @param path the pathname for the resource whose localized version
  +     *          we are seeking
  +     *  @param loc the Locale we are interested in.
  +     *  @param fbLoc the fallback Locale to use if unsuccessful
  +     *
  +     *  @return a String with the path of the "best localized match" for
  +     *          the file whose path has been passed as argument.
  +     */
  +    public String getRealPath (String path, Locale reqLocale, Locale fbLocale)
  +    {
  +        String base = getAbsolutePath();
  +        if (path == null) path = "";
  +
  +        String realPath = FileUtil.getLocalizedFile (base, path,
  +						     reqLocale, fbLocale);
  +	if( debug>5) {
  +	    log("Get real path " + path + " " + realPath + " " + base
  +		 + reqLocale.toString() + " " + fbLocale.toString() );
  +	}
  +
  +        return realPath;
       }
   
       // -------------------- Deprecated
  
  
  
  No                   revision
  
  
  No                   revision
  
  
  1.7.2.3   +106 -16   jakarta-tomcat/src/share/org/apache/tomcat/request/StaticInterceptor.java
  
  Index: StaticInterceptor.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/request/StaticInterceptor.java,v
  retrieving revision 1.7.2.2
  retrieving revision 1.7.2.3
  diff -u -r1.7.2.2 -r1.7.2.3
  --- StaticInterceptor.java	2000/08/24 21:30:28	1.7.2.2
  +++ StaticInterceptor.java	2000/10/11 00:24:45	1.7.2.3
  @@ -75,14 +75,62 @@
   /**
    * Handler for static files.
    *
  + * In order to take advantage of doing searches for file-localized
  + * versions of the static files, the "localization" property needs to
  + * be set to "file" in the StaticInterceptor entry in the server.xml file.
  + *
    * @author costin@dnt.ro
  + * @author Arieh Markel [arieh.markel@sun.com]
    */
   public class StaticInterceptor extends BaseInterceptor {
       int realFileNote=-1;
   
  +    //  values for localization
  +    //
  +    int NONE_LOC = 0;
  +    int FILE_LOC = 1;
  +    int DOCB_LOC = 2;
  +
  +    int localization = NONE_LOC;
  +
  +    public static final String  FILE_LOCALIZATION = "file";
  +    public static final String  DOCBASE_LOCALIZATION = "docbase";
  +    public static final String  NO_LOCALIZATION = "none";
  +    public static final String  LOCALIZATION_PROPERTY = "localization";
  +
       public StaticInterceptor() {
       }
   
  +    /**  set the mode of localization for resource lookups
  +     *
  +     *  The following are possible localization modes:
  +     *<UL>
  +     *<LI>file</LI>
  +     *<LI>docbase</LI>
  +     *<LI>none</LI>
  +     *</UL>
  +     *
  +     *  @param s the localization mode
  +     */
  +    public void setLocalization (String s) {
  +	if (FILE_LOCALIZATION.equals(s))
  +	    localization = FILE_LOC;
  +	else if (DOCBASE_LOCALIZATION.equals(s))
  +	    localization = DOCB_LOC;
  +    }
  +
  +    /**  return the mode of localization for resource lookups
  +     *
  +     *  @return the localization mode
  +     */
  +    public String getLocalization() {
  +	return (localization == FILE_LOC)
  +	            ? FILE_LOCALIZATION
  +	            : (localization == DOCB_LOC)
  +	                        ? DOCBASE_LOCALIZATION
  +	                        : NO_LOCALIZATION;
  +    }
  +
       public void engineInit(ContextManager cm) throws TomcatException {
   	super.engineInit( cm );
   	
  @@ -119,7 +167,16 @@
   	// and a number of checks
   	String pathInfo=req.getServletPath();
   	if( pathInfo==null ) pathInfo="";
  -	String absPath=ctx.getRealPath( pathInfo );
  +
  +	String absPath = null;
  +
  +	if (localization == FILE_LOC)
  +	    absPath = ctx.getRealPath (pathInfo,
  +				       RequestUtil.getLocale(req),
  +				       Locale.getDefault());
  +	else
  +	    absPath = ctx.getRealPath( pathInfo );
  +
   	if( absPath == null ) return 0;
   	String requestURI=req.getRequestURI();
   
  @@ -142,7 +199,14 @@
   	}
   
   	// Directory, check if we have a welcome file
  -	String welcomeFile = getWelcomeFile(ctx, file);
  +	String welcomeFile = null;
  +	if (localization == FILE_LOC)
  +	    welcomeFile = getWelcomeFile(ctx, file,
  +					 RequestUtil.getLocale(req),
  +				         Locale.getDefault());
  +	else
  +	    welcomeFile = getWelcomeFile(ctx, file);
  +
   	if( debug > 0 )
   	    log( "DefaultServlet: welcome file: "  + welcomeFile);
   
  @@ -184,7 +248,7 @@
       }
       
       private String getWelcomeFile(Context context, File dir) {
  -        Enumeration enum = context.getWelcomeFiles();
  +	Enumeration enum = context.getWelcomeFiles();
   
   	while (enum.hasMoreElements()) {
   	    String fileName = (String)enum.nextElement();
  @@ -196,7 +260,33 @@
   	return null;
       }
   
  +    private String getWelcomeFile(Context context, File dir,
  +				  Locale loc, Locale fbloc) {
  +	Enumeration enum = context.getWelcomeFiles();
  +
  +	while (enum.hasMoreElements()) {
  +	    String fileName = (String)enum.nextElement();
   
  +	    int  ftype = fileName.lastIndexOf ('.');
  +	    String fbasen = (ftype != -1)
  +				? fileName.substring (0, ftype)
  +				: fileName;
  +
  +	    String fPath = dir.getAbsolutePath()
  +			 + File.separatorChar
  +			 + fileName;
  +
  +	    String retPath = FileUtil.getLocalizedResource (fPath,
  +							    loc,
  +							    fbloc);
  +	    if ((new File(retPath)).exists())
  +	    {
  +		int pathPos = retPath.lastIndexOf (fbasen);
  +		return retPath.substring (pathPos);
  +	    }
  +	}
  +	return null;
  +    }
   }
   
   // -------------------- Handlers --------------------
  @@ -243,7 +333,7 @@
   	File file = new File( absPath );
   	if( debug>0) log( "After paranoic checks = " + absPath);
   	
  -        String mimeType=ctx.getMimeMap().getContentTypeFor(absPath);
  +	String mimeType=ctx.getMimeMap().getContentTypeFor(absPath);
   
   	if (mimeType == null) {
   	    mimeType = "text/plain";
  @@ -432,7 +522,7 @@
   	for (int i = 0; i < fileNames.length; i++) {
   	    String fileName = fileNames[i];
   
  -            // Don't display special dirs at top level
  +	    // Don't display special dirs at top level
   	    if( (pathInfo.length() == 0 || "/".equals(pathInfo)) &&
        		"WEB-INF".equalsIgnoreCase(fileName) ||
    	    	"META-INF".equalsIgnoreCase(fileName) )
  @@ -450,25 +540,25 @@
   		    buf.append("</font></td></tr>\r\n");
   		}
   
  -                String fileN = f.getName();
  +	        String fileN = f.getName();
   
  -                buf.append("<tr");
  +	        buf.append("<tr");
   
  -                if (shaderow) buf.append(" bgcolor=#eeeeee");
  +	        if (shaderow) buf.append(" bgcolor=#eeeeee");
   		shaderow=!shaderow;
   		
  -                buf.append("><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");
  -                buf.append("<tt><a href=\"")
  +	        buf.append("><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");
  +	        buf.append("<tt><a href=\"")
   		    .append(slashedRequestURI)
  -                    .append(fileN)
  +	            .append(fileN)
   		    .append("\">")
   		    .append(fileN)
  -                    .append("/</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;")
  -                    .append("</tt>\r\n");
  -                buf.append("</td><td><tt>&nbsp;&nbsp;</tt></td>");
  -                buf.append("<td align=right><tt>");
  +	            .append("/</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;")
  +	            .append("</tt>\r\n");
  +	        buf.append("</td><td><tt>&nbsp;&nbsp;</tt></td>");
  +	        buf.append("<td align=right><tt>");
   		buf.append(dateFormat.format(new Date(f.lastModified())));
  -                buf.append("</tt></td></tr>\r\n");
  +	        buf.append("</tt></td></tr>\r\n");
   	    }
   	}
   
  
  
  
  No                   revision
  
  
  No                   revision
  
  
  1.9.2.4   +341 -65   jakarta-tomcat/src/share/org/apache/tomcat/util/FileUtil.java
  
  Index: FileUtil.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/FileUtil.java,v
  retrieving revision 1.9.2.3
  retrieving revision 1.9.2.4
  diff -u -r1.9.2.3 -r1.9.2.4
  --- FileUtil.java	2000/09/13 23:16:00	1.9.2.3
  +++ FileUtil.java	2000/10/11 00:24:45	1.9.2.4
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/FileUtil.java,v 1.9.2.3 2000/09/13 23:16:00 pier Exp $
  - * $Revision: 1.9.2.3 $
  - * $Date: 2000/09/13 23:16:00 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/FileUtil.java,v 1.9.2.4 2000/10/11 00:24:45 arieh Exp $
  + * $Revision: 1.9.2.4 $
  + * $Date: 2000/10/11 00:24:45 $
    *
    * ====================================================================
    *
  @@ -66,6 +66,7 @@
   
   import java.io.File;
   import java.io.IOException;
  +import java.util.Locale;
   
   /*
    * FileUtil contains utils for dealing with Files. Some of these are 
  @@ -78,6 +79,7 @@
    *
    * @author James Todd [gonzo@eng.sun.com]
    * @author Anil K. Vijendran [akv@eng.sun.com]
  + * @author Arieh Markel [arieh.markel@sun.com]
    */
   
   public class FileUtil {
  @@ -187,17 +189,17 @@
   
   	// This absPath/canPath comparison plugs security holes...
   	// On Windows, makes "x.jsp.", "x.Jsp", and "x.jsp%20"
  -        // return 404 instead of the JSP source
  +	// return 404 instead of the JSP source
   	// On all platforms, makes sure we don't let ../'s through
  -        // Unfortunately, on Unix, it prevents symlinks from working
  +	// Unfortunately, on Unix, it prevents symlinks from working
   	// So, a check for File.separatorChar='\\' ..... It hopefully
   	// happens on flavors of Windows.
   	if (File.separatorChar  == '\\') {
   	    // On Windows check ignore case....
   	    if (!realPath.equals(canPath)){
  -            int ls=realPath.lastIndexOf('\\');
  -            if ( (ls > 0) && !realPath.substring(0,ls).equals(canPath) )
  -        		return null;
  +	    int ls=realPath.lastIndexOf('\\');
  +	    if ( (ls > 0) && !realPath.substring(0,ls).equals(canPath) )
  +			return null;
   	    }
   	}
   
  @@ -224,54 +226,54 @@
   	// extra-extra safety check, ( but slow )
   	return realPath;
       }
  -    
  +
       public static String patch(String path) {
  -        String patchPath = path.trim();
  +	String patchPath = path.trim();
   
  -        // Move drive spec to the front of the path
  -        if (patchPath.length() >= 3 &&
  -            patchPath.charAt(0) == '/'  &&
  -            Character.isLetter(patchPath.charAt(1)) &&
  -            patchPath.charAt(2) == ':') {
  -            patchPath=patchPath.substring(1,3)+"/"+patchPath.substring(3);
  -        }
  +	// Move drive spec to the front of the path
  +	if (patchPath.length() >= 3 &&
  +	    patchPath.charAt(0) == '/'  &&
  +	    Character.isLetter(patchPath.charAt(1)) &&
  +	    patchPath.charAt(2) == ':') {
  +	    patchPath=patchPath.substring(1,3)+"/"+patchPath.substring(3);
  +	}
   
  -        // Eliminate consecutive slashes after the drive spec
  +	// Eliminate consecutive slashes after the drive spec
   	if (patchPath.length() >= 2 &&
  -            Character.isLetter(patchPath.charAt(0)) &&
  -            patchPath.charAt(1) == ':') {
  -            char[] ca = patchPath.replace('/', '\\').toCharArray();
  -            char c;
  -            StringBuffer sb = new StringBuffer();
  -
  -            for (int i = 0; i < ca.length; i++) {
  -                if ((ca[i] != '\\') ||
  -                    (ca[i] == '\\' &&
  -                        i > 0 &&
  -                        ca[i - 1] != '\\')) {
  -                    if (i == 0 &&
  -                        Character.isLetter(ca[i]) &&
  -                        i < ca.length - 1 &&
  -                        ca[i + 1] == ':') {
  -                        c = Character.toUpperCase(ca[i]);
  -                    } else {
  -                        c = ca[i];
  -                    }
  -
  -                    sb.append(c);
  -                }
  -            }
  -
  -            patchPath = sb.toString();
  -        }
  -
  -        // fix path on NetWare
  -        if (System.getProperty("os.name").startsWith("NetWare") &&
  -            path.length() >=3 &&
  -            path.indexOf(':') > 0)
  -            patchPath = patchPath.replace('/', '\\');
  +	    Character.isLetter(patchPath.charAt(0)) &&
  +	    patchPath.charAt(1) == ':') {
  +	    char[] ca = patchPath.replace('/', '\\').toCharArray();
  +	    char c;
  +	    StringBuffer sb = new StringBuffer();
  +
  +	    for (int i = 0; i < ca.length; i++) {
  +		if ((ca[i] != '\\') ||
  +		    (ca[i] == '\\' &&
  +		        i > 0 &&
  +		        ca[i - 1] != '\\')) {
  +		    if (i == 0 &&
  +		        Character.isLetter(ca[i]) &&
  +		        i < ca.length - 1 &&
  +		        ca[i + 1] == ':') {
  +		        c = Character.toUpperCase(ca[i]);
  +		    } else {
  +		        c = ca[i];
  +		    }
  +
  +		    sb.append(c);
  +		}
  +	    }
   
  -        return patchPath;
  +	    patchPath = sb.toString();
  +	}
  +
  +	// fix path on NetWare
  +	if (System.getProperty("os.name").startsWith("NetWare") &&
  +	    path.length() >=3 &&
  +	    path.indexOf(':') > 0)
  +	    patchPath = patchPath.replace('/', '\\');
  +
  +	return patchPath;
       }
   
       public static boolean isAbsolute( String path ) {
  @@ -282,30 +284,304 @@
   
   	// win c:
   	if (path.length() >= 3 &&
  -            Character.isLetter(path.charAt(0)) &&
  -            path.charAt(1) == ':')
  +	    Character.isLetter(path.charAt(0)) &&
  +	    path.charAt(1) == ':')
   	    return true;
   
  -        // NetWare volume:
  -        if (System.getProperty("os.name").startsWith("NetWare") &&
  -            path.length() >=3 &&
  -            path.indexOf(':') > 0)
  -            return true;
  +	// NetWare volume:
  +	if (System.getProperty("os.name").startsWith("NetWare") &&
  +	    path.length() >=3 &&
  +	    path.indexOf(':') > 0)
  +	    return true;
   
   	return false;
       }
  -    
  +
       // Used in few places.
       public static String getCanonicalPath(String name ) {
   	if( name==null ) return null;
  -        File f = new File(name);
  -        try {
  -            return  f.getCanonicalPath();
  -        } catch (IOException ioe) {
  +	File f = new File(name);
  +	try {
  +	    return  f.getCanonicalPath();
  +	} catch (IOException ioe) {
   	    ioe.printStackTrace();
   	    return name; // oh well, we tried...
  -        }
  +	}
  +    }
  +
  +    /**  method to return the Localized version of the file whose
  +     *   name is passed as an argument.
  +     *
  +     *  The method performs a resource lookup in a manner similar to the
  +     *  one specified by java.util.ResourceBundle.
  +     *
  +     *  In the case of 'typed' files (files whose name is [file].[ftype])
  +     *  search for localized versions of the file are looked for:
  +     *
  +     *   file + "_" + language1 + "_" + country1 + "_" + variant1 + "." + ftype
  +     *   file + "_" + language1 + "_" + country1 + "." + ftype
  +     *   file + "_" + language1 + "." + ftype
  +     *   file + "_" + language2 + "_" + country2 + "_" + variant2 "." + ftype
  +     *   file + "_" + language2 + "_" + country2 "." + ftype
  +     *   file + "_" + language2 + "." + ftype
  +     *   file + "." + ftype
  +     *
  +     *  Where language1, country1, variant1 are associated with the Locale
  +     *  passed as an argument and language2, country2, variant2 are associated
  +     *  with the default Locale passed as argument.
  +     *
  +     *  For example, if the preferred Locale is <CODE>es_AR_POSIX</CODE> and
  +     *  the default Locale passed is <CODE>fr_CA_WIN</CODE>, and the requested
  +     *  pathname is <CODE>/foo/bar/index.html</CODE>, then a search for
  +     *  the following localized versions of that file will be done, in order:
  +     *<UL>
  +     *<LI>/foo/bar/index_es_AR_POSIX.html</LI>
  +     *<LI>/foo/bar/index_es_AR.html</LI>
  +     *<LI>/foo/bar/index_es_AR.html</LI>
  +     *<LI>/foo/bar/index_es.html</LI>
  +     *<LI>/foo/bar/index_fr_CA_WIN.html</LI>
  +     *<LI>/foo/bar/index_fr_CA.html</LI>
  +     *<LI>/foo/bar/index_fr.html</LI>
  +     *<LI>/foo/bar/index.html</LI>
  +     *</UL>
  +     *
  +     *  If the resource passed has no 'ftype' component, then the same
  +     *  rules above apply, with the exception that '.' + ftype are not
  +     *  concatenated.
  +     *
  +     *  @param path the pathname for the resource whose localized version
  +     *          we are seeking
  +     *  @param loc the Locale we are interested in.
  +     *  @param fbLoc the fallback Locale to use if unsuccessful
  +     *
  +     *  @return a String with the path of the "best localized match" for
  +     *          the file whose path has been passed as argument.
  +     */
  +    public static String getLocalizedResource (String path,
  +		                               Locale loc,
  +		                               Locale fbLoc)
  +    {
  +	String locRes = null;
  +
  +	if (null != loc)
  +	    locRes = getLocalizedResource (path, loc);
  +
  +	if (null != locRes)
  +	    return locRes;
  +
  +	if (null != fbLoc)
  +	    locRes= getLocalizedResource (path, fbLoc);
  +
  +	if (null != locRes)
  +	    return locRes;
  +
  +	return path;
  +    } 
  +
  +    /**  utility method to return the name of the localized file whose
  +     *   name best-matches the Locale passed as an argument
  +     *
  +     *  @param base the directory that is the Document Base for the context
  +     *			in which the 'path' passed is expected to be located
  +     *  @param path the pathname for the file that is being searched for its
  +     *			best-matched Localized version
  +     *  @param loc the requested Locale to match
  +     *  @param fbloc the fallback Locale if the requested one not found
  +     *
  +     *  @return the name of the file that best-matched the Locale requested
  +     */
  +    public static String getLocalizedFile (String base,
  +					   String path,
  +					   Locale loc,
  +					   Locale fbloc) {
  +	
  +	String locRes = null;
  +
  +	if (null != loc)
  +	    locRes = getLocalizedFile (base, path, loc);
  +
  +	if (null != locRes)
  +	    return locRes;
  +
  +	if (null != fbloc)
  +	    locRes= getLocalizedFile (base, path, fbloc);
  +
  +	if (null != locRes)
  +	    return locRes;
  +
  +	return safePath (base, path);
  +    }
  +
  +    /**  utility method to return the name of the localized file whose
  +     *   name best-matches the Locale passed as an argument
  +     *
  +     *  @param base the directory that is the Document Base for the context
  +     *			in which the 'path' passed is expected to be located
  +     *  @param path the pathname for the file that is being searched for its
  +     *			best-matched Localized version
  +     *  @param loc the requested Locale to match
  +     *
  +     *  @return the name of the file that best-matched the Locale requested
  +     */
  +    public static String getLocalizedFile (String base,
  +					   String path,
  +					   Locale loc) {
  +	
  +	return getLocalizedResource (base, path, loc, true);
  +    }
  +
  +    /**  utility method to get the best-match for getting the Localized
  +     *   version of the file whose 'path' is passed as an argument, using
  +     *   the 'loc' Locale, and performing 'safePath'checks
  +     *
  +     *  The method performs a resource lookup in a manner similar to the
  +     *  one specified by java.util.ResourceBundle.
  +     *
  +     *  In the case of 'typed' files (files whose name is [file].[ftype])
  +     *  search for localized versions of the file are looked for:
  +     *
  +     *   file + "_" + language1 + "_" + country1 + "_" + variant1 + "." + ftype
  +     *   file + "_" + language1 + "_" + country1 + "." + ftype
  +     *   file + "_" + language1 + "." + ftype
  +     *   file + "." + ftype
  +     *
  +     *  Where language1, country1, variant1 are associated with the Locale
  +     *  passed as an argument. 
  +     *
  +     *  For example, if the preferred Locale is <CODE>es_AR_POSIX</CODE>
  +     *  pathname is <CODE>/foo/bar/index.html</CODE>, then a search for
  +     *  the following localized versions of that file will be done, in order:
  +     *<UL>
  +     *<LI>/foo/bar/index_es_AR_POSIX.html</LI>
  +     *<LI>/foo/bar/index_es_AR.html</LI>
  +     *<LI>/foo/bar/index_es_AR.html</LI>
  +     *<LI>/foo/bar/index_es.html</LI>
  +     *</UL>
  +     *
  +     *  @param base the document base for the path passed
  +     *  @param rPath the path to the file relative to the base
  +     *  @param loc the Locale preferred
  +     *  @param safechek perform safePath checks
  +     *
  +     *  @return the name of the file that best-matched the Locale requested
  +     *		null, if no localization matching could be done.
  +     */
  +    public static String getLocalizedResource (String base, String rPath,
  +					       Locale loc, boolean safechek) {
  +
  +	if (null == rPath)
  +	    return null;
  +
  +	String path = (safechek ? safePath (base, rPath) : rPath);
  +
  +	return getLocalizedResource (path, loc);
  +    }
  +
  +    /**  utility method to get the best-match for getting the Localized
  +     *   version of the file whose 'path' is passed as an argument, using
  +     *   the 'loc' Locale, and performing 'safePath'checks
  +     *
  +     *  The method performs a resource lookup in a manner similar to the
  +     *  one specified by java.util.ResourceBundle.
  +     * 
  +     *  See above explanation of lookup order.
  +     *
  +     *  @param path the path to the file 
  +     *  @param loc Locale with which to match.
  +     *
  +     *  @return the name of the file that best-matched the Locale requested
  +     *		null if no Locale match existed. Invokers of the method
  +     *  	need to test whether null is returned, and then decide
  +     *		what to do (whether to default to the original path
  +     *		or not).
  +     */
  +    public static String getLocalizedResource (String path, Locale loc) {
  +
  +	if (null == path)
  +	    return null;
  +
  +	String wPath = null;
  +	String pPath = null;    // parent path
  +	String gpPath = null;   // grand-parent path
  +
  +	String rLang = loc.getLanguage();
  +	String rCoun = loc.getCountry();
  +	String rVar  = loc.getVariant();
  +
  +	int    pathLen   = path.length();
  +	int    lastParen = path.lastIndexOf (File.separator);
  +	int    lastDot   = path.lastIndexOf ('.');
  +
  +	//  evaluate the following conditions
  +	//
  +	//  a. path passed includes the File.separator
  +	//	  the path specified is a 'dotted' file if:
  +	//		lastParen < lastDot
  +	//
  +	//  b. path passed has not File.separator
  +	//	  the path specified is a 'dotted' file if:
  +	//		-1 < lastDot
  +	//
  +	//  c. path is not a dotted file if:
  +	//		-1 == lastDot
  +	//
  +	//
  +	//  'pathBase' is anything to the left of the 'lastDot' position
  +	//  (if 'lastDot' is -1, 'pathBase' is 'path')
  +	//
  +	String pathBase = null;
  +	String dotTail  = null;
  +
  +	if (lastParen < lastDot && lastDot > 0)
  +	{
  +	    pathBase = path.substring (0, lastDot);
  +	    dotTail = path.substring (lastDot);
  +	}
  +	else
  +	    pathBase = path;
  +	    
  +	File file = null;
  +
  +	gpPath = pathBase + '_' + rLang;
  +
  +	//  first, try the language+country+variant match
  +	//
  +	if (null != rCoun && ! ("".equals (rCoun)) ) {
  +
  +	    pPath = gpPath + '_' + rCoun;
  +	    if (null != rVar && ! ("".equals (rVar)) ) {
  +
  +		wPath = pPath + '_' + rVar;
  +
  +		//  append the dotTail if necessary
  +		//
  +		if (null != dotTail)
  +		    wPath += dotTail;
  +
  +		// perform existence test
  +		//
  +		if ((new File(wPath).exists()))
  +		    return wPath;
  +	    }
  +
  +	    //  append the dotTail if necessary
  +	    //
  +	    if (null != dotTail)
  +		pPath += dotTail;
  +
  +	    if ((new File(pPath)).exists())
  +		return pPath;
  +	}
  +
  +	//  append the dotTail if necessary
  +	//
  +	if (null != dotTail)
  +	    gpPath += dotTail;
  +
  +	if ((new File(gpPath)).exists())
  +	    return gpPath;
  +
  +	return null;
       }
  -    
   
   }
  
  
  

Re: cvs commit: jakarta-tomcat/src/share/org/apache/tomcat/util FileUtil.java

Posted by Hans Bergsten <ha...@gefionsoftware.com>.
arieh@locus.apache.org wrote:
> 
> arieh       00/10/10 17:24:46
> 
>   Modified:    src/share/org/apache/tomcat/core Tag: tomcat_32 Context.java
>                src/share/org/apache/tomcat/request Tag: tomcat_32
>                         StaticInterceptor.java
>                src/share/org/apache/tomcat/util Tag: tomcat_32
>                         FileUtil.java
>   Log:
>   Add support for searching for Localized versions of static files.
>   [...]

This looks like a new feature that is not part of the servlet spec. Maybe
I missed the discussion about adding this, but I question if we should
really add new features to the 3.2 branch this late in the game.

We need to get 3.2 release ASAP and IMHO only *critical* bugs should be
fixed at this point (I'm not even sure we should bother with those
anymore).

Hans
-- 
Hans Bergsten		hans@gefionsoftware.com
Gefion Software		http://www.gefionsoftware.com