nicolaken 2002/09/02 06:48:44
Added: jenny build.xml
jenny/src/java/org/apache/alexandria/jenny Jenny.java
Module.java Project.java Repository.java
Server.java Workspace.java
Log:
Initial commit of the Jenny sub-project.
Code taken from Gump, and added package.
this makes it possible to keep the Gump proposal running till the new
version in alexandria works.
Will just change module->project and project->subproject;
Will make a Gump subproject also that depends on this on
In the meantime use the Gump proposal.
Revision Changes Path
1.1 jakarta-alexandria/jenny/build.xml
Index: build.xml
===================================================================
<project name="jenny" default="package" basedir=".">
<target name="compile">
<mkdir dir="build/classes"/>
<javac srcdir="src/java" destdir="build/classes"/>
</target>
<target name="package" depends="compile">
<jar destfile="build/jenny.jar" basedir="build/classes"/>
</target>
<!-- Merge the xml sources, resolving references -->
<target name="jenny" depends="package">
<java classname="org.apache.alexandria.jenny.Jenny" fork="yes"
failonerror="true">
<arg value="${workspace}"/>
</java>
</target>
<!-- Generate javadocs -->
<target name="javadocs" depends="package">
<mkdir dir="build/javadocs"/>
<javadoc packagenames="org.apache.alexandria.jenny.*" sourcepath="src/java"
destdir="build/javadocs" classpath="build/jenny.jar">
</javadoc>
</target>
<!-- Do everything -->
<target name="all" depends="package,javadocs"/>
<!-- Remove all outputs and intermediate results -->
<target name="clean">
<delete dir="build"/>
</target>
</project>
1.1
jakarta-alexandria/jenny/src/java/org/apache/alexandria/jenny/Jenny.java
Index: Jenny.java
===================================================================
/*
* $Header:
/home/cvs/jakarta-alexandria/jenny/src/java/org/apache/alexandria/jenny/Jenny.java,v
1.1 2002/09/02 13:48:43 nicolaken Exp $
* $Revision: 1.1 $
* $Date: 2002/09/02 13:48:43 $
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999-2002 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Alexandria", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.alexandria.jenny;
// TRaX classes
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.TransformerFactory;
// Java API for XML Parsing classes
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
// DOM classes
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.xml.sax.SAXParseException;
// Java classes
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
public class Jenny {
DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
TransformerFactory tFactory = TransformerFactory.newInstance();
/**
* Parse an XML source file into an DOM.
* @param source name of source file
* @return Node
*/
private Document parse(String source) throws Exception {
try {
DocumentBuilder dBuilder = dFactory.newDocumentBuilder();
return dBuilder.parse(source);
} catch (SAXParseException e) {
System.err.print("Error parsing file " + source);
System.err.println(" line " + e.getLineNumber() + ": ");
throw e;
} catch (java.net.UnknownHostException uhe) {
System.out.println(uhe.toString());
return null;
}
}
/**
* Replace all occurances of @@DATE@@ with the current datestamp in
* attribute values. The datestamp to be used is persisted on disk,
* so it will remain stable until the .timestamp file is touched or
* removed.
* @param parent node to be processed recursively
* @param dstamp string to substitute for @@DATE@@
*/
private void replaceDate(Element parent, String dstamp) {
Node first = parent.getFirstChild();
for (Node child=first; child != null; child=child.getNextSibling()) {
if (child.getNodeType()==Node.ELEMENT_NODE) {
NamedNodeMap attrs = ((Element)child).getAttributes();
for (int i=0; i<attrs.getLength(); i++) {
Node a = attrs.item(i);
String v = a.getNodeValue();
int start = v.indexOf("@@DATE@@");
while (start>=0) {
v = v.substring(0,start) + dstamp + v.substring(start+8);
((Element)child).setAttribute(a.getNodeName(),v);
start = v.indexOf("@@DATE@@");
}
}
replaceDate((Element)child, dstamp);
}
}
}
/**
* Move child nodes (attributes, elements, text, etc).
* @param source element to move from
* @param target element to update
*/
protected static void moveChildren(Element source, Element target) {
Node child=source.getFirstChild();
while (child != null) {
Node next=child.getNextSibling();
target.appendChild(child);
child=next;
}
NamedNodeMap attrs = source.getAttributes();
for (int i=0; i<attrs.getLength(); i++) {
Node a = attrs.item(i);
if (target.getAttributeNode(a.getNodeName())==null) {
target.setAttribute(a.getNodeName(),a.getNodeValue());
}
}
}
/**
* Expand hrefs in place, recursively.
* @param node source element
*/
private Element expand(Element node) throws Exception {
// expand hrefs
Attr href = node.getAttributeNode("href");
if (href != null && !node.getNodeName().equals("url")) {
String source=href.getValue();
Node sub = parse(source);
boolean isExtern = source.startsWith("http://")
|| source.startsWith("file://");
if (sub != null) {
if (source.lastIndexOf(".")>0) {
source=source.substring(0,source.lastIndexOf("."));
}
if (source.lastIndexOf("/")>0) {
source=source.substring(source.lastIndexOf("/")+1);
}
node.removeAttribute("href");
node.setAttribute("defined-in", source);
Document doc = node.getOwnerDocument();
Element copy = null;
Node first = sub.getFirstChild();
for (Node child=first; child!=null;
child=child.getNextSibling()) {
if (child.getNodeType() == Node.ELEMENT_NODE) {
copy = (Element)doc.importNode(child, true);
break;
}
}
moveChildren(node, copy);
node.getParentNode().replaceChild(copy,node);
node = copy;
// if expanded xml is not local to gump, make a local copy
// and "redirect" location using extern-prefix attribute
if (isExtern) {
String prefix = node.getNodeName() + "_";
// try to use name attribute as source, otherwise cross
// fingers and hope the current source is unique
if (node.getAttribute("name") != null) {
source = node.getAttribute("name");
}
output (sub, "work/" + prefix + source + ".xml");
node.setAttribute("defined-in", source);
node.setAttribute("extern-prefix",prefix);
}
}
}
// move all profile information to the front
Node first = node.getFirstChild();
for (Node child=first; child!=null; child=child.getNextSibling()) {
if (child.getNodeName().equals("profile")) {
child = expand((Element)child);
while (child.getFirstChild() != null) {
node.insertBefore(child.getFirstChild(), first);
}
}
}
// recurse through the children
first = node.getFirstChild();
for (Node child=first; child != null; child=child.getNextSibling()) {
if (child.getNodeType()==Node.ELEMENT_NODE) {
Element elem = (Element)child;
try {
child=expand(elem);
} catch (Throwable t) {
String tagName = elem.getTagName();
String nameAttr = elem.getAttribute("name");
String hrefAttr = elem.getAttribute("href");
StringBuffer name = new StringBuffer(tagName);
if (!"".equals(nameAttr)) {
name.append(" with name ").append(nameAttr);
}
if (!"".equals(hrefAttr)) {
name.append(" with href ").append(hrefAttr);
}
System.err.println("Failed to expand "
+ name.toString()
+ " because of exception "
+ t);
}
}
}
return node;
}
/**
* Merge the contents of nodes with the same value for the name attribute.
* Attributes from later definitions get added (or overlay) prior
* definitions. Elements get appended. Elements marked for removal are
* removed.
* @param type Element localname. Typically project or repository.
* @param document Starting point for search.
* @return hashtable of resulting elements
*/
private Hashtable merge(String type, Node document)
throws Exception
{
boolean needRemove = false;
Hashtable list = new Hashtable();
Node child=document.getFirstChild();
for (; child!=null; child=child.getNextSibling()) {
if (!child.getNodeName().equals(type)) continue;
Element element = (Element) child;
String name = element.getAttribute("name");
// check for "removed" elements
if (!needRemove
&& !element.getAttribute("remove").equals("")) {
needRemove = true;
}
Element priorDefinition = (Element)list.get(name);
if (priorDefinition != null && priorDefinition != element) {
Element parent = (Element)priorDefinition.getParentNode();
String definedIn = parent.getAttribute("defined-in");
if (!definedIn.equals("")) {
element.setAttribute("defined-in",definedIn);
}
moveChildren(priorDefinition, element);
parent.removeChild(priorDefinition);
}
list.put(name, element);
}
if (needRemove) {
Vector removeThem = new Vector();
Enumeration enum = list.elements();
while (enum.hasMoreElements()) {
Element element = (Element)enum.nextElement();
if (!element.getAttribute("remove").equals("")) {
removeThem.addElement(element);
}
}
enum = removeThem.elements();
while (enum.hasMoreElements()) {
Element element = (Element)enum.nextElement();
element.getParentNode().removeChild(element);
list.remove(element.getAttribute("name"));
}
}
return list;
}
/**
* Serialize a DOM tree to file.
* @param dom document to be transformed
* @param dest name of file where the results are to be placed
*/
private void output(Node dom, String dest) throws Exception {
DOMSource in = new DOMSource(dom);
StreamResult out = new StreamResult(dest);
tFactory.newTransformer().transform(in, out);
}
/**
* merge, sort, and insert defaults into a workspace
* @param source document to be transformed
*/
private Jenny(String source) throws Exception {
// Obtain the date to be used
Date lastModified = new Date();
try {
File timestamp = new File(".timestamp");
timestamp.createNewFile();
lastModified = new Date(timestamp.lastModified());
} catch (java.io.IOException ioe) {
ioe.printStackTrace();
}
String dstamp = (new SimpleDateFormat("yyyyMMdd")).format(lastModified);
// process documents
Document doc = parse(source);
Element workspace = (Element)doc.getFirstChild();
Workspace.init(workspace);
expand(workspace);
replaceDate(workspace, dstamp);
Repository.load(merge("repository", workspace).elements());
Server.load(merge("server", workspace).elements());
Module.load(merge("module",workspace).elements());
Project.load(merge("project",workspace).elements());
output (doc, "work/merge.xml");
}
/**
* Combine, colasce, and sort the files referenced by a workspace
* definition into a single XML file.
*/
public static void main(String[] args) {
try {
if (args.length == 1) {
new Jenny(args[0]);
} else {
System.out.println("Usage: Jenny workspace.xml");
}
} catch (Exception e) {
e.printStackTrace();
System.exit(99);
}
}
}
1.1
jakarta-alexandria/jenny/src/java/org/apache/alexandria/jenny/Module.java
Index: Module.java
===================================================================
/*
* $Header:
/home/cvs/jakarta-alexandria/jenny/src/java/org/apache/alexandria/jenny/Module.java,v
1.1 2002/09/02 13:48:43 nicolaken Exp $
* $Revision: 1.1 $
* $Date: 2002/09/02 13:48:43 $
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999-2002 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Alexandria", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.alexandria.jenny;
// DOM classes
import org.w3c.dom.Element;
import org.w3c.dom.Node;
// Java classes
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
public class Module {
static private Hashtable modules = new Hashtable();
private Element element;
private Element cvs;
private String name;
private String srcdir;
private Element description;
private Element url;
private static String cvspass = System.getProperty("user.home")+"/.cvspass";
/** cvspass char conversion data */
private static final char shifts[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
114,120, 53, 79, 96,109, 72,108, 70, 64, 76, 67,116, 74, 68, 87,
111, 52, 75,119, 49, 34, 82, 81, 95, 65,112, 86,118,110,122,105,
41, 57, 83, 43, 46,102, 40, 89, 38,103, 45, 50, 42,123, 91, 35,
125, 55, 54, 66,124,126, 59, 47, 92, 71,115, 78, 88,107,106, 56,
36,121,117,104,101,100, 69, 73, 99, 63, 94, 93, 39, 37, 61, 48,
58,113, 32, 90, 44, 98, 60, 51, 33, 97, 62, 77, 84, 80, 85,223,
225,216,187,166,229,189,222,188,141,249,148,200,184,136,248,190,
199,170,181,204,138,232,218,183,255,234,220,247,213,203,226,193,
174,172,228,252,217,201,131,230,197,211,145,238,161,179,160,212,
207,221,254,173,202,146,224,151,140,196,205,130,135,133,143,246,
192,159,244,239,185,168,215,144,139,165,180,157,147,186,214,176,
227,231,219,169,175,156,206,198,129,164,150,210,154,177,134,127,
182,128,158,208,162,132,167,209,149,241,153,251,237,236,171,195,
243,233,253,240,194,250,191,155,142,137,245,235,163,242,178,152 };
/**
* Create a set of Module definitions based on XML nodes.
* @param moudules list of <module> elements
*/
public static void load(Enumeration modules) throws Exception {
Vector dropThem = new Vector();
while (modules.hasMoreElements()) {
Element element = (Element)modules.nextElement();
try {
new Module(element);
} catch (Throwable t) {
dropThem.addElement(element);
System.err.println("Dropping module "
+ element.getAttribute("name")
+ " because of Exception " + t);
}
}
Enumeration enum = dropThem.elements();
while (enum.hasMoreElements()) {
Element element = (Element)enum.nextElement();
element.getParentNode().removeChild(element);
}
cvslogin();
}
/**
* Find a Module given its name.
* @param String module name
* @return Module
*/
public static Module find(String name) {
return (Module) modules.get(name);
}
/**
* Constructor.
* @param element <module> element
*/
public Module(Element element) throws Exception {
this.element = element;
name = element.getAttribute("name");
computeSrcDir();
promoteProjects();
resolveCvsroot();
Node child=element.getFirstChild();
for (; child != null; child=child.getNextSibling()) {
if (child.getNodeName().equals("description")) {
description = (Element) child;
} else if (child.getNodeName().equals("url")) {
url = (Element) child;
} else if (child.getNodeName().equals("svn")) {
Element svn = (Element) child;
svn.setAttribute("srcdir", name);
}
}
modules.put(name, this);
}
/**
* Property accessor for srcdir attribute.
* @return Source directory associated with this module
*/
public String getSrcDir() {
return srcdir;
}
/**
* Property accessor for description attribute.
* @param name attribute name
* @return Value of the specified attribute.
*/
public Element getDescription() {
return description;
}
/**
* Property accessor for url attribute.
* @param name attribute name
* @return Value of the specified attribute.
*/
public Element getUrl() {
return url;
}
/**
* Append arbitrary XML data to this node.
* @param child Node to be deep copied to this tree.
*/
public void appendChild(Node child) {
element.appendChild(child.cloneNode(true));
}
/**
* Resolve the source directory for this module.
*/
private void computeSrcDir() throws Exception {
srcdir=element.getAttribute("srcdir");
if (srcdir.equals("")) srcdir=name;
srcdir = Workspace.getBaseDir() + "/" + srcdir;
element.setAttribute("srcdir", srcdir);
}
/**
* Set module name on any projects contained herein, and move the
* element up to the workspace.
*/
private void promoteProjects() throws Exception {
Vector projects = new Vector();
// Collect a list of projects, marking them as we go
Node child=element.getFirstChild();
for (; child != null; child=child.getNextSibling()) {
if (! child.getNodeName().equals("project")) continue;
Element project = (Element) child;
if (project.getAttributeNode("module") == null) {
project.setAttribute("module", name);
}
projects.add(project);
}
// Move each project from the module to the workspace
Node parent = element.getParentNode();
String definedIn = element.getAttribute("defined-in");
String prefix = element.getAttribute("extern-prefix");
for (Enumeration e=projects.elements(); e.hasMoreElements(); ) {
Element project = (Element) e.nextElement();
if (project.getAttributeNode("defined-in") == null) {
project.setAttribute("defined-in", definedIn);
if (!prefix.equals(""))
project.setAttribute("extern-prefix",prefix);
}
element.removeChild(project);
parent.appendChild(project);
}
}
/**
* Resolves a repository name into a cvsroot. If there are multiple
* cvs entries, first they are combined into a single elemnt. Then
* the single resulting element (if any) will get decorated with the
* the module name, cvsroot, and password info.
*/
private void resolveCvsroot() throws Exception {
Node child=element.getFirstChild();
for (; child != null; child=child.getNextSibling()) {
if (! child.getNodeName().equals("cvs")) continue;
if (cvs == null) {
cvs = (Element) child;
} else {
Jenny.moveChildren((Element) child, cvs);
}
}
if (cvs != null) {
cvs.setAttribute("srcdir", name);
if (cvs.getAttributeNode("module") == null) {
cvs.setAttribute("module", name);
}
String tag = element.getAttribute("tag");
if (!tag.equals("")) cvs.setAttribute("tag", tag);
String value = cvs.getAttribute("repository");
Repository r = Repository.find(value);
if (r == null) {
throw new Exception(
"repository \"" + value +
"\" not found processing module " + name);
}
String cvsroot = ":" + r.get("method") + ":";
if (r.get("user").length() > 0) {
cvsroot += r.get("user");
}
if (r.get("hostname").length() > 0) {
cvsroot += "@";
if (cvs.getAttributeNode("host-prefix") != null) {
cvsroot += cvs.getAttribute("host-prefix") + ".";
}
cvsroot += r.get("hostname") + ":";
}
cvsroot += r.get("path");
if (cvs.getAttributeNode("dir") != null) {
cvsroot += "/" + cvs.getAttribute("dir");
}
cvs.setAttribute("cvsroot", cvsroot);
cvs.setAttribute("password", r.get("password"));
}
}
/**
* Add entries to cvspass, as necessary, to simulate logon to
* cvs repositories accessed as :pserver:. Note: the .cvspass file
* will not be updated unless there are new entries to add.
*/
private static void cvslogin() throws Exception {
Hashtable password = new Hashtable();
File file = new File(cvspass);
// read existing cvsroot entries
if (file.exists()) {
BufferedReader reader = new BufferedReader(new FileReader(file));
for (String line = null; (line=reader.readLine())!=null; ) {
int split = line.indexOf(' ');
password.put(line.substring(0,split), line.substring(split+1));
}
reader.close();
}
// append new entries
PrintWriter writer = null;
for (Enumeration e=modules.elements(); e.hasMoreElements(); ) {
Element cvs = ((Module) e.nextElement()).cvs;
if (cvs == null) continue;
String cvsroot = cvs.getAttribute("cvsroot");
if (!cvsroot.startsWith(":pserver:")) continue;
if (password.get(cvsroot) == null) {
if (writer == null) {
writer = new PrintWriter(new FileWriter(cvspass, true));
}
String data = "A" + mangle(cvs.getAttribute("password"));
password.put(cvsroot, data);
writer.println(cvsroot + " " + data);
}
}
if (writer != null) writer.close();
}
/**
* Encode a password using the same encryption scheme that cvs uses.
*/
private static String mangle(String password){
char[] buf = password.toCharArray();
for(int i=0; i<buf.length; i++) {
buf[i] = shifts[buf[i]];
}
return new String(buf);
}
}
1.1
jakarta-alexandria/jenny/src/java/org/apache/alexandria/jenny/Project.java
Index: Project.java
===================================================================
/*
* $Header:
/home/cvs/jakarta-alexandria/jenny/src/java/org/apache/alexandria/jenny/Project.java,v
1.1 2002/09/02 13:48:43 nicolaken Exp $
* $Revision: 1.1 $
* $Date: 2002/09/02 13:48:43 $
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999-2002 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Alexandria", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.alexandria.jenny;
// DOM classes
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
// Java classes
import java.util.Comparator;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeSet;
import java.util.Vector;
public class Project {
static private Hashtable projects = new Hashtable();
private Document document;
private Element element;
private String name;
private Element ant = null;
private Hashtable dependsOn = new Hashtable();
private Hashtable referencedBy = new Hashtable();
private Hashtable jars = new Hashtable();
private Element description;
private Element url;
private Vector deliver = new Vector();
private static String nagTo = null;
private static String nagPrefix = null;
/**
* Create a set of Project definitions based on XML nodes.
* @param elements list of <project> elements
*/
public static void load(Enumeration elements) throws Exception {
Element element = null;
while (elements.hasMoreElements()) {
try {
element = (Element)elements.nextElement();
new Project(element);
} catch (Throwable t) {
System.err.println("Dropping project "
+ element.getAttribute("name")
+ " because of Exception " + t);
}
}
// Resolve all references so that the XML can be processed in
// one pass.
for (Enumeration e=((Hashtable) projects.clone()).elements();
e.hasMoreElements();) {
Project p = ((Project)(e.nextElement()));
try {
p.expandDepends();
p.resolveProperties();
} catch (Throwable t) {
System.err.println("Dropping project " + p.get("name")
+ " because of Exception " + t);
p.remove();
}
}
sort();
}
/**
* General attribute accessor.
* @param name attribute name
* @return Value of the specified attribute.
*/
public String get(String name) {
return element.getAttribute(name);
}
/**
* Constructor.
* @param element <project> element
*/
public Project(Element element) throws Exception {
this.element = element;
document = element.getOwnerDocument();
name = element.getAttribute("name");
Element home = null;
Element javadoc = null;
Node child=element.getFirstChild();
for (; child != null; child=child.getNextSibling()) {
if (child.getNodeName().equals("depend")) {
dependsOn.put(((Element)child).getAttribute("project"), child);
} else if (child.getNodeName().equals("option")) {
dependsOn.put(((Element)child).getAttribute("project"), child);
} else if (child.getNodeName().equals("ant")) {
if (ant != null) {
// multiple ant children? Merge them!
Jenny.moveChildren(ant, (Element)child);
element.removeChild(ant);
}
ant = (Element)child;
} else if (child.getNodeName().equals("home")) {
home = (Element)child;
} else if (child.getNodeName().equals("description")) {
description = (Element)child;
} else if (child.getNodeName().equals("url")) {
url = (Element)child;
} else if (child.getNodeName().equals("javadoc")) {
javadoc = (Element)child;
} else if (child.getNodeName().equals("jar")) {
jars.put(((Element)child).getAttribute("id"), child);
} else if (child.getNodeName().equals("deliver")) {
deliver.add(child);
} else if (child.getNodeName().equals("nag")) {
expandNag((Element) child);
}
}
computeHome(home);
if (ant != null) {
genProperties(ant);
genDepends(ant);
if (!get("target").equals("")) {
ant.setAttribute("target", get("target"));
}
}
resolveJavadoc(javadoc);
handleDeliver();
// if only one jar is found, make sure that it can be accessed without
// specifying an id.
if (jars.size() == 1) {
jars.put("", jars.elements().nextElement());
}
projects.put(name, this);
}
/**
* Replace ant "depend" elements with "property" elements. This is
* a convenience "syntatic sugar" that makes for simpler project
* definitions. Attribute "property" becomes name. Attributes
* reference="jarpath" and classpath="true" are added.
* @param ant <ant> element to be processed
*/
private void genProperties(Element ant) throws Exception {
Node child=ant.getFirstChild();
while (child != null) {
Node next = child.getNextSibling();
if (child.getNodeName().equals("depend")) {
// create a new element based on existing element
Element property = document.createElement("property");
property.setAttribute("reference", "jarpath");
property.setAttribute("classpath", "add");
Jenny.moveChildren((Element)child, property);
// change property attribute to name attribute
if (property.getAttributeNode("name")==null) {
Attr pname = property.getAttributeNode("property");
if (pname != null) {
property.setAttribute("name",pname.getValue());
property.removeAttributeNode(pname);
}
}
// replace existing element with new one
ant.replaceChild(property, child);
}
child = next;
}
}
/**
* Generate Depend elements from property references to projects.
* @param ant <ant> element to be processed
*/
private void genDepends(Element ant) throws Exception {
Node child=ant.getFirstChild();
for (;child!=null; child=child.getNextSibling()) {
if (!child.getNodeName().equals("property")) continue;
Element property = (Element) child;
String dependency = property.getAttribute("project");
if (dependency.equals("")) continue;
if (dependency.equals(name)) continue;
if (dependsOn.get(dependency) != null) continue;
if (property.getAttribute("reference").equals("srcdir")) continue;
Element depend = document.createElement("depend");
depend.setAttribute("project", dependency);
if (property.getAttributeNode("classpath") == null) {
depend.appendChild(document.createElement("noclasspath"));
}
Attr runtime = property.getAttributeNode("runtime");
if (runtime != null) {
depend.setAttribute("runtime", runtime.getValue());
}
element.appendChild(depend);
dependsOn.put(dependency, depend);
}
}
/**
* Resolve home directory. In the process copy any description and
* url elements necessary to complete this definition.
* @param home <ant> element which may contain info
*/
private void computeHome(Element home) {
String basedir = Workspace.getBaseDir();
Module module = Module.find(element.getAttribute("module"));
if (module == null) return;
String srcdir;
String pkg = element.getAttribute("package");
if (pkg.equals("")) {
srcdir = module.getSrcDir();
} else {
srcdir = Workspace.getPkgDir() + "/" + pkg;
}
element.setAttribute("srcdir", srcdir);
// if a description is not provided, copy the one from the module
if (description == null) {
description = module.getDescription();
if (description != null) {
element.appendChild(description.cloneNode(true));
}
}
// if a url is not provided, copy the one from the module
if (url == null) {
url = module.getUrl();
if (url != null) {
element.appendChild(url.cloneNode(true));
}
}
// compute home directory
String result=element.getAttribute("home");
if (result.equals("")) {
if (home != null) {
String attr;
if (! (attr=home.getAttribute("parent")).equals("")) {
result = basedir + "/" + attr;
} else if (! (attr=home.getAttribute("nested")).equals("")) {
result = srcdir + "/" + attr;
} else if (! (attr=home.getAttribute("dir")).equals("")) {
result = attr;
}
}
if (result.equals("")) result=srcdir;
element.setAttribute("home", result);
} else {
element.setAttribute("srcdir", result);
}
}
/**
* Copy selected attribute and elements from dependent projects. This
* simplifies generation by essentially making project definitions
* self contained.
*/
private void expandDepends() throws Exception {
String jardir = Workspace.getJarDir();
for (Enumeration e=dependsOn.keys(); e.hasMoreElements(); ) {
String name = (String)e.nextElement();
Element depend = (Element) dependsOn.get(name);
Project target = (Project)projects.get(name);
String idsAttr = depend.getAttribute("ids");
StringTokenizer tok = new StringTokenizer(idsAttr, " ", false);
Vector jarIds = new Vector();
while (tok.hasMoreTokens()) {
jarIds.add(tok.nextToken());
}
boolean buildable = false;
if (!depend.getNodeName().equals("option")) {
require(target, "project", name);
}
if (target == null) continue;
target.referencedBy.put(this, depend);
depend.setAttribute("home",target.get("home"));
depend.setAttribute("defined-in",target.get("defined-in"));
Node child=target.element.getFirstChild();
for (; child != null; child=child.getNextSibling()) {
if (child.getNodeName().equals("jar")) {
String id = ((Element) child).getAttribute("id");
if (idsAttr.equals("")
|| (!id.equals("") && jarIds.contains(id))) {
depend.appendChild(child.cloneNode(false));
}
} else if (child.getNodeName().equals("ant")) {
depend.appendChild(document.createElement("ant"));
buildable = true;
} else if (child.getNodeName().equals("script")) {
depend.appendChild(document.createElement("script"));
buildable = true;
}
}
if (buildable && !jardir.equals("")) {
String module = target.get("module");
depend.setAttribute("home", jardir + "/" + module);
child=depend.getFirstChild();
for (; child != null; child=child.getNextSibling()) {
if (child.getNodeName().equals("jar")) {
String jarname = ((Element)child).getAttribute("name");
jarname = jarname.substring(jarname.lastIndexOf("/")+1);
((Element)child).setAttribute("name", jarname);
}
}
}
}
}
/**
* Determine if this project has any unsatisfied dependencies left
* on the todo list.
* @param todo the list of projects yet to be done (includes this one).
* @return true if this project is ready to go
*/
private boolean isReady(Set todo) {
for (Enumeration e=dependsOn.keys(); e.hasMoreElements();) {
if (todo.contains(e.nextElement())) return false;
}
return true;
}
/**
* Determine if this project is referenced by anything on the todo list.
* @param todo the list of projects yet to be done (includes this one).
* @return true if this project is holding up progress
*/
private boolean isPrereq(Set todo) {
for (Enumeration e=referencedBy.keys(); e.hasMoreElements();) {
Project p = (Project)e.nextElement();
if (todo.contains(p.name)) return true;
}
return false;
}
/**
* Move this element to the end of the parents set of children.
*/
private void moveToLast() {
Element parent = (Element) element.getParentNode();
parent.removeChild(element);
parent.appendChild(element);
}
/**
* Process all inherited dependencies.
*/
private void inheritDependencies() {
Vector inheritance = new Vector();
for (Enumeration e=dependsOn.elements(); e.hasMoreElements(); ) {
Element depend = (Element) e.nextElement();
String inherit = depend.getAttribute("inherit");
Project p = (Project) projects.get(depend.getAttribute("project"));
if (p == null) continue;
for (Enumeration d=p.dependsOn.keys(); d.hasMoreElements(); ) {
String name = (String) d.nextElement();
if (dependsOn.get(name) != null) continue;
Element source = (Element) p.dependsOn.get(name);
String type = source.getNodeName();
// if inherit="all" is specified on a depends element, then all
// of the optional and depends elements on the referenced
// project are inherited by this project.
//
// if inherit="hard", the same thing happens except that all
// optional dependencies are converted to "hard" dependencies
// in the copy.
if (inherit.equals("all") || inherit.equals("hard")) {
Element clone = (Element) source.cloneNode(true);
if (inherit.equals("hard") && type.equals("option")) {
Element renamed = document.createElement("depend");
Jenny.moveChildren(clone, renamed);
clone = renamed;
}
inheritance.add(clone);
// look for runtime="true" dependencies in the referenced
// project. Convert depends to options if the reference to
// the project is an option.
} else if (inherit.equals("runtime")) {
if (source.getAttribute("runtime").equals("true")) {
Element clone = (Element) source.cloneNode(true);
if (type.equals("option")) {
Element renamed = document.createElement("option");
Jenny.moveChildren(clone, renamed);
clone = renamed;
}
inheritance.add(clone);
}
}
// if this project depends on any project which in turn has
// a dependency which specifies inherit="jars", then inherit
// that dependency.
if (source.getAttribute("inherit").equals("jars")) {
Element clone = (Element) source.cloneNode(true);
clone.setAttribute("runtime", "true");
inheritance.add(clone);
}
}
}
// Add the inherited nodes
for (Enumeration e=inheritance.elements(); e.hasMoreElements(); ) {
Element inherited = (Element) e.nextElement();
String project = inherited.getAttribute("project");
if (dependsOn.get(project) == null) {
inherited.setAttribute("inherited", "true");
dependsOn.put(project, inherited);
element.appendChild(inherited);
}
}
}
/**
* Implement a deterministing sort order. Projects which are most
* referenced get priority. After that, order is determined alphabetically.
*/
private static class Ranker implements Comparator {
public int compare(Object o1, Object o2) {
Project p1 = (Project) projects.get(o1);
Project p2 = (Project) projects.get(o2);
if (p1 == p2) return 0;
if (p1 == null) return -1;
if (p2 == null) return 1;
int diff = p2.referencedBy.size() - p1.referencedBy.size();
if (diff != 0) return diff;
return ((String)o1).compareTo((String)o2);
}
}
/**
* Sort all projects in an order that respects the dependencies. If such
* an order can not be determined, print out the ones that form a loop.
* As we determine the order, process the inherited dependencies. This
* way the inheritance will recurse properly.
*/
private static void sort() throws Exception {
TreeSet todo = new TreeSet(new Ranker());
todo.addAll(projects.keySet());
// As long as there are projects which are ready, put the next
// available one at the end of the list.
for (Iterator i=todo.iterator(); i.hasNext();) {
Project p = (Project) projects.get(i.next());
if (p.isReady(todo)) {
p.moveToLast();
p.inheritDependencies();
todo.remove(p.name);
i=todo.iterator();
}
}
// Did we succeed?
if (todo.isEmpty()) return;
// Remove all elements which are not prereqed by any projects
// remaining
if (todo.isEmpty()) return;
for (Iterator i=todo.iterator(); i.hasNext();) {
Project p = (Project) projects.get(i.next());
if (!p.isPrereq(todo)) {
todo.remove(p.name);
i=todo.iterator();
}
}
// Construct a list of the rest, and throw an exception
String message="Circular dependency loop involving:";
for (Iterator i=todo.iterator(); i.hasNext();) {
Project p = (Project) projects.get(i.next());
message += "\n " + p.name;
}
throw new Exception(message);
}
/**
* Resolve property references, based on the value of "reference"
* attribute (if present). Supported values for reference are:
*
* <ul>
* <li> home: the home directory for the referenced project </li>
* <li> jar: the simple name (path relative to home) of the jar in a
* referenced project. </li>
* <li> jarpath: the fully qualified path of the jar in a referenced
* project. </li>
* <li> srcdir: the srcdir for the module containing the project. </li>
* <li> path: a path which is to be interpreted relative to the srcdir
* for the module containing this project </li>
* </ul>
*/
private void resolveProperties() throws Exception {
if (ant == null) return;
Node child=ant.getFirstChild();
for (;child!=null; child=child.getNextSibling()) {
if (!child.getNodeName().equals("property")) continue;
Element property = (Element) child;
if (property.getAttributeNode("value") != null) continue;
String reference = property.getAttribute("reference");
String projectName = property.getAttribute("project");
String value = null;
if (reference.equals("home")) {
Project project = (Project) projects.get(projectName);
require (project, "project", projectName);
value = project.get("home");
property.setAttribute("type", "path");
} else if (reference.equals("jar")) {
String id = property.getAttribute("id");
Element jar = getJar (projectName, property.getAttribute("id"));
value = jar.getAttribute("name");
} else if (reference.equals("jarpath")) {
Project project = (Project) projects.get(projectName);
Element jar = getJar (projectName, property.getAttribute("id"));
value = project.get("home") + "/" + jar.getAttribute("name");
property.setAttribute("type", "path");
} else if (reference.equals("srcdir")) {
Module module = Module.find(projectName);
require (module, "module", projectName);
value = module.getSrcDir();
property.setAttribute("type", "path");
} else if (property.getAttributeNode("path") != null) {
Project project = (Project) projects.get(projectName);
if (project == null) project=this;
value = project.get("srcdir");
value += "/" + property.getAttribute("path");
property.setAttribute("type", "path");
}
if (value != null) property.setAttribute("value", value);
}
}
/**
* Locate a specific jar from a dependency, issuing an exception if
* the jar can not be found.
* @param projectName the name of the project
* @param id the identifier for which jar is desired
* @return Value of the specified attribute.
*/
private Element getJar(String projectName, String id)
throws Exception
{
Project project = (Project) projects.get(projectName);
require (project, "project", projectName);
Element jar = (Element)project.jars.get(id);
if (jar != null) return jar;
if (!id.equals("")) {
throw new Exception(
"A jar with id \"" + id + "\" was not found in project \"" +
projectName + "\" referenced by project " + name);
} else if (project.jars.size() > 1) {
throw new Exception(
"Multiple jars defined by project \"" + projectName + "\" " +
"referenced by project \"" + name + "\"; " +
"an id attribute is required to select the one you want.");
} else {
throw new Exception(
"Project \"" + projectName + "\" referenced by project " +
name + " defines no jars as output.");
}
}
/**
* If a javadoc child was found, add any missing project, module,
* or description information; resolve path; and copy the resulting
* node to the specified module.
* @param javadoc child XML element
*/
private void resolveJavadoc(Element javadoc) throws Exception {
if (javadoc == null) return;
// retrieve url and dir of javadoc from the workspace
Element config = Workspace.getJavaDoc();
if (config == null) return;
String url = config.getAttribute("url");
String javadocDir = config.getAttribute("dir");
// default project attribute to the name of this project
if (javadoc.getAttributeNode("project") == null)
javadoc.setAttribute("project", name);
// default module attribute to the module which this project belongs
String moduleName = javadoc.getAttribute("module");
if (moduleName.equals("")) moduleName = this.get("module");
Module module = Module.find(moduleName);
require (module, "module", moduleName);
if (!moduleName.equals(this.get("module"))) {
javadoc.setAttribute("defined-in", this.get("module"));
}
// if there are no child nodes, add this project's description
if (!javadoc.hasChildNodes() && description!=null) {
Element desc = (Element) description.cloneNode(true);
javadoc.appendChild(desc);
}
// resolve relative and full path to this javadoc entry
String path = javadoc.getAttribute("nested");
String fullpath;
if (!path.equals("")) {
fullpath = get("srcdir") + "/" + path;
} else {
path = javadoc.getAttribute("parent");
fullpath = Workspace.getBaseDir() + "/" + path;
}
path = moduleName + "/" + path;
// for each description entry, resolve source, url, and dest attrs.
Node child=javadoc.getFirstChild();
for (; child != null; child=child.getNextSibling()) {
if (child.getNodeName().equals("description")) {
Element desc = (Element) child;
String dir = desc.getAttribute("dir");
String append = "";
if (!dir.equals("")) append = "/" + dir;
desc.setAttribute("source", fullpath + append);
if (url.equals("")) {
desc.setAttribute("url", "file:///" + fullpath + append);
} else {
desc.setAttribute("url", url + path + append);
}
if (!javadocDir.equals("")) {
desc.setAttribute("dest", javadocDir + "/" + path + append);
}
}
}
// copy the entire result to the desired module
module.appendChild(javadoc);
}
/**
* Require that a specified object not be null, otherwise produce an error
* message indicating what attribute the problem occurred on.
* @param object the object which must not be null
* @param attr the attribute from which this value was derived
* @param value the value of this attribute
* @return Value of the specified attribute.
*/
private void require(Object object, String attr, String value)
throws Exception
{
if (object != null) return;
throw new Exception(
attr + " \"" + value + "\" not found processing project " + name
);
}
/**
* Remove this Project instance from the workspace.
*/
private void remove() {
projects.remove(name);
element.getParentNode().removeChild(element);
}
/**
* For all deliver elements, add them to the corresponding site
* elements, if these are defined.
*/
private void handleDeliver() {
Enumeration elements = deliver.elements();
String srcdir = element.getAttribute("srcdir");
while (elements.hasMoreElements()) {
Element deliver = (Element) elements.nextElement();
String siteName = deliver.getAttribute("tosite");
Element site = Server.getSite(siteName);
if (site != null) {
String fromdir = deliver.getAttribute("fromdir");
deliver.setAttribute("fromdir", srcdir + "/" + fromdir);
site.appendChild(deliver);
}
}
}
/**
* Add default values for subjects and regexp if none have been
* specified.
*
* Push attributes to nested regexp elements
*/
private void expandNag(Element nag) {
if (nagPrefix == null) {
Element workspaceNag = Workspace.getNag();
if (workspaceNag == null) {
nagPrefix = "[GUMP]";
} else {
if (!workspaceNag.getAttribute("prefix").equals("")) {
nagPrefix = workspaceNag.getAttribute("prefix");
} else {
nagPrefix = "[GUMP]";
}
if (!workspaceNag.getAttribute("to").equals("")) {
nagTo = workspaceNag.getAttribute("to");
}
}
}
String subject = nagPrefix + " Build Failure - "+name;
String to = nagTo == null ? nag.getAttribute("to") : nagTo;
String from = nag.getAttribute("from");
if (!nag.getAttribute("subject").equals("")) {
subject = nagPrefix + " " + nag.getAttribute("subject");
}
if (!nag.hasChildNodes()) {
Element regexp = nag.getOwnerDocument().createElement("regexp");
regexp.setAttribute("pattern", "/BUILD FAILED/");
regexp.setAttribute("subject", subject);
regexp.setAttribute("to", to);
regexp.setAttribute("from", from);
nag.appendChild(regexp);
} else {
Node child = nag.getFirstChild();
for (; child != null; child = child.getNextSibling()) {
if (child.getNodeName().equals("regexp")) {
Element regexp = (Element)child;
if (regexp.getAttribute("pattern").equals("")) {
regexp.setAttribute("pattern", "/BUILD FAILED/");
}
if (regexp.getAttribute("subject").equals("")) {
regexp.setAttribute("subject", subject);
} else {
String orig = regexp.getAttribute("subject");
regexp.setAttribute("subject", nagPrefix + " " + orig);
}
if (nagTo != null
|| regexp.getAttribute("to").equals("")) {
regexp.setAttribute("to", to);
}
if (regexp.getAttribute("from").equals("")) {
regexp.setAttribute("from", from);
}
}
}
}
}
}
1.1
jakarta-alexandria/jenny/src/java/org/apache/alexandria/jenny/Repository.java
Index: Repository.java
===================================================================
/*
* $Header:
/home/cvs/jakarta-alexandria/jenny/src/java/org/apache/alexandria/jenny/Repository.java,v
1.1 2002/09/02 13:48:43 nicolaken Exp $
* $Revision: 1.1 $
* $Date: 2002/09/02 13:48:43 $
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999-2002 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Alexandria", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.alexandria.jenny;
// DOM classes
import org.w3c.dom.Element;
import org.w3c.dom.Node;
// Java classes
import java.util.Enumeration;
import java.util.Vector;
import java.util.Hashtable;
public class Repository {
static private Hashtable repositories = new Hashtable();
private Element element;
private String name;
/**
* Create a set of Repository definitions based on XML nodes.
* @param moudules list of <module> elements
*/
public static void load(Enumeration repositories) throws Exception {
while (repositories.hasMoreElements()) {
new Repository((Element)repositories.nextElement());
}
}
/**
* Find a Repository given its name.
* @param name module name
* @return Repository
*/
public static Repository find(String name) {
return (Repository) repositories.get(name);
}
/**
* Constructor.
* @param element <module> element
*/
public Repository(Element element) throws Exception {
this.element = element;
name = element.getAttribute("name");
resolve(element);
repositories.put(name, this);
}
/**
* General attribute accessor.
* @param name attribute name
* @return Value of the specified attribute.
*/
public String get(String name) {
return element.getAttribute(name);
}
/**
* Use text nodes under root elements to fill in defaults for repository
* attributes.
*/
private void resolve(Node node) throws Exception {
// recurse through all children
Node child=node.getFirstChild();
for (; child != null; child=child.getNextSibling()) {
resolve(child);
}
// <parent>text<parent> => <element parent="text">
if (node.getNodeType() != Node.TEXT_NODE) return;
Node parent = node.getParentNode();
Node gparent = parent.getParentNode();
if (!gparent.getNodeName().equals("root")) return;
if (element.getAttributeNode(parent.getNodeName()) == null) {
element.setAttribute(parent.getNodeName(), node.getNodeValue());
}
}
}
1.1
jakarta-alexandria/jenny/src/java/org/apache/alexandria/jenny/Server.java
Index: Server.java
===================================================================
/*
* $Header:
/home/cvs/jakarta-alexandria/jenny/src/java/org/apache/alexandria/jenny/Server.java,v
1.1 2002/09/02 13:48:43 nicolaken Exp $
* $Revision: 1.1 $
* $Date: 2002/09/02 13:48:43 $
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999-2002 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Alexandria", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.alexandria.jenny;
// DOM classes
import org.w3c.dom.Element;
import org.w3c.dom.Node;
// Java classes
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
public class Server {
private static HashMap sites = new HashMap();
/**
* Create a set of site definitions based on XML nodes.
* @param elements list of <server> elements
*/
public static void load(Enumeration elements) throws Exception {
Element element = null;
while (elements.hasMoreElements()) {
try {
element = (Element)elements.nextElement();
new Server(element);
} catch (Throwable t) {
System.err.println("Dropping server "
+ element.getAttribute("name")
+ " because of Exception " + t);
}
}
}
/**
* Static accessor for the named site
* @return the element corresponding to the site, if it is defined
* in a server document as well as in the workspace.
*/
public static Element getSite(String name) {
return (Element) sites.get(name);
}
/**
* Constructor
*
* <p>Promotes all <site> children to workspace, if the site
* is defined in the workspace's deliver element. Otherwise,
* simply remove the site child element.</p>
*/
private Server(Element element) {
String name = element.getAttribute("name");
ArrayList children = new ArrayList();
Node child = element.getFirstChild();
for (; child != null; child=child.getNextSibling()) {
if (child.getNodeName().equals("site")) {
Element site = (Element) child;
site.setAttribute("server", name);
String siteName = site.getAttribute("name");
if (Workspace.getServer(name) != null
&& Workspace.isSiteDefined(siteName)) {
sites.put(siteName, site);
}
children.add(site);
}
}
Iterator iter = children.iterator();
Node parent = element.getParentNode();
while (iter.hasNext()) {
Element site = (Element) iter.next();
element.removeChild(site);
Element server = Workspace.getServer(name);
if (server != null
&& Workspace.isSiteDefined(site.getAttribute("name"))) {
addServerAttributes(server, site);
parent.appendChild(site);
}
}
}
/**
* Adds attributes defined in Workspace to the site element.
*
* @param server server element from workspace
* @param site site element from server
*/
private void addServerAttributes(Element server, Element site) {
site.setAttribute("scratchdir", Workspace.getScratchDir());
site.setAttribute("username",
server.getAttribute("username"));
String drop = server.getAttribute("dropdir");
if (drop.equals("")) {
drop = "/tmp";
}
site.setAttribute("dropdir", drop);
}
}
1.1
jakarta-alexandria/jenny/src/java/org/apache/alexandria/jenny/Workspace.java
Index: Workspace.java
===================================================================
/*
* $Header:
/home/cvs/jakarta-alexandria/jenny/src/java/org/apache/alexandria/jenny/Workspace.java,v
1.1 2002/09/02 13:48:43 nicolaken Exp $
* $Revision: 1.1 $
* $Date: 2002/09/02 13:48:43 $
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999-2002 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Alexandria", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.alexandria.jenny;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import java.util.HashMap;
public class Workspace {
static final String GUMP_VERSION = "0.3";
private static Element element;
private static String basedir;
private static Element javadoc;
private static Element deliver;
private static Element nag;
private static HashMap servers = new HashMap();
private static HashMap sites = new HashMap();
/**
* Static property accessor for basedir attribute.
* @return Base directory associated with this workspace
*/
public static String getBaseDir() {
return element.getAttribute("basedir");
}
/**
* Static property accessor for pkgdir attribute.
* @return Package directory associated with this workspace
*/
public static String getPkgDir() {
return element.getAttribute("pkgdir");
}
/**
* Static property accessor for jardir attribute.
* @return Package directory associated with this workspace
*/
public static String getJarDir() {
return element.getAttribute("jardir");
}
/**
* Static property accessor for javadoc element.
* @return Javadoc element (if any) associated with this workspace
*/
public static Element getJavaDoc() {
return javadoc;
}
/**
* Static property accessor for nag element.
* @return Javadoc element (if any) associated with this workspace
*/
public static Element getNag() {
return nag;
}
/**
* Static accessor - do we deliver to the given site?
* @return true if a server of the given name is defined in the workspace.
*/
public static boolean isSiteDefined(String name) {
return sites.containsKey(name);
}
/**
* Static accessor for deliver's scratchdir attribute.
* @return Deliver scratchdir associated with this workspace.
*/
public static String getScratchDir() {
if (deliver != null) {
return deliver.getAttribute("scratchdir");
}
return null;
}
/**
* Static accessor for deliver's named server child.
* @return null if server is not defined, the server element otherwise.
*/
public static Element getServer(String name) {
return (Element) servers.get(name);
}
/**
* Default and verify various workspace attributes.
* If not specified:
* banner-image="http://jakarta.apache.org/images/jakarta-logo.gif"
* banner-link="http://jakarta.apache.org"
* cvsdir=basedir+"/cvs"
* logdir=basedir+"/log"
* pkgdir=basedir
* @param Workspace element to be updated
*/
public static void init(Element workspace) throws Exception {
Workspace.element = workspace;
if (!workspace.getAttribute("version").equals(GUMP_VERSION)) {
throw new Exception("workspace version " + GUMP_VERSION +
" required.");
}
basedir = workspace.getAttribute("basedir");
if (workspace.getAttribute("banner-image").equals("")) {
workspace.setAttribute("banner-image",
"http://jakarta.apache.org/images/jakarta-logo.gif");
}
if (workspace.getAttribute("banner-link").equals("")) {
workspace.setAttribute("banner-link", "http://jakarta.apache.org");
}
if (workspace.getAttribute("logdir").equals("")) {
workspace.setAttribute("logdir", basedir + "/log");
}
if (workspace.getAttribute("cvsdir").equals("")) {
workspace.setAttribute("cvsdir", basedir + "/cvs");
}
if (workspace.getAttribute("pkgdir").equals("")) {
workspace.setAttribute("pkgdir", basedir);
}
Node child=element.getFirstChild();
for (; child != null; child=child.getNextSibling()) {
if (child.getNodeName().equals("javadoc")) {
javadoc = (Element) child;
} else if (child.getNodeName().equals("nag")) {
nag = (Element) child;
} else if (child.getNodeName().equals("deliver")) {
handleDeliver((Element) child);
}
}
if (deliver != null) {
element.removeChild(deliver);
String scratchdir = deliver.getAttribute("scratchdir");
if (scratchdir.equals("")) {
deliver.setAttribute("scratchdir", basedir+"/scratch");
}
}
}
/**
* Fill map of servers.
*/
private static void handleDeliver(Element element) {
deliver = element;
Node child=element.getFirstChild();
for (; child != null; child=child.getNextSibling()) {
if (child.getNodeName().equals("server")) {
Element server = (Element) child;
servers.put(server.getAttribute("name"), server);
handleSites(server);
}
}
}
/**
* Fill map of sites.
*/
private static void handleSites(Element element) {
Node child=element.getFirstChild();
for (; child != null; child=child.getNextSibling()) {
if (child.getNodeName().equals("site")) {
Element site = (Element) child;
sites.put(site.getAttribute("name"), site);
}
}
}
}
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>