Initial commit of Sigil contribution. (FELIX-1142)


git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@793581 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/sigil/sigil-builder/.classpath b/sigil/sigil-builder/.classpath
new file mode 100644
index 0000000..5805c94
--- /dev/null
+++ b/sigil/sigil-builder/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="build-libs/classes" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="lib" path="build-libs/ant.jar"/>
+	<classpathentry kind="lib" path="build-libs/osgi.core.jar"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/sigil/sigil-builder/.project b/sigil/sigil-builder/.project
new file mode 100644
index 0000000..646a5cd
--- /dev/null
+++ b/sigil/sigil-builder/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>sigil-builder</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/sigil/sigil-builder/build.xml b/sigil/sigil-builder/build.xml
new file mode 100644
index 0000000..4161e54
--- /dev/null
+++ b/sigil/sigil-builder/build.xml
@@ -0,0 +1,227 @@
+<?xml version="1.0"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+  
+    http://www.apache.org/licenses/LICENSE-2.0
+  
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<project name="sigil-builder" default="build">
+  <property name="user.props" value="user.properties" />
+  <property file="${user.props}"/>
+  <property file="project.properties"/>
+  <property file="download.properties"/>
+
+  <property name="error.internal.target" value="Do not call this target directly"/>
+
+  <property name="eclipse.sdk" value="${eclipse.install.dir}"/>
+  <property name="extras.sdk" value="build-libs/target-platform-extras"/>
+
+  <condition property="isUnix">
+      <os family="unix"/>
+  </condition>
+
+  <!-- PUBLIC TARGETS -->
+
+  <target name="build"
+    depends="clean-tmp, target-platform, pdebuild"/>
+
+  <target name="clean-tmp">
+    <delete dir="target/tmp" />
+  </target>
+  
+  <target name="clean">
+    <delete dir="target"/>
+    <delete dir="build-libs/classes"/>
+  </target>
+
+  <!-- create target platform -->
+  <target name="target-platform" depends="rsync-platform, copy-platform"/>
+
+  <target name="rsync-platform" if="isUnix">
+      <mkdir dir="${target.platform}/eclipse" />
+      <exec executable="rsync" append="true"
+        output="${target.platform}/rsync.log" >
+	<arg line="-av --delete ${eclipse.sdk}/ ${extras.sdk}/ ${target.platform}/eclipse" />
+      </exec>
+  </target>
+
+  <target name="copy-platform" unless="isUnix">
+      <mkdir dir="${target.platform}/eclipse" />
+      <copy todir="${target.platform}/eclipse">
+	<fileset dir="${eclipse.sdk}"/>
+	<fileset dir="${extras.sdk}" />
+      </copy>
+  </target>
+
+  <target name="init">
+    <mkdir dir="target"/>
+    <mkdir dir="target/features"/>
+    <mkdir dir="target/plugins"/>
+  </target>
+
+  <target name="custom.tasks">
+    <mkdir dir="build-libs/classes"/>
+    <javac srcdir="src" destdir="build-libs/classes" debug="on">
+      <classpath>
+        <fileset dir="build-libs">
+          <include name="osgi.core.jar"/>
+        </fileset>
+      </classpath>
+    </javac>
+    <taskdef name="findbundle" classname="org.cauldron.sigil.build.FindBundlesTask">
+      <classpath>
+        <pathelement location="build-libs/osgi.core.jar"/>
+        <pathelement location="build-libs/classes"/>
+      </classpath>
+    </taskdef>
+    <taskdef name="siteInsertFeatures" classname="org.cauldron.sigil.build.SiteInsertFeatures">
+      <classpath>
+        <pathelement location="build-libs/classes"/>
+      </classpath>
+    </taskdef>
+  </target>
+
+  <target name="findbundles" depends="custom.tasks">
+    <!-- Find the Equinox launcher JAR -->
+    <echo>${eclipse.install.dir}</echo>
+    <findbundle dir="${eclipse.install.dir}/plugins" symbolicname="org.eclipse.equinox.launcher" property="eclipse.launcher.version"/>
+    <property name="eclipse.launcher.jar" location="${eclipse.install.dir}/plugins/org.eclipse.equinox.launcher_${eclipse.launcher.version}.jar"/>
+
+    <!-- Find the PDE Build scripts -->
+    <findbundle dir="${eclipse.install.dir}/plugins" symbolicname="org.eclipse.pde.build" property="eclipse.pdebuild.version"/>
+    <property name="eclipse.productBuild.xml" location="${eclipse.install.dir}/plugins/org.eclipse.pde.build_${eclipse.pdebuild.version}/scripts/productBuild/productBuild.xml"/>
+    <property name="eclipse.featureBuild.xml" location="${eclipse.install.dir}/plugins/org.eclipse.pde.build_${eclipse.pdebuild.version}/scripts/build.xml"/>
+  </target>
+
+  <!-- Unused
+  <target name="download" depends="init">
+    <mkdir dir="${target.platform}"/>
+
+    <echo message="Downloading platform runtime"/>
+    <get dest="${target.platform}/platform-runtime.zip"
+       src="${download.base}/${download.dir}/${download.platform.runtime}" verbose="true"/>
+
+    <echo message="Downloading RCP delta pack"/>
+    <get dest="${target.platform}/deltapack.zip"
+       src="${download.base}/${download.dir}/${download.deltapack}" verbose="true"/>
+
+    <echo message="Downloading CVS client"/>
+    <get dest="${target.platform}/cvsclient.zip"
+       src="${download.base}/${download.dir}/${download.cvsclient}" verbose="true"/>
+
+    <unzip src="${target.platform}/platform-runtime.zip" dest="${target.platform}" overwrite="true"/>
+    <unzip src="${target.platform}/deltapack.zip" dest="${target.platform}" overwrite="true"/>
+    <unzip src="${target.platform}/cvsclient.zip" dest="${target.platform}" overwrite="true"/>
+  </target>
+  -->
+
+  <target name="copy.projects" depends="init">
+    <foreach list="${plugins}" param="plugin.id"  target="__copy.plugin"/>
+    <foreach list="${features}" param="feature.id" target="__copy.feature"/>
+  </target>
+
+  <target name="copy.properties" depends="init">
+    <copy file="builder/template.build.properties" tofile="builder/build.properties" overwrite="true"/>
+    <pathconvert property="basedir.unix" targetos="unix">
+      <path location="${basedir}"/>
+    </pathconvert>
+    <replace file="builder/build.properties">
+      <replacefilter token="@@WARNING_TEXT" value="Warning! This file is auto-generated. Changes will be overwritten!"/>
+      <replacefilter token="@@BUILD_PROJECT_DIR" value="${basedir.unix}"/>
+      <replacefilter token="@@TARGET_PLATFORM" value="${target.platform}"/>
+    </replace>
+  </target>
+
+  <!-- Unused
+  <target name="copy.deps">
+    <copy todir="${target.platform}/eclipse/plugins">
+      <fileset dir="target-libs" includes="*.jar"/>
+    </copy>
+  </target>
+  -->
+
+  <target name="pdebuild" depends="findbundles,copy.projects,copy.properties">
+    <java jar="${eclipse.launcher.jar}" fork="true" failonerror="true">
+      <sysproperty key="builder" path="${basedir}/builder"/>
+      <arg line="-application org.eclipse.ant.core.antRunner"/>
+      <arg line="-buildfile ${eclipse.featureBuild.xml}"/>
+    </java>
+  </target>
+  
+  <target name="new.updateSite">
+    <copy file="site.xml" todir="${updateSiteDir}"/>
+    <antcall target="copy.updateSite" />
+  </target>
+
+  <target name="copy.updateSite" depends="custom.tasks">
+    <copy todir="${updateSiteDir}">
+      <fileset dir="target/tmp/eclipse" includes="**/*.jar"/>
+    </copy>
+    <property file="target/finalFeaturesVersions.properties" prefix="featureVersions"/>
+    <siteInsertFeatures sitexmlfile="${updateSiteDir}/site.xml"
+      features="${features}"
+      versionPropPrefix="featureVersions"
+      categoryPropPrefix="category"/>
+  </target>
+
+  <!-- INTERNAL TARGETS -->
+  <target name="__copy.plugin">
+    <fail unless="plugin.id" message="${error.internal.target}"/>
+    <echo message="Copying plugin ${plugin.id}"/>
+    <antcall target="__copy.artifact">
+      <param name="artifact.id" value="${plugin.id}"/>
+      <param name="artifact.type" value="plugin"/>
+    </antcall>
+  </target>
+
+  <target name="__copy.feature">
+    <fail unless="feature.id" message="${error.internal.target}"/>
+    <antcall target="__copy.artifact">
+      <param name="artifact.id" value="${feature.id}"/>
+      <param name="artifact.type" value="feature"/>
+    </antcall>
+    
+    <replace file="target/features/${feature.id}/feature.xml">
+      <replacefilter token="http://replace.with.real.url" value="${updateUrl}"/>
+    </replace>
+  </target>
+
+  <target name="__copy.artifact">
+    <fail unless="artifact.id" message="${error.internal.target}"/>
+    <fail unless="artifact.type" message="${error.internal.target}"/>
+
+    <echo message="Copying from ${source.dir}/${artifact.id} to target/${artifact.type}s"/>
+    <copy todir="target/${artifact.type}s">
+      <fileset dir="${source.dir}">
+        <exclude name="${artifact.id}/bin/**"/>
+        <exclude name="${artifact.id}/build/**"/>
+        <exclude name="${artifact.id}/**/*.class"/>
+        <include name="${artifact.id}/**"/>
+      </fileset>
+    </copy>
+  </target>
+
+  <target name="__nodefault">
+    <fail message="There is no default target"/>
+  </target>
+
+  <!-- TASK DEFINITIONS -->
+  <taskdef resource="net/sf/antcontrib/antlib.xml">
+    <classpath>
+      <pathelement location="build-libs/ant-contrib/ant-contrib-1.0b3.jar"/>
+    </classpath>
+  </taskdef>
+
+</project>
diff --git a/sigil/sigil-builder/builder/template.build.properties b/sigil/sigil-builder/builder/template.build.properties
new file mode 100644
index 0000000..a097442
--- /dev/null
+++ b/sigil/sigil-builder/builder/template.build.properties
@@ -0,0 +1,215 @@
+###############################################################################
+#
+# @@WARNING_TEXT
+#
+############# WHAT SHOULD WE BUILD? #############
+
+#To build a Product
+#product=/org.blah.blah/blah.product
+#runPackager=true
+
+#To build a Feature
+topLevelElementId=org.cauldron.sigil.all.feature
+topLevelElementType=feature
+
+#The prefix that will be used in the generated archive.
+archivePrefix=eclipse
+
+# The location underwhich all of the build output will be collected.
+collectingFolder=${archivePrefix}
+
+# The list of {os, ws, arch} configurations to build.  This 
+# value is a '&' separated list of ',' separate triples.  For example, 
+#     configs=win32,win32,x86 & linux,motif,x86
+# By default the value is *,*,*
+configs=\
+	*, *, *
+#	win32, win32, x86
+#	macosx, carbon, ppc &\
+#	linux, gtk, ppc &\
+#	linux, gtk, x86 & \
+#	linux, gtk, x86_64 & \
+#	linux, motif, x86 & \
+#	solaris, motif, sparc & \
+#	solaris, gtk, sparc & \
+#	aix, motif, ppc & \
+#	hpux, motif, PA_RISC & \
+#	macosx, carbon, ppc
+
+# By default PDE creates one archive (result) per entry listed in the configs property.
+# Setting this value to try will cause PDE to only create one output containing all 
+# artifacts for all the platforms listed in the configs property.
+#groupConfigurations=true
+
+#The format of the archive. By default a zip is created using antZip.
+#The list can only contain the configuration for which the desired format is different than zip.
+archivesFormat=*,*,* - folder
+#archivesFormat=win32, win32, x86 - antZip& \
+#	linux, gtk, ppc - antZip &\
+#    linux, gtk, x86 - antZip& \
+#	linux, gtk, x86_64 - antZip& \
+# linux, motif, x86 - antZip& \
+#	solaris, motif, sparc - antZip& \
+#	solaris, gtk, sparc - antZip& \
+#	aix, motif, ppc - antZip& \
+#	hpux, motif, PA_RISC - antZip& \
+#	macosx, carbon, ppc - antZip
+	
+#Set to true if you want the output to be ready for an update jar (no site.xml generated)
+outputUpdateJars=true
+
+#Set to true for Jnlp generation
+#codebase should be a URL that will be used as the root of all relative URLs in the output.
+#generateJnlp=false
+#jnlp.codebase=<codebase url>
+#jnlp.j2se=<j2se version>
+#jnlp.locale=<a locale>
+#jnlp.generateOfflineAllowed=true or false generate <offlineAllowed/> attribute in the generated features
+#jnlp.configs=${configs}			#uncomment to filter the content of the generated jnlp files based on the configuration being built
+
+#Set to true if you want to sign jars
+#signJars=false
+#sign.alias=<alias>
+#sign.keystore=<keystore location>
+#sign.storepass=<keystore password>
+
+#Arguments to send to the zip executable
+zipargs=
+
+#Arguments to send to the tar executable
+tarargs=
+
+#Control the creation of a file containing the version included in each configuration - on by default 
+#generateVersionsLists=false
+
+############## BUILD NAMING CONTROL ################
+# The directory into which the build elements are fetched and where
+# the build takes place.
+buildProjectDirectory=@@BUILD_PROJECT_DIR
+buildDirectory=${buildProjectDirectory}/target
+
+# Type of build.  Used in naming the build output.  Typically this value is
+# one of I, N, M, S, ...
+buildType=N
+
+# ID of the build.  Used in naming the build output.
+buildId=Sigil
+
+# Label for the build.  Used in naming the build output
+buildLabel=${buildType}.${buildId}
+
+# Timestamp for the build.  Used in naming the build output
+timestamp=007
+
+#The value to be used for the qualifier of a plugin or feature when you want to override the value computed by pde.
+#The value will only be applied to plugin or features indicating build.properties, qualifier = context 
+#forceContextQualifier=<the value for the qualifier>
+
+#Enable / disable the generation of a suffix for the features that use .qualifier. 
+#The generated suffix is computed according to the content of the feature   
+#generateFeatureVersionSuffix=true
+
+############# BASE CONTROL #############
+# Settings for the base Eclipse components and Java class libraries 
+# against which you are building.
+# Base location for anything the build needs to compile against.  For example,
+# in most RCP app or a plug-in,  the baseLocation should be the location of a previously
+# installed Eclipse against which the application or plug-in code will be compiled and the RCP delta pack.
+
+base=@@TARGET_PLATFORM
+baseLocation=${base}/eclipse
+#Os/Ws/Arch/nl of the eclipse specified by baseLocation
+baseos=win32
+basews=win32
+basearch=x86
+
+#this property indicates whether you want the set of plug-ins and features to be considered during the build to be limited to the ones reachable from the features / plugins being built
+filteredDependencyCheck=false
+
+#this property indicates whether the resolution should be done in development mode (i.e. ignore multiple bundles with singletons)
+resolution.devMode=false
+
+#pluginPath is a list of locations in which to find plugins and features.  This list is separated by the platform file separator (; or :)
+#a location is one of:  
+#- the location of the jar or folder that is the plugin or feature : /path/to/foo.jar or /path/to/foo
+#- a directory that contains a /plugins or /features subdirectory
+#- the location of a feature.xml, or for 2.1 style plugins, the plugin.xml or fragment.xml
+#pluginPath=
+
+skipBase=true
+eclipseURL=http://www.eclipse.org/downloads/
+eclipseBuildId=3.3RC2
+eclipseBaseURL=${eclipseURL}/eclipse-platform-${eclipseBuildId}-win32.zip
+
+
+############# MAP FILE CONTROL ################
+# This section defines CVS tags to use when fetching the map files from the repository.
+# If you want to fetch the map file from repository / location, change the getMapFiles target in the customTargets.xml
+
+skipMaps=true
+mapsRepo=:pserver:anonymous@example.com/path/to/repo
+mapsRoot=path/to/maps
+mapsCheckoutTag=HEAD
+
+#tagMaps=true
+mapsTagTag=v${buildId}
+
+
+############ REPOSITORY CONTROL ###############
+# This section defines properties parameterizing the repositories where plugins, fragments
+# bundles and features are being obtained from. 
+
+# The tags to use when fetching elements to build.
+# By default thebuilder will use whatever is in the maps.  
+# This value takes the form of a comma separated list of repository identifier (like used in the map files) and the 
+# overriding value
+# For example fetchTag=CVS=HEAD, SVN=v20050101
+# fetchTag=HEAD
+skipFetch=true
+
+
+############# JAVA COMPILER OPTIONS ##############
+# The location of the Java jars to compile against.  Typically the rt.jar for your JDK/JRE
+#bootclasspath=${java.home}/lib/rt.jar
+
+# specific JRE locations to compile against. These values are used to compile bundles specifying a 
+# Bundle-RequiredExecutionEnvironment. Uncomment and set values for environments that you support
+#CDC-1.0/Foundation-1.0= /path/to/rt.jar
+#CDC-1.1/Foundation-1.1=
+#OSGi/Minimum-1.0=
+#OSGi/Minimum-1.1=
+#JRE-1.1=
+#J2SE-1.2=
+#J2SE-1.3=
+#J2SE-1.4=
+#J2SE-1.5=
+#JavaSE-1.6=
+#PersonalJava-1.1=
+#PersonalJava-1.2=
+#CDC-1.0/PersonalBasis-1.0=
+#CDC-1.0/PersonalJava-1.0=
+#CDC-1.1/PersonalBasis-1.1=
+#CDC-1.1/PersonalJava-1.1=
+
+# Specify the output format of the compiler log when eclipse jdt is used
+logExtension=.log
+
+# Whether or not to include debug info in the output jars
+javacDebugInfo=true
+
+# Whether or not to fail the build if there are compiler errors
+javacFailOnError=true
+
+# Enable or disable verbose mode of the compiler
+javacVerbose=true
+
+# Extra arguments for the compiler. These are specific to the java compiler being used.
+#compilerArg=
+
+# Default value for the version of the source code. This value is used when compiling plug-ins that do not set the Bundle-RequiredExecutionEnvironment or set javacSource in build.properties
+javacSource=1.5
+
+# Default value for the version of the byte code targeted. This value is used when compiling plug-ins that do not set the Bundle-RequiredExecutionEnvironment or set javacTarget in build.properties.
+javacTarget=1.5
+
+
diff --git a/sigil/sigil-builder/download.properties b/sigil/sigil-builder/download.properties
new file mode 100644
index 0000000..fd21601
--- /dev/null
+++ b/sigil/sigil-builder/download.properties
@@ -0,0 +1,10 @@
+# For UK mirror service
+download.base=http://www.mirrorservice.org/sites/download.eclipse.org/eclipseMirror/eclipse/downloads/drops/
+
+# 3.3.1.1 Release
+download.dir=R-3.3.1.1-200710231652
+
+#
+download.platform.runtime=eclipse-platform-3.3.1.1-win32.zip
+download.deltapack=eclipse-RCP-3.3.1.1-delta-pack.zip
+download.cvsclient=eclipse-CVS-Client-3.3.1.1.zip
\ No newline at end of file
diff --git a/sigil/sigil-builder/project.properties b/sigil/sigil-builder/project.properties
new file mode 100644
index 0000000..b244e72
--- /dev/null
+++ b/sigil/sigil-builder/project.properties
@@ -0,0 +1,18 @@
+# The list of plugins to be build
+plugins=org.cauldron.sigil.core,\
+	org.cauldron.sigil.obr,\
+	org.cauldron.sigil.search,\
+	org.cauldron.sigil.ui,\
+	org.cauldron.sigil.help,\
+	org.cauldron.sigil.utils,\
+	org.cauldron.bld.core,\
+	org.cauldron.bld.obr
+
+# The list of features to be built
+features=org.cauldron.sigil.all.feature,\
+	org.cauldron.sigil.feature,\
+	org.cauldron.sigil.obr.feature
+
+# Mapping of features to categories in the Update Site
+category.org.cauldron.sigil.feature=Sigil
+category.org.cauldron.sigil.obr.feature=Sigil
diff --git a/sigil/sigil-builder/readme.html b/sigil/sigil-builder/readme.html
new file mode 100644
index 0000000..2427241
--- /dev/null
+++ b/sigil/sigil-builder/readme.html
@@ -0,0 +1,131 @@
+<html>
+<head>
+<title>Sigil Build Instructions</title>
+</head>
+<body>
+
+<h1>Build Instructions</h1>
+
+<h2>1. Install Prerequisites</h2>
+
+<p>A full copy of Eclipse SDK is required to build. This must be
+installed in a directory called <code>eclipse</code>, and the full path
+should not contain any spaces. For example:</p>
+
+<ul>
+	<li><code>C:/eclipse-SDK-3.4/eclipse</code> is GOOD</li>
+	<li><code>C:/eclipse-SDK-3.4/</code> is BAD</li>
+	<li><code>C:/Program Files/Eclipse 3.4/</code> is VERY BAD</li>
+</ul>
+
+<p>This directory (<strong>including</strong> the final <code>eclipse</code>)
+will be referred to as the SDK directory.</p>
+
+<h2>2. Setup the Target Platform</h2>
+
+<p>The target platform is the collection of binary plugins and
+features against which the source projects are built. It is an Eclipse
+installation (with a <code>plugins</code> and <code>features</code>
+directory), and so can be setup by downloading the correct zip or
+tarball from the Eclipse website. Like the SDK directory, the target
+platform must be inside a directory called <code>eclipse</code>. In your
+IDE, you should point PDE at the target platform by opening Preferences
+and navigating to "Plug-in Development" --&gt; "Target Platform". Click
+Browse and select the <code>eclipse</code> directory.</p>
+
+<p>Note that since we are building SDK plugins, the Target Platform
+will be a full SDK (eg "Eclipse Classic SDK"). Therefore we can reuse
+the same SDK directory that we setup in the previous step. However it
+can also be useful to separate these because we might want to use
+different Eclipse versions for each function. For example, we may want
+to use Eclipse 3.4 to build a 3.3-based product.</p>
+
+<h2>3. Create and edit <code>user.properties</code></h2>
+
+<p>User-specific properties are supplied in the file <code>user.properties</code>.
+After checkout this file does not exist, so please copy <code>template.user.properties</code>
+to <code>user.properties</code> and change the following settings:</p>
+
+<ul>
+	<li><code>target.platform</code>: this should be set to the <strong>parent
+	</strong> directory of the <code>eclipse</code> directory which contains the
+	Target Platform.</li>
+	<li><code>eclipse.install.dir</code>: the SDK directory (including
+	final <code>eclipse</code> segment).</li>
+</ul>
+
+<p>Do not check <code>user.properties</code> into version control:
+the settings inside are specific to your machine.</p>
+
+<h2>4. Configure the Update Site URL</h2>
+
+<p>The Update Site URL can be specified by setting the <code>updateUrl</code>
+property in <code>project.properties</code> . This will be copied into
+the <code>feature.xml</code> descriptor for each feature that is part of
+the build. For this to work, the update site URL setting in the <code>feature.xml</code>
+of each source feature project must be set to the following placeholder
+string: <code>http://replace.with.real.url</code></p>
+
+<h2>5. Execute the Build</h2>
+
+<p>Execute a full build by running the <code>pdebuild</code> target
+in ANT, e.g.:</p>
+
+<pre>
+    ant pdebuild
+</pre>
+
+<p>This will generate a directory named <code>target/tmp/eclipse</code>
+which contains a <code>plugins</code> directory for the built plugin
+JARs and a <code>features</code> directory for the built features. If
+the build fails then compilation logs for each plugin can be found in <code>target/N.Sigil/compilelogs/plugins</code>.</p>
+
+<h2>6. Deploy to Update Site</h2>
+
+<p>After the features and plugins are built we can deploy them to an
+update site on the local filesystem. The update site directory must
+already exist with the following layout:</p>
+
+<pre>
+${updateSiteDir}/
+ |--plugins/
+ |--features/
+ \--site.xml
+</pre>
+
+<p>And <code>site.xml</code> must have at least the following
+content:</p>
+
+<pre>
+&lt;site&gt;
+    &lt;category-def name="Sigil" label="Sigil"&gt;
+        &lt;description&gt;Blah blah&lt;/description&gt;
+    &lt;/category-def&gt;
+&lt;/site&gt;
+</pre>
+
+<p>It can also have any number of pre-existing <code>&lt;feature&gt;</code>
+entries as direct children of the <code>&lt;site&gt;</code> element.</p>
+
+<p>Next set the <code>updateSiteDir</code> property in <code>project.properties</code>
+to point at the above directory. Now we can run the deploy target as
+follows:</p>
+
+<pre>
+    ant copy.updateSite
+</pre>
+
+<p>This will copy all of the plugin and feature JARs that were built
+in the previous step into the update site directory. It will also add a
+new entry into <code>site.xml</code> for each feature. Note that the
+update site directory will grow continually. Since the plugins and
+features are generated with a timestamp in their version qualifier (e.g.
+1.2.3.200808091200 for version 1.2.3 built on 9 Aug 2008 at 12 o'clock
+GMT), Eclipse Update Manager will always select the newest version
+available.</p>
+
+<p>NB: the deploy target will overwrite <code>site.xml</code>. A
+backup will be saved in <code>site.xml.bak</code> but this backup will
+be overwritten next time the build is run.</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/sigil/sigil-builder/server-nightly.properties b/sigil/sigil-builder/server-nightly.properties
new file mode 100644
index 0000000..c049a4a
--- /dev/null
+++ b/sigil/sigil-builder/server-nightly.properties
@@ -0,0 +1,6 @@
+eclipse.install.dir=/opt/eclipse-SDK-3.4/eclipse
+source.dir=${basedir}/..
+target.platform=target/target-platform
+updateSiteDir=target/update-site
+# updateUrl is over-ridden from Hudson
+updateUrl=http://sigil.codecauldron.org/update-site-daily
diff --git a/sigil/sigil-builder/site.xml b/sigil/sigil-builder/site.xml
new file mode 100644
index 0000000..5ad74f3
--- /dev/null
+++ b/sigil/sigil-builder/site.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+  
+    http://www.apache.org/licenses/LICENSE-2.0
+  
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<site>
+   <category-def name="Sigil" label="Sigil Core">
+      <description>
+         Sigil is an SDK for developing applications to be deployed on the Newton framework (http://newton.codecauldron.org)
+      </description>
+   </category-def>
+</site>
diff --git a/sigil/sigil-builder/src/org/cauldron/sigil/build/Feature.java b/sigil/sigil-builder/src/org/cauldron/sigil/build/Feature.java
new file mode 100644
index 0000000..6f4378a
--- /dev/null
+++ b/sigil/sigil-builder/src/org/cauldron/sigil/build/Feature.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+/**
+ * 
+ */
+package org.cauldron.sigil.build;
+
+class Feature {
+	String id, version, url;
+	String[] categories;
+}
diff --git a/sigil/sigil-builder/src/org/cauldron/sigil/build/FindBundlesTask.java b/sigil/sigil-builder/src/org/cauldron/sigil/build/FindBundlesTask.java
new file mode 100644
index 0000000..0f7b4a2
--- /dev/null
+++ b/sigil/sigil-builder/src/org/cauldron/sigil/build/FindBundlesTask.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.cauldron.sigil.build;
+
+import java.io.File;
+import java.io.FilenameFilter;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Task;
+import org.osgi.framework.Version;
+
+public class FindBundlesTask extends Task {
+
+	private File dir;
+	private String symbolicName;
+	private String property;
+
+	public File getDir() {
+		return dir;
+	}
+
+	public void setDir(File dir) {
+		this.dir = dir;
+	}
+
+	public String getSymbolicName() {
+		return symbolicName;
+	}
+
+	public void setSymbolicName(String symbolicName) {
+		this.symbolicName = symbolicName;
+	}
+
+	public String getProperty() {
+		return property;
+	}
+
+	public void setProperty(String property) {
+		this.property = property;
+	}
+
+	@Override
+	public void execute() throws BuildException {
+		System.out.println("Searching " + dir + " for bundle '" + symbolicName + "'");
+		final String prefix = symbolicName + "_";
+		String[] files = dir.list(new FilenameFilter() {
+			public boolean accept(File dir, String name) {
+				return name.startsWith(prefix);
+			}
+		});
+		if (files == null)
+		    files = new String[0];
+
+		System.out.println("Found " + files.length + " file(s) starting with " + symbolicName);
+
+		Version highest = null;
+		for (String filename : files) {
+			System.out.println("Testing " + filename);
+			// Drop the prefix
+			int startIndex = prefix.length();
+
+			// Drop the ".jar" suffix if present
+			int endIndex = filename.length();
+			if (filename.toLowerCase().endsWith(".jar")) {
+				endIndex -= 4;
+			}
+
+			String versionString = filename.substring(startIndex, endIndex);
+			System.out.println("Version string is '" + versionString + "'");
+
+			Version version = new Version(versionString);
+			if (highest == null || version.compareTo(highest) > 0) {
+				highest = version;
+			}
+		}
+
+		if (highest == null) {
+			throw new BuildException("No matches for symbolic name '"
+					+ symbolicName + "'");
+		}
+
+		getProject().setNewProperty(property, highest.toString());
+	}
+
+}
diff --git a/sigil/sigil-builder/src/org/cauldron/sigil/build/SiteInsertFeatureContentHandler.java b/sigil/sigil-builder/src/org/cauldron/sigil/build/SiteInsertFeatureContentHandler.java
new file mode 100644
index 0000000..bf710a7
--- /dev/null
+++ b/sigil/sigil-builder/src/org/cauldron/sigil/build/SiteInsertFeatureContentHandler.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.cauldron.sigil.build;
+
+import java.util.List;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+class SiteInsertFeatureContentHandler implements ContentHandler {
+	
+	private final ContentHandler output;
+	private final List<org.cauldron.sigil.build.Feature> featureList;
+
+	public SiteInsertFeatureContentHandler(ContentHandler output,
+			List<Feature> featureList) {
+		this.output = output;
+		this.featureList = featureList;
+	}
+
+	public void characters(char[] ch, int start, int length) throws SAXException {
+		output.characters(ch, start, length);
+	}
+
+	public void endDocument() throws SAXException {
+		output.endDocument();
+	}
+
+	public void endElement(String uri, String localName, String name) throws SAXException {
+		output.endElement(uri, localName, name);
+	}
+
+	public void endPrefixMapping(String prefix) throws SAXException {
+		output.endPrefixMapping(prefix);
+	}
+
+	public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
+		//output.ignorableWhitespace(ch, start, length);
+	}
+
+	public void processingInstruction(String target, String data) throws SAXException {
+		output.processingInstruction(target, data);
+	}
+
+	public void setDocumentLocator(Locator locator) {
+		output.setDocumentLocator(locator);
+	}
+
+	public void skippedEntity(String name) throws SAXException {
+		output.skippedEntity(name);
+	}
+
+	public void startDocument() throws SAXException {
+		output.startDocument();
+	}
+
+	public void startElement(String uri, String localName, String name, Attributes atts)
+			throws SAXException {
+		output.startElement(uri, localName, name, atts);
+		
+		if("site".equals(name)) {
+			for (Feature feature : featureList) {
+				AttributesImpl featureAtts = new AttributesImpl();
+				featureAtts.addAttribute("", "", "url", "CDATA", feature.url);
+				featureAtts.addAttribute("", "", "id", "CDATA", feature.id);
+				featureAtts.addAttribute("", "", "version", "CDATA", feature.version);
+				output.startElement("", "", "feature", featureAtts);
+				
+				for (int i = 0; i < feature.categories.length; i++) {
+					AttributesImpl categoryAtts = new AttributesImpl();
+					categoryAtts.addAttribute("", "", "name", "CDATA", feature.categories[i]);
+					output.startElement("", "", "category", categoryAtts);
+					output.endElement("", "", "category");
+				}
+				
+				output.endElement("", "", "feature");
+			}
+		}
+	}
+
+	public void startPrefixMapping(String prefix, String uri) throws SAXException {
+		output.startPrefixMapping(prefix, uri);
+	}
+
+}
diff --git a/sigil/sigil-builder/src/org/cauldron/sigil/build/SiteInsertFeatures.java b/sigil/sigil-builder/src/org/cauldron/sigil/build/SiteInsertFeatures.java
new file mode 100644
index 0000000..9d09008
--- /dev/null
+++ b/sigil/sigil-builder/src/org/cauldron/sigil/build/SiteInsertFeatures.java
@@ -0,0 +1,179 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.cauldron.sigil.build;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.transform.sax.SAXTransformerFactory;
+import javax.xml.transform.sax.TransformerHandler;
+import javax.xml.transform.stream.StreamResult;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+
+public class SiteInsertFeatures extends Task {
+
+	private File siteXmlFile;
+	private String features;
+	private String versionPropPrefix;
+	private String categoryPropPrefix;
+	
+	public File getSiteXmlFile() {
+		return siteXmlFile;
+	}
+	public void setSiteXmlFile(File siteXmlFile) {
+		this.siteXmlFile = siteXmlFile;
+	}
+	public String getFeatures() {
+		return features;
+	}
+	public void setFeatures(String features) {
+		this.features = features;
+	}
+	public String getVersionPropPrefix() {
+		return versionPropPrefix;
+	}
+	public void setVersionPropPrefix(String versionPropPrefix) {
+		this.versionPropPrefix = versionPropPrefix;
+	}
+	public String getCategoryPropPrefix() {
+		return categoryPropPrefix;
+	}
+	public void setCategoryPropPrefix(String categoryPropPrefix) {
+		this.categoryPropPrefix = categoryPropPrefix;
+	}
+	
+	@Override
+	public void execute() throws BuildException {
+		Project project = getProject();
+		
+		List<Feature> featureList = new ArrayList<Feature>(); 
+		StringTokenizer tokenizer = new StringTokenizer(features, ",");
+		while(tokenizer.hasMoreTokens()) {
+			Feature feature = new Feature();
+			feature.id = tokenizer.nextToken().trim();
+			
+			// Find the version property
+			String versionProp;
+			if(versionPropPrefix == null) {
+				versionProp = feature.id;
+			} else {
+				versionProp = versionPropPrefix + "." + feature.id;
+			}
+			feature.version = project.getProperty(versionProp);
+			
+			// Find the categories for this feature
+			feature.categories = new String[0];
+			if(categoryPropPrefix != null) {
+				String categoriesStr = project.getProperty(categoryPropPrefix + "." + feature.id);
+				if(categoriesStr != null) {
+					StringTokenizer categoriesTokenizer = new StringTokenizer(categoriesStr, ",");
+					feature.categories = new String[categoriesTokenizer.countTokens()];
+					for(int i=0; i<feature.categories.length; i++) {
+						feature.categories[i] = categoriesTokenizer.nextToken();
+					}
+				}
+			}
+
+			if(feature.version != null) {
+				feature.url = "features/" + feature.id + "_" + feature.version + ".jar";
+				featureList.add(feature);
+			} else {
+				System.out.println("Skipping feature " + feature.id);
+			}
+		}
+		
+		if(!siteXmlFile.isFile()) {
+			throw new BuildException(siteXmlFile + " does not exist or is not a normal file");
+		}
+		try {
+			// Generate new XML into a temporary file
+			File tempFile = File.createTempFile("tmp", ".xml", siteXmlFile.getParentFile());
+			tempFile.deleteOnExit();
+
+			SAXTransformerFactory transformerFactory = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
+			TransformerHandler transformerHandler = transformerFactory.newTransformerHandler();
+			transformerHandler.setResult(new StreamResult(tempFile));
+			
+			SAXParserFactory parserFactory = SAXParserFactory.newInstance();
+			SAXParser parser = parserFactory.newSAXParser();
+			
+			SiteInsertFeatureContentHandler contentHandler = new SiteInsertFeatureContentHandler(transformerHandler, featureList);
+			
+			XMLReader reader = parser.getXMLReader();
+			reader.setContentHandler(contentHandler);
+			reader.parse(new InputSource(new FileInputStream(siteXmlFile)));
+			
+			// Backup original file
+			File backup = new File(siteXmlFile.getParentFile(), siteXmlFile.getName() + ".bak");
+			copyFile(siteXmlFile, backup);
+			
+			// Replace original file
+			copyFile(tempFile, siteXmlFile);
+			
+		} catch (IOException e) {
+			throw new BuildException(e);
+		} catch (TransformerConfigurationException e) {
+			throw new BuildException(e);
+		} catch (IllegalArgumentException e) {
+			throw new BuildException(e);
+		} catch (TransformerFactoryConfigurationError e) {
+			throw new BuildException(e);
+		} catch (ParserConfigurationException e) {
+			throw new BuildException(e);
+		} catch (SAXException e) {
+			throw new BuildException(e);
+		}
+	}
+	
+	private void copyFile(File source, File dest) throws IOException {
+		FileInputStream in = null;
+		FileOutputStream out = null;
+		try {
+			in = new FileInputStream(source);
+			out = new FileOutputStream(dest);
+			
+			byte[] buffer = new byte[1024];
+			
+			int read;
+			while((read = in.read(buffer, 0, 1024)) > -1) {
+				out.write(buffer, 0, read);
+			}
+		} finally {
+			try { if(in != null) in.close(); } catch(IOException e) {}
+			try { if(out != null) out.close(); } catch(IOException e) {}
+		}
+		
+	}
+}
diff --git a/sigil/sigil-builder/template.user.properties b/sigil/sigil-builder/template.user.properties
new file mode 100644
index 0000000..ed14a54
--- /dev/null
+++ b/sigil/sigil-builder/template.user.properties
@@ -0,0 +1,14 @@
+#
+source.dir=${basedir}/..
+
+#
+target.platform=/path/to/target
+
+# path to eclipse sdk
+eclipse.install.dir=/path/to/sdk/eclipse
+
+# The URL of the Update Site, for insertion into each feature.xml
+updateUrl=http://sigil.codecauldron.org/update-site-nightly
+
+# The path to an Update Site directory on the local filesystem
+updateSiteDir=/opt/development/sigil-trunk/update-site-nightly