View Javadoc
1 /* 2 * Copyright (c) 2001, 2002 The XDoclet team 3 * All rights reserved. 4 */ 5 package xdoclet; 6 7 import org.apache.commons.logging.LogFactory; 8 import org.apache.commons.collections.CollectionUtils; 9 import org.apache.commons.collections.Predicate; 10 11 import xdoclet.beans.Invocation; 12 import xdoclet.beans.BeanContextSupportEx; 13 import xdoclet.sdk.ant.BuildXmlPlugin; 14 import xdoclet.sdk.ant.BuildXmlMetadataProvider; 15 import xdoclet.util.ClasspathManager; 16 17 import java.util.*; 18 import java.io.File; 19 import java.io.IOException; 20 import java.beans.BeanInfo; 21 import java.beans.Introspector; 22 import java.beans.IntrospectionException; 23 import java.beans.MethodDescriptor; 24 import java.lang.reflect.Method; 25 26 /*** 27 * <p>This class as an entry-point for starting XDoclet. Adapter classes for 28 * particular environments such as various IDEs and Ant should be maintained 29 * separately. It's important to keep XDoclet's core environment agnostic.</p> 30 * 31 * <p>This class also extends {@link java.beans.beancontext.BeanContextSupport}, 32 * and thereby this is actually a Collection, so we can store the plugins 33 * "in ourself". The main reason for extending BeanContextSupport is to 34 * be a ble to provide IDE integration in a convenient way. See the 35 * <a href="../gui/package.html"></a>xdoclet.gui</p> package. 36 * 37 * @bean.class displayName="Simple XDoclet" 38 * shortDescription="This is a simple XDoclet that can be used as a container by generic Plugins" 39 * 40 * @bean.attribute name="xdoclet.beans.InvocationFactory" value="xdoclet.beans.XDocletInvocationFactory" 41 * 42 * @see Plugin 43 * @see ClasspathManager 44 * @see PluginFactory 45 * @see XDocletException 46 * 47 * @author <a href="mailto:aslak.hellesoy at netcom.no">Aslak Hellesøy</a> 48 * @version $Revision: 1.22 $ 49 */ 50 public class XDoclet extends BeanContextSupportEx { 51 public static final String XDOCLET_VERSION = "@XDOCLET_VERSION@"; 52 53 /*** The PluginFactory registers and creates plugins found on the classpath. */ 54 private PluginFactory _pluginFactory; 55 56 /*** 57 * To work around the fact that org.apache.commons.jelly.tags.ant.AntTag 58 * swallows BuildException in its createNestedObject method, we keep 59 * a ref here, so we can fail the build ourself. 60 */ 61 private transient Throwable _failure; 62 63 /*** 64 * If set, a simple build.xml will be generated and dumped here. 65 */ 66 private BuildXmlPlugin _buildXmlPlugin = new BuildXmlPlugin(); 67 68 /*** 69 * Creates a new XDoclet. 70 */ 71 public XDoclet() { 72 printVersion(); 73 } 74 75 private MetadataProvider getCurrentMetadataProvider() { 76 return (MetadataProvider) CollectionUtils.find(this, 77 new Predicate() { 78 public boolean evaluate(Object o) { 79 return o instanceof MetadataProvider; 80 } 81 }); 82 } 83 84 private Collection getPlugins() { 85 return CollectionUtils.select(this, 86 new Predicate() { 87 public boolean evaluate(Object o) { 88 return o instanceof Plugin; 89 } 90 }); 91 } 92 93 /*** 94 * If this is set, a build.xml file will be written out to the 95 * specified file. 96 * 97 * @bean.property 98 * shortDescription="Location of generated Ant script (build.xml)." 99 * displayName="build.xml" 100 * @param buildXmlDir the file where build.xml should be written. 101 * 102 * @todo this isn't an elegant way to do it. fixme. 103 */ 104 public final void setBuildXmlDir(File buildXmlDir) { 105 _buildXmlPlugin.setDestinationDir( buildXmlDir ); 106 } 107 108 public final File getBuildXmlDir() { 109 return _buildXmlPlugin.getDestinationDir(); 110 } 111 112 public MetadataProvider createMetadataProvider( String name ) throws XDocletException { 113 if( getCurrentMetadataProvider() != null ) { 114 throw new XDocletException("A " + getCurrentMetadataProvider().getClass().getName() + 115 "MetaDataProvider has already been created. Shouldn't create a " + name + " now."); 116 } 117 118 MetadataProvider result = _pluginFactory.createMetadataProvider( name, this ); 119 120 setClasspathOnMetadataProviderMaybe(); 121 return result; 122 } 123 124 public void setFailure(Throwable failure) { 125 _failure = failure; 126 } 127 128 /*** 129 * Sets the classpath under which XDoclet is run. 130 * @param classpath the classpath under which XDoclet is run 131 * @bean.ignore 132 */ 133 public void setClasspath(String classpath) throws XDocletException { 134 ClasspathManager classpathManager = new ClasspathManager(classpath); 135 136 _pluginFactory = new PluginFactory(classpathManager); 137 138 setClasspathOnMetadataProviderMaybe(); 139 } 140 141 /*** 142 * If the current matadata provider is xjavadoc, set classpath on it. 143 * This is done via reflection, to keep 144 */ 145 private void setClasspathOnMetadataProviderMaybe() throws XDocletException { 146 if( getCurrentMetadataProvider() != null ) { 147 getCurrentMetadataProvider().setClasspath( _pluginFactory.getClasspathManager().getClasspath() ); 148 } 149 } 150 151 /*** 152 * Gets that ClasspathManager. 153 * @return the ClasspathManager. 154 */ 155 public ClasspathManager getClasspathManager() { 156 return _pluginFactory.getClasspathManager(); 157 } 158 159 /*** 160 * Executes all the plugins. 161 * 162 * @throws XDocletException if execution fails. 163 */ 164 public void execute() throws IOException, XDocletException { 165 failIfFailureSet(); 166 167 if (isEmpty()) { 168 throw new XDocletException("At least one plugin must be specified."); 169 } 170 171 long start = System.currentTimeMillis(); 172 173 for (Iterator i = getPlugins().iterator(); i.hasNext();) { 174 Plugin plugin = (Plugin) i.next(); 175 // Let the plugin use our MetadataProvider. 176 plugin.setMetadataProvider( getCurrentMetadataProvider() ); 177 plugin.execute(); 178 } 179 180 long end = System.currentTimeMillis(); 181 182 LogFactory.getLog(getClass()).debug("XDoclet ran in " + (end - start) + " ms."); 183 184 generateBuildXmlMaybe(); 185 } 186 187 public void generateBuildXmlMaybe() throws IOException, XDocletException { 188 // Add the special build.xml plugin if a build.xml dir is set. 189 if( getBuildXmlDir() != null ) { 190 XDoclet buildXmlDoclet = new XDoclet(); 191 // Activate the BuildXmlMetadataProvider 192 BuildXmlMetadataProvider buildXmlMetadataProvider = 193 (BuildXmlMetadataProvider) buildXmlDoclet.createMetadataProvider("ant"); 194 buildXmlMetadataProvider.setXDoclet( this ); 195 buildXmlDoclet.add(_buildXmlPlugin); 196 _buildXmlPlugin.execute(); 197 remove(_buildXmlPlugin); 198 } 199 } 200 201 /*** 202 * Called by {@link xdoclet.ant.AntProxy#createDynamicElement} when a dynamic element is added 203 * to the XDoclet task. This method will route the call to {@link #createPlugin}. 204 * 205 * @param name the name of the plugin to create. 206 * @return a {@link Plugin} object mapped to name. 207 * @throws XDocletException 208 */ 209 public Object createElement(String name) 210 throws XDocletException { 211 LogFactory.getLog(XDoclet.class).debug("createElement(" + name + ")"); 212 213 Object result = null; 214 try { 215 // First try to create a plugin 216 result = createPlugin(name); 217 } catch (XDocletException e) { 218 // It wasn't a plugin. Try MetadataProvider instead. 219 result = createMetadataProvider(name); 220 } 221 if( result == null ) { 222 throw new XDocletException("Don't know what to instantiate for " + name + "."); 223 } 224 return result; 225 } 226 227 private static final void printVersion() { 228 // This should really be a System.out.print[ln], as we want this to be printed 229 // every time XDoclet is run. The version string will be substituted by maven.xml 230 System.out.print("."); 231 232 for (int i = 0; i < (XDOCLET_VERSION.length() + 2); i++) { 233 System.out.print("-"); 234 } 235 236 System.out.println("."); 237 System.out.println("| " + XDOCLET_VERSION + " |"); 238 System.out.print("`"); 239 240 for (int i = 0; i < (XDOCLET_VERSION.length() + 2); i++) { 241 System.out.print("-"); 242 } 243 244 System.out.println("'"); 245 } 246 247 private void failIfFailureSet() 248 throws XDocletException { 249 if (_failure != null) { 250 if (_failure instanceof XDocletException) { 251 throw (XDocletException) _failure; 252 } else { 253 throw new XDocletException(_failure.getMessage(), _failure); 254 } 255 } 256 } 257 258 /*** 259 * Adds a new Plugin. 260 * 261 * @bean.method shortDescription="Add a new plugin" 262 * displayName="New Plugin" 263 * 264 * @param name Plugin name 265 * @return a Plugin instance 266 * @throws XDocletException plugin creation fails. 267 * @see PluginFactory#createPlugin(java.lang.String, xdoclet.XDoclet) 268 */ 269 public Plugin createPlugin(String name) 270 throws XDocletException { 271 return _pluginFactory.createPlugin(name, this); 272 } 273 274 protected Collection createInvocations() { 275 Collection result = new ArrayList(); 276 277 BeanInfo beanInfo = null; 278 279 try { 280 beanInfo = Introspector.getBeanInfo(getClass()); 281 } catch (IntrospectionException e) { 282 LogFactory.getLog(XDoclet.class).error(e.getMessage(), e); 283 throw new IllegalStateException("Couldn't get BeanInfo for " + getClass() + ":" + e.getMessage()); 284 } 285 286 Method createPlugin = null; 287 288 try { 289 createPlugin = getClass().getMethod("createPlugin", new Class[] { String.class }); 290 } catch (NoSuchMethodException e) { 291 LogFactory.getLog(XDoclet.class).error(e.getMessage(), e); 292 throw new IllegalStateException("Couldn't find createPlugin(String) in " + getClass() + ":" 293 + e.getMessage()); 294 } catch (SecurityException e) { 295 LogFactory.getLog(XDoclet.class).error(e.getMessage(), e); 296 throw new IllegalStateException("Couldn't find createPlugin(String) in " + getClass() + ":" 297 + e.getMessage()); 298 } 299 300 MethodDescriptor[] methodDescriptors = beanInfo.getMethodDescriptors(); 301 302 for (int m = 0; m < methodDescriptors.length; m++) { 303 if (createPlugin.equals(methodDescriptors[m].getMethod())) { 304 // See Xdoclet.updateBeanInfo 305 List pluginNames = (List) methodDescriptors[m].getValue("pluginNames"); 306 307 for (Iterator i = pluginNames.iterator(); i.hasNext();) { 308 String pluginName = (String) i.next(); 309 Object[] args = new Object[] { pluginName }; 310 Invocation invocation = new Invocation(methodDescriptors[m], this, args); 311 312 result.add(invocation); 313 } 314 } 315 } 316 317 return result; 318 } 319 }

This page was automatically generated by Maven