View Javadoc

1   /*
2   This file is part of the xframe software package
3   hosted at http://xframe.sourceforge.net
4   
5   Copyright (c) 2003 Kurt Riede.
6   
7   This library is free software; you can redistribute it and/or
8   modify it under the terms of the GNU Lesser General Public
9   License as published by the Free Software Foundation; either
10  version 2.1 of the License, or (at your option) any later version.
11  
12  This library is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  Lesser General Public License for more details.
16  
17  You should have received a copy of the GNU Lesser General Public
18  License along with this library; if not, write to the Free Software
19  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
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                  // Note: this should arguably stick in a '/' forward
84                  //  slash character instead of the file separator,
85                  //  since we're effectively assuming it's a hierarchical
86                  //  URI and adding in the abs_path separator -s
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 }