aquarium 0.5.1 → 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES +240 -215
  3. data/README +61 -44
  4. data/RELEASE-PLAN +21 -23
  5. data/Rakefile +64 -94
  6. data/UPGRADE +45 -35
  7. data/aquarium.gemspec +50 -0
  8. data/examples/README.txt +6 -0
  9. data/examples/aspect_design_example_spec.rb +2 -2
  10. data/examples/design_by_contract_example_spec.rb +3 -3
  11. data/examples/exception_wrapping_example_spec.rb +2 -2
  12. data/examples/introductions_example_spec.rb +1 -1
  13. data/examples/method_tracing_example_spec.rb +17 -16
  14. data/examples/reusable_aspect_hack_example_spec.rb +5 -5
  15. data/jruby/Rakefile +61 -0
  16. data/jruby/java/example/Worker.java +9 -0
  17. data/jruby/java/example/sorter/StringListSorter.java +22 -0
  18. data/jruby/java/example/sorter/converter/StringListCaseConverterAndSorter.java +42 -0
  19. data/jruby/java/example/visibility/Visibility.java +13 -0
  20. data/jruby/spec/java_class_aspects_spec.rb +434 -0
  21. data/jruby/spec/java_visibility_spec.rb +122 -0
  22. data/jruby/spec/spec_helper.rb +5 -0
  23. data/lib/aquarium/aspects/aspect.rb +8 -4
  24. data/lib/aquarium/utils/type_utils.rb +4 -1
  25. data/lib/aquarium/version.rb +29 -28
  26. data/previous_failures.txt +0 -0
  27. data/rspec.watchr +60 -0
  28. data/spec/aquarium/aspects/advice_spec.rb +10 -10
  29. data/spec/aquarium/aspects/aspect_invocation_spec.rb +79 -79
  30. data/spec/aquarium/aspects/aspect_spec.rb +73 -73
  31. data/spec/aquarium/aspects/aspect_with_nested_types_spec.rb +5 -5
  32. data/spec/aquarium/aspects/concurrent_aspects_spec.rb +1 -1
  33. data/spec/aquarium/aspects/default_objects_handler_spec.rb +5 -5
  34. data/spec/aquarium/aspects/join_point_spec.rb +40 -40
  35. data/spec/aquarium/aspects/pointcut_and_composition_spec.rb +8 -8
  36. data/spec/aquarium/aspects/pointcut_spec.rb +25 -25
  37. data/spec/aquarium/extensions/regex_spec.rb +6 -6
  38. data/spec/aquarium/extras/design_by_contract_spec.rb +6 -6
  39. data/spec/aquarium/finders/finder_result_spec.rb +2 -2
  40. data/spec/aquarium/finders/method_finder_spec.rb +24 -24
  41. data/spec/aquarium/finders/pointcut_finder_spec.rb +10 -10
  42. data/spec/aquarium/finders/pointcut_finder_spec_test_classes.rb +4 -4
  43. data/spec/aquarium/finders/type_finder_spec.rb +5 -5
  44. data/spec/aquarium/finders/type_finder_with_descendents_and_ancestors_spec.rb +6 -5
  45. data/spec/aquarium/finders/type_finder_with_nested_types_spec.rb +2 -2
  46. data/spec/aquarium/utils/logic_error_spec.rb +1 -1
  47. data/spec/aquarium/utils/method_utils_spec.rb +38 -38
  48. data/spec/aquarium/utils/nil_object_spec.rb +11 -11
  49. data/spec/aquarium/utils/options_utils_spec.rb +8 -8
  50. data/spec/aquarium/utils/type_utils_spec.rb +3 -3
  51. metadata +238 -57
data/README CHANGED
@@ -7,6 +7,18 @@ Aquarium is a toolkit for Aspect-Oriented Programming (AOP) whose goals include:
7
7
  * A user-friendly DSL.
8
8
  * Support for advising Java types through JRuby.
9
9
 
10
+ === SOMEBODY ADOPT ME!!
11
+
12
+ While I've enjoyed working on Aquarium, I no longer do Ruby development. I just don't have the time to keep updating Aquarium as Ruby evolves. There are plenty of deprecation warnings now when you build Aquarium and JRuby support has been spotty since Aquarium v0.6.0.
13
+
14
+ === Supported Ruby Versions (and Caveats)
15
+
16
+ Aquarium v0.7.0 was tested with Ruby 2.6.3p62 (2019-04-16 revision 67580) and JRuby 9.2.7.0 (Ruby 2.5.3) 2019-04-09 8a269e3. There are many deprecation warnings about constants that have been renamed, all of which appear to be in old libraries still used by Aquarium.
17
+
18
+ Aquarium v0.6.0 supports only Ruby 2.0.0p247. JRuby 1.7.4 (Ruby 1.9.3p392) does *not* currently pass all the custom Java specs in the `jruby/spec` directory, which specifically test working with Java classes. However, JRuby does pass all the Ruby specs in the `spec` directory. I didn't want to release v0.6.0 with the Java-specific specs not working, but I didn't have time to resolve the issues. Patches are welcome.
19
+
20
+ If you need support for even earlier versions of Ruby and JRuby, use Aquarium v0.5.0.
21
+
10
22
  === Why Is an AOP Framework Useful in Ruby?
