AntBuilder 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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