001: package com.sun.portal.log.common;
002:
003: import java.util.Properties;
004: import java.util.Enumeration;
005: import java.util.Hashtable;
006: import java.util.Vector;
007: import java.io.*;
008:
009: /**
010: * Enhanced Properties implementation to retain the comments in the properties file and
011: * also the sequence of properties in the file
012: */
013: public class EnhancedProperties extends Properties {
014: private static final String specialSaveChars = "=: \t\r\n\f#!";
015: private static final String whiteSpaceChars = " \t\r\n\f";
016: private static final String strictKeyValueSeparators = "=:";
017: private static final String keyValueSeparators = "=: \t\r\n\f";
018: private Hashtable keyToCommentsTable = new Hashtable();
019: private Vector keySequence = new Vector();
020:
021: public EnhancedProperties() {
022: super ();
023: }
024:
025: public EnhancedProperties(Properties props) {
026: super (props);
027: }
028:
029: /**
030: * Overloaded load method. Keeps track of
031: * @param inStream
032: * @throws IOException
033: */
034: public synchronized void load(InputStream inStream)
035: throws IOException {
036: inStream.mark(Integer.MAX_VALUE);
037: super .load(inStream);
038: inStream.reset();
039: BufferedReader in = new BufferedReader(new InputStreamReader(
040: inStream, "8859_1"));
041: StringBuffer prevComments = new StringBuffer();
042: boolean SOF = true;
043: boolean SOFReady = false;
044: while (true) {
045: // Get next line
046: String line = in.readLine();
047: if (line == null) {
048: keyToCommentsTable.put("EOF", prevComments.toString());
049: return;
050: }
051:
052: if (line.length() > 0) {
053:
054: // Find start of key
055: int len = line.length();
056: int keyStart;
057: for (keyStart = 0; keyStart < len; keyStart++)
058: if (whiteSpaceChars.indexOf(line.charAt(keyStart)) == -1)
059: break;
060:
061: // Blank lines are ignored
062: if (keyStart == len) {
063: prevComments.append(line);
064: if (SOF) {
065: SOFReady = true;
066: SOF = false;
067: }
068: continue;
069: }
070:
071: // Continue lines that end in slashes if they are not comments
072: char firstChar = line.charAt(keyStart);
073: if (firstChar == '#' || firstChar == '!') {
074: if (SOFReady) {
075: keyToCommentsTable.put("SOF", prevComments
076: .toString());
077: prevComments = new StringBuffer();
078: SOFReady = false;
079: }
080: prevComments.append(line).append("\n");
081: }
082: if ((firstChar != '#') && (firstChar != '!')) {
083: while (continueLine(line)) {
084: String nextLine = in.readLine();
085: if (nextLine == null)
086: nextLine = "";
087: String loppedLine = line.substring(0, len - 1);
088: // Advance beyond whitespace on new line
089: int startIndex;
090: for (startIndex = 0; startIndex < nextLine
091: .length(); startIndex++)
092: if (whiteSpaceChars.indexOf(nextLine
093: .charAt(startIndex)) == -1)
094: break;
095: nextLine = nextLine.substring(startIndex,
096: nextLine.length());
097: line = new String(loppedLine + nextLine);
098: len = line.length();
099: }
100:
101: // Find separation between key and value
102: int separatorIndex;
103: for (separatorIndex = keyStart; separatorIndex < len; separatorIndex++) {
104: char currentChar = line.charAt(separatorIndex);
105: if (currentChar == '\\')
106: separatorIndex++;
107: else if (keyValueSeparators
108: .indexOf(currentChar) != -1)
109: break;
110: }
111:
112: // Skip over whitespace after key if any
113: int valueIndex;
114: for (valueIndex = separatorIndex; valueIndex < len; valueIndex++)
115: if (whiteSpaceChars.indexOf(line
116: .charAt(valueIndex)) == -1)
117: break;
118:
119: // Skip over one non whitespace key value separators if any
120: if (valueIndex < len)
121: if (strictKeyValueSeparators.indexOf(line
122: .charAt(valueIndex)) != -1)
123: valueIndex++;
124:
125: // Skip over white space after other separators if any
126: while (valueIndex < len) {
127: if (whiteSpaceChars.indexOf(line
128: .charAt(valueIndex)) == -1)
129: break;
130: valueIndex++;
131: }
132: String key = line.substring(keyStart,
133: separatorIndex);
134: String value = (separatorIndex < len) ? line
135: .substring(valueIndex, len) : "";
136:
137: // Convert then store key and value
138: key = loadConvert(key);
139: value = loadConvert(value);
140: put(key, value);
141: keySequence.add(key);
142: keyToCommentsTable
143: .put(key, prevComments.toString());
144: prevComments = new StringBuffer();
145: }
146: } else {
147: prevComments.append(line).append("\n");
148: if (SOF) {
149: SOF = false;
150: SOFReady = true;
151: }
152: }
153: }
154: }
155:
156: public synchronized void store(OutputStream out, String header)
157: throws IOException {
158: BufferedWriter awriter;
159: awriter = new BufferedWriter(new OutputStreamWriter(out,
160: "8859_1"));
161: if (header != null)
162: writeln(awriter, "#" + header);
163: if (keyToCommentsTable.containsKey("SOF"))
164: writeComment(awriter, (String) keyToCommentsTable
165: .get("SOF"));
166: for (int i = 0; i < keySequence.size(); i++) {
167: String key = (String) keySequence.get(i);
168: saveKeyValueWithComment(key, awriter);
169: }
170: for (Enumeration e = keys(); e.hasMoreElements();) {
171: String key = (String) e.nextElement();
172: if (keySequence.contains(key))
173: continue;
174: saveKeyValueWithComment(key, awriter);
175: }
176: writeComment(awriter, (String) keyToCommentsTable.get("EOF"));
177: awriter.flush();
178: }
179:
180: private void saveKeyValueWithComment(String key,
181: BufferedWriter awriter) throws IOException {
182: String val = (String) get(key);
183: if (val != null) {
184: key = saveConvert(key, true);
185:
186: /* No need to escape embedded and trailing spaces for value, hence
187: * pass false to flag.
188: */
189: val = saveConvert(val, false);
190: if (keyToCommentsTable.containsKey(key)) {
191: writeComment(awriter, (String) keyToCommentsTable
192: .get(key));
193: }
194: writeln(awriter, key + "=" + val);
195: }
196:
197: }
198:
199: private static void writeComment(BufferedWriter bw, String s)
200: throws IOException {
201: bw.write(s);
202: }
203:
204: //DO NOT MODIFY ANY CODE BELOW THIS LINE
205: ///////////////////////////////////
206: private static void writeln(BufferedWriter bw, String s)
207: throws IOException {
208: bw.write(s);
209: bw.newLine();
210: }
211:
212: /*
213: * Converts unicodes to encoded \uxxxx
214: * and writes out any of the characters in specialSaveChars
215: * with a preceding slash
216: */
217: private String saveConvert(String theString, boolean escapeSpace) {
218: int len = theString.length();
219: StringBuffer outBuffer = new StringBuffer(len * 2);
220:
221: for (int x = 0; x < len; x++) {
222: char aChar = theString.charAt(x);
223: switch (aChar) {
224: case ' ':
225: if (x == 0 || escapeSpace)
226: outBuffer.append('\\');
227:
228: outBuffer.append(' ');
229: break;
230: case '\\':
231: outBuffer.append('\\');
232: outBuffer.append('\\');
233: break;
234: case '\t':
235: outBuffer.append('\\');
236: outBuffer.append('t');
237: break;
238: case '\n':
239: outBuffer.append('\\');
240: outBuffer.append('n');
241: break;
242: case '\r':
243: outBuffer.append('\\');
244: outBuffer.append('r');
245: break;
246: case '\f':
247: outBuffer.append('\\');
248: outBuffer.append('f');
249: break;
250: default:
251: if ((aChar < 0x0020) || (aChar > 0x007e)) {
252: outBuffer.append('\\');
253: outBuffer.append('u');
254: outBuffer.append(toHex((aChar >> 12) & 0xF));
255: outBuffer.append(toHex((aChar >> 8) & 0xF));
256: outBuffer.append(toHex((aChar >> 4) & 0xF));
257: outBuffer.append(toHex(aChar & 0xF));
258: } else {
259: if (specialSaveChars.indexOf(aChar) != -1)
260: outBuffer.append('\\');
261: outBuffer.append(aChar);
262: }
263: }
264: }
265: return outBuffer.toString();
266: }
267:
268: /**
269: * Convert a nibble to a hex character
270: * @param nibble the nibble to convert.
271: */
272: private static char toHex(int nibble) {
273: return hexDigit[(nibble & 0xF)];
274: }
275:
276: /** A table of hex digits */
277: private static final char[] hexDigit = { '0', '1', '2', '3', '4',
278: '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
279:
280: /*
281: * Returns true if the given line is a line that must
282: * be appended to the next line
283: */
284: private boolean continueLine(String line) {
285: int slashCount = 0;
286: int index = line.length() - 1;
287: while ((index >= 0) && (line.charAt(index--) == '\\'))
288: slashCount++;
289: return (slashCount % 2 == 1);
290: }
291:
292: /*
293: * Converts encoded \uxxxx to unicode chars
294: * and changes special saved chars to their original forms
295: */
296: private String loadConvert(String theString) {
297: char aChar;
298: int len = theString.length();
299: StringBuffer outBuffer = new StringBuffer(len);
300:
301: for (int x = 0; x < len;) {
302: aChar = theString.charAt(x++);
303: if (aChar == '\\') {
304: aChar = theString.charAt(x++);
305: if (aChar == 'u') {
306: // Read the xxxx
307: int value = 0;
308: for (int i = 0; i < 4; i++) {
309: aChar = theString.charAt(x++);
310: switch (aChar) {
311: case '0':
312: case '1':
313: case '2':
314: case '3':
315: case '4':
316: case '5':
317: case '6':
318: case '7':
319: case '8':
320: case '9':
321: value = (value << 4) + aChar - '0';
322: break;
323: case 'a':
324: case 'b':
325: case 'c':
326: case 'd':
327: case 'e':
328: case 'f':
329: value = (value << 4) + 10 + aChar - 'a';
330: break;
331: case 'A':
332: case 'B':
333: case 'C':
334: case 'D':
335: case 'E':
336: case 'F':
337: value = (value << 4) + 10 + aChar - 'A';
338: break;
339: default:
340: throw new IllegalArgumentException(
341: "Malformed \\uxxxx encoding.");
342: }
343: }
344: outBuffer.append((char) value);
345: } else {
346: if (aChar == 't')
347: aChar = '\t';
348: else if (aChar == 'r')
349: aChar = '\r';
350: else if (aChar == 'n')
351: aChar = '\n';
352: else if (aChar == 'f')
353: aChar = '\f';
354: outBuffer.append(aChar);
355: }
356: } else
357: outBuffer.append(aChar);
358: }
359: return outBuffer.toString();
360: }
361:
362: public static void main(String[] args) throws IOException {
363: EnhancedProperties enProp = new EnhancedProperties();
364: enProp.load(new BufferedInputStream(new FileInputStream(
365: new File("e://sandhya//logging//platform1.conf"))));
366: enProp.put("debug.com.sun.portal.kkkk", "gggg");
367: enProp.put("debug.ttt.kkkk", "gggg");
368:
369: enProp.store(new BufferedOutputStream(new FileOutputStream(
370: new File("e://sandhya//logging//platform1.conf"))),
371: null);
372: }
373: }
|