11
23
 
12
24
  Ruby's metaprogramming facilities already provide some of the capabilities for which static-language AOP toolkits like AspectJ are typically used. With Ruby, you can easily add new methods and attributes to existing classes and objects. You can alias and redefine existing methods, which provides the method interception and "wrapping" needed to extend or modify existing behavior.
@@ -35,7 +47,6 @@ Only around advice can prevent execution of the join point, except for the speci
35
47
  * You cannot advice "String", "Symbol" or instances there of, because trying to specify either one will be confused with naming a type.
36
48
  * Concurrent advice on type AND advice on objects of the type can't be removed cleanly.
37
49
  * The pointcut language is still limited, compared to AspectJ's. See also the comparison with AspectJ behavior next.
38
- * The API and wrapper DSL will probably evolve until the 1.0.0 release. Backwards compatibility will be maintained between releases as much as possible. When it is necessary to break backwards compatibility, translation tools will be provided, if possible.
39
50
  * There are limitations when advising Java types through JRuby. The separate RSpec suite in the "jruby" directory documentations the details on how to use Aquarium with JRuby-wrapped Java types and the limitations thereof. Here we summarize what works and what doesn't:
40
51
  * Aquarium advice on a method in a Java type will only be invoked when the method is called directly from Ruby.
41
52
  * To have the advice invoked when the method is called from either Java or Ruby, it is necessary to create a subclass of the Java type in Ruby and an override of the method, which can just call "super". Note that it will be necessary for instances of this Ruby type to be used throughout, not instances of a Java parent type.
@@ -51,19 +62,19 @@ The goal of Aquarium is to provide a superset of the functionality provided by t
51
62
  === Differences With AspectJ Behavior
52
63
 
53
64
  Many of AspectJ's features are not currently supported by Aquarium, but some of them are planned for future releases.
54
-
55
- * Attribute reading and writing join points are not supported. The :attributes and :attributes_options parameters (and their synonyms) for Aspect.new are actually "syntactic sugar" for the corresponding accessor methods.
65
+
66
+ * Attribute reading and writing join points are not supported. The :attributes and :attributes_options parameters (and their synonyms) for Aspect.new are actually "syntactic sugar" for the corresponding accessor methods.
56
67
  * More advanced AspectJ pointcut language features are not supported, such as the runtime pointcut designators like "if" conditionals and "cflow" (context flow) and the compile time "within" and "withincode" designators. Most of AspectJ pointcut language features are planned, however.
57
68
  * While AspectJ provides "intertype declaration" capabilities (i.e., adding state and behavior to existing classes), Ruby's native metaprogramming support satisfies this need. There may be convenience hooks added in a future release, however.
58
- * User defined advice precedence is not supported. However, advice precedence is unambiguous; the last aspects created while modules are loaded at runtime have higher precedence than earlier aspects. Ensuring a particular order is not always easy, of course.
69
+ * User defined advice precedence is not supported. However, advice precedence is unambiguous; the last aspects created while modules are loaded at runtime have higher precedence than earlier aspects. Ensuring a particular order is not always easy, of course.
59
70
 
60
71
  However, Aquarium does have a few advantages over AspectJ, especially when advising Java types when running in JRuby.
61
72
 
62
73
  * Aquarium can add and remove advice dynamically, at runtime.
63
74
  * Aquarium can advise individual objects, not just classes.
64
75
  * Aquarium can advise JDK classes. AspectJ can also do this, but not by default.
65
- * Aquarium supports named advice that can be defined separately from the aspects that use the advice.
66
- * Aquarium can advise ancestor (parent) types, not just derived (descendent) types of specified types.
76
+ * Aquarium supports named advice that can be defined separately from the aspects that use the advice.
77
+ * Aquarium can advise ancestor (parent) types, not just derived (descendent) types of specified types.
67
78
 
68
79
  Note: at the time of this writing (V0.4.0 release), there is an important limitation of Aquarium when used with java code; it appears that advice is only invoked if an advised method is called directly from Ruby code. If the advised method is called by other Java code, the advice is *not* invoked. Whether or not this limitation can be removed is under investigation.
69
80
 
@@ -134,7 +145,7 @@ If you use the DSL inside a class and omit the :type(s) and :object(s) options,
134
145
  It is important to note that aspect "instances" usually behave like class (static) variables, in terms of the lifetime of their effects. In the example shown, class Foo is permanently modified to do the print statements shown for all "critical methods", unless you save the result of calling "around" to a variable, e.g., critical_operation_logging, and you explicitly call "critical_operation_logging.unadvise" at some future time. Put another way, the effects scope just like changes made when you reopen a class or module.
135
146
 
136
147
  A common mistake is to create an aspect in an initialize method and assign it to an attribute. This usually means that you are creating long-lived, redundant aspects every time an instance of your class is created. The aspect modifications remain in effect even when the instances themselves are garbage collected!
