KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > xml > XMLBaseSupport


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.cocoon.xml;
17
18 import org.xml.sax.Attributes JavaDoc;
19 import org.xml.sax.SAXException JavaDoc;
20 import org.apache.excalibur.source.SourceResolver;
21 import org.apache.excalibur.source.Source;
22 import org.apache.avalon.framework.logger.Logger;
23
24 import java.util.Stack JavaDoc;
25 import java.util.Collections JavaDoc;
26 import java.io.IOException JavaDoc;
27
28 /**
29  * Helper class for handling xml:base attributes.
30  *
31  * <p>Usage:
32  * <ul>
33  * <li>set location of the containing document by calling {@link #setDocumentLocation(String)}.
34  * This is usually done when getting setDocumentLocator SAX event.
35  * <li>forward each startElement and endElement event to this object.
36  * <li>to resolve a relative URL against the current base, call {@link #makeAbsolute(String)}.
37  * </ul>
38  *
39  * <p>External entities are not yet taken into account when determing the current base.
40  */

41 public class XMLBaseSupport {
42     public static final String JavaDoc XMLBASE_NAMESPACE_URI = "http://www.w3.org/XML/1998/namespace";
43     public static final String JavaDoc XMLBASE_ATTRIBUTE = "base";
44
45     /** Increased on each startElement, decreased on each endElement. */
46     private int level = 0;
47     /**
48      * The stack contains an instance of {@link BaseInfo} for each XML element
49      * that contained an xml:base attribute (not for the other elements).
50      */

51     private Stack JavaDoc bases = new Stack JavaDoc();
52     private SourceResolver resolver;
53     private Logger logger;
54
55     public XMLBaseSupport(SourceResolver resolver, Logger logger) {
56         this.resolver = resolver;
57         this.logger = logger;
58     }
59
60     public void setDocumentLocation(String JavaDoc loc) throws SAXException JavaDoc {
61         // -2 is used as level to avoid this BaseInfo to be ever popped of the stack
62
bases.push(new BaseInfo(loc, -2));
63     }
64
65     public void startElement(String JavaDoc namespaceURI, String JavaDoc localName, String JavaDoc qName, Attributes JavaDoc attrs) throws SAXException JavaDoc {
66         level++;
67         String JavaDoc base = attrs.getValue(XMLBASE_NAMESPACE_URI, XMLBASE_ATTRIBUTE);
68         if (base != null) {
69             Source baseSource = null;
70             String JavaDoc baseUrl;
71             try {
72                 baseSource = resolve(getCurrentBase(), base);
73                 baseUrl = baseSource.getURI();
74             } finally {
75                 if (baseSource != null) {
76                     resolver.release(baseSource);
77                 }
78             }
79             bases.push(new BaseInfo(baseUrl, level));
80         }
81     }
82
83     public void endElement(String JavaDoc namespaceURI, String JavaDoc localName, String JavaDoc qName) {
84         if (getCurrentBaseLevel() == level)
85             bases.pop();
86         level--;
87     }
88
89     /**
90      * Warning: do not forget to release the source returned by this method.
91      */

92     private Source resolve(String JavaDoc baseURI, String JavaDoc location) throws SAXException JavaDoc {
93         try {
94             Source source;
95             if (baseURI != null) {
96                 source = resolver.resolveURI(location, baseURI, Collections.EMPTY_MAP);
97             } else {
98                 source = resolver.resolveURI(location);
99             }
100             if (logger.isDebugEnabled()) {
101                 logger.debug("XMLBaseSupport: resolved location " + location +
102                              " against base URI " + baseURI + " to " + source.getURI());
103             }
104             return source;
105         } catch (IOException JavaDoc e) {
106             throw new SAXException JavaDoc("XMLBaseSupport: problem resolving uri.", e);
107         }
108     }
109
110     /**
111      * Makes the given path absolute based on the current base URL. Do not forget to release
112      * the returned source object!
113      * @param spec any URL (relative or absolute, containing a scheme or not)
114      */

115     public Source makeAbsolute(String JavaDoc spec) throws SAXException JavaDoc {
116         return resolve(getCurrentBase(), spec);
117     }
118
119     private String JavaDoc getCurrentBase() {
120         if (bases.size() > 0) {
121             BaseInfo baseInfo = (BaseInfo)bases.peek();
122             return baseInfo.getUrl();
123         }
124         return null;
125     }
126
127     private int getCurrentBaseLevel() {
128         if (bases.size() > 0) {
129             BaseInfo baseInfo = (BaseInfo)bases.peek();
130             return baseInfo.getLevel();
131         }
132         return -1;
133     }
134
135     private static final class BaseInfo {
136         private String JavaDoc url;
137         private int level;
138
139         public BaseInfo(String JavaDoc url, int level) {
140             this.url = url;
141             this.level = level;
142         }
143
144         public String JavaDoc getUrl() {
145             return url;
146         }
147
148         public int getLevel() {
149             return level;
150         }
151     }
152 }
153
Popular Tags