AntBuilder 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,20 @@
1
+ Project Version : V1-0-0
2
+ Tagged by : Joe Smith
3
+ Comments : First try
4
+
5
+ Project Version : V1-1-1
6
+ Tagged by : Denis Menace
7
+ Comments : Lots of features added
8
+
9
+ Project Version : V1-2-3
10
+ Tagged by : Tim James
11
+ Comments : RFC183492/1 RFC183342/3
12
+
13
+ Project Version : V1-2-7
14
+ Tagged by : Tim James
15
+ Comments : RFC293646/4
16
+
17
+
18
+
19
+
20
+
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #--
4
+ # Copyright 2006 by Tim Azzopardi (tim@tigerfive.com).
5
+ # All rights reserved.
6
+
7
+ # Permission is granted for use, copying, modification, distribution,
8
+ # and distribution of modified versions of this work as long as the
9
+ # above copyright notice is included.
10
+ #++
11
+
12
+ require 'builder/antbuilder'
13
+
@@ -0,0 +1,225 @@
1
+ #!/usr/bin/env ruby
2
+ #--
3
+ # Copyright 2005 by Tim Azzopardi (tim@tigerfive.com).
4
+ # All rights reserved.
5
+
6
+ # Permission is granted for use, copying, modification, distribution,
7
+ # and distribution of modified versions of this work as long as the
8
+ # above copyright notice is included.
9
+ #++
10
+ require 'builder/xmlbase'
11
+
12
+ require 'java'
13
+ include_class 'org.leafcutter.core.TaskRunner'
14
+
15
+ module Builder
16
+
17
+ class AntBuilder < XmlBase
18
+
19
+ # Create an ant markup builder. Parameters are specified by an
20
+ # option hash.
21
+ #
22
+ # :target=><em>target_object</em>::
23
+ # Object receiving the markup. +out+ must respond to the
24
+ # <tt><<</tt> operator. The default is a plain string target.
25
+ # :indent=><em>indentation</em>::
26
+ # Number of spaces used for indentation. The default is no
27
+ # indentation and no line breaks.
28
+ # :margin=><em>initial_indentation_level</em>::
29
+ # Amount of initial indentation (specified in levels, not
30
+ # spaces).
31
+ #
32
+ def initialize(options={})
33
+ indent = options[:indent] || 0
34
+ margin = options[:margin] || 0
35
+ super(indent, margin)
36
+ @target = options[:target] || ""
37
+ @debug = options[:debug]
38
+ @debug = false if @debug.nil?
39
+ end
40
+
41
+ # Return the target of the builder.
42
+ def target!
43
+ @target
44
+ end
45
+
46
+ def _check_for_circular_dependencies(call_stack, some_method_name)
47
+ # remove noise from the stack - all we want left are the ant task methods
48
+ method_name_on_stack_regexp = /`\w+'/
49
+ call_stack.reject!{|c| c =~ /#{__FILE__}/ or c=~ /`instance_eval'/ or c=~ /`each'/ or not c=~ method_name_on_stack_regexp }
50
+
51
+ # collect just those lines that look like method names
52
+ call_stack.collect!{|c| (method_name_on_stack_regexp.match(c))[0] }
53
+
54
+ # check whether some_method_name is on the stack
55
+ call_stack.each do |c|
56
+ if c=~ /`#{some_method_name}'/
57
+ # circular dependecy detected
58
+ err = call_stack.inject(some_method_name){|message,method_name| "#{message} <- #{method_name}"}
59
+ raise RuntimeError, "\nBUILD FAILED\nCircular dependency: #{err}", []
60
+ end
61
+ end
62
+ end
63
+
64
+ # implement the ant depends clause
65
+ def depends(*ant_task_dependecies)
66
+
67
+ # who called me?
68
+ my_caller_matcher = caller[0].match(/`(\w+)'/)
69
+ my_caller = my_caller_matcher[1] if not my_caller_matcher.nil?
70
+
71
+ # Call the dependencies if they haven't been called already
72
+ for ant_task_dependency in ant_task_dependecies
73
+
74
+ if not respond_to?(ant_task_dependency)
75
+ raise RuntimeError, "\nBUILD FAILED\nTarget '#{ant_task_dependency}' does not exist in this project. It is used from target `#{my_caller}'.", []
76
+ end
77
+ _check_for_circular_dependencies(caller, ant_task_dependency.to_s)
78
+
79
+ cmd = "puts \"\n#{ant_task_dependency}:\" if not @__#{ant_task_dependency}__.nil?; @__#{ant_task_dependency}__ ||= #{ant_task_dependency} || true"
80
+ puts "#{cmd}" if @debug
81
+ instance_eval(cmd)
82
+ end
83
+
84
+ # Now print the name of the calling task, from the first line of stack
85
+ puts
86
+ puts "#{my_caller}:"
87
+
88
+ # and make sure we also record the fact that the caller has been called (as we have done for its dependencies)
89
+ instance_eval("@__#{my_caller}__ = true ")
90
+
91
+ end
92
+
93
+ # Subclasses ONLY can use this at the end of their class definition to run targets from the command line like ant does.
94
+ # For example:
95
+ # "jruby build.rb clean compile release" is like saying "ant clean compile release # this is any comment"
96
+ def AntBuilder.run_targets_from_command_line
97
+ # self would be expected to be a subclass here, because AntBuilder doesnt define any 'ant_target'
98
+ builder = self.new
99
+ ARGV.each do |ant_target|
100
+ return if ant_target == "#"
101
+ if builder.respond_to?(ant_target)
102
+ builder.instance_eval("builder.#{ant_target}")
103
+ else
104
+ raise RuntimeError, "\nBUILD FAILED\nTarget '#{ant_target}' does not exist in this project.", []
105
+ end
106
+ end
107
+ end
108
+
109
+ private
110
+
111
+ ########################################################################
112
+ # NOTE: All private methods of a builder object are prefixed when
113
+ # a "_" character to avoid possible conflict with ant tags.
114
+ ########################################################################
115
+
116
+ def _execute ()
117
+ # Remove the outer brackets as requied by the leafcutter syntax
118
+ cmd = @target.slice(1,@target.size-2)
119
+ puts __FILE__ << " _execute " << cmd if @debug
120
+ case cmd
121
+ when /^([\w]+) id=([\w.]+)(\()/
122
+ # leafcutter supports ant references explicitly http://ant.apache.org/manual/using.html#references
123
+ # An ant reference of form for example path id=project.class.path
124
+ reference = $1 +$3 + $' #'
125
+ reference_name = $2
126
+ puts __FILE__ << " _execute " << "TaskRunner.addReference(\"#{reference_name}\",\"#{reference}\");" if@debug
127
+ TaskRunner.addReference(reference_name, reference);
128
+ when /taskdef .* name=(\w+)/
129
+ name=$1
130
+ # match on classname
131
+ cmd =~ /classname=([\w.]+)/
132
+ classname = $1
133
+ puts __FILE__ << " _execute " << "TaskRunner.addTaskDef(\"#{name}\",\"#{classname}\");" if@debug
134
+ TaskRunner.addTaskDef(name, classname)
135
+ else
136
+ # The "normal" case of some ant command
137
+
138
+ # get the ant properties before the ant command
139
+ ant_properties_before = _get_ant_properties_as_hash
140
+
141
+ begin
142
+ puts __FILE__ << " _execute " << "TaskRunner.run(\"#{cmd}\");" if@debug
143
+ TaskRunner.run(cmd);
144
+ rescue
145
+ raise RuntimeError, "BUILD FAILED\n#{$!}", []
146
+ end
147
+
148
+ # get the ant properties after the ant command
149
+ ant_properties_after = _get_ant_properties_as_hash
150
+
151
+ # get the new ant properties after the command (if any).
152
+ # (Remember ant properties can't be redefined so we only need the new ones.)
153
+ ant_properties_new = ant_properties_after.select{|k, v| not ant_properties_before.has_key?(k) }
154
+
155
+ # define the ant properies as ruby instance variables
156
+ ant_properties_new.each do | k,v |
157
+
158
+ # property name may contain alot of different wacky characters which are not legal in ruby instance variable names
159
+ # so replace all wacky characters with underscores
160
+ k.gsub!(/\W/, "_")
161
+
162
+ # Replace \ with \\ : this is hell : some windows env vars can look like "C:\some\windows\dir"
163
+ v.gsub!(/\\/, "\\\\\\\\")
164
+ v.gsub!(/"/, "\\\"")
165
+ decl = "@#{k}=\"#{v}\""
166
+ puts "About to define ruby instance variable: " << decl if @debug
167
+ instance_eval(decl)
168
+ puts "Defined ruby instance variable: " << decl << " read back as: " << instance_eval("@#{k}") if @debug
169
+ end
170
+
171
+ end
172
+
173
+ @target = ''
174
+ end
175
+
176
+ def _get_ant_properties_as_hash
177
+ hash = Hash.new
178
+ TaskRunner.getAntProjectProperties.each { | k,v | hash[k] = v }
179
+ hash
180
+ end
181
+
182
+ # Insert text directly in to the builder's target.
183
+ def _text(text)
184
+ @target << text
185
+ end
186
+
187
+ def _indent
188
+ raise ArgumentError, "It looks like this object has not been initialized. Did the object get an initialize call?" if @target.nil?
189
+ super
190
+ end
191
+
192
+ def method_missing(sym, *args, &block)
193
+ ret = super
194
+ _execute if @level==0
195
+ ret
196
+ end
197
+
198
+
199
+ # Start an tag. If <tt>end_too</tt> is true, then the start
200
+ # tag is also the end tag
201
+ def _start_tag(sym, attrs, end_too=false)
202
+ @target << "(#{sym}"
203
+ _insert_attributes(attrs)
204
+ @target << ")" if end_too
205
+ # @target << ")"
206
+ end
207
+
208
+ # Insert an ending tag.
209
+ def _end_tag(sym)
210
+ @target << ")"
211
+ end
212
+
213
+ # Insert the attributes (given in the hash).
214
+ def _insert_attributes(attrs)
215
+ return if attrs.nil?
216
+ attrs.each do |k, v|
217
+ # if the attribute value contains spaces then put single quotes around the string
218
+ v = "'#{v}'" if v =~ " "
219
+ @target << %{ #{k}=#{v}}
220
+ end
221
+ end
222
+
223
+ end # class
224
+
225
+ end # module
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env ruby
2
+ #--
3
+ # Copyright 2004 by Jim Weirich (jim@weirichhouse.org).
4
+ # Copyright 2005 by Tim Azzopardi (tim@tigerfive.com).
5
+ # All rights reserved.
6
+
7
+ # Permission is granted for use, copying, modification, distribution,
8
+ # and distribution of modified versions of this work as long as the
9
+ # above copyright notice is included.
10
+ #++
11
+
12
+ module Builder
13
+
14
+ # BlankSlate provides an abstract base class with no predefined
15
+ # methods (except for <tt>\_\_send__</tt> and <tt>\_\_id__</tt>).
16
+ # BlankSlate is useful as a base class when writing classes that
17
+ # depend upon <tt>method_missing</tt> (e.g. dynamic proxies).
18
+ class BlankSlate
19
+ class << self
20
+ def hide(name)
21
+ undef_method name if
22
+ instance_methods.include?(name.to_s) and
23
+ name !~ /^(__|instance_eval)/ and
24
+ name !~ /^(__|respond_to?)/
25
+ end
26
+ end
27
+
28
+ instance_methods.each { |m| hide(m) }
29
+ end
30
+ end
31
+
32
+ # Since Ruby is very dynamic, methods added to the ancestors of
33
+ # BlankSlate <em>after BlankSlate is defined</em> will show up in the
34
+ # list of available BlankSlate methods. We handle this by defining a hook in the Object and Kernel classes that will hide any defined
35
+ module Kernel
36
+ class << self
37
+ alias_method :blank_slate_method_added, :method_added
38
+ def method_added(name)
39
+ blank_slate_method_added(name)
40
+ return if self != Kernel
41
+ Builder::BlankSlate.hide(name)
42
+ end
43
+ end
44
+ end
45
+
46
+ class Object
47
+ class << self
48
+ alias_method :blank_slate_method_added, :method_added
49
+ def method_added(name)
50
+ blank_slate_method_added(name)
51
+ return if self != Object
52
+ Builder::BlankSlate.hide(name)
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,153 @@
1
+ #!/usr/bin/env ruby
2
+ #--
3
+ # Copyright 2004 by Jim Weirich (jim@weirichhouse.org).
4
+ # All rights reserved.
5
+
6
+ # Permission is granted for use, copying, modification, distribution,
7
+ # and distribution of modified versions of this work as long as the
8
+ # above copyright notice is included.
9
+ #++
10
+
11
+ require 'builder/blankslate'
12
+
13
+ module Builder
14
+
15
+ # Generic error for builder
16
+ class IllegalBlockError < RuntimeError; end
17
+
18
+ # XmlBase is a base class for building XML builders. See
19
+ # Builder::XmlMarkup and Builder::XmlEvents for examples.
20
+ class XmlBase < BlankSlate
21
+
22
+ # Create an XML markup builder.
23
+ #
24
+ # out:: Object receiving the markup.1 +out+ must respond to
25
+ # <tt><<</tt>.
26
+ # indent:: Number of spaces used for indentation (0 implies no
27
+ # indentation and no line breaks).
28
+ # initial:: Level of initial indentation.
29
+ #
30
+ def initialize(indent=0, initial=0)
31
+ @indent = indent
32
+ @level = initial
33
+ end
34
+
35
+ # Create a tag named +sym+. Other than the first argument which
36
+ # is the tag name, the arguements are the same as the tags
37
+ # implemented via <tt>method_missing</tt>.
38
+ def tag!(sym, *args, &block)
39
+ self.__send__(sym, *args, &block)
40
+ end
41
+
42
+ # Create XML markup based on the name of the method. This method
43
+ # is never invoked directly, but is called for each markup method
44
+ # in the markup block.
45
+ def method_missing(sym, *args, &block)
46
+ text = nil
47
+ attrs = nil
48
+ sym = "#{sym}:#{args.shift}" if args.first.kind_of?(Symbol)
49
+ args.each do |arg|
50
+ case arg
51
+ when Hash
52
+ attrs ||= {}
53
+ attrs.merge!(arg)
54
+ else
55
+ text ||= ''
56
+ text << arg.to_s
57
+ end
58
+ end
59
+ if block
60
+ unless text.nil?
61
+ raise ArgumentError, "XmlMarkup cannot mix a text argument with a block"
62
+ end
63
+ _capture_outer_self(block) if @self.nil?
64
+ _indent
65
+ _start_tag(sym, attrs)
66
+ _newline
67
+ _nested_structures(block)
68
+ _indent
69
+ _end_tag(sym)
70
+ _newline
71
+ elsif text.nil?
72
+ _indent
73
+ _start_tag(sym, attrs, true)
74
+ _newline
75
+ else
76
+ _indent
77
+ _start_tag(sym, attrs)
78
+ text! text
79
+ _end_tag(sym)
80
+ _newline
81
+ end
82
+ @target
83
+ end
84
+
85
+
86
+
87
+ # Append text to the output target. Escape any markup. May be
88
+ # used within the markup brakets as:
89
+ #
90
+ # builder.p { |b| b.br; b.text! "HI" } #=> <p><br/>HI</p>
91
+ def text!(text)
92
+ _text(_escape(text))
93
+ end
94
+
95
+ # Append text to the output target without escaping any markup.
96
+ # May be used within the markup brakets as:
97
+ #
98
+ # builder.p { |x| x << "<br/>HI" } #=> <p><br/>HI</p>
99
+ #
100
+ # This is useful when using non-builder enabled software that
101
+ # generates strings. Just insert the string directly into the
102
+ # builder without changing the inserted markup.
103
+ #
104
+ # It is also useful for stacking builder objects. Builders only
105
+ # use <tt><<</tt> to append to the target, so by supporting this
106
+ # method/operation builders can use other builders as their
107
+ # targets.
108
+ def <<(text)
109
+ _text(text)
110
+ end
111
+
112
+ # For some reason, nil? is sent to the XmlMarkup object. If nil?
113
+ # is not defined and method_missing is invoked, some strange kind
114
+ # of recursion happens. Since nil? won't ever be an XML tag, it
115
+ # is pretty safe to define it here. (Note: this is an example of
116
+ # cargo cult programming,
117
+ # cf. http://fishbowl.pastiche.org/2004/10/13/cargo_cult_programming).
118
+ def nil?
119
+ false
120
+ end
121
+
122
+ private
123
+
124
+ def _escape(text)
125
+ text.
126
+ gsub(%r{&}, '&amp;').
127
+ gsub(%r{<}, '&lt;').
128
+ gsub(%r{>}, '&gt;')
129
+ end
130
+
131
+ def _capture_outer_self(block)
132
+ @self = eval("self", block)
133
+ end
134
+
135
+ def _newline
136
+ return if @indent == 0
137
+ text! "\n"
138
+ end
139
+
140
+ def _indent
141
+ return if @indent == 0 || @level == 0
142
+ text!(" " * (@level * @indent))
143
+ end
144
+
145
+ def _nested_structures(block)
146
+ @level += 1
147
+ block.call(self)
148
+ ensure
149
+ @level -= 1
150
+ end
151
+
152
+ end
153
+ end