137
-
148
+
138
149
  Here are some more succinct examples, illustrating the API (using the DSL methods) and some of the various synonyms for methods, types, etc.
139
150
 
140
151
  You can pass in pointcuts defined elsewhere:
@@ -147,8 +158,8 @@ As a convenience, since a JoinPoint is a Pointcut with one element, you can pass
147
158
 
148
159
  my_join_point1 = JoinPoint.new :type => Foo::Bar, :method => do_this
149
160
  my_join_point2 = JoinPoint.new :type => Foo::Bar, :method => do_that
150
- around :pointcuts => my_join_point1 do |jp, obj, *args| ...
151
- around :pointcuts => [my_join_point1, my_join_point2, ...] do |jp, obj, *args| ...
161
+ around :pointcuts => my_join_point1 do |jp, obj, *args| ...
162
+ around :pointcuts => [my_join_point1, my_join_point2, ...] do |jp, obj, *args| ...
152
163
 
153
164
  You can specify a single type, a type name, a type regular expression, or an array of the same. Note that :type and :types are synonymous. Use the singular form for better readability when you are specifying just one type. Other synonyms include :on_types, :within_types, and :in_types, plus the singular forms.
154
165
 
@@ -189,8 +200,8 @@ Some of the synonyms:
189
200
  around :calls_to => :all_methods, :in_types_and_ancestors = A, ...
190
201
  around :calls_to => :all_methods, :within_types_and_ancestors = A, ...
191
202
  and similarly for descendents
192
-
193
- You can specify a single object or an array of objects. As for :types, you can use :object, :objects, :on_objects, :within_object, :in_objects, and the singular forms synonymously.
203
+
204
+ You can specify a single object or an array of objects. As for :types, you can use :object, :objects, :on_objects, :within_object, :in_objects, and the singular forms synonymously.
194
205
 
195
206
  a1 = A.new
196
207
  a2 = A.new
@@ -208,7 +219,7 @@ If no types or objects are specified, the object defaults to "self". However, th
208
219
  class MyClass
209
220
  include Aquarium::DSL
210
221
  def doit; ...; end
211
-
222
+
212
223
  around :method => doit, ... # Implicit :object => self, i.e., MyClass
213
224
  end
214
225
 
@@ -232,15 +243,15 @@ You can specify method options. By default, public instance methods only are mat
232
243
 
233
244
  around :methods = /foo/, :method_options => [:instance], ... # match instance methods (default)
234
245
  around :methods = /foo/, :method_options => [:class], ... # match class methods
235
- around :methods = /foo/, :method_options => [:public, :protected, :private], ...
246
+ around :methods = /foo/, :method_options => [:public, :protected, :private], ...
236
247
  # match public, protected, and private instance methods
237
248
  around :methods = /foo/, :method_options => [:singleton], ... # match singleton methods
238
- around :methods = /foo/, :method_options => [:exclude_ancestor_methods], ...
239
- # ignore methods defined in ancestors, inherited classes and included modules
249
+ around :methods = /foo/, :method_options => [:exclude_ancestor_methods], ...
250
+ # ignore methods defined in ancestors, inherited classes and included modules
240
251
 
241
252
  With synonyms:
242
253
 
243
- around :calls_to = /foo/, :restricting_methods_to => [:singleton_methods], ...
254
+ around :calls_to = /foo/, :restricting_methods_to => [:singleton_methods], ...
244
255
 
245
256
  You can specify attributes, which are actually convenience methods for the attribute accessors. They work very much like the :method options. Note that :all is NOT supported in this case. The available synonyms are slightly more complicated, as shown in these examples.
246
257
 
@@ -248,11 +259,11 @@ You can specify attributes, which are actually convenience methods for the attri
248
259
  around :attributes = :foo, ... # the same
249
260
  around :accessing = :foo, ... # the same
250
261
 
251
- around :attribute = :foo, :attribute_options => [:readers]... # only matches #foo
262
+ around :attribute = :foo, :attribute_options => [:readers]... # only matches #foo
252
263
  around :reading = :foo # the same
253
-
254
-
255
- around :attribute = :foo, :attribute_options => [:writers]... # only matches #foo=
264
+
265
+
266
+ around :attribute = :foo, :attribute_options => [:writers]... # only matches #foo=
256
267
  around :writing = :foo # the same
257
268
 
258
269
  around :attributes = [:foo, :bar, :baz], ...
@@ -282,10 +293,10 @@ in an around advice aspect will match all of them:
282
293
 
283
294
  around :named_pointcuts => { :constants_matching => :STATE_CHANGE, :in_types => /App::.*/ } ...
284
295
 
285
- For the type specification, which is required, any valid option for the TypeFinder class is allowed.
296
+ For the type specification, which is required, any valid option for the TypeFinder class is allowed.
286
297
 
287
298
  You can also match on class variables, using ":class_variables_matching". To match on either kind of definition, use just
