1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 *
19 */
20 package org.apache.mina.util;
21
22 import java.io.IOException;
23 import java.io.LineNumberReader;
24 import java.io.PrintWriter;
25 import java.io.StringReader;
26 import java.io.StringWriter;
27 import java.util.ArrayList;
28
29 /**
30 * Utility class for working with xml data
31 *
32 * Implementation is heavily based on org.apache.log4j.helpers.Transform
33 *
34 * @author <a href="http://mina.apache.org">Apache MINA Project</a>
35 */
36 public class Transform {
37
38 private static final String CDATA_START = "<![CDATA[";
39
40 private static final String CDATA_END = "]]>";
41
42 private static final String CDATA_PSEUDO_END = "]]>";
43
44 private static final String CDATA_EMBEDED_END = CDATA_END + CDATA_PSEUDO_END + CDATA_START;
45
46 private static final int CDATA_END_LEN = CDATA_END.length();
47
48 /**
49 * This method takes a string which may contain HTML tags (ie,
50 * <b>, <table>, etc) and replaces any
51 * '<', '>' , '&' or '"'
52 * characters with respective predefined entity references.
53 *
54 * @param input The text to be converted.
55 * @return The input string with the special characters replaced.
56 * */
57 static public String escapeTags(final String input) {
58 // Check if the string is null, zero length or devoid of special characters
59 // if so, return what was sent in.
60
61 if (input == null
62 || input.length() == 0
63 || (input.indexOf('"') == -1 && input.indexOf('&') == -1 && input.indexOf('<') == -1 && input
64 .indexOf('>') == -1)) {
65 return input;
66 }
67
68 StringBuilder buf = new StringBuilder(input.length() + 6);
69 char ch;
70
71 int len = input.length();
72 for (int i = 0; i < len; i++) {
73 ch = input.charAt(i);
74 if (ch > '>') {
75 buf.append(ch);
76 } else if (ch == '<') {
77 buf.append("<");
78 } else if (ch == '>') {
79 buf.append(">");
80 } else if (ch == '&') {
81 buf.append("&");
82 } else if (ch == '"') {
83 buf.append(""");
84 } else {
85 buf.append(ch);
86 }
87 }
88 return buf.toString();
89 }
90
91 /**
92 * Ensures that embeded CDEnd strings (]]>) are handled properly
93 * within message, NDC and throwable tag text.
94 *
95 * @param buf StringBuffer holding the XML data to this point. The
96 * initial CDStart (<![CDATA[) and final CDEnd (]]>) of the CDATA
97 * section are the responsibility of the calling method.
98 * @param str The String that is inserted into an existing CDATA Section within buf.
99 * */
100 static public void appendEscapingCDATA(final StringBuffer buf, final String str) {
101 if (str != null) {
102 int end = str.indexOf(CDATA_END);
103 if (end < 0) {
104 buf.append(str);
105 } else {
106 int start = 0;
107 while (end > -1) {
108 buf.append(str.substring(start, end));
109 buf.append(CDATA_EMBEDED_END);
110 start = end + CDATA_END_LEN;
111 if (start < str.length()) {
112 end = str.indexOf(CDATA_END, start);
113 } else {
114 return;
115 }
116 }
117 buf.append(str.substring(start));
118 }
119 }
120 }
121
122 /**
123 * convert a Throwable into an array of Strings
124 * @param throwable
125 * @return string representation of the throwable
126 */
127 public static String[] getThrowableStrRep(Throwable throwable) {
128 StringWriter sw = new StringWriter();
129 PrintWriter pw = new PrintWriter(sw);
130 throwable.printStackTrace(pw);
131 pw.flush();
132 LineNumberReader reader = new LineNumberReader(new StringReader(sw.toString()));
133 ArrayList<String> lines = new ArrayList<String>();
134 try {
135 String line = reader.readLine();
136 while (line != null) {
137 lines.add(line);
138 line = reader.readLine();
139 }
140 } catch (IOException ex) {
141 lines.add(ex.toString());
142 }
143 String[] rep = new String[lines.size()];
144 lines.toArray(rep);
145 return rep;
146 }
147
148 }