View Javadoc

1   /*
2    * Copyright Emmanouil Batsis
3    * 
4    * Licensed under the GNU General Public 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.gnu.org/licenses/gpl.txt
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   */
17  package com.geekologue.md4j.generators;
18  
19  import java.io.BufferedInputStream;
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.net.MalformedURLException;
23  import java.net.URL;
24  import javax.xml.parsers.ParserConfigurationException;
25  import javax.xml.parsers.SAXParserFactory;
26  import javax.xml.transform.Source;
27  import javax.xml.transform.TransformerException;
28  import javax.xml.transform.URIResolver;
29  import javax.xml.transform.sax.SAXSource;
30  import org.apache.tools.ant.Project;
31  import org.apache.tools.ant.Task;
32  import org.apache.tools.ant.types.XMLCatalog;
33  import org.xml.sax.EntityResolver;
34  import org.xml.sax.InputSource;
35  import org.xml.sax.SAXException;
36  import org.xml.sax.XMLReader;
37  import com.geekologue.md4j.tools.ant.HibernateMappingProcessorTask;
38  
39  /***
40   * EntityResolver and URIResolver implementation for Md4j Ant tasks. Used to
41   * load XSLT files, XML entities etc from the MD4J jar. Used only within Ant
42   * builds. Delegates non-MD4J resource resolution to the XML Catalogue used by
43   * the task.
44   * 
45   * @author Emmanouil Batsis
46   * 
47   */
48  public class ResourceResolver implements EntityResolver, URIResolver {
49      private Task       task;
50  
51      private XMLCatalog xmlCatalogue;
52  
53      private ResourceResolver() {
54          super();
55      }
56  
57      /***
58       * 
59       * @param belongingTask
60       *            the task object using this instance
61       * @param catalogue
62       *            the XMLCatalogue to delegate non-MD4J resource resolution
63       */
64      public ResourceResolver(HibernateMappingProcessorTask belongingTask) {
65          this();
66          // used to log properly
67          this.task = belongingTask;
68          // used to delegate lookups when requested resources are not
69          // specific to MD4J
70          this.xmlCatalogue = belongingTask.getXmlCatalog();
71      }
72  
73      private void log(String msg, int level) {
74          this.task.log(this.getClass().getName() + ": " + msg, level);
75      }
76  
77      /***
78       * Get a resource from the MD4J jar as an InputSource.
79       * 
80       * @param path
81       * @return
82       */
83      private InputSource resolveInternalResource(String path) {
84          InputSource inputSource;
85          String s = path.startsWith(HibernateMappingProcessorTask.MD4J_BASE_URI) ? path
86                  .substring(HibernateMappingProcessorTask.MD4J_BASE_URI.length())
87                  : path;
88          InputStream inputStream = ResourceResolver.class.getClassLoader()
89                  .getResourceAsStream(s);
90          inputSource = new InputSource(new BufferedInputStream(inputStream));
91          inputSource.setSystemId(path);
92          this.log("Loaded MD4J resource: " + path, Project.MSG_DEBUG);
93          return inputSource;
94      }
95  
96      /***
97       * @throws IOException
98       * @throws SAXException
99       * @see org.xml.sax.EntityResolver#resolveEntity(java.lang.String,
100      *      java.lang.String)
101      */
102     public InputSource resolveEntity(String publicId, String systemId)
103             throws SAXException, IOException {
104         InputSource inputSource = null;
105         if (systemId != null
106                 && systemId
107                         .startsWith(HibernateMappingProcessorTask.MD4J_BASE_URI)) {
108             inputSource = resolveInternalResource(systemId);
109         } else {
110             inputSource = this.xmlCatalogue.resolveEntity(publicId, systemId);
111         }
112         return inputSource;
113     }
114 
115     /***
116      * @param href
117      * @param base
118      * @see javax.xml.transform.URIResolver#resolve(java.lang.String,
119      *      java.lang.String)
120      */
121     public Source resolve(String href, String base) throws TransformerException {
122         Source source = null;
123         try {
124             if (base != null
125                     && base
126                             .startsWith(HibernateMappingProcessorTask.MD4J_BASE_URI)) {
127                 URL resolved = new URL(new URL(base), href);
128                 // i think i keep the SAX plumbing here to set
129                 // the URIResolver for the Reader used, need to check
130                 SAXParserFactory spFactory = SAXParserFactory.newInstance();
131                 spFactory.setNamespaceAware(true);
132                 spFactory.setValidating(false);
133                 XMLReader reader = spFactory.newSAXParser().getXMLReader();
134                 reader.setEntityResolver(this);
135                 source = new SAXSource(reader, this
136                         .resolveInternalResource(resolved.toString()));
137                 source.setSystemId(resolved.toString());
138             } else {
139                 // i really tried, but simply cannot make simple FS lookups
140                 // work; URI and File objects simply do not share a consistent
141                 // view
142                 // of the file: URI scheme and i haven't even tried my Linux or
143                 // a Windowes box yet...
144                 // Passing the responsibility to an XMLCatalogue object
145                 source = this.xmlCatalogue.resolve(href, base);
146             }
147         } catch (SAXException e) {
148             throw new TransformerException(e);
149         } catch (ParserConfigurationException e) {
150             throw new TransformerException(e);
151         } catch (MalformedURLException e) {
152             throw new TransformerException(e);
153         }
154         return source;
155     }
156 }