288
- ":matching". If no :*matching is specified, then any class constant or variable Pointcut found will be matched.
299
+ ":matching". If no :*matching is specified, then any class constant or variable Pointcut found will be matched.
289
300
 
290
301
  Here are the variaus :*matching options and their synonyms:
291
302
 
@@ -314,7 +325,7 @@ You can also use the following synonyms for :named_pointcuts:
314
325
  around :on_named_pointcuts => {...}
315
326
  around :in_named_pointcuts => {...}
316
327
  around :within_named_pointcuts => {...}
317
-
328
+
318
329
  You can specifically exclude particular pointcuts, join points, types, objects, methods, or attributes. This is useful when you specify a list or regular expression of "items" to match and you want to exclude some of the items.
319
330
  Note that there is an open bug (#15202) that appears to affect advising types, unadvising the types, then advising objects of the same types. (This is not likely to happen a lot in real applications, but it shows up when running Aquarium's specs.)
320
331
 
@@ -347,21 +358,21 @@ You can advice methods after returning successfully (i.e., no exceptions were ra
347
358
 
348
359
  after_returning :types => ...
349
360
  after_returning_from :types => ... # synonym
350
-
361
+
351
362
  You can advice methods after raising exceptions:
352
363
 
353
364
  after_raising :types => ... # After any exception is thrown
354
365
  after_raising_within :types => ... # synonym
355
366
  after_raising => MyError, :types => ... # Only invoke advice if "MyError" is raised.
356
- after_raising => [MyError1, MyError2], :types => ...
367
+ after_raising => [MyError1, MyError2], :types => ...
357
368
  # Only invoke advice if "MyError1" or "MyError2" is raised.
358
-
369
+
359
370
  You can advice methods after returning successfully or raising exceptions. (You can't specify
360
371
  a set of exceptions in this case.):
361
372
 
362
373
  after :types => ...
363
374
  after_raising_within_or_returning_from : types => # synonym
364
-
375
+
365
376
  You can advice methods both before after. This is different from around advice, where the around advice has to explicitly invoke the join point (using JoinPoint#proceed). Instead, the before-and-after methods are convenience wrappers around the creation of separate before advice and the corresponding after advice.
366
377
 
367
378
  before_and_after :types =>, ...
@@ -371,10 +382,10 @@ You can advice methods both before after. This is different from around advice,
371
382
  before_and_after_raising_within :types =>, ... # synonym
372
383
  before_and_after_raising_within_or_returning_from :types =>, ... # synonym
373
384
 
374
- If you pass a block to Aspect.new, it will be the advice. When invoked, the advice will be passed the following three arguments,
375
- 1) the JoinPoint, which will contain a JoinPoint::Context object with useful context information,
376
- 2) the object being sent the current message, and
377
- 3) the parameters passed with the original message.
385
+ If you pass a block to Aspect.new, it will be the advice. When invoked, the advice will be passed the following three arguments,
386
+ 1) the JoinPoint, which will contain a JoinPoint::Context object with useful context information,
387
+ 2) the object being sent the current message, and
388
+ 3) the parameters passed with the original message.
378
389
  Recall that a Proc doesn't check the number of arguments (while lambdas do), so if you don't care about any of the trailing parameters, you can leave them out of the parameter list. Recall that the other difference between the two is that a return statement in a Proc returns from the method that contains it. As rule, do NOT use return statements in advices!
379
390
 
380
391
  around :type => [...], :methods => :all do |join_point, object, *args|
@@ -388,10 +399,10 @@ Recall that a Proc doesn't check the number of arguments (while lambdas do), so
388
399
  In the example, we show that you must be careful to return the correct value, usually the value returned by "proceed" or a value created by the block itself.
389
400
 
390
401
  Note, prior to V0.2.0, the advice argument list was |join_point, *args|. Aquarium will look for such obsolete signatures (by looking at the arity of the proc) and raise an exception, if found. This check will be removed in a future release.
391
-
402
+
392
403
  Rather than passing a block as the advice, you can pass a previously-created Proc:
393
-
394
- around :type => [...], :methods => :all, :advice => advice
404
+
405
+ around :type => [...], :methods => :all, :advice => advice
395
406
  around :type => [...], :methods => :all, :advise_with => advice # synonym for advice. Note the "s"!
396
407
  around :type => [...], :methods => :all, :call => advice # synonym for advice.
397
408
  around :type => [...], :methods => :all, :invoke => advice # synonym for advice.
@@ -420,12 +431,19 @@ The simplest approach is to install the gem:
420
431
 
421
432
  If you prefer to build the gem locally, clone from GitHub,
422
433
 
423
- git clone git://github.com/deanwampler/Aquarium.git
434
+ git clone git://github.com/deanwampler/Aquarium.git
424
435
 
425
436
  Then do the following:
426
437
 
