KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > components > source > impl > QDoxSourceFactory


1 /*
2  * Copyright 1999-2002,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.components.source.impl;
17
18
19 import java.io.File JavaDoc;
20 import java.io.IOException JavaDoc;
21 import java.net.MalformedURLException JavaDoc;
22 import java.util.ArrayList JavaDoc;
23 import java.util.Iterator JavaDoc;
24 import java.util.List JavaDoc;
25 import java.util.Map JavaDoc;
26
27 import org.apache.avalon.framework.configuration.Configurable;
28 import org.apache.avalon.framework.configuration.Configuration;
29 import org.apache.avalon.framework.configuration.ConfigurationException;
30 import org.apache.avalon.framework.logger.AbstractLogEnabled;
31 import org.apache.avalon.framework.service.ServiceException;
32 import org.apache.avalon.framework.service.ServiceManager;
33 import org.apache.avalon.framework.service.Serviceable;
34 import org.apache.avalon.framework.thread.ThreadSafe;
35 import org.apache.excalibur.source.Source;
36 import org.apache.excalibur.source.SourceException;
37 import org.apache.excalibur.source.SourceFactory;
38 import org.apache.excalibur.source.SourceResolver;
39 import org.apache.regexp.RE;
40 import org.apache.regexp.RESyntaxException;
41
42
43 /**
44  * This {@link org.apache.excalibur.source.SourceFactory SourceFactory} creates {@link
45  * org.apache.excalibur.source.Source Source}s for the <code>javadoc:</code> URI scheme.
46  *
47  * <p>The goal for this <code>SourceFactory</code> is to provide a <code>Source</code>
48  * for a Java sourcefile containing as much information as possible to mimic the
49  * standard Javadoc output.</p>
50  *
51  * <p>The Source provides the following content:
52  * <ul>
53  * <li>Classname</li>
54  * <li>Superclass</li>
55  * <li>Imports, including <code>java.lang</code> and the class' package</li>
56  * <li>Implemented interfaces</li>
57  * <li>Inner classes/interfaces, including superclass, implemented interfaces and
58  * Javadoc (inner classes can be requested separately)</li>
59  * <li>Fields, including type, name and Javadoc</li>
60  * <li>Constructors, including parameters with their types and names, signature,
61  * Javadoc and thrown exceptions</li>
62  * <li>Methods, including returntype, parameters, signature, Javadoc and thrown
63  * exceptions</li>
64  * <li>Inheritance tree for each Class member, if needed</li>
65  * <li>Private members, if needed</li>
66  * </ul>
67  * </p>
68  *
69  * <p>With this <code>SourceFactory</code>, you create Doclets with XSLT stylesheets
70  * instead of Java code.</p>
71  *
72  * <p>The <code>QDoxSourceFactory</code> uses <a HREF="http://qdox.sf.net/">QDox</a>
73  * to parse the Java sourcefiles.
74  * </p>
75  *
76  * @author <a HREF="mailto:b.guijt1@chello.nl">Bart Guijt</a>
77  * @version CVS $Id: QDoxSourceFactory.java 124685 2005-01-08 22:20:56Z antonio $
78  */

