View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.jetspeed.anttasks;
18  
19  import java.io.File;
20  import java.io.FileOutputStream;
21  import java.io.IOException;
22  import java.io.OutputStreamWriter;
23  import java.io.PrintWriter;
24  import java.util.ArrayList;
25  import java.util.Iterator;
26  import java.util.List;
27  
28  import org.apache.tools.ant.BuildException;
29  import org.apache.tools.ant.DirectoryScanner;
30  import org.apache.tools.ant.Task;
31  import org.apache.tools.ant.types.AbstractFileSet;
32  import org.apache.tools.ant.types.Reference;
33  
34  /***
35   * ArchetypeDescriptor
36   * 
37   * This Ant task is used to generate a Maven2 Archetype Descriptor file.
38   *
39   * @author <a href="mailto:rwatler@apache.org">Randy Watler</a>
40   * @version $Id: $
41   */
42  public class ArchetypeDescriptor extends Task
43  {
44      private String header;
45      private String artifactId;
46      private Boolean allowPartial = new Boolean(true);
47      private File baseDir;
48      private File destFile;
49      private Reference sourcesRefId;
50      private Reference resourcesRefId;
51      private Reference testSourcesRefId;
52      private Reference testResourcesRefId;
53      private Reference siteResourcesRefId;
54  
55      /***
56       * Set archetype descriptor header text
57       *
58       * @param header archetype header text
59       */
60      public void addText(String header)
61      {
62          this.header = getProject().replaceProperties(header);
63      }
64  
65      /***
66       * Set archetype artifact id.
67       *
68       * @param artifactId archetype artifact id
69       */
70      public void setArtifactid(String artifactId)
71      {
72          this.artifactId = artifactId;
73      }
74  
75      /***
76       * Set archetype partial rules to support execution in existing projects.
77       *
78       * @param allowPartial archetype allow partial setting 
79       */
80      public void setAllowpartial(Boolean allowPartial)
81      {
82          this.allowPartial = allowPartial;
83      }
84  
85      /***
86       * Set archetype base directory for all sources/resources.
87       *
88       * @param baseDir archtype source/resource base directory
89       */
90      public void setBasedir(File baseDir)
91      {
92          this.baseDir = baseDir;
93      }
94  
95      /***
96       * Set archetype descriptor destination file.
97       *
98       * @param destFile archetype descriptor file to generate
99       */
100     public void setDestfile(File destFile)
101     {
102         this.destFile = destFile;
103     }
104 
105     /***
106      * Set archetype sources refid.
107      *
108      * @param sourcesRefId archetype sources
109      */
110     public void setSourcesrefid(Reference sourcesRefId)
111     {
112         this.sourcesRefId = sourcesRefId;
113     }
114 
115     /***
116      * Set archetype resources fileset refid.
117      *
118      * @param resourcesRefId archetype resources
119      */
120     public void setResourcesrefid(Reference resourcesRefId)
121     {
122         this.resourcesRefId = resourcesRefId;
123     }
124 
125     /***
126      * Set archetype test sources fileset refid.
127      *
128      * @param testSourcesRefId archetype test sources
129      */
130     public void setTestsourcesrefid(Reference testSourcesRefId)
131     {
132         this.testSourcesRefId = testSourcesRefId;
133     }
134 
135     /***
136      * Set archetype test resources fileset refid.
137      *
138      * @param testResourcesRefId archetype test resources
139      */
140     public void setTestresourcesrefid(Reference testResourcesRefId)
141     {
142         this.testResourcesRefId = testResourcesRefId;
143     }
144 
145     /***
146      * Set archetype site resources fileset refid.
147      *
148      * @param siteResourcesRefId archetype site resources
149      */
150     public void setSiteresourcesrefid(Reference siteResourcesRefId)
151     {
152         this.siteResourcesRefId = siteResourcesRefId;
153     }
154 
155     /***
156      * Executes task to generate desciptor file.
157      *
158      * @throws BuildException
159      */
160     public void execute() throws BuildException
161     {
162         // basic validation
163         if ((artifactId == null) || (baseDir == null) || (destFile == null))
164         {
165             throw new BuildException("required artifactid, basedir, or destfile attribute missing", getLocation());
166         }
167 
168         // reference sources/resources
169         List sources = archetypeFiles(sourcesRefId, "sourcesrefid");
170         List resources = archetypeFiles(resourcesRefId, "resourcesrefid");
171         List testSources = archetypeFiles(testSourcesRefId, "testsourcesrefid");
172         List testResources = archetypeFiles(testResourcesRefId, "testresourcesrefid");
173         List siteResources = archetypeFiles(siteResourcesRefId, "siteresourcesrefid");
174 
175         // write archetype descriptor file
176         PrintWriter writer = null;
177         try
178         {
179             // make sure destination ddirectory exists
180             File destDir = destFile.getParentFile();
181             if (!destDir.exists())
182             {
183                 destDir.mkdirs();
184             }
185 
186             // write descriptor to destination file
187             writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(destFile), "UTF-8"));
188             writer.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
189             if (header != null)
190             {
191                 writer.println(header);
192             }
193             writer.println("<archetype>");
194             writer.println("    <id>" + artifactId + "</id>");
195             writer.println("    <allowPartial>" + allowPartial + "</allowPartial>");
196             writeFiles(writer, "sources", "source", sources);
197             writeFiles(writer, "resources", "resource", resources);
198             writeFiles(writer, "testSources", "source", testSources);
199             writeFiles(writer, "testResources", "resource", testResources);
200             writeFiles(writer, "siteResources", "resource", siteResources);
201             writer.println("</archetype>");
202         }
203         catch (IOException ioe)
204         {
205             throw new BuildException("unable to write decriptor", ioe, getLocation());
206         }
207         finally
208         {
209             if (writer != null)
210             {
211                 writer.close();
212             }
213         }
214 
215         // log task success
216         int archetypeSourcesCount = sources.size() + resources.size() + testSources.size() + testResources.size() + siteResources.size();
217         log("generated " + destFile + " including " + archetypeSourcesCount + " source/resource files");
218     }
219 
220     /***
221      * Utility to read fileset refid attributes.
222      *
223      * @param refId attribute refid
224      * @param name attribute name
225      * @return list of String file paths
226      * @throws BuildException
227      */
228     private List archetypeFiles(Reference refId, String name) throws BuildException
229     {
230         List archetypeFiles = new ArrayList();
231         if (refId != null)
232         {
233             // access fileset from refid
234             if (!(refId.getReferencedObject(getProject()) instanceof AbstractFileSet))
235             {
236                 throw new BuildException(name + " attribute must reference a fileset", getLocation());
237             }
238             AbstractFileSet fileSet = (AbstractFileSet)refId.getReferencedObject(getProject());
239             DirectoryScanner directoryScanner = fileSet.getDirectoryScanner(getProject());
240             String [] files = directoryScanner.getIncludedFiles();
241             if ((files != null) && (files.length > 0))
242             {
243                 String basePath = canonicalPath(baseDir);
244                 for (int i = 0; (i < files.length); i++)
245                 {
246                     // convert file relative to fileset to file relative
247                     // to archetype base dir
248                     String archetypePath = files[i];
249                     if (basePath != null)
250                     {
251                         File file = new File(fileSet.getDir(getProject()), files[i]);
252                         String filePath = canonicalPath(file);
253                         if ((filePath != null) && filePath.startsWith(basePath))
254                         {
255                             // path relative to baseDir
256                             archetypePath = filePath.substring(basePath.length());
257                             if (archetypePath.startsWith("/"))
258                             {
259                                 archetypePath = archetypePath.substring(1);
260                             }
261                         }
262                     }
263                     // add archetype files
264                     archetypeFiles.add(archetypePath);
265                 }
266             }
267         }
268         return archetypeFiles;
269     }
270 
271     /***
272      * Utility to get canonical file path
273      *
274      * @param file file to convert to canonical path
275      * @return canonical path
276      */
277     private String canonicalPath(File file)
278     {
279         try
280         {
281             String path = file.getCanonicalPath();
282             return path.replace('//', '/');
283         }
284         catch (IOException ioe)
285         {
286             return null;
287         }
288     }
289 
290     /***
291      * Utility to write archetype descriptor file lists.
292      *
293      * @param writer descriptor writer
294      * @param collectionElementName collection element name
295      * @param elementName file element name
296      * @param files list of String file paths
297      * @throws IOException
298      */
299     private void writeFiles(PrintWriter writer, String collectionElementName, String elementName, List files) throws IOException
300     {
301         // write file list to descriptor
302         if (!files.isEmpty())
303         {
304             writer.println("    <" + collectionElementName + ">");
305             Iterator fileIter = files.iterator();
306             while (fileIter.hasNext())
307             {
308                 writer.println("        <" + elementName + ">" + (String)fileIter.next() + "</" + elementName + ">");
309             }
310             writer.println("    </" + collectionElementName + ">");
311         }
312     }
313 }