1:
43:
44: package ;
45:
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51:
52:
57: public class XMLWriterSupport {
58:
59:
60: public static final int OPEN_TAG_INCREASE = 1;
61:
62:
63: public static final int CLOSE_TAG_DECREASE = 2;
64:
65:
66: public static final int INDENT_ONLY = 3;
67:
68:
69: public static final boolean CLOSE = true;
70:
71:
72: public static final boolean OPEN = false;
73:
74:
75: private static String lineSeparator;
76:
77:
78: private SafeTagList safeTags;
79:
80:
81: private int indentLevel;
82:
83:
84: private String indentString;
85:
86:
90: private boolean newLineOk;
91:
92:
96: public XMLWriterSupport() {
97: this(new SafeTagList(), 0);
98: }
99:
100:
106: public XMLWriterSupport(final SafeTagList safeTags, final int indentLevel) {
107: this(safeTags, indentLevel, " ");
108: }
109:
110:
117: public XMLWriterSupport(final SafeTagList safeTags, final int indentLevel,
118: final String indentString) {
119: if (indentString == null) {
120: throw new NullPointerException("IndentString must not be null");
121: }
122:
123: this.safeTags = safeTags;
124: this.indentLevel = indentLevel;
125: this.indentString = indentString;
126: }
127:
128:
133: public void startBlock() throws IOException {
134: this.indentLevel++;
135: allowLineBreak();
136: }
137:
138:
143: public void endBlock() throws IOException {
144: this.indentLevel--;
145: allowLineBreak();
146: }
147:
148:
153: public void allowLineBreak() throws IOException {
154: this.newLineOk = true;
155: }
156:
157:
162: public static String getLineSeparator() {
163: if (lineSeparator == null) {
164: try {
165: lineSeparator = System.getProperty("line.separator", "\n");
166: }
167: catch (SecurityException se) {
168: lineSeparator = "\n";
169: }
170: }
171: return lineSeparator;
172: }
173:
174:
182: public void writeTag(final Writer w, final String name) throws IOException {
183: if (this.newLineOk) {
184: w.write(getLineSeparator());
185: }
186: indent(w, OPEN_TAG_INCREASE);
187:
188: w.write("<");
189: w.write(name);
190: w.write(">");
191: if (getSafeTags().isSafeForOpen(name)) {
192: w.write(getLineSeparator());
193: }
194: }
195:
196:
204: public void writeCloseTag(final Writer w, final String tag)
205: throws IOException {
206:
207: if (this.newLineOk || getSafeTags().isSafeForOpen(tag)) {
208: if (this.newLineOk) {
209: w.write(getLineSeparator());
210: }
211: indent(w, CLOSE_TAG_DECREASE);
212: }
213: else {
214: decreaseIndent();
215: }
216: w.write("</");
217: w.write(tag);
218: w.write(">");
219: if (getSafeTags().isSafeForClose(tag)) {
220: w.write(getLineSeparator());
221: }
222: this.newLineOk = false;
223: }
224:
225:
236: public void writeTag(final Writer w, final String name,
237: final String attributeName, final String attributeValue,
238: final boolean close) throws IOException {
239: final AttributeList attr = new AttributeList();
240: if (attributeName != null) {
241: attr.setAttribute(attributeName, attributeValue);
242: }
243: writeTag(w, name, attr, close);
244: }
245:
246:
257: public void writeTag(final Writer w, final String name,
258: final Properties attributes, final boolean close)
259: throws IOException {
260: final AttributeList attList = new AttributeList();
261: final Enumeration keys = attributes.keys();
262: while (keys.hasMoreElements()) {
263: final String key = (String) keys.nextElement();
264: attList.setAttribute(key, attributes.getProperty(key));
265: }
266: writeTag(w, name, attList, close);
267: }
268:
269:
279: public void writeTag(final Writer w, final String name,
280: final AttributeList attributes, final boolean close)
281: throws IOException {
282:
283: if (this.newLineOk) {
284: w.write(getLineSeparator());
285: this.newLineOk = false;
286: }
287: indent(w, OPEN_TAG_INCREASE);
288:
289: w.write("<");
290: w.write(name);
291: final Iterator keys = attributes.keys();
292: while (keys.hasNext()) {
293: final String key = (String) keys.next();
294: final String value = attributes.getAttribute(key);
295: w.write(" ");
296: w.write(key);
297: w.write("=\"");
298: w.write(normalize(value));
299: w.write("\"");
300: }
301: if (close) {
302: w.write("/>");
303: if (getSafeTags().isSafeForClose(name)) {
304: w.write(getLineSeparator());
305: }
306: decreaseIndent();
307: }
308: else {
309: w.write(">");
310: if (getSafeTags().isSafeForOpen(name)) {
311: w.write(getLineSeparator());
312: }
313: }
314: }
315:
316:
324: public static String normalize(final String s) {
325: if (s == null) {
326: return "";
327: }
328: final StringBuffer str = new StringBuffer();
329: final int len = s.length();
330:
331: for (int i = 0; i < len; i++) {
332: final char ch = s.charAt(i);
333:
334: switch (ch) {
335: case '<':
336: {
337: str.append("<");
338: break;
339: }
340: case '>':
341: {
342: str.append(">");
343: break;
344: }
345: case '&':
346: {
347: str.append("&");
348: break;
349: }
350: case '"':
351: {
352: str.append(""");
353: break;
354: }
355: case '\n':
356: {
357: if (i > 0) {
358: final char lastChar = str.charAt(str.length() - 1);
359:
360: if (lastChar != '\r') {
361: str.append(getLineSeparator());
362: }
363: else {
364: str.append('\n');
365: }
366: }
367: else {
368: str.append(getLineSeparator());
369: }
370: break;
371: }
372: default :
373: {
374: str.append(ch);
375: }
376: }
377: }
378:
379: return (str.toString());
380: }
381:
382:
389: public void indent(final Writer writer, final int increase)
390: throws IOException {
391: if (increase == CLOSE_TAG_DECREASE) {
392: decreaseIndent();
393: }
394: for (int i = 0; i < this.indentLevel; i++) {
395: writer.write(this.indentString);
396:
397:
398: }
399: if (increase == OPEN_TAG_INCREASE) {
400: increaseIndent();
401: }
402: }
403:
404:
409: public int getIndentLevel() {
410: return this.indentLevel;
411: }
412:
413:
416: protected void increaseIndent() {
417: this.indentLevel++;
418: }
419:
420:
423: protected void decreaseIndent() {
424: this.indentLevel--;
425: }
426:
427:
432: public SafeTagList getSafeTags() {
433: return this.safeTags;
434: }
435: }