FileLookup.java revision 5c099afa7c9361afc2f4477fec0e3018588d7840
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * The contents of this file are subject to the terms
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * of the Common Development and Distribution License
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * (the License). You may not use this file except in
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * compliance with the License.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * You can obtain a copy of the License at
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * https://opensso.dev.java.net/public/CDDLv1.0.html or
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * See the License for the specific language governing
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * permission and limitations under the License.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * When distributing Covered Code, include this CDDL
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Header Notice in each file and include the License file
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * If applicable, add the following below the CDDL Header,
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * with the fields enclosed by brackets [] replaced by
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * your own identifying information:
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * "Portions Copyrighted [year] [name of copyright owner]"
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * $Id: FileLookup.java,v 1.4 2008/06/25 05:53:05 qcheng Exp $
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport com.sun.identity.common.HttpURLConnectionManager;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * This class provides a generic file path generation utility for
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * data file types, be it template, JSP, or property.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * FileLookup should follow the same look up pattern of the Java
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Resource Bundle Lookup. Failure to do so results in messages in mixed
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * languages. With the Java lookup mechanism, if the platform locale is
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * ja_JP and the Resource Bundle locale is zh_CN, the lookup
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * sequence is rb_zh_CN, rb_zh, rb_JA_JP, rb_ja, rb. We can not fall
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * back to rb if the zh resource bundle is not found. Hence, we have
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * added more steps to file lookup
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private static Debug debug = Debug.getInstance("amFileLookup");
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private static final String NULL_LOCALE = "nullLocale";
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private static int numberOfPlatformLocales = 0;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster platformLocale = java.util.Locale.getDefault().toString();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster numberOfPlatformLocales++; // one for the entire localename
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster numberOfPlatformLocales++; // and one for each variant
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster platformLocales = new String[numberOfPlatformLocales];
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster String thisPartOfStr = frontOfStr.substring(0, idx);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Returns all possible paths for the specified file in an ordered array.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * If all parameters specified are non-null, then the order of the
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * filepaths is generated in the following manner:
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <type>_<locale>/<component>/<clientPath>/<filename>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <type>_<locale>/<component>/<filename>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <type>_<locale>/<component>/<orgPath>/<clientPath>/<filename>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <type>_<locale>/<component>/<orgPath>/<filename>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <type>_<locale>/<clientPath>/<filename>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <type>_<locale>/<filename>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Repeat pattern above, taking off the ending "_xx" portion
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * of the locale. For example, if the original <locale> value
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * was "jp_JP_WIN", then the above would be <type>_jp_JP_WIN.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * The next groups would be <type>_jp_JP and <type>_jp.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * If the platform locale is different from the specified locale,
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * then the pattern for <locale> is repeated with the platform
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * locale, with the addition of using no "_<locale>" (i.e.,
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * the last set consists of "<type>/...").
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Additionally, "default" is used as "<type>", and the above
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * patterns are repeated.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param type The base filepath to begin the search. If null, "default"
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * is the start of the filepath.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param locale The locale for the file of interest.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param component The component part of the filepath, if any.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param orgPath The organization part of the filepath, if any.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param clientPath The client type for that part of the filepath
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param filename The filename of interest
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @throws FileLookupException
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @return <code>File[]</code> of ordered search paths.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster debug.error("FileLookup.getOrderedPaths():Filename was null");
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster throw new FileLookupException("filename is null");
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster debug.message("getting ordered paths for =" + type + "|" + locale
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster + "|" + component + "|" + orgPath + "|" + clientPath + "|"
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster boolean haveType = false;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * probably would be easier to add type = "default" automatically, then
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * we wouldn't have to process it separately later... you get "type" (if
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * it's not null or == "default") and "default"
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * see how many parts to the locale. one part: e.g., "fr"; or two part:
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * e.g., "fr_FR" three part: e.g., "jp_JP_WIN"
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster debug.message("platformLocale is : " + platformLocale);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // locale specified
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster numberOfLocales++; // one for the entire localename
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster indexOfLastUS = frontOfStr.lastIndexOf(UNDERSCORE);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster frontOfStr = frontOfStr.substring(0, indexOfLastUS);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // add one for dummy null locale
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster indexOfLastUS = frontOfStr.lastIndexOf(UNDERSCORE);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // add platform locale to the locale array
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster for (int j = 0; j < numberOfPlatformLocales; j++) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster boolean haveClientPath = false;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if ((clientPath != null) && (clientPath.length() > 0)) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster orderedPathLength = orderedPathLength * (clientkeys.length + 1);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster boolean haveComponent = false;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (component != null && component.length() != 0) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster boolean haveOrgPath = false;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if ((orgPath != null) && (orgPath.length() > 0)) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster orderedPathLength = orderedPathLength * (orgPathKeys.length + 1);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster File[] orderedPaths = new File[orderedPathLength];
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster thisFilePath += (Constants.FILE_SEPARATOR + component);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster orderedPaths[numberOfOrderedPaths++] = new File(
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * no clientPath specified thisFilePath =
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster orderedPaths[numberOfOrderedPaths++] = new File(
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * if orgPath is not null do the following this is used by auth
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster oPath = thisFilePath + Constants.FILE_SEPARATOR + iPath;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster filePath = getClientFilePath(oPath, clientkeys,
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster orderedPaths[numberOfOrderedPaths++] = new File(
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster orderedPaths[numberOfOrderedPaths++] = new File(oPath,
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * have a component, but don't include it. use the clientPath,
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * if specified
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster orderedPaths[numberOfOrderedPaths++] = new File(
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // no component, no orgPath ,no clientkeys
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster thisFilePath = currentFilePath + UNDERSCORE + locales[j];
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster orderedPaths[numberOfOrderedPaths++] = new File(thisFilePath,
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster } // end for (int j = 0; j < numberOfLocales; j++)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster } // end for (int i = 0; i < numberOfTypes; i++)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Return the first existing file in the ordered search paths.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param type An arbitrary profile-stored string
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param locale The locale for the file of interest.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param component The component part of the filepath, if any.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param clientPath The client type for that part of the filepath
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param filename The filename of interest
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param templateDir
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param enableCache
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @return first existing file in the ordered search paths.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @throws FileLookupException
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return getFirstExisting(type, locale, component, null, clientPath,
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Returns the first existing file in the ordered search paths.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param type The base filepath to begin the search.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param locale The locale for the file of interest.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param component The component part of the filepath, if any.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param clientPath The client type for that part of the filepath.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param orgFilePath The organization part of the filepath.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param filename The filename of interest
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param templateDir The base template filepath to prepend.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param enableCache True if the File object is to be cached.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @return first existing file in the ordered search paths.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @throws FileLookupException
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster String tempFile = type + ":" + locale + ":" + component + ":"
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster + orgFilePath + ":" + clientPath + ":" + filename + ":"
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster debug.message("Found existing file=" + tempFile);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster File[] orderedPaths = getOrderedPaths(type, locale, component,
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster debug.message("getFirstExisting:orderedPaths.length = "
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster for (int i = 0; i < orderedPaths.length; i++) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster File file = new File(templateDir, orderedPaths[i].toString());
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster debug.message("returning file=" + file.toString());
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster synchronized (fileTable) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Returns the first existing url found on the remote server. The search is
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * done based on the users locale. If no document is found in the users
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * locale the default locale will be searched.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param server Server where document is located
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param type The base filepath to begin the search.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param locale The locale for the file of interest.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param filename The filename of interest.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @return url of document, or null if no document was found.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @throws FileLookupException
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster debug.message("FileLookup:getFirstExistingRemote");
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster File[] orderedPaths = getOrderedPaths(type, locale, null, null, null,
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster for (int i = 0; i < orderedPaths.length; i++) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // make sure the path starts with a '/'
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster HttpURLConnectionManager.getConnection(handle);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster debug.error("ioexcecption opening the connection", ioerror);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (responseCode == HttpURLConnection.HTTP_OK) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster debug.message("returning remote file = " + document);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster debug.message("could not locate " + filename + " on " + server
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster + "; returning null");
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Build client path based on the client keys.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private static String buildClientPath(String[] keys, int len) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster sb.append(Constants.FILE_SEPARATOR).append(keys[i]);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Tokenize clientPath on "/".
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private static String[] getClientPathKeys(String cp) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster StringTokenizer st = new StringTokenizer(cp, Constants.FILE_SEPARATOR);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private static String[] getOrgPathKeys(String orgPath) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster int k = orgPath.lastIndexOf(Constants.FILE_SEPARATOR);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (k != -1) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster static String getClientFilePath(String currentFilePath,