001: // Copyright 2004, 2005 The Apache Software Foundation
002: //
003: // Licensed under the Apache License, Version 2.0 (the "License");
004: // you may not use this file except in compliance with the License.
005: // You may obtain a copy of the License at
006: //
007: // http://www.apache.org/licenses/LICENSE-2.0
008: //
009: // Unless required by applicable law or agreed to in writing, software
010: // distributed under the License is distributed on an "AS IS" BASIS,
011: // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: // See the License for the specific language governing permissions and
013: // limitations under the License.
014:
015: package org.apache.hivemind.ant;
016:
017: import java.io.BufferedOutputStream;
018: import java.io.File;
019: import java.io.FileOutputStream;
020: import java.io.IOException;
021: import java.io.OutputStream;
022: import java.net.URL;
023: import java.util.ArrayList;
024: import java.util.List;
025:
026: import org.apache.hivemind.ModuleDescriptorProvider;
027: import org.apache.hivemind.Resource;
028: import org.apache.hivemind.impl.DefaultClassResolver;
029: import org.apache.hivemind.impl.XmlModuleDescriptorProvider;
030: import org.apache.hivemind.util.FileResource;
031: import org.apache.hivemind.util.URLResource;
032: import org.apache.tools.ant.BuildException;
033: import org.apache.tools.ant.Task;
034: import org.apache.tools.ant.types.Path;
035: import org.apache.xml.serialize.OutputFormat;
036: import org.apache.xml.serialize.XMLSerializer;
037: import org.w3c.dom.Document;
038:
039: /**
040: * Reads some number of hivemodule deployment descriptors (specified as a fileset) and builds a
041: * composite registry by simply concatinating them all. The resulting file is suitable for passing
042: * through an XSLT processor to create documentation.
043: * <p>
044: * The resulting XML file does not conform to the hivemind module deployment descriptor schema. The
045: * following changes occur:
046: * <ul>
047: * <li>The outermost element is <registry> (which contains a list of <module>)
048: * <li>A unique id (unique within the file) is assigned to each <module>,
049: * <configuration-point>, <service-point>, <contribution>, &tl;schema> and
050: * <implementation> (this is to make it easier to generate links and anchors)
051: * <li>Unqualified ids are converted to qualified ids (whereever possible).
052: * </ul>
053: *
054: * @author Howard Lewis Ship
055: */
056: public class ConstructRegistry extends Task {
057: private File _output;
058:
059: private Path _descriptorsPath;
060:
061: /**
062: * List of {@link org.apache.hivemind.Resource} of additional descriptors to parse.
063: */
064: private List _resourceQueue = new ArrayList();
065:
066: public void execute() throws BuildException {
067: if (_output == null)
068: throw new BuildException("You must specify an output file");
069:
070: if (_descriptorsPath == null)
071: throw new BuildException(
072: "You must specify a set of module descriptors");
073:
074: long outputStamp = _output.lastModified();
075:
076: String[] paths = _descriptorsPath.list();
077: int count = paths.length;
078:
079: boolean needsUpdate = false;
080:
081: File[] descriptors = new File[count];
082:
083: for (int i = 0; i < count; i++) {
084: File f = new File(paths[i]);
085:
086: if (f.isDirectory())
087: continue;
088:
089: if (f.lastModified() > outputStamp)
090: needsUpdate = true;
091:
092: descriptors[i] = f;
093: }
094:
095: if (needsUpdate) {
096: Document registry = constructRegistry(descriptors);
097:
098: log("Writing registry to " + _output);
099:
100: writeDocument(registry, _output);
101: }
102:
103: }
104:
105: private Document constructRegistry(File[] moduleDescriptors)
106: throws BuildException {
107: try {
108: enqueue(moduleDescriptors);
109:
110: ModuleDescriptorProvider provider = new XmlModuleDescriptorProvider(
111: new DefaultClassResolver(), _resourceQueue);
112:
113: RegistrySerializer generator = new RegistrySerializer();
114:
115: generator.addModuleDescriptorProvider(provider);
116:
117: Document result = generator.createRegistryDocument();
118:
119: return result;
120: } catch (Exception ex) {
121: throw new BuildException(ex);
122: }
123: }
124:
125: private void enqueue(File[] descriptors) throws IOException {
126: for (int i = 0; i < descriptors.length; i++)
127: enqueue(descriptors[i]);
128: }
129:
130: /**
131: * Queues up a single descriptor which may be a raw XML file, or a JAR (containing the XML
132: * file).
133: */
134: private void enqueue(File file) throws IOException {
135: // This occurs when a bare directory is part of the classpath.
136:
137: if (file == null)
138: return;
139:
140: if (file.getName().endsWith(".jar")) {
141: enqueueJar(file);
142: return;
143: }
144:
145: String path = file.getPath().replace('\\', '/');
146:
147: Resource r = new FileResource(path);
148:
149: enqueue(r);
150: }
151:
152: private void enqueue(Resource resource) {
153: if (!_resourceQueue.contains(resource))
154: _resourceQueue.add(resource);
155: }
156:
157: private void enqueueJar(File jarFile) throws IOException {
158: URL jarRootURL = new URL("jar:" + jarFile.toURL() + "!/");
159:
160: Resource jarResource = new URLResource(jarRootURL);
161:
162: enqueueIfExists(jarResource,
163: XmlModuleDescriptorProvider.HIVE_MODULE_XML);
164: }
165:
166: private void enqueueIfExists(Resource jarResource, String path) {
167: Resource r = jarResource.getRelativeResource(path);
168:
169: if (r.getResourceURL() != null)
170: enqueue(r);
171: }
172:
173: private void writeDocument(Document document, File file)
174: throws BuildException {
175: try {
176: OutputStream out = new FileOutputStream(file);
177: BufferedOutputStream buffered = new BufferedOutputStream(
178: out);
179:
180: writeDocument(document, buffered);
181:
182: buffered.close();
183: } catch (IOException ex) {
184: throw new BuildException("Unable to write registry to "
185: + file + ": " + ex.getMessage(), ex);
186: }
187: }
188:
189: private void writeDocument(Document document, OutputStream out)
190: throws IOException {
191: XMLSerializer serializer = new XMLSerializer(out,
192: new OutputFormat(document, null, true));
193: serializer.serialize(document);
194: }
195:
196: public Path createDescriptors() {
197: _descriptorsPath = new Path(getProject());
198: return _descriptorsPath;
199: }
200:
201: public File getOutput() {
202: return _output;
203: }
204:
205: public void setOutput(File file) {
206: _output = file;
207: }
208:
209: }
|