summaryrefslogtreecommitdiffstats
path: root/wixl/wix.vala
diff options
context:
space:
mode:
Diffstat (limited to 'wixl/wix.vala')
-rw-r--r--wixl/wix.vala598
1 files changed, 598 insertions, 0 deletions
diff --git a/wixl/wix.vala b/wixl/wix.vala
new file mode 100644
index 0000000..d3468c5
--- /dev/null
+++ b/wixl/wix.vala
@@ -0,0 +1,598 @@
+namespace Wixl {
+
+ public enum VisitState {
+ ENTER,
+ INFIX,
+ LEAVE
+ }
+
+ public abstract class WixNodeVisitor: Object {
+ public abstract void visit_product (WixProduct product) throws GLib.Error;
+ public abstract void visit_icon (WixIcon icon) throws GLib.Error;
+ public abstract void visit_package (WixPackage package) throws GLib.Error;
+ public abstract void visit_property (WixProperty prop) throws GLib.Error;
+ public abstract void visit_media (WixMedia media) throws GLib.Error;
+ public abstract void visit_directory (WixDirectory dir) throws GLib.Error;
+ public abstract void visit_component (WixComponent comp) throws GLib.Error;
+ public abstract void visit_feature (WixFeature feature, VisitState state) throws GLib.Error;
+ public abstract void visit_component_ref (WixComponentRef ref) throws GLib.Error;
+ public abstract void visit_remove_folder (WixRemoveFolder rm) throws GLib.Error;
+ public abstract void visit_registry_value (WixRegistryValue reg) throws GLib.Error;
+ public abstract void visit_file (WixFile reg) throws GLib.Error;
+ public abstract void visit_shortcut (WixShortcut shortcut) throws GLib.Error;
+ public abstract void visit_create_folder (WixCreateFolder folder) throws GLib.Error;
+ public abstract void visit_fragment (WixFragment fragment) throws GLib.Error;
+ public abstract void visit_directory_ref (WixDirectoryRef ref) throws GLib.Error;
+ public abstract void visit_sequence (WixSequence sequence) throws GLib.Error;
+ public abstract void visit_condition (WixCondition condition) throws GLib.Error;
+ public abstract void visit_upgrade (WixUpgrade upgrade) throws GLib.Error;
+ public abstract void visit_upgrade_version (WixUpgradeVersion version) throws GLib.Error;
+ public abstract void visit_action (WixAction action) throws GLib.Error;
+ public abstract void visit_text (WixText text) throws GLib.Error;
+ }
+
+ public abstract class WixNode: Object {
+ public WixElement? parent;
+
+ static construct {
+ Value.register_transform_func (typeof (WixNode), typeof (string), (ValueTransform)WixNode.value_to_string);
+ }
+
+ public abstract string to_string ();
+
+ public static void value_to_string (Value src, out Value dest) {
+ WixNode e = value_get_node (src);
+
+ dest = e.to_string ();
+ }
+
+ public static WixNode? value_get_node (Value value) {
+ if (! value.holds (typeof (WixNode)))
+ return null;
+
+ return (WixNode)value.get_object ();
+ }
+
+ public abstract void accept (WixNodeVisitor visitor) throws GLib.Error;
+ }
+
+ public class WixText: WixNode {
+ public string Text;
+
+ public WixText (string str) {
+ Text = str;
+ }
+
+ public override string to_string () {
+ return Text;
+ }
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ visitor.visit_text (this);
+ }
+ }
+
+ public abstract class WixElement: WixNode {
+ public class string name;
+
+ public string Id { get; set; }
+ public List<WixNode> children;
+
+ // FIXME: would be nice if vala always initialize class member to null
+ // GObject copy class init so other class hashtable will be unrefed...??
+ protected class HashTable<string, Type> *child_types = null;
+ class construct {
+ child_types = new HashTable<string, Type> (str_hash, str_equal);
+ }
+
+ public class void add_child_types (HashTable<string, Type> table, Type[] child_types) {
+ foreach (var t in child_types) {
+ var n = ((WixElement) Object.new (t)).name;
+ table.insert (n, t);
+ }
+ }
+
+ public void add_child (WixNode e) {
+ e.parent = this;
+ children.append (e);
+ }
+
+ public G[] add_elements<G> (owned G[] a) {
+ // jeez, vala, took me a while to workaround generics & array issues..
+ var array = a;
+ var type = typeof (G);
+
+ if (this.get_type ().is_a (type))
+ array += this;
+
+ foreach (var c in children) {
+ if (c is WixElement)
+ array = (c as WixElement).add_elements<G> (array);
+ else if (c.get_type ().is_a (type))
+ array += c;
+ }
+
+ return array;
+ }
+
+ public G[] get_elements<G> () {
+ return add_elements<G> ({});
+ }
+
+ public G? find_element<G> (string Id) {
+ var type = typeof (G);
+ if (this.Id == Id && this.get_type () == type)
+ return this;
+
+ foreach (var c in children) {
+ if (c is WixElement) {
+ var e = (c as WixElement).find_element<G> (Id);
+ if (e != null)
+ return e;
+ }
+ }
+
+ return null;
+ }
+
+ public virtual void load (Xml.Node *node) throws Wixl.Error {
+ if (node->name != name)
+ throw new Error.FAILED ("%s: invalid node %s".printf (name, node->name));
+
+ for (var prop = node->properties; prop != null; prop = prop->next) {
+ if (prop->type == Xml.ElementType.ATTRIBUTE_NODE)
+ set_property (prop->name, get_attribute_content (prop));
+ }
+
+ for (var child = node->children; child != null; child = child->next) {
+ switch (child->type) {
+ case Xml.ElementType.COMMENT_NODE:
+ continue;
+ case Xml.ElementType.TEXT_NODE:
+ add_child (new WixText (child->content));
+ continue;
+ case Xml.ElementType.ELEMENT_NODE:
+ var t = child_types->lookup (child->name);
+ if (t != 0) {
+ var elem = Object.new (t) as WixElement;
+ elem.load (child);
+ add_child (elem);
+ continue;
+ }
+ break;
+ }
+ debug ("unhandled child %s node %s", name, child->name);
+ }
+ }
+
+ public override string to_string () {
+ var type = get_type ();
+ var klass = (ObjectClass)type.class_ref ();
+ var str = "<" + name;
+
+ var i = 0;
+ foreach (var p in klass.list_properties ()) {
+ if (!(ParamFlags.READABLE in p.flags))
+ continue;
+ var value = Value (p.value_type);
+ get_property (p.name, ref value);
+ var valstr = value.holds (typeof (string)) ?
+ (string)value : value.strdup_contents ();
+ if (valstr != null)
+ str += " " + p.name + "=\"" + valstr + "\"";
+ i += 1;
+ }
+
+ if (children.length () != 0) {
+ str += ">\n";
+
+ foreach (var child in children) {
+ str += child.to_string () + "\n";
+ }
+
+ return str + "</" + name + ">";
+ } else
+ return str + "/>";
+ }
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ foreach (var child in children)
+ child.accept (visitor);
+ }
+ }
+
+ public class WixFragment: WixElement {
+ static construct {
+ name = "Fragment";
+
+ add_child_types (child_types, {
+ typeof (WixDirectory),
+ typeof (WixDirectoryRef),
+ });
+ }
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ base.accept (visitor);
+ visitor.visit_fragment (this);
+ }
+ }
+
+ public class WixProperty: WixElement {
+ static construct {
+ name = "Property";
+ }
+
+ public string Value { get; set; }
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ visitor.visit_property (this);
+ }
+ }
+
+ public class WixPackage: WixElement {
+ static construct {
+ name = "Package";
+ }
+
+ public string Keywords { get; set; }
+ public string InstallerDescription { get; set; }
+ public string InstallerComments { get; set; }
+ public string Manufacturer { get; set; }
+ public string InstallerVersion { get; set; }
+ public string Languages { get; set; }
+ public string Compressed { get; set; }
+ public string SummaryCodepage { get; set; }
+ public string Comments { get; set; }
+ public string Description { get; set; }
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ base.accept (visitor);
+ visitor.visit_package (this);
+ }
+ }
+
+ public class WixCreateFolder: WixElement {
+ static construct {
+ name = "CreateFolder";
+ }
+
+ public string Directory { get; set; }
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ visitor.visit_create_folder (this);
+ }
+ }
+
+ public class WixIcon: WixElement {
+ static construct {
+ name = "Icon";
+ }
+
+ public string SourceFile { get; set; }
+
+ public File file;
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ visitor.visit_icon (this);
+ }
+ }
+
+ public class WixShortcut: WixElement {
+ static construct {
+ name = "Shortcut";
+ }
+
+ public string Directory { get; set; }
+ public string Name { get; set; }
+ public string IconIndex { get; set; }
+ public string WorkingDirectory { get; set; }
+ public string Icon { get; set; }
+ public string Advertise { get; set; }
+
+ public Libmsi.Record record;
+
+ public WixComponent? get_component () {
+ if (parent is WixFile || parent is WixCreateFolder)
+ return parent.parent as WixComponent;
+ else
+ return parent as WixComponent;
+ }
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ visitor.visit_shortcut (this);
+ }
+ }
+
+ public abstract class WixKeyElement: WixElement {
+ public string KeyPath { get; set; }
+ }
+
+ public class WixFile: WixKeyElement {
+ static construct {
+ name = "File";
+
+ add_child_types (child_types, { typeof (WixShortcut) });
+ }
+
+ public string DiskId { get; set; }
+ public string Source { get; set; }
+ public string Name { get; set; }
+
+ public Libmsi.Record record;
+ public File file;
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ base.accept (visitor);
+ visitor.visit_file (this);
+ }
+ }
+
+ public class WixRegistryValue: WixKeyElement {
+ static construct {
+ name = "RegistryValue";
+ }
+
+ public string Root { get; set; }
+ public string Key { get; set; }
+ public string Type { get; set; }
+ public string Value { get; set; }
+ public string Name { get; set; }
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ visitor.visit_registry_value (this);
+ }
+ }
+
+ public class WixRemoveFolder: WixElement {
+ static construct {
+ name = "RemoveFolder";
+ }
+
+ public string On { get; set; }
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ visitor.visit_remove_folder (this);
+ }
+ }
+
+ public class WixFeature: WixElement {
+ static construct {
+ name = "Feature";
+
+ add_child_types (child_types, {
+ typeof (WixComponentRef),
+ typeof (WixFeature),
+ });
+ }
+
+ public string Level { get; set; }
+ public string Title { get; set; }
+ public string Description { get; set; }
+ public string Display { get; set; }
+ public string ConfigurableDirectory { get; set; }
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ visitor.visit_feature (this, VisitState.ENTER);
+ base.accept (visitor);
+ visitor.visit_feature (this, VisitState.LEAVE);
+ }
+ }
+
+ public class WixComponentRef: WixElementRef<WixComponent> {
+ static construct {
+ name = "ComponentRef";
+ ref_type = typeof (WixComponent);
+ }
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ visitor.visit_component_ref (this);
+ }
+ }
+
+ public class WixCondition: WixElement {
+ static construct {
+ name = "Condition";
+ }
+
+ public string Message { get; set; }
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ visitor.visit_condition (this);
+ }
+ }
+
+ public abstract class WixAction: WixElement {
+ public string After { get; set; }
+ public string Before { get; set; }
+ public string Overridable { get; set; }
+ public string Sequence { get; set; }
+ public string Suppress { get; set; }
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ visitor.visit_action (this);
+ }
+ }
+
+ public class WixRemoveExistingProducts: WixAction {
+ static construct {
+ name = "RemoveExistingProducts";
+ }
+ }
+
+ public class WixSequence: WixElement {
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ base.accept (visitor);
+ visitor.visit_sequence (this);
+ }
+ }
+
+ public class WixInstallExecuteSequence: WixSequence {
+ static construct {
+ name = "InstallExecuteSequence";
+
+ add_child_types (child_types, {
+ typeof (WixRemoveExistingProducts),
+ });
+ }
+ }
+
+ public class WixUpgrade: WixElement {
+ static construct {
+ name = "Upgrade";
+
+ add_child_types (child_types, {
+ typeof (WixUpgradeVersion),
+ });
+ }
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ base.accept (visitor);
+ visitor.visit_upgrade (this);
+ }
+ }
+
+ public class WixUpgradeVersion: WixElement {
+ static construct {
+ name = "UpgradeVersion";
+ }
+
+ public string Minimum { get; set; }
+ public string Maximum { get; set; }
+ public string IncludeMinimum { get; set; }
+ public string IncludeMaximum { get; set; }
+ public string OnlyDetect { get; set; }
+ public string Property { get; set; }
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ visitor.visit_upgrade_version (this);
+ }
+ }
+
+ public class WixProduct: WixElement {
+ static construct {
+ name = "Product";
+
+ add_child_types (child_types, {
+ typeof (WixCondition),
+ typeof (WixDirectory),
+ typeof (WixFeature),
+ typeof (WixIcon),
+ typeof (WixInstallExecuteSequence),
+ typeof (WixMedia),
+ typeof (WixPackage),
+ typeof (WixProperty),
+ typeof (WixUpgrade),
+ });
+ }
+
+ public string Name { get; set; }
+ public string UpgradeCode { get; set; }
+ public string Language { get; set; }
+ public string Codepage { get; set; }
+ public string Version { get; set; }
+ public string Manufacturer { get; set; }
+
+ public WixProduct () {
+ }
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ base.accept (visitor);
+ visitor.visit_product (this);
+ }
+ }
+
+ public class WixMedia: WixElement {
+ static construct {
+ name = "Media";
+ }
+
+ public string Cabinet { get; set; }
+ public string EmbedCab { get; set; }
+ public string DiskPrompt { get; set; }
+
+ public Libmsi.Record record;
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ visitor.visit_media (this);
+ }
+ }
+
+ public class WixComponent: WixElement {
+ static construct {
+ name = "Component";
+
+ add_child_types (child_types, {
+ typeof (WixRemoveFolder),
+ typeof (WixRegistryValue),
+ typeof (WixFile)
+ });
+ }
+
+ public string Guid { get; set; }
+ public WixKeyElement? key;
+
+ public List<WixFeature> in_feature;
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ base.accept (visitor);
+ visitor.visit_component (this);
+ }
+ }
+
+ public class WixDirectory: WixElement {
+ static construct {
+ name = "Directory";
+
+ add_child_types (child_types, {
+ typeof (WixDirectory),
+ typeof (WixComponent),
+ });
+ }
+
+ public string Name { get; set; }
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ base.accept (visitor);
+ visitor.visit_directory (this);
+ }
+ }
+
+ public class WixElementRef<G>: WixElement {
+ public class Type ref_type;
+ public G? resolved;
+
+ // protected WixElementRef () {
+ // // FIXME vala: class init/construct fails, construct fails...
+ // ref_type = typeof (G);
+ // }
+ }
+
+ public class WixDirectoryRef: WixElementRef<WixDirectory> {
+ static construct {
+ name = "DirectoryRef";
+ ref_type = typeof (WixDirectory);
+
+ add_child_types (child_types, {
+ typeof (WixDirectory),
+ typeof (WixComponent),
+ });
+ }
+
+ public override void accept (WixNodeVisitor visitor) throws GLib.Error {
+ base.accept (visitor);
+ visitor.visit_directory_ref (this);
+ }
+ }
+
+ class WixRoot: WixElement {
+ static construct {
+ name = "Wix";
+
+ add_child_types (child_types, {
+ typeof (WixProduct),
+ typeof (WixFragment),
+ });
+ }
+ }
+
+} // Wixl