001: package com.sun.portal.desktop.template;
002:
003: import java.util.Hashtable;
004: import java.text.MessageFormat;
005: import java.util.Properties;
006:
007: import java.io.File;
008: import java.io.FileInputStream;
009: import javax.servlet.http.HttpServletRequest;
010:
011: import com.sun.portal.providers.context.ContainerProviderContext;
012: import com.sun.portal.providers.context.ProviderContextException;
013:
014: import com.sun.portal.desktop.DesktopError;
015: import com.sun.portal.desktop.DesktopRequestThreadLocalizer;
016: import com.sun.portal.desktop.context.DesktopAppContextThreadLocalizer;
017: import com.sun.portal.desktop.context.DesktopAppContext;
018: import com.sun.portal.desktop.util.NSStringBuffer;
019:
020: /**
021: * <P>Resolves tag references for template files.
022: *
023: * <P>For instance:
024: *
025: * <P><CODE><PRE>
026: * Hashtable tagTable = new Hashtable();
027: * StringBuffer result = new StringBuffer();
028: *
029: * tagTable.put("firstName", "Charlie");
030: * tagTable.put("lastName", "Brown");
031: *
032: * result = TagSwapper.doSwap(session, getTemplate("display.template"), tagTable);
033: * </PRE></CODE>
034: *
035: * <P>Assuming the template file <CODE>display.template</CODE>
036: * looks like this:
037: *
038: * <P><CODE><PRE>
039: * <B><I>Welcome [tag:fullName] [tag:lastName] !</I></B>
040: * </PRE></CODE>
041: *
042: * <P>then the tag swapper will resolve as so:
043: *
044: * <P><CODE><PRE>
045: * <B><I>Welcome Charlie Brown !</I></B>
046: * </PRE></CODE>
047: *
048: * <P><B>NOTE:</B> This class is <B>NOT</B> part of the public
049: * API and therefore is subject to change; <U>use at your own
050: * risk.</U>
051: */
052:
053: public class TagSwapper {
054:
055: /**
056: * <P>Resolves tag references for the template.
057: *
058: * <P>For the template, each <CODE>[tag:<I>key</I>]</CODE> is resolved
059: * to the string value mapped to by the key in the hashtable. The
060: * form of the hashtable is keys as strings and values as objects
061: * that will be resolved using <CODE>toString()</CODE>. Thus the
062: * objects inserted in the hashtable must implement <CODE>toString</CODE>.
063: *
064: * <P>If the key is not found in the hashtable, an attempt is made
065: * to resolve the key as an property from the provider context. And if
066: * still not found, try to find it as an string attribute from the provider
067: * context. If the key is not resolved from the provider context, an
068: * error is logged in the desktop debug file, and the tag won't be replaced
069: * in the template.
070: *
071: * <P>Tags are recursively resolved. For example, if the hashtable
072: * defines:
073: * <CODE><UL>
074: * <li>fullName=[tag:firstName] [tag:lastName]
075: * <li>firstName=Charlie
076: * <li>lastName=Brown
077: * </UL></CODE>
078: * and the template specified contains
079: * <CODE>[tag:fullName]</CODE> the method will resolve it to
080: * <CODE>Charlie Brown</CODE>
081: *
082: * @deprecated This method has been deprecated. Use doSwapFromParsedTagArray() to
083: * perform tag swapping in the future.
084: *
085: * @param inBuffer the template
086: * @param aTagTable the hashtable with keys as tag names (strings)
087: * @param sContent the static content path, which defines the static content (e.g., images) directory
088: * @param channel Channel name, used to read properties through the
089: * <code>ContainerProviderContext</code> object.
090: * @param pc the ContainerProviderContext object
091: * @return resolved output
092: */
093:
094: private static String propertiesfile = "message.properties";
095: private static DesktopAppContext dac = null;
096: static {
097: dac = DesktopAppContextThreadLocalizer.get();
098: }
099:
100: public static StringBuffer doSwap(StringBuffer inBuffer,
101: Hashtable aTagTable, String sContent, String channel,
102: ContainerProviderContext pc) {
103:
104: //
105: // Make sure these are ok to access
106: //
107: if (inBuffer == null) {
108: return inBuffer;
109: }
110:
111: Properties p = new Properties();
112: FileInputStream propFile = null;
113: try {
114: File message = pc.getTemplatePath(channel, propertiesfile);
115: String messageFile = message.getPath();
116: propFile = new FileInputStream(messageFile);
117: p.load(propFile);
118: } catch (ProviderContextException pce) {
119: return null;
120: } catch (java.lang.Exception ex) {
121: return null;
122: } finally {
123: try {
124: if (propFile != null) {
125: propFile.close();
126: }
127: } catch (java.io.IOException ex) {
128: return null;
129: }
130: }
131:
132: // create a parsed tag array on the fly
133: ParsedTagArray pta = new ParsedTagArray(inBuffer);
134: return doSwapFromParsedTagArray(pta, pc, channel, sContent,
135: aTagTable, p);
136: }
137:
138: /*
139: * this method looks up the key in the provider context properties.If key
140: * exists, then it returns the value, otherwise it will return
141: * null.
142: */
143:
144: private static String getPropertyValue(String channel,
145: ContainerProviderContext pc, String key) {
146: if (!pc.existsChannel(channel)) {
147: return null;
148: }
149:
150: try {
151: if (!pc.existsStringProperty(channel, key)) {
152: return null;
153: }
154:
155: String value = pc.getStringProperty(channel, key);
156: return value;
157: } catch (ProviderContextException pce) {
158: //pc.debugError( "TagSwapper.getPropertyValue(): channel " + channel + " key " + key, pce );
159: return null;
160: }
161: }
162:
163: /*
164: * this method looks up the key in the provider context attributes.If key
165: * exists, then it returns the value, otherwise it will log an error and
166: * return null.
167: */
168:
169: private static String getAttributeValue(
170: ContainerProviderContext pc, String key) {
171: String value = pc.getStringAttribute(key);
172: return value;
173: }
174:
175: public static StringBuffer doSwapFromParsedTagArray(
176: ParsedTagArray pta, ContainerProviderContext pc,
177: String channel, String sContent, Hashtable aTagTable,
178: Properties p) {
179:
180: if (pta == null) {
181: return null;
182: }
183:
184: if (aTagTable == null) {
185: return pta.getTemplateSB();
186: }
187:
188: StringBuffer outBuffer = new StringBuffer(pta.getStaticLength()
189: + (pta.getNumberTags() * 100));
190:
191: int numpte = pta.size();
192: if (numpte == 0) {
193: return outBuffer;
194: }
195:
196: String dtURL = null;
197:
198: for (int i = 0; i < numpte; i++) {
199: ParsedTagElement pte = pta.get(i);
200: String key = pte.getKey();
201: doTags(pc, channel, sContent, aTagTable, pte, key,
202: outBuffer, dtURL, p);
203: }
204: return outBuffer;
205: }
206:
207: /*
208: * This method do the actual swapping based on the tag type.
209: * Note that this method is recursively called if a default
210: * element is defined in the target <code>ParsedTagElemtn</code>
211: */
212: private static void doTags(ContainerProviderContext pc,
213: String channel, String sContent, Hashtable aTagTable,
214: ParsedTagElement pte, String key, StringBuffer outBuffer,
215: String dtURL, Properties p) {
216:
217: switch (pte.getType()) {
218: case ParsedTagElement.STRING:
219: outBuffer.append(key);
220: break;
221: case ParsedTagElement.TAG:
222: Object value = aTagTable.get(key);
223:
224: // using default value if value is null,
225: // the default value is defined inside
226: // another tag.
227: // the format of using a default tag is:
228: // [dtag:key[another tag:key]
229: // where another tag can be any of the tags:
230: // tag, surl, url, or dturl
231: if (value == null && pte.getDefault() != null) {
232: ParsedTagElement dElement = pte.getDefault();
233: doTags(pc, channel, sContent, aTagTable, dElement,
234: dElement.getKey(), outBuffer, dtURL, p);
235: }
236:
237: if ((value == null) && (pc != null)) {
238: //
239: // Not in tag table, try to get from provider context properties
240: //
241: value = getPropertyValue(channel, pc, key);
242: }
243:
244: if ((value == null) && (pc != null)) {
245: //
246: // Not in tag table, try to get from provider context attributes
247: //
248: value = getAttributeValue(pc, key);
249: }
250: //
251: // Allow any sort of object to be passed in the hashtable
252: //
253: if (value != null) {
254: String valueStr = value.toString();
255: if (value instanceof NSStringBuffer) {
256: outBuffer.append(valueStr);
257: } else {
258: StringBuffer tagValue = new StringBuffer(valueStr);
259: outBuffer.append(doSwapFromParsedTagArray(
260: new ParsedTagArray(tagValue), pc, channel,
261: sContent, aTagTable, p));
262: }
263: } else {
264: /*
265: if( pc.isDebugWarningEnabled() ) {
266: pc.debugWarning( "TagSwapper.doSwapFromParsedTagArray(): tag value unavailable: " + key );
267: }
268: */
269: }
270: break;
271: case ParsedTagElement.URL:
272: String encodedURL = null;
273: if (pc != null) {
274: encodedURL = pc.encodeURL(key);
275: } else {
276: encodedURL = key;
277: }
278: outBuffer.append(encodedURL);
279: break;
280: case ParsedTagElement.SURL:
281: outBuffer.append(sContent);
282: outBuffer.append(key);
283: break;
284: case ParsedTagElement.DTURL:
285: if (dtURL == null) {
286: HttpServletRequest req = DesktopRequestThreadLocalizer
287: .getRequest();
288: if (pc != null) {
289: dtURL = pc.getDesktopURL(req);
290: } else {
291: dtURL = dac.getDesktopURL(req);
292: }
293: }
294: outBuffer.append(dtURL);
295:
296: break;
297: case ParsedTagElement.MSG:
298: //Insert the localized message by reading from properties file.
299: //The first argument after msg determines the key used for
300: //retrieving the message from the properties file. The arguments
301: //following this will be tag keys which will get resolved and
302: //the tag values will be used to format the message
303:
304: String[] pat = key.split(":");
305: //If message.properties file is not present output the key
306: if (p == null) {
307: outBuffer.append(key);
308: } else if (pat.length == 1) {
309: String val = p.getProperty(pat[0]);
310: if (val == null) {
311: outBuffer.append(pat[0]);
312: } else {
313: outBuffer.append(val);
314: }
315: } else if (pat.length > 1) {
316: String rbKey = pat[0];
317: String[] formatVal = new String[pat.length - 1];
318: String msgFormat = p.getProperty(rbKey);
319: //If message not found in message.properties file then output the key
320: if (msgFormat == null) {
321: outBuffer.append(rbKey);
322: } else {
323: for (int i = 1; i < pat.length; i++) {
324: formatVal[i - 1] = getTagAttribute(pc, channel,
325: sContent, aTagTable, pte, pat[i], p);
326: }
327: MessageFormat mf = new MessageFormat(msgFormat);
328: outBuffer.append(mf.format(formatVal));
329: }
330: }
331: break;
332: default:
333: throw new DesktopError(
334: "TagSwapper.doSwapFromParsedTagArray(): invalid ParsedTagElement type");
335: }
336: }
337:
338: static private String getTagAttribute(ContainerProviderContext pc,
339: String channel, String sContent, Hashtable aTagTable,
340: ParsedTagElement pte, String key, Properties p) {
341:
342: Object value = aTagTable.get(key);
343:
344: if ((value == null) && (pc != null)) {
345: //
346: // Not in tag table, try to get from provider context properties
347: //
348: value = getPropertyValue(channel, pc, key);
349: }
350:
351: if ((value == null) && (pc != null)) {
352: //
353: // Not in tag table, try to get from provider context attributes
354: //
355: value = getAttributeValue(pc, key);
356: }
357: //
358: // Allow any sort of object to be passed in the hashtable
359: //
360: if (value != null) {
361: String valueStr = value.toString();
362: if (value instanceof NSStringBuffer) {
363: return (valueStr);
364: } else {
365: StringBuffer tagValue = new StringBuffer(valueStr);
366: return doSwapFromParsedTagArray(
367: new ParsedTagArray(tagValue), pc, channel,
368: sContent, aTagTable, p).toString();
369: }
370: } else {
371: /*if( pc.isDebugWarningEnabled() ) {
372: pc.debugWarning( "TagSwapper.doSwapFromParsedTagArray(): tag value unavailable: " + key );
373: }*/
374: }
375: return null;
376: }
377:
378: }
|