79 public final class QDoxSourceFactory
80     extends AbstractLogEnabled
81     implements SourceFactory, Serviceable, Configurable, ThreadSafe {
82     
83     protected final static String JavaDoc INCLUDE_INHERITANCE_ELEMENT = "include-inheritance";
84     protected final static String JavaDoc VALUE_ATTRIBUTE = "value";
85     protected final static String JavaDoc SOURCE_GROUP_ELEMENT = "source-roots";
86     protected final static String JavaDoc GROUP_ATTRIBUTE = "group";
87     protected final static String JavaDoc SOURCE_ROOT_ELEMENT = "source-root";
88     protected final static String JavaDoc URI_ATTRIBUTE = "uri";
89     
90     protected ServiceManager manager;
91     protected List JavaDoc sourceRootUris;
92     
93     /**
94      * RegExp matcher for Java classnames: distinguishes package and classname.
95      */

96     protected RE rePackageClass;
97     
98     /**
99      * RegExp matcher for Java classnames: distinguishes package, classname and innerclassname.
100      */

101     protected RE rePackageClassInnerclass;
102     
103     
104     /**
105      * Represents an URI and which packages it contains.
106      *
107      * <p>Using this class, the QDoxSourceFactory can quickly find the right SourceRoot URI given a specified
108      * package.</p>
109      */

110     protected static final class SourceRoot {
111         private List JavaDoc packages;
112         private String JavaDoc sourceRootUri;
113         
114         protected SourceRoot(String JavaDoc uri) {
115             if (!uri.endsWith(File.separator)) {
116                 uri += '/';
117             }
118             sourceRootUri = uri;
119             packages = new ArrayList JavaDoc();
120         }
121         
122         protected void addPackage(String JavaDoc packageName) {
123             packages.add(packageName);
124         }
125         
126         protected boolean hasPackage(String JavaDoc packageName) {
127             return packages.contains(packageName);
128         }
129         
130         protected String JavaDoc getUri() {
131             return sourceRootUri;
132         }
133     }
134     
135     
136     /**
137      * @see org.apache.excalibur.source.SourceFactory#getSource(java.lang.String, java.util.Map)
138      */

139     public Source getSource(String JavaDoc location, Map JavaDoc parameters) throws MalformedURLException JavaDoc, IOException JavaDoc, SourceException {
140         String JavaDoc className = location.substring(location.indexOf(':') + 1);
141         Source javaSource = null;
142         if (className.length() > 0) {
143             try {
144                 if(getLogger().isDebugEnabled()) {
145                     getLogger().debug("getSource called with className=" + className);
146                 }
147                 javaSource = getSource(className);
148             } catch (ServiceException se) {
149                 throw new SourceException("SourceResolver not found", se);
150             }
151         } else {
152             throw new MalformedURLException JavaDoc();
153         }
154
155         QDoxSource result = null;
156         if (javaSource != null) {
157             return new QDoxSource(location, javaSource, getLogger(), manager);
158         }
159
160         if(getLogger().isDebugEnabled()) {
161             getLogger().debug("returning source=" + result + " for className=" + className);
162         }
163
164         return result;
165     }
166     
167     /**
168      * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
169      */

170     public void service(ServiceManager manager) throws ServiceException {
171         if (getLogger().isDebugEnabled()) {
172             getLogger().debug("Composing the QDoxSourceFactory...");
173         }
174         this.manager = manager;
175         
176         try {
177             rePackageClass = new RE("([$\\w.]+)\\.([$\\w]+)");
178             rePackageClassInnerclass = new RE("([$\\w.]+)\\.([$\\w]+)\\.([$\\w]+)");
179         } catch (RESyntaxException e) {
180             getLogger().error("RegExp syntax error!", e);
181         }
182     }
183     
184     /**
185      * @see org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration)
186      */

187     public void configure(Configuration config) throws ConfigurationException {
188         Configuration[] sourceRootGroups = config.getChildren(SOURCE_GROUP_ELEMENT);
189         sourceRootUris = new ArrayList JavaDoc();
190         
191         for (int i=0; i<sourceRootGroups.length; i++) {
192             Configuration[] sourceRootConfigs = sourceRootGroups[i].getChildren(SOURCE_ROOT_ELEMENT);
193             
194             for (int j=0; j<sourceRootConfigs.length; j++) {
195                 String JavaDoc uri = sourceRootConfigs[j].getAttribute(URI_ATTRIBUTE);
196                 sourceRootUris.add(new SourceRoot(uri));
197             }
198         }
199         
200         if (sourceRootUris.size() == 0 && getLogger().isErrorEnabled()) {
201             getLogger().error("No source roots configured!");
202         }
203     }
204     
205     /**
206      * Releases the specified Source.
207      *
208      * @see org.apache.excalibur.source.SourceFactory#release(org.apache.excalibur.source.Source)
209      */

210     public void release(Source source) {
211         // ??? What to do here?
212
}
213     
214     /**
215      * Method getSource.
216      *
217      * @param className
218      * @return File
219      */

220     private Source getSource(String JavaDoc className) throws ServiceException {
221         String JavaDoc classFileName = className;
222         String JavaDoc packageName;
223         
224         if (rePackageClass.match(className)) {
225             packageName = rePackageClass.getParen(1);
226         } else {
227             packageName = "";
228         }
229         
230         classFileName = classFileName.replace('.', '/') + ".java";
231         SourceResolver resolver = (SourceResolver) manager.lookup(SourceResolver.ROLE);
232         
233         Source source = getSource(classFileName, packageName, resolver);
234         if (source == null && rePackageClassInnerclass.match(className)) {
235             // Inner class?
236

237             packageName = rePackageClassInnerclass.getParen(1);
238             classFileName = className.substring(0, className.lastIndexOf('.')).replace('.', '/') + ".java";
239             source = getSource(classFileName, packageName, resolver);
240         }
241         manager.release(resolver);
242             
243         if (source == null && getLogger().isWarnEnabled()) {
244             getLogger().warn("No source found for class '" + className + "'!");
245         }
246
247         return source;
248     }
249     
250     private Source getSource(String JavaDoc classFileName, String JavaDoc packageName, SourceResolver resolver) {
251         // First, test whether there are configured packages to speed things up:
252
for (Iterator JavaDoc i = sourceRootUris.iterator(); i.hasNext();) {
253             SourceRoot sourceRoot = (SourceRoot) i.next();
254             
255             if (sourceRoot.hasPackage(packageName)) {
256                 String JavaDoc uri = sourceRoot.getUri() + classFileName;
257                 Source source = getSource(uri, resolver);
258                 if (source != null) {
259                     return source;
260                 }
261             }
262         }
263         
264         // No suitable package found, iterate all source roots:
265
for (Iterator JavaDoc i = sourceRootUris.iterator(); i.hasNext();) {
266             SourceRoot sourceRoot = (SourceRoot) i.next();
267             String JavaDoc uri = sourceRoot.getUri() + classFileName;
268             
269             Source source = getSource(uri, resolver);
270             if (source != null) {
271                 sourceRoot.addPackage(packageName);
272                 return source;
273             }
274         }
275         return null;
276     }
277     
278     /**
279      * Method getSource.
280      *
281      * @param uri
282      * @param resolver
283      * @return Source
284      */

285     private Source getSource(String JavaDoc uri, SourceResolver resolver) {
286         if (getLogger().isDebugEnabled()) {
287             getLogger().debug("Testing uri <" + uri + ">...");
288         }
289         try {
290             Source source = resolver.resolveURI(uri);
291                 
292             if (source != null && source.getInputStream() != null) {
293                 return source;
294             } else {
295                 if (getLogger().isDebugEnabled()) {
296                     getLogger().debug("uri <" + uri + "> is invalid.");
297                 }
298             }
299         } catch (Exception JavaDoc e) {
300             if (getLogger().isDebugEnabled()) {
301                 getLogger().debug("uri <" + uri + "> is invalid: " + e.getClass().getName() + " says " + e.getMessage());
302             }
303         }
304         return null;
305     }
306 }
307
Popular Tags