001: /**
002: * $Id: FileLookup.java,v 1.15 2006/07/28 02:32:38 portalbld Exp $
003: * Copyright 2002 Sun Microsystems, Inc. All
004: * rights reserved. Use of this product is subject
005: * to license terms. Federal Acquisitions:
006: * Commercial Software -- Government Users
007: * Subject to Standard License Terms and
008: * Conditions.
009: *
010: * Sun, Sun Microsystems, the Sun logo, and Sun ONE
011: * are trademarks or registered trademarks of Sun Microsystems,
012: * Inc. in the United States and other countries.
013: */package com.sun.portal.desktop.util;
014:
015: import java.util.*;
016: import java.io.*;
017:
018: import com.sun.portal.desktop.DesktopError;
019:
020: import com.sun.portal.desktop.context.DesktopAppContext;
021: import com.sun.portal.desktop.context.DesktopAppContextThreadLocalizer;
022:
023: /**
024: * This class provides a generic file path generation utility
025: * for all portal data file types, be they templates, JSP.
026: * All portal code interested in accessing data files would use
027: * this utility to locate them on disk.
028: */
029: public class FileLookup {
030:
031: private static final String UNDERSCORE = "_";
032: private static final String NULL_LOCALE = "nullLocale";
033:
034: private static Map paths = Collections
035: .synchronizedMap(new HashMap());
036:
037: private static File[] getCachedPaths(String base, String type,
038: String locale, String app, String provider,
039: String clientPath, String file) {
040: Map types = (Map) paths.get(base);
041: if (types == null) {
042: return null;
043: }
044: Map locales = (Map) types.get(type);
045: if (locales == null) {
046: return null;
047: }
048: Map apps = (Map) locales.get(locale);
049: if (apps == null) {
050: return null;
051: }
052: Map providers = (Map) apps.get(app);
053: if (providers == null) {
054: return null;
055: }
056: Map clientPaths = (Map) providers.get(provider);
057: if (clientPaths == null) {
058: return null;
059: }
060: Map files = (Map) clientPaths.get(clientPath);
061: if (files == null) {
062: return null;
063: }
064:
065: File[] fs = (File[]) files.get(file);
066:
067: return fs;
068: }
069:
070: private static void putCachedPaths(String base, String type,
071: String locale, String app, String provider,
072: String clientPath, String file, File[] fs) {
073: Map types = (Map) paths.get(base);
074: if (types == null) {
075: types = new HashMap();
076: paths.put(base, types);
077: }
078: Map locales = (Map) types.get(type);
079: if (locales == null) {
080: locales = new HashMap();
081: types.put(type, locales);
082: }
083: Map apps = (Map) locales.get(locale);
084: if (apps == null) {
085: apps = new HashMap();
086: locales.put(locale, apps);
087: }
088: Map providers = (Map) apps.get(app);
089: if (providers == null) {
090: providers = new HashMap();
091: apps.put(app, providers);
092: }
093: Map clientPaths = (Map) providers.get(provider);
094: if (clientPaths == null) {
095: clientPaths = new HashMap();
096: providers.put(provider, clientPaths);
097: }
098: Map files = (Map) clientPaths.get(clientPath);
099: if (files == null) {
100: files = new HashMap();
101: clientPaths.put(clientPath, files);
102: }
103:
104: files.put(file, fs);
105: }
106:
107: /**
108: * The getOrderedPaths() method will return the full search order for a file;
109: * all possible paths for the file, ordered.
110: * @param base
111: * @param type (an arbitrary profile-stored string)
112: * @param locale
113: * @param channel
114: * @param provider
115: * @param clientPath
116: * @param filename
117: * @return <code>File[]</code> of ordered search paths.
118: */
119: protected static File[] getOrderedPaths(String base, String type,
120: String locale, String channel, String provider,
121: String clientPath, String filename) {
122: File[] files = getCachedPaths(base, type, locale, channel,
123: provider, clientPath, filename);
124: if (files == null) {
125: files = buildPaths(base, type, locale, channel, provider,
126: clientPath, filename);
127: putCachedPaths(base, type, locale, channel, provider,
128: clientPath, filename, files);
129: }
130: return files;
131: }
132:
133: private static List split(String type, String separator) {
134: List tl = null;
135:
136: if (type != null) {
137: String typeStr = type.trim();
138: StringTokenizer st = new StringTokenizer(typeStr, separator);
139: int numberOfTokens = st.countTokens();
140: if (numberOfTokens > 0) {
141: tl = new ArrayList(numberOfTokens);
142: while (st.hasMoreTokens()) {
143: String next = st.nextToken().trim();
144: tl.add(next);
145: }
146: }
147: } else {
148: tl = new ArrayList();
149: }
150:
151: return tl;
152: }
153:
154: protected static File[] buildPaths(String base, String type,
155: String locale, String channel, String provider,
156: String clientPath, String filename) {
157:
158: if (filename == null) {
159: throw new DesktopError(
160: "FileLookup.getOrderedPaths(): file was null");
161: }
162:
163: String types[] = null;
164: int numberOfTypes = 1;
165: int numberOfTokens = 0;
166: int orderedPathLength;
167: StringTokenizer st = null;
168:
169: //
170: // type string is a list of types, e.g., "sampleportal,
171: // foo", or "default, foo", the type list is separated by commas.
172: // if the type list does not include "default", then we'll put
173: // default in the last in the types array. So "foo,sampleportal"
174: // will have types[0] = "foo", types[1] = "sampleportal",
175: // types[3] = "default". And "foo,default" will have types[0]
176: // = "foo", types[1] = "default". If type string is null, the
177: // types[0] = "default".
178: //
179:
180: List typeList = split(type, ",");
181: if (typeList.size() == 0 || !typeList.contains("default")) {
182: typeList.add("default");
183: }
184: orderedPathLength = typeList.size();
185: numberOfTypes = orderedPathLength;
186: types = new String[orderedPathLength];
187: types = (String[]) typeList.toArray(types);
188:
189: //
190: // see how many parts to the locale. one part: e.g., "fr"; or two part: e.g., "fr_FR"
191: // three part: e.g., "jp_JP_WIN"
192: //
193: int numberOfLocales = 0;
194: int indexOfLastUS = 0;
195: String locales[] = null;
196:
197: if (locale != null && locale.length() != 0) { // locale specified
198:
199: numberOfLocales++; // one for the entire localename
200: String frontOfStr = locale;
201: while (indexOfLastUS != -1) {
202: indexOfLastUS = frontOfStr.lastIndexOf(UNDERSCORE);
203: if (indexOfLastUS != -1) {
204: frontOfStr = frontOfStr.substring(0, indexOfLastUS);
205: numberOfLocales++; // and one for each variant
206: }
207: }
208:
209: frontOfStr = locale;
210: locales = new String[numberOfLocales + 1]; // one for the dummy "nullLocale"
211: locales[0] = locale;
212: indexOfLastUS = 0;
213: int i = 1;
214:
215: while (indexOfLastUS != -1) {
216: indexOfLastUS = frontOfStr.lastIndexOf(UNDERSCORE);
217: if (indexOfLastUS != -1) {
218: String this PartOfStr = frontOfStr.substring(0,
219: indexOfLastUS);
220: locales[i++] = this PartOfStr;
221: frontOfStr = this PartOfStr;
222: }
223: }
224:
225: //
226: // dummy "null" locale so it'll get processed below
227: //
228:
229: locales[i++] = NULL_LOCALE;
230: numberOfLocales++;
231:
232: if (numberOfLocales > 1) {
233: orderedPathLength *= numberOfLocales;
234: }
235:
236: } else {
237: locales = new String[1];
238: locales[numberOfLocales++] = NULL_LOCALE;
239: } // end if (locale != null && locale.length() != 0)
240:
241: boolean haveClientPath = false;
242: String[] clientkeys = null;
243:
244: if ((clientPath != null) && (clientPath.length() > 0)) {
245: clientkeys = getClientPathKeys(clientPath);
246: orderedPathLength = orderedPathLength
247: * (clientkeys.length + 1); // this stays
248: haveClientPath = true;
249: }
250:
251: boolean haveChannel = false;
252:
253: int tempPathLength = orderedPathLength;
254:
255: if (channel != null && channel.length() != 0) {
256: haveChannel = true;
257: orderedPathLength *= 2;
258: }
259:
260: boolean haveProvider = false;
261:
262: if (provider != null && provider.length() != 0) {
263: haveProvider = true;
264: if (haveChannel) {
265: orderedPathLength += tempPathLength;
266: } else {
267: orderedPathLength *= 2;
268: }
269: }
270:
271: //
272: // for the root entry
273: //
274: orderedPathLength++;
275:
276: File[] orderedPaths = new File[orderedPathLength];
277:
278: String this FileName = "";
279:
280: int numberOfOrderedPaths = 0;
281:
282: for (int i = 0; i < numberOfTypes; i++) {
283: String currentFilePath = base + "/" + types[i];
284: for (int j = 0; j < numberOfLocales; j++) {
285: String this FilePath = null;
286: if (locales[j].equals(NULL_LOCALE)) {
287: this FilePath = currentFilePath;
288: } else {
289: this FilePath = currentFilePath
290: + (UNDERSCORE + locales[j]);
291: }
292:
293: if (haveClientPath) {
294: int len = clientkeys.length;
295: while (len > 0) {
296: String filePath;
297: if (haveChannel) {
298: filePath = this FilePath + "/" + channel
299: + buildClientPath(clientkeys, len);
300: addPath(orderedPaths,
301: numberOfOrderedPaths++, filePath,
302: filename);
303: }
304: if (haveProvider) {
305: filePath = this FilePath + "/" + provider
306: + buildClientPath(clientkeys, len);
307: addPath(orderedPaths,
308: numberOfOrderedPaths++, filePath,
309: filename);
310: }
311:
312: len--;
313: }
314: //
315: // no clientPath specified
316: // thisFilePath = path_locale/component
317: //
318: if (haveChannel) {
319: String channelFilePath = this FilePath + "/"
320: + channel;
321: addPath(orderedPaths, numberOfOrderedPaths++,
322: channelFilePath, filename);
323: }
324:
325: if (haveProvider) {
326: String providerFilePath = this FilePath + "/"
327: + provider;
328: addPath(orderedPaths, numberOfOrderedPaths++,
329: providerFilePath, filename);
330: }
331: } // if (haveComponent)
332:
333: if (haveClientPath) {
334: int len = clientkeys.length;
335: while (len > 0) {
336: if (locales[j].equals(NULL_LOCALE)) {
337: this FilePath = currentFilePath;
338: } else {
339: this FilePath = currentFilePath + UNDERSCORE
340: + locales[j];
341: }
342:
343: String filePath = this FilePath
344: + buildClientPath(clientkeys, len);
345: addPath(orderedPaths, numberOfOrderedPaths++,
346: filePath, filename);
347:
348: len--;
349: }
350: } // if (haveClientPath)
351:
352: //
353: // no component, no clientkeys
354: //
355:
356: if (!locales[j].equals(NULL_LOCALE)) {
357: this FilePath = currentFilePath + UNDERSCORE
358: + locales[j];
359: } else {
360: this FilePath = currentFilePath;
361: }
362:
363: addPath(orderedPaths, numberOfOrderedPaths++,
364: this FilePath, filename);
365: } // for (int j = 0; j < numberOfLocales; j++)
366: } // end for (int i = 0; i < numberOfTypes; i++)
367:
368: //
369: // root entry
370: //
371: addPath(orderedPaths, numberOfOrderedPaths++, base, filename);
372:
373: return orderedPaths;
374: }
375:
376: private static void addPath(File[] files, int index, String path,
377: String file) {
378: File f = new File(path, file);
379: files[index] = f;
380: }
381:
382: /**
383: * The getFirstExisting() method will return the first existing file
384: * in the ordered search paths.
385: * @param base (base directory of the ps document root)
386: * @param type (an arbitrary profile-stored string)
387: * @param locale
388: * @param channel
389: * @param provider
390: * @param clientPath
391: * @param filename
392: * @return <code>File</code> first existing file in the ordered search paths.
393: */
394: public static File getFirstExisting(String base, String type,
395: String locale, String channel, String provider,
396: String clientPath, String filename) {
397: File[] files = getOrderedPaths(base, type, locale, channel,
398: provider, clientPath, filename);
399: for (int i = 0; i < files.length; i++) {
400: if (files[i].exists()) {
401: return files[i];
402: }
403: }
404:
405: return null;
406: }
407:
408: /**
409: * The getMostSpecificFile() method will return the first file
410: * in the ordered search paths (whether exists or not).
411: * @param base (base directory of the ps document root)
412: * @param type (an arbitrary profile-stored string)
413: * @param locale
414: * @param channel
415: * @param provider
416: * @param clientPath
417: * @param filename
418: * @return <code>File</code> first file in the ordered search paths.
419: */
420: public static File getMostSpecific(String base, String type,
421: String locale, String channel, String provider,
422: String clientPath, String filename) {
423: File[] files = getOrderedPaths(base, type, locale, channel,
424: provider, clientPath, filename);
425: return files[0];
426: }
427:
428: //build client path based on the client keys.
429: private static String buildClientPath(String[] keys, int len) {
430: StringBuffer sb = new StringBuffer();
431: for (int i = 0; i < len; i++) {
432: sb.append("/").append(keys[i]);
433: }
434: return sb.toString();
435: }
436:
437: //tokenize clientPath on File.separator.
438: private static String[] getClientPathKeys(String cp) {
439: StringTokenizer st = new StringTokenizer(cp, "/");
440: int numTokens = st.countTokens();
441: String[] keyArray = new String[numTokens];
442: for (int i = 0; i < numTokens; i++) {
443: keyArray[i] = st.nextToken();
444: }
445: return keyArray;
446: }
447:
448: private static String toString(File[] files) {
449: String s = "[";
450:
451: for (int i = 0; i < files.length; i++) {
452: if (files[i] == null) {
453: s += "<null>";
454: } else {
455: s += files[i].toString();
456: }
457:
458: if (i < files.length - 1) {
459: s += ", ";
460: }
461: }
462:
463: s += "]";
464:
465: return s;
466: }
467:
468: private static void logFiles(File[] files) {
469: String f = toString(files);
470: log("FileLookup.logFiles(): f=" + f);
471: }
472:
473: private static void log(String msg) {
474: if (DesktopAppContextThreadLocalizer.exists()) {
475: DesktopAppContext dac = DesktopAppContextThreadLocalizer
476: .get();
477: //dac.debugError(msg);
478: }
479: }
480: }
|