427
- rake gem
428
- gem install pkg/aquarium-x.y.z.gem # sudo may be required
438
+ rake install
439
+
440
+ This builds the gem file, pkg/aquarium-x.y.z.gem, and installs it locally.
441
+
442
+ If you are a maintainer and want to upload a new version to RubyGems.org, first see [this page](https://guides.rubygems.org/make-your-own-gem/) for creating a `~/.gem/credentials` file, then run this command to publish a new version.
443
+
444
+ gem push pkg/aquarium-0.7.0.gem
445
+
446
+ At this time, with the demise of RubyForge, the docs and home page are temporarily hosted at https://deanwampler.github.io/open-source/aquarium/index.html. I'll move them to a better location soon. I build them by running `rake website`, then copying the entire output of `../doc/aquarium/out/` to my GitHub site under the `open-source/Aquarium` directory. TBD - move somewhere better!
429
447
 
430
448
  == Running Aquarium's RSpec Specs
431
449
 
@@ -433,14 +451,14 @@ In order to run Aquarium's full suite of specs (rake pre_commit) you must instal
433
451
 
434
452
  * rake # Runs the build script
435
453
  * rspec # Used instead of Test::Unit for TDD
436
- * rcov # Verifies that the code is 100% covered by specs
454
+ * rcov # For running coverage checks
437
455
  * webgen # Generates the static HTML website
456
+ * bundler # Gem manager
438
457
  * coderay # Required by webgen
439
458
  * diff-lcs # Required if you use the --diff switch
440
459
  * win32console # Required by the --colour switch if you're on Windows
441
- * meta_project # Required in order to make releases at RubyForge
442
460
  * heckle # Required if you use the --heckle switch
443
- * jruby # Required if run the separate spec suite in the "jruby" directory (v1.3+)
461
+ * jruby # Required if run the separate spec suite in the "jruby" directory
444
462
 
445
463
  Once those are all installed, you should be able to run the suite with the following steps:
446
464
 
@@ -452,13 +470,13 @@ or
452
470
 
453
471
  Note that Aquarium itself - once built - doesn't have any dependencies outside the Ruby core and stdlib.
454
472
 
455
- If you want to run the tests for the JRuby support, you must also have JRuby 1.1RC2 or later installed. To run the specs for JRuby, use the command
473
+ If you want to run the tests for the JRuby support, you must also have JRuby installed (see version information above). To run the specs for JRuby, use the command
456
474
 
457
475
  * rake verify_jruby
458
476
 
459
477
  This command runs the standard Aquarium specs using JRuby instead of MRI, then runs a separate set of specs in the "jruby/spec" directory which test Aquarium with Java classes inside JRuby.
460
478
 
461
- See http://aquarium.rubyforge.org for further documentation.
479
+ > **WARNING:** Currently, not all JRuby-specific specs pass!
462
480
 
463
481
  === Acknowledgments
464
482
 
@@ -468,5 +486,4 @@ The RSpec team, in particular David Chelimsky, have really inspired my thinking
468
486
 
469
487
  Keita Yamaguchi contributed some key patches that enabled Ruby 1.9.3 and JRuby 1.6.7 support, in addition to the prior support for Ruby 1.8.7. These patches allowed me to final release version 0.5.X. Thank you!
470
488
 
471
- Finally, a number of users have contributed valuable feedback. In particular, thanks to Brendan L., Matthew F., and Mark V.
472
-
489
+ Finally, a number of users have contributed valuable feedback. In particular, thanks to Brendan L., Matthew F., and Mark V.
@@ -6,26 +6,26 @@ Mostly bug fixes and enhancements. Only "minor" breakages of backwards compatibi
6
6
 
7
7
  === Versions 0.2
8
8
 
9
- Change the argument list for advice to |join_point, object, *args| from |join_point, *args|,
10
- where "*args" are the arguments passed to the invoked join point (method). Since nontrivial
11
- advice usually needs the object being advised, it became clear that having to call
12
- "join_point.context.advised_object" is too tedious.
9
+ Change the argument list for advice to |join_point, object, *args| from |join_point, *args|,
10
+ where "*args" are the arguments passed to the invoked join point (method). Since nontrivial
11
+ advice usually needs the object being advised, it became clear that having to call
12
+ "join_point.context.advised_object" is too tedious.
13
13
 
14
14
  This change will obvious break existing aspects.
15
15
 
16
16
  === Versions 0.3+
17
17
 
18
- More refinements and simplifications to the API and functionality, including much-needed
18
+ More refinements and simplifications to the API and functionality, including much-needed
19
19
  redundancy reduction. I haven't used mocks much in the specs, but they would help improve the
20
- performance of the RSpec runs.
20
+ performance of the RSpec runs.
21
21
 
22
- The main thrust of new feature work will be expanding the pointcut language to include
23
- conditionals and stack context constructs, as well as more intuitive ways of expressing sets of
24
- types, such as types nested arbitrarily deep in module "namespaces" (e.g., #13403), etc.
22
+ The main thrust of new feature work will be expanding the pointcut language to include
23
+ conditionals and stack context constructs, as well as more intuitive ways of expressing sets of
24
+ types, such as types nested arbitrarily deep in module "namespaces" (e.g., #13403), etc.
25
25
 
26
26
  I'm also thinking about an alternative syntax for the DSL. Instead of just this:
27
27
 
28
- Aspect.new :around :pointcuts => [pc1, pc2, ...] do |jp, object, *args|
28
+ Aspect.new :around :pointcuts => [pc1, pc2, ...] do |jp, object, *args|
29
29
  # advise
30
30
  end
31
31
 
@@ -33,12 +33,12 @@ How about something like the following?
33
33
 
34
34
  around do
35
35
  pointcuts pc1 or pc2
36
- advise_with do |jp, object, *args|
36
+ advise_with do |jp, object, *args|
37
37
  # advise
38
38
  end
39
39
  end
40
40
 
41
- I'm not sure it adds much (at this stage of thinking about it...) except that it could make
41
+ I'm not sure it adds much (at this stage of thinking about it...) except that it could make
42
42
  composition of complex pointcuts easier.
43
43
 
44
44
  I also want to ensure full support for running in JRuby. In particular, you should be able to
@@ -47,13 +47,13 @@ advise Java types!
47
47
  === Version 0.5
48
48
 
49
49
  My goals for this release include more performance improvements (#19321) and investigating some ideas
50
- for a real DSL, meaning declarative statements in blocks, rather than method arguments. It will be
50
+ for a real DSL, meaning declarative statements in blocks, rather than method arguments. It will be
51
51
  redundant somewhat with the existing "method-argument form", as it exists today, but it will set
52
52
  the stage for much more complex aspect definitions than would be convenient with the current form.
53
53
 
54
54
  Another big change is to make pointcut evaluation and advice application happen continuous at runtime,
55
55
  rather than only when the aspect is defined. This would eliminate subtle problems related to the order
56
- of loading and also makes the declarative nature of aspects more fully realized. For example, if I
56
+ of loading and also makes the declarative nature of aspects more fully realized. For example, if I
57
57
  declare an aspect for all types in a module namespace, it should still apply to nested types defined
58
58
  or loaded after the aspect is defined. This enhancement will also make it easier to define reusable
59
59
  and "abstract" aspects, where they aren't applied immediately, but only when extended by "concrete"
@@ -64,16 +64,14 @@ simpler aspects.
64
64
 
65
65
  Finally, this release will finally support Ruby 1.9.X and the latest JRuby at the time of the release.
66
66
 
67
- === Version 0.6+
67
+ === Version 0.6.X and 0.7.X
68
+
69
+ These releases updated to the latest with Ruby and JRuby versions without other significant changes.
70
+
71
+ === Version 1.0+
68
72
 
69
73
  I have been thinking about higher-order abstractions that work above the "Pointcut + Advice
70
- Model" of Aquarium (and AspectJ...) today. I consider the pointcut + advice model to be an
74
+ Model" of Aquarium (and AspectJ...) today. I consider the pointcut + advice model to be an
71
75
  important, maybe essential, building block of AOP, but if that's all AOP is, then we've probably
72
- already hit the limit of what we can expect AOP to do. That doesn't seem right to me, but it's
76
+ already hit the limit of what we can expect AOP to do. That doesn't seem right to me, but it's
73
77
  not at all clear what the higher-order abstractions should be.
74
-
75
- === Version 1.0.0
76
-
77
- Reasonably stable and full-featured API and DSL. Also, to justify Aquarium's existence ;), I want
78
- to produce some non-trivial examples of refactoring known APIs and demonstrating improved clarity,
79
- productivity, modularity, etc., etc.
data/Rakefile CHANGED
@@ -1,9 +1,9 @@
1
1
  $:.unshift('lib')
2
2
  require 'rubygems'
3
3
  require 'rake'
4
- require 'rake/gempackagetask'
5
- require 'rake/contrib/rubyforgepublisher'
6
4
  require 'rake/clean'
5
+ require "bundler/gem_tasks"
6
+ require 'rake/packagetask'
7
7
  require 'rdoc/task'
8
8
  require 'aquarium/version'
9
9
 
@@ -20,8 +20,8 @@ PKG_VERSION = Aquarium::VERSION::STRING
20
20
  PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
21
21
  PKG_FILES = FileList[
22
22
  '[A-Z]*',
23
- 'lib/**/*.rb',
24
- 'spec/**/*.rb',
23
+ 'lib/**/*.rb',
24
+ 'spec/**/*.rb',
25
25
  'examples/**/*.rb',
26
26
  'rake_tasks/**/*.rake'
27
27
  ]
@@ -29,71 +29,20 @@ FileUtils.touch(File.dirname(__FILE__) + '/previous_failures.txt')
29
29
 
30
30
  IS_WINDOWS = (RUBY_VERSION == "1.8.7" ? PLATFORM : RUBY_PLATFORM) =~ /mswin/
31
31
 
32
- task :default => :spec
32
+ WEBSITE_ROOT = "../doc/aquarium"
33
+
34
+ task :default => :spec
33
35
 
34
36
  desc "Run all specs"
35
37
  RSpec::Core::RakeTask.new do |t|
36
38
  t.rspec_opts = ['--color', '--format progress', '--profile']
37
39
  end
38
40
 
39
- # desc "Run all specs and store html output in doc/aquarium/out/report.html"
40
- # RSpec::Core::RakeTask.new('spec_html') do |t|
41
- # t.rspec_opts = ['--format html:../doc/aquarium/out/report.html','--backtrace']
42
- # end
43
-
44
- desc 'Generate HTML documentation for website'
45
- task :webgen do
46
- Dir.chdir '../doc/aquarium' do
47
- output = nil
48
- IO.popen('rake webgen 2>&1') do |io|
49
- output = io.read
50
- end
51
- raise "ERROR while running webgen: #{output}" if output =~ /ERROR/n || $? != 0
52
- end
53
- end
54
-
55
- desc 'Generate RDoc'
56
- rd = Rake::RDocTask.new do |rdoc|
57
- rdoc.rdoc_dir = '../doc/aquarium/out/rdoc'
58
- rdoc.options << '--title' << 'Aquarium' << '--line-numbers' << '--inline-source' << '--main' << 'README'
59
- rdoc.rdoc_files.include('README', 'CHANGES', 'MIT_LICENSE', 'examples/**/*.rb', 'UPGRADE', 'lib/**/*.rb') # 'EXAMPLES.rd'
60
- end
61
-
62
- # desc "Generate EXAMPLES.rb"
63
- # task :rdoc do
64
- # core.rdoc
65
- # end
66
-
67
- aquarium = Gem::Specification.new do |s|
68
- s.name = PKG_NAME
69
- s.version = PKG_VERSION
70
- s.summary = Aquarium::VERSION::DESCRIPTION
71
- s.description = <<-EOF
72
- Aquarium is a full-featured Aspect-Oriented Programming (AOP) framework for Ruby that is
73
- designed to provide an intuitive syntax and support for large-scale, dynamic aspects.
74
- EOF
75
-
76
- s.files = PKG_FILES.to_a
77
- s.require_path = 'lib'
78
-
79
- s.has_rdoc = true
80
- s.rdoc_options = rd.options
81
- s.extra_rdoc_files = rd.rdoc_files.reject { |fn| fn =~ /\.rb$|^EXAMPLES.rd$/ }.to_a
82
-
83
- s.autorequire = 'aquarium'
84
- s.bindir = 'bin'
85
- s.executables = []
86
- s.default_executable = ''
87
- s.authors = ["Aquarium Development Team"]
88
- s.email = "aquarium-devel@rubyforge.org"
89
- s.homepage = "http://aquarium.rubyforge.org"
90
- s.rubyforge_project = "aquarium"
91
- end
92
-
93
- Rake::GemPackageTask.new(aquarium) do |pkg|
94
- pkg.need_zip = true
95
- pkg.need_tar = true
96
- end
41
+ Rake::PackageTask.new("aquarium", "#{Aquarium::VERSION::STRING}") do |p|
42
+ p.need_zip = true
43
+ p.need_tar = true
44
+ p.package_files = `git ls-files`.split("\n")
45
+ end
97
46
 
98
47
  def egrep(pattern)
99
48
  Dir['**/*.rb'].each do |fn|
@@ -115,12 +64,15 @@ task :todo do
115
64
  end
116
65
 
117
66
  task :clobber do
118
- rm_rf '../doc/aquarium/out'
119
- rm_rf '../doc/aquarium/webgen.cache'
67
+ rm_rf "#{WEBSITE_ROOT}/out"
68
+ rm_rf "#{WEBSITE_ROOT}/webgen/out"
69
+ rm_rf "#{WEBSITE_ROOT}/webgen/tmp"
120
70
  rm_rf 'translated_specs'
121
71
  end
122
72
 
123
- task :release => [:clobber, :verify_committed, :verify_user, :spec, :publish_packages, :tag, :publish_website, :publish_news]
73
+ task :release => [:clobber, :verify_committed, :verify_user, :spec, :package_release]
74
+
75
+ task :package_release => [:website, :install, :package, :publish_packages, :tag, :publish_website, :publish_news]
124
76
 
125
77
  # TODO!
126
78
  desc "Verifies that there is no uncommitted code"
@@ -132,37 +84,55 @@ task :verify_committed do
132
84
  end
133
85
  end
134
86
 
135
- # TODO!
136
87
  desc "Creates a tag in git"
137
88
  task :tag do
138
- end
89
+ `git tag #{Aquarium::VERSION::TAG}`
90
+ end
91
+
92
+ # desc "Creates a tag in svn (obsolete)"
93
+ # task :svntag do
94
+ # from = `svn info #{File.dirname(__FILE__)}`.match(/URL: (.*)\/aquarium/n)[1]
95
+ # to = from.gsub(/trunk/, "tags/#{Aquarium::VERSION::TAG}")
96
+ # tag_cmd = "svn cp #{from} #{to} -m \"Tag release #{Aquarium::VERSION::FULL_VERSION}\""
97
+ # raise "Can't tag to the same place: #{tag_cmd}" if to == from
98
+ # puts "Creating tag in SVN"
99
+ # `#{tag_cmd}`
100
+ # raise "Tagging failed" unless $? == 0
101
+ # end
139
102
 
140
- desc "Creates a tag in svn (obsolete)"
141
- task :svntag do
142
- from = `svn info #{File.dirname(__FILE__)}`.match(/URL: (.*)\/aquarium/n)[1]
143
- to = from.gsub(/trunk/, "tags/#{Aquarium::VERSION::TAG}")
144
- tag_cmd = "svn cp #{from} #{to} -m \"Tag release #{Aquarium::VERSION::FULL_VERSION}\""
145
- raise "Can't tag to the same place: #{tag_cmd}" if to == from
146
- puts "Creating tag in SVN"
147
- `#{tag_cmd}`
148
- raise "Tagging failed" unless $? == 0
103
+ desc "Build the website, but do not publish it"
104
+ task :website => [:clobber, :rdoc, :webgen, :stage_website]
105
+
106
+ desc 'Generate HTML documentation for website'
107
+ task :webgen do
108
+ puts "In #{WEBSITE_ROOT}, running 'rake webgen':"
109
+ Dir.chdir "#{WEBSITE_ROOT}" do
110
+ output = nil
111
+ IO.popen('rake webgen 2>&1') do |io|
112
+ output = io.read
113
+ end
114
+ if $? != 0
115
+ puts "ERROR while running webgen: #{output}"
116
+ raise "ERROR while running webgen"
117
+ end
118
+ end
149
119
  end
150
120
 
151
- # TODO: adapt from rspec.
152
- # desc "Run this task before you commit. You should see 'OK TO COMMIT'"
153
- # task :pre_commit => [
154
- # :website,
155
- # :examples
156
- # ]
121
+ desc 'Generate RDoc'
122
+ rd = Rake::RDocTask.new do |rdoc|
123
+ rdoc.rdoc_dir = "#{WEBSITE_ROOT}/out/rdoc"
124
+ rdoc.options << '--title' << 'Aquarium' << '--line-numbers' << '--main' << 'README'
125
+ rdoc.rdoc_files.include('README', 'CHANGES', 'MIT_LICENSE', 'examples/**/*.rb', 'UPGRADE', 'lib/**/*.rb') # 'EXAMPLES.rd'
126
+ end
157
127
 
158
- desc "Build the website, but do not publish it"
159
- task :website => [:clobber, :rdoc, :webgen] # :spec_html, :verify_jruby, :verify_rcov,
128
+ task :stage_website do
129
+ # Hack so that cp_r works correctly:
130
+ mv "#{WEBSITE_ROOT}/out/", "#{WEBSITE_ROOT}/out-tmp/"
131
+ puts "cp_r #{WEBSITE_ROOT}/webgen/out, #{WEBSITE_ROOT}/out"
132
+ cp_r "#{WEBSITE_ROOT}/webgen/out", "#{WEBSITE_ROOT}/out"
133
+ mv "#{WEBSITE_ROOT}/out-tmp/rdoc", "#{WEBSITE_ROOT}/out"
134
+ rmdir "#{WEBSITE_ROOT}/out-tmp/"
160
135
 
161
- task :rdoc_rails do
162
- Dir.chdir '../aquarium_on_rails' do
163
- rake = IS_WINDOWS ? "rake.cmd" : "rake"
164
- `#{rake} rdoc`
165
- end
166
136
  end
167
137
 
168
138
  desc "Verify that the Aquarium specs run under JRuby and that JRuby can advise Java types. If this task fails, try running 'jruby -S rake' separately."
@@ -173,7 +143,7 @@ task :verify_jruby do
173
143
  sh "jruby -S #{rake}"
174
144
  end
175
145
  end
176
-
146
+
177
147
 
178
148
  task :verify_user do
179
149
  raise "RUBYFORGE_USER environment variable not set!" unless ENV['RUBYFORGE_USER']
@@ -189,7 +159,7 @@ task :do_publish_website do
189
159
  publisher = Rake::SshDirPublisher.new(
190
160
  "#{host}",
191
161
  "/var/www/gforge-projects/#{PKG_NAME}",
192
- "../doc/aquarium/out"
162
+ "#{WEBSITE_ROOT}/out"
193
163
  )
194
164
  publisher.upload
195
165
  else
@@ -204,7 +174,7 @@ task :archive_website => [:verify_user, :website] do
204
174
  publisher = Rake::SshDirPublisher.new(
205
175
  "#{host}",
206
176
  "/var/www/gforge-projects/#{PKG_NAME}/#{Spec::VERSION::TAG}",
207
- "../doc/aquarium/out"
177
+ "#{WEBSITE_ROOT}/out"
208
178
  )
209
179
  publisher.upload
210
180
  end
@@ -241,7 +211,7 @@ task :publish_packages => [:verify_user, :package] do
241
211
  *release_files
242
212
  )
243
213
  publisher.upload
244
-
214
+
245
215
  puts "UPLADED THE FOLLOWING FILES:"
246
216
  release_files.each do |file|
247
217
  name = file.match(/pkg\/(.*)/)[1]