1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package net.sf.xframe.xsddoc.util;
22
23 import java.io.File;
24
25 import javax.xml.transform.TransformerException;
26
27 import org.apache.xml.utils.URI;
28 import org.apache.xml.utils.URI.MalformedURIException;
29 import org.xml.sax.SAXParseException;
30
31 /***
32 * This class is used to resolve relative URIs and SystemID
33 * strings into absolute URIs.
34 *
35 * <p>This is a generic utility for resolving URIs, other than the
36 * fact that it's declared to throw TransformerException. Please
37 * see code comments for details on how resolution is performed.</p>
38 *
39 * <p>This utility class should be used instead of the original
40 * class <code>org.apache.xml.utils.SystemIDResolver</code> to be independent
41 * of xerces.</p>
42 *
43 * @author <a href="mailto:kriede@users.sourceforge.net">Kurt Riede</a>
44 */
45 public final class XMLUtil {
46
47 /***
48 * Private constructor to prevent instantiation.
49 */
50 private XMLUtil() {
51 }
52
53 /***
54 * Get absolute URI from a given relative URI.
55 *
56 * <p>The URI is resolved relative to the system property "user.dir"
57 * if it is available; if not (i.e. in an Applet perhaps which
58 * throws SecurityException) then it is currently resolved
59 * relative to "" or a blank string. Also replaces all
60 * backslashes with forward slashes.</p>
61 *
62 * @param uri Relative URI to resolve
63 *
64 * @return Resolved absolute URI or the input relative URI if
65 * it could not be resolved.
66 */
67 public static String getAbsoluteURIFromRelative(final String uri) {
68 String result = uri;
69 String curdir = "";
70 try {
71 curdir = System.getProperty("user.dir");
72 } catch (SecurityException se) {
73 curdir = "";
74 }
75 if (null != curdir) {
76 String base;
77 if (curdir.startsWith(File.separator)) {
78 base = "file://" + curdir;
79 } else {
80 base = "file:///" + curdir;
81 }
82 if (result != null) {
83
84
85
86
87 result = base + System.getProperty("file.separator") + uri;
88 } else {
89 result = base + System.getProperty("file.separator");
90 }
91 }
92
93 if (null != result && (result.indexOf('//') > -1)) {
94 result = result.replace('//', '/');
95 }
96 return result;
97 }
98
99 /***
100 * Take a SystemID string and try and turn it into a good absolute URL.
101 *
102 * @param url A URL string, which may be relative or absolute.
103 *
104 * @return The resolved absolute URI
105 */
106 public static String getAbsoluteURI(final String url) {
107 if (url.startsWith("..")) {
108 return new File(url).getAbsolutePath();
109 }
110 if (url.startsWith(File.separator)) {
111 return "file://" + url;
112 } else if (url.indexOf(':') < 0) {
113 return getAbsoluteURIFromRelative(url);
114 }
115 return url;
116 }
117
118 /***
119 * Take a SystemID string and try and turn it into a good absolute URL.
120 *
121 * @param urlString SystemID string
122 * @param base Base URI to use to resolve the given systemID
123 *
124 * @return The resolved absolute URI
125 * @throws TransformerException thrown if the string can't be turned into a URL.
126 */
127 public static String getAbsoluteURI(final String urlString, final String base) throws TransformerException {
128 String theUrlString = urlString;
129 String theBase = base;
130 boolean isAbsouteUrl = false;
131 boolean needToResolve = false;
132 if (theUrlString.indexOf(':') > 0) {
133 isAbsouteUrl = true;
134 } else if (theUrlString.startsWith(File.separator)) {
135 theUrlString = "file://" + theUrlString;
136 isAbsouteUrl = true;
137 }
138 if ((!isAbsouteUrl) && ((null == theBase) || (theBase.indexOf(':') < 0))) {
139 if (theBase != null && theBase.startsWith(File.separator)) {
140 theBase = "file://" + theBase;
141 } else {
142 theBase = getAbsoluteURIFromRelative(theBase);
143 }
144 }
145 if ((null != theBase) && needToResolve) {
146 if (theBase.equals(theUrlString)) {
147 theBase = "";
148 } else {
149 final int protcolLength = theBase.indexOf(':') + 1;
150 theUrlString = theUrlString.substring(protcolLength);
151 isAbsouteUrl = false;
152 }
153 }
154 if (null != theBase && (theBase.indexOf('//') > -1)) {
155 theBase = theBase.replace('//', '/');
156 }
157 if (null != theUrlString && (theUrlString.indexOf('//') > -1)) {
158 theUrlString = theUrlString.replace('//', '/');
159 }
160 final URI uri;
161 try {
162 if ((null == theBase) || (theBase.length() == 0) || (isAbsouteUrl)) {
163 uri = new URI(theUrlString);
164 } else {
165 URI baseURI = new URI(theBase);
166
167 uri = new URI(baseURI, theUrlString);
168 }
169 } catch (MalformedURIException mue) {
170 throw new TransformerException(mue);
171 }
172
173 String uriStr = uri.toString();
174
175 if ((Character.isLetter(uriStr.charAt(0))
176 && (uriStr.charAt(1) == ':')
177 && (uriStr.charAt(2) == '/')
178 && (uriStr.length() == 3 || uriStr.charAt(3) != '/'))
179 || ((uriStr.charAt(0) == '/') && (uriStr.length() == 1 || uriStr.charAt(1) != '/'))) {
180 uriStr = "file:///" + uriStr;
181 }
182 return uriStr;
183 }
184
185 /***
186 * Get the localized error message of a TransformerException with location
187 * information appended.
188 *
189 * @param e the exception
190 * @return A <code>String</code> representing the error message with
191 * location information appended.
192 */
193 public static String getLocallizedMessageAndLocation(final TransformerException e) {
194 String systemID = null;
195 int line = 0;
196 int column = 0;
197 if (null != e.getLocator()) {
198 systemID = e.getLocator().getSystemId();
199 line = e.getLocator().getLineNumber();
200 column = e.getLocator().getColumnNumber();
201 }
202 final String message = e.getLocalizedMessage();
203 return formaLocallizedMessageAndLocation(systemID, line, column, message);
204 }
205
206 /***
207 * Formats the systemId, column and row into to a String.
208 *
209 * @param e the exception
210 * @return formatted location
211 */
212 public static String getLocallizedMessageAndLocation(final SAXParseException e) {
213 final String systemID = e.getSystemId();
214 final int line = e.getLineNumber();
215 final int column = e.getColumnNumber();
216 final String message = e.getLocalizedMessage();
217 return formaLocallizedMessageAndLocation(systemID, line, column, message);
218 }
219
220 /***
221 * Formats a message and a location into a locallized string.
222 *
223 * @param systemID the systemID of the file (optional)
224 * @param line the line number within the file (optional)
225 * @param column the column number within the file (optional)
226 * @param message the message
227 * @return a locallized message string with location
228 */
229 private static String formaLocallizedMessageAndLocation(final String systemID,
230 final int line, final int column, final String message) {
231 final StringBuffer sbuffer = new StringBuffer();
232 if (null != systemID) {
233 sbuffer.append(systemID);
234 }
235 if (0 != line) {
236 sbuffer.append(":").append(line);
237 }
238 if (0 != column) {
239 sbuffer.append(":").append(column);
240 }
241 if (null != message) {
242 sbuffer.append(" ").append(message);
243 }
244 return sbuffer.toString();
245 }
246 }