caterpillar 1.0.7 → 1.2.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. data/ChangeLog +28 -0
  2. data/README.rdoc +91 -0
  3. data/Rakefile +2 -9
  4. data/bin/caterpillar +1 -0
  5. data/generators/caterpillar/caterpillar_generator.rb +3 -0
  6. data/generators/caterpillar/templates/config/portlets.rb +14 -7
  7. data/init.rb +3 -0
  8. data/install.rb +3 -0
  9. data/lib/caterpillar.rb +12 -3
  10. data/lib/caterpillar/config.rb +14 -7
  11. data/lib/caterpillar/helpers/liferay.rb +3 -0
  12. data/lib/caterpillar/liferay.rb +37 -12
  13. data/lib/caterpillar/navigation.rb +10 -1
  14. data/lib/caterpillar/parser.rb +3 -0
  15. data/lib/caterpillar/portlet.rb +31 -6
  16. data/lib/caterpillar/security.rb +132 -0
  17. data/lib/caterpillar/task.rb +29 -37
  18. data/lib/caterpillar/usage.rb +3 -0
  19. data/lib/caterpillar/util.rb +17 -7
  20. data/lib/java/rails-portlet-0.9.2.jar +0 -0
  21. data/lib/rails_gem_chooser.rb +77 -0
  22. data/lib/web/portlet.rb +3 -0
  23. data/portlet_test_bench/{README → README.rdoc} +3 -1
  24. data/portlet_test_bench/controllers/caterpillar/application.rb +15 -5
  25. data/portlet_test_bench/controllers/caterpillar/css_controller.rb +3 -0
  26. data/portlet_test_bench/controllers/caterpillar/http_methods_controller.rb +3 -0
  27. data/portlet_test_bench/controllers/caterpillar/js_controller.rb +3 -0
  28. data/portlet_test_bench/controllers/caterpillar/junit_controller.rb +217 -0
  29. data/portlet_test_bench/controllers/caterpillar/liferay_controller.rb +3 -0
  30. data/portlet_test_bench/controllers/caterpillar/login_controller.rb +3 -0
  31. data/portlet_test_bench/controllers/caterpillar/resource_controller.rb +3 -0
  32. data/portlet_test_bench/controllers/caterpillar/session_controller.rb +23 -31
  33. data/portlet_test_bench/controllers/caterpillar/user_controller.rb +3 -0
  34. data/portlet_test_bench/helpers/caterpillar/application_helper.rb +7 -2
  35. data/portlet_test_bench/helpers/caterpillar/junit_helper.rb +18 -0
  36. data/portlet_test_bench/routing.rb +8 -14
  37. data/portlet_test_bench/views/caterpillar/application/index.html.erb +67 -3
  38. data/portlet_test_bench/views/caterpillar/http_methods/post.html.erb +10 -1
  39. data/portlet_test_bench/views/caterpillar/junit/basic_tags.html.erb +27 -0
  40. data/portlet_test_bench/views/caterpillar/junit/css.html.erb +45 -0
  41. data/portlet_test_bench/views/caterpillar/junit/doctype_html4_strict.html.erb +12 -0
  42. data/portlet_test_bench/views/caterpillar/junit/doctype_html5.html.erb +12 -0
  43. data/portlet_test_bench/views/caterpillar/junit/doctype_html5_minified.html.erb +4 -0
  44. data/portlet_test_bench/views/caterpillar/junit/doctype_undefined.html.erb +11 -0
  45. data/portlet_test_bench/views/caterpillar/junit/doctype_xhtml10_strict.html.erb +12 -0
  46. data/portlet_test_bench/views/caterpillar/junit/doctype_xhtml10_transitional.html.erb +12 -0
  47. data/portlet_test_bench/views/caterpillar/junit/doctype_xhtml11.html.erb +12 -0
  48. data/portlet_test_bench/views/caterpillar/junit/form.html.erb +6 -0
  49. data/portlet_test_bench/views/caterpillar/junit/http_post.html.erb +17 -0
  50. data/portlet_test_bench/views/caterpillar/junit/post_and_redirect.html.erb +25 -0
  51. data/portlet_test_bench/views/caterpillar/junit/target1.html.erb +1 -0
  52. data/portlet_test_bench/views/caterpillar/junit/xhr.html.erb +6 -0
  53. data/portlet_test_bench/views/caterpillar/junit/xslt_simple.html.erb +12 -0
  54. data/portlet_test_bench/views/caterpillar/session/cookie.html.erb +1 -0
  55. data/portlet_test_bench/views/layouts/bare.html.erb +12 -0
  56. data/test/liferay_helpers_test.rb +6 -3
  57. data/test/portlets_test.rb +8 -3
  58. data/test/xml_test.rb +49 -3
  59. data/views/layouts/caterpillar.html.erb +12 -0
  60. metadata +85 -50
  61. data/README +0 -70
  62. data/lib/java/rails-portlet-0.7.2.jar +0 -0
  63. data/lib/load_rails.rb +0 -29
  64. data/test/generator_test.rb +0 -11
data/ChangeLog CHANGED
@@ -1,3 +1,31 @@
1
+ = 1.2.5
2
+ - Ruby 1.9 compatibility fix
3
+ - define utf8 encoding (thanks to Hendie Dijkman for mentioning about it)
4
+
5
+ = 1.2.4
6
+ - use standalone Rails defaults in the installed config file
7
+ - updated xUnit tests in the portlet test bench
8
+
9
+ = 1.2.3
10
+ - include rails-portlet 0.9.2
11
+ - parse session key and secret into the XML
12
+ - provide Caterpillar::Security actions for Rails controllers
13
+
14
+ = 1.1.2
15
+ - allow to defining the deploy_dir in config/portlets.rb
16
+ (requested by Túlio Ornelas dos Santos, who sent the original patch)
17
+
18
+ = 1.1.1
19
+ - regression fix
20
+
21
+ = 1.1.0
22
+ - include rails-portlet 0.8.1
23
+ - improved test bench appearance, updated available tests
24
+ - added JUnit test controller for automatic testing
25
+ - moved db:migrate and db:rollback to lportal
26
+ - gem loading is now handled by a static class
27
+ - fixed gem loading with Rails 2.3.5'
28
+
1
29
  = 1.0.7
2
30
  - include rails-portlet 0.7.2
3
31
 
@@ -0,0 +1,91 @@
1
+ Caterpillar is a developer tool to help building and deploying Rails applications for Liferay portlets.
2
+ The aim is to minimize the needed additions to the Rails framework and interfere with the developer workflow.
3
+
4
+ Main features:
5
+
6
+ * installs the portlet JAR to Liferay's [+CLASSPATH+]
7
+ * dynamic portlet XML creation based on named routes
8
+ * deploys the generated XML to Liferay, requires Liferay restart
9
+ * implements session security by shared key authentication
10
+
11
+ For developers:
12
+
13
+ * portlet test bench
14
+ * a Rails view helper which lists portlets during development
15
+
16
+
17
+ == Quickstart
18
+ NOTE: *Rubygems does not seem to get the most uptodate version.* The release should be >= 1.2.3.
19
+ Please download the latest release from Rubyforge.
20
+
21
+ $ gem install caterpillar-1.2.3.gem
22
+
23
+ Start up a new Rails project:
24
+
25
+ $ rails example
26
+ $ cd example
27
+ $ caterpillar pluginize
28
+
29
+ Activate Caterpillar routes by updating <tt>RAILS_ROOT/config/routes.rb</tt> to read as follows:
30
+
31
+ ActionController::Routing::Routes.draw do |map|
32
+ map.caterpillar # add this line
33
+ # ... other routes ...
34
+
35
+ This route mapping is also needed to use portlet security features to prevent UID faking. Update <tt>ApplicationController</tt>:
36
+ class ApplicationController < ActionController::Base
37
+ include Caterpillar::Security
38
+ secure_portlet_sessions
39
+
40
+ If you are connecting to the Liferay database, add lportal[http://lportal.rubyforge.org/] in the Rails startup:
41
+ $ echo "require 'lportal'" > config/initializers/lportal.rb
42
+ And set up the database connection.
43
+
44
+ Now run <tt>caterpillar portlets</tt> to check if the installation is working.
45
+ The output should include these lines:
46
+
47
+ * Portlet configuration ***********************
48
+ Caterpillar
49
+ Rails-portlet test bench "portlet_test_bench" []
50
+
51
+ Then you can start up the server (<tt>./script/server</tt>) and navigate to http://localhost:3000/caterpillar/test_bench
52
+
53
+
54
+ == Good to know
55
+ The command-line tool <tt>caterpillar</tt> should be executed in the Rails project root directory.
56
+ You can install and upgrade the <tt>rails-portlet</tt> JAR and generate dynamic portlet XML and also
57
+ deploy them. See the task description below - and you can also run <tt>caterpillar --describe</tt>.
58
+
59
+ The optional Caterpillar Rails plugin offers specialized helpers and views for better Liferay integration
60
+ and to ease the development. Not to mention the portlet test bench application.
61
+
62
+ Developers should know that this is required to successfully run the <tt>rails-portlet</tt> test suite,
63
+ where JUnit tests do actual requests to the Rails app.
64
+
65
+ You can take plugins into use by running
66
+ $ caterpillar pluginize
67
+ in the Rails directory, but you need to remember that with each subsequent upgrade of Caterpillar, you would need to
68
+ rm vendor/plugins/caterpillar && caterpillar pluginize
69
+ each time. Rails is quite picky where it will load the views - security issue.
70
+
71
+ Maybe caterpillar could have an upgrade task to handle this?
72
+
73
+
74
+ == Useful tasks
75
+ Here are the most useful tasks; see the rdoc documentation and caterpillar --describe for the full feature list.
76
+
77
+ <tt>xml</tt>:: processes the portlet XML configuration in accordance with the named routes
78
+
79
+ <tt>xml:deploy</tt>:: deploys the created XML to the J2EE portlet container
80
+
81
+ <tt>jar:install</tt>:: installs the Rails-portlet JAR into Liferay's classpath
82
+
83
+ <tt>deploy</tt>:: warbles the application, updates the XML configuration and copies these to Liferay
84
+
85
+ <tt>pluginize</tt>:: copies caterpillar to vendor/plugins
86
+
87
+ <tt>fixtures</tt>:: imports live data from the production database for testing
88
+
89
+
90
+ Join the bugs mailing list (http://rubyforge.org/mailman/listinfo/rails-portlet-bugs) to request help.
91
+
data/Rakefile CHANGED
@@ -5,19 +5,12 @@ require 'rake/rdoctask'
5
5
  desc 'Default: create API doc.'
6
6
  task :default => :rdoc
7
7
 
8
- desc 'Test the example plugin.'
9
- Rake::TestTask.new(:test) do |t|
10
- t.libs << 'lib'
11
- t.pattern = 'test/**/*_test.rb'
12
- t.verbose = true
13
- end
14
-
15
8
  desc 'Generate documentation for the example plugin.'
16
9
  Rake::RDocTask.new(:rdoc) do |rdoc|
17
10
  rdoc.rdoc_dir = 'rdoc'
18
11
  rdoc.title = 'Caterpillar'
19
- rdoc.main = 'README'
20
- rdoc.rdoc_files.include('README')
12
+ rdoc.main = 'README.rdoc'
13
+ rdoc.rdoc_files.include('README.rdoc')
21
14
  rdoc.rdoc_files.include('lib/**/*.rb')
22
15
  rdoc.rdoc_files.include('generators/**/*.rb')
23
16
  rdoc.options << '--line-numbers' << '--inline-source' << '-U'
@@ -2,6 +2,7 @@
2
2
  #
3
3
  #--
4
4
  # (c) Copyright 2008 Mikael Lammentausta, Cel'Amanzi Ltd
5
+ # 2010 Mikael Lammentausta, Youleaf Ltd
5
6
  #
6
7
  # Constructed heavily upon Warbler's structure.
7
8
  # Thanks to Nick Sieger!
@@ -1,3 +1,6 @@
1
+ # encoding: utf-8
2
+
3
+
1
4
  # This generator installs the required files into the main Rails application.
2
5
  # This generator should always be run after upgrading the plugin.
3
6
  class CaterpillarGenerator < Rails::Generator::Base
@@ -1,3 +1,6 @@
1
+ # encoding: utf-8
2
+
3
+
1
4
  Caterpillar::Config.new do |portlet|
2
5
 
3
6
  # JRUBY_HOME can be set here, unless the environment variable can be used.
@@ -7,7 +10,7 @@ Caterpillar::Config.new do |portlet|
7
10
  # By default only portlet.xml is created.
8
11
  # Currently only Liferay is supported. You may optionally define the version.
9
12
  portlet.container = Liferay
10
- # portlet.container.version = '5.1.1'
13
+ # portlet.container.version = '5.2.3'
11
14
 
12
15
  # If you want to install the Rails-portlet JAR into the container, the container
13
16
  # WEB-INF will be used.
@@ -30,19 +33,23 @@ Caterpillar::Config.new do |portlet|
30
33
  # By default the first entry in the directory is chosen.
31
34
  # portlet.container.server_dir = 'default'
32
35
 
36
+ # Allow to defining the deploy_dir - both the WAR file and the XML files
37
+ # are deployed under this directory.
38
+ # portlet.container.deploy_dir = '/opt/myDeployDir'
39
+
33
40
  # The hostname and port.
34
41
  # By default the values are taken from the request.
35
- # portlet.host
36
-
42
+ portlet.host = 'http://0.0.0.0:3000'
43
+
37
44
  # If the Rails is running inside a servlet container such as Tomcat,
38
45
  # you can define the servlet here.
39
46
  # By default the servlet is the name of the Rails app.
40
- # Remember to update this if you override Warbler's default.
41
- # portlet.servlet
42
-
47
+ # Without Warbler this should be an empty string.
48
+ portlet.servlet = ''
49
+
43
50
  # Portlet category. This is only available for Liferay.
44
51
  # By default this is the same as the servlet.
45
- # portlet.category = 'Zcore'
52
+ # portlet.category = 'Example Rails app'
46
53
 
47
54
  # Portlet instances.
48
55
  #
data/init.rb CHANGED
@@ -1,3 +1,6 @@
1
+ # encoding: utf-8
2
+
3
+
1
4
  #--
2
5
  # (c) Copyright 2008,2009 Mikael Lammentausta
3
6
  #
data/install.rb CHANGED
@@ -1,3 +1,6 @@
1
+ # encoding: utf-8
2
+
3
+
1
4
  # This will install required files into the main Rails application.
2
5
  system('./script/generate caterpillar')
3
6
 
@@ -1,12 +1,15 @@
1
+ # encoding: utf-8
2
+
3
+
1
4
  #--
2
- # (c) Copyright 2008,2009 Mikael Lammentausta
5
+ # (c) Copyright 2008-2010 Mikael Lammentausta
3
6
  #
4
7
  # See the file MIT-LICENSE included with the distribution for
5
8
  # software license details.
6
9
  #++
7
10
 
8
11
  module Caterpillar
9
- VERSION='1.0.7'
12
+ VERSION='1.2.5'
10
13
  end
11
14
 
12
15
  this_file = File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__
@@ -20,7 +23,13 @@ require 'find'
20
23
  require 'rake'
21
24
  require 'rake/tasklib'
22
25
 
23
- require File.join(this_dir,'load_rails')
26
+ # NOTE: During normal startup (not while building the gem),
27
+ # ActiveRecord should be loaded at this point, before loading any of the models.
28
+ # However, this may conflict later when Rails' rake task activates the boot process.
29
+ # The correct versions should be loaded at this point.
30
+ # Maybe this is too heavy, as some tasks do not need any Rails modules.
31
+ require File.join(this_dir,'rails_gem_chooser')
32
+ RailsGemChooser.__load # detects the Rails config file from RAILS_ROOT
24
33
 
25
34
  # include all ruby files
26
35
  Find.find(this_dir) do |file|
@@ -1,3 +1,6 @@
1
+ # encoding: utf-8
2
+
3
+
1
4
  #--
2
5
  # (c) Copyright 2008 Mikael Lammentausta
3
6
  # See the file LICENSES.txt included with the distribution for
@@ -37,8 +40,8 @@ module Caterpillar
37
40
  def initialize
38
41
  # RAILS_ROOT is at least defined in Caterpillar initialization
39
42
  @rails_root = File.expand_path(RAILS_ROOT)
40
- @servlet = File.basename(@rails_root)
41
- @category = @servlet
43
+ @servlet = nil
44
+ @category = nil
42
45
  @instances = []
43
46
  @javascripts = []
44
47
  @include_all_named_routes = true
@@ -46,11 +49,15 @@ module Caterpillar
46
49
  rails_conf = File.join(@rails_root,'config','environment.rb')
47
50
  unless File.exists?(rails_conf)
48
51
  STDERR.puts 'Rails configuration file could not be found'
49
- end
50
-
51
- @warbler_conf = File.join(@rails_root,'config','warble.rb')
52
- unless File.exists?(@warbler_conf)
53
- #STDERR.puts 'Warbler configuration file could not be found'
52
+ @rails_root = nil
53
+ else
54
+ @servlet = File.basename(@rails_root)
55
+ @category = @servlet
56
+
57
+ @warbler_conf = File.join(@rails_root,'config','warble.rb')
58
+ unless File.exists?(@warbler_conf)
59
+ #STDERR.puts 'Warbler configuration file could not be found'
60
+ end
54
61
  end
55
62
 
56
63
  #@logger = (defined?(RAILS_DEFAULT_LOGGER) ? RAILS_DEFAULT_LOGGER : Logger.new)
@@ -1,3 +1,6 @@
1
+ # encoding: utf-8
2
+
3
+
1
4
  require 'rubygems'
2
5
  require 'action_controller'
3
6
 
@@ -1,3 +1,6 @@
1
+ # encoding: utf-8
2
+
3
+
1
4
  #--
2
5
  # (c) Copyright 2008,2009 Mikael Lammentausta
3
6
  #
@@ -51,13 +54,18 @@ module Caterpillar # :nodoc:
51
54
 
52
55
  # the name of the JBoss server directory
53
56
  attr_accessor :server_dir
57
+
58
+ # For setting @deploy dir from the config file.
59
+ # The "get" method is deploy_dir().
60
+ attr_writer :deploy_dir
54
61
 
55
62
  # Liferay version is given as a String, eg. '5.2.2'.
56
63
  # Defaults to +Lportal::Schema.version+.
57
64
  def initialize(version=nil)
58
- @version = version
59
- @root = '/usr/local/liferay'
60
- @server = 'Tomcat'
65
+ @version = version
66
+ @root = '/usr/local/liferay'
67
+ @server = 'Tomcat'
68
+ @deploy_dir = nil
61
69
  end
62
70
 
63
71
  # The name of the portal. Used in STDOUT messages.
@@ -65,26 +73,34 @@ module Caterpillar # :nodoc:
65
73
  'Liferay'
66
74
  end
67
75
 
76
+ # The directory where to deploy.
77
+ # By default, it is based on the servlet container name and
78
+ # the confured location of its root.
79
+ # It can also be defined from the configuration file:
80
+ # portlet.container.deploy_dir = '/opt/myDeployDir'
68
81
  def deploy_dir
82
+ return @deploy_dir unless @deploy_dir.nil?
83
+
69
84
  raise 'Configure container root folder' unless self.root
70
85
  case @server
71
86
 
72
87
  when 'Tomcat'
73
88
  root_dir = 'ROOT'
74
- File.join(self.root,'webapps')
89
+ @deploy_dir = File.join(self.root,'webapps')
75
90
 
76
91
  when 'JBoss/Tomcat'
77
92
  # detect server name if not configured
78
93
  @server_dir ||= Dir.new(
79
94
  File.join(self.root,'server')).entries.first
80
- path = File.join(self.root,'server',@server_dir,'deploy')
95
+ @deploy_dir = File.join(self.root,'server',@server_dir,'deploy')
81
96
 
82
- unless File.exists?(path)
83
- raise 'Portal deployment directory does not exist: %s' % path
84
- end
97
+ end
85
98
 
86
- return path
99
+ unless File.exists?(@deploy_dir)
100
+ raise 'Portal deployment directory does not exist: %s' % @deploy_dir
87
101
  end
102
+
103
+ return @deploy_dir
88
104
  end
89
105
 
90
106
  # The location of Liferay's WEB-INF folder for XML analyzation.
@@ -95,7 +111,7 @@ module Caterpillar # :nodoc:
95
111
 
96
112
  when 'Tomcat'
97
113
  root_dir = 'ROOT'
98
- File.join(self.deploy_dir,root_dir,'WEB-INF')
114
+ return web_inf_dir(root_dir)
99
115
 
100
116
  when 'JBoss/Tomcat'
101
117
  # detect lportal dir (ROOT.war or lportal.war)
@@ -110,11 +126,20 @@ module Caterpillar # :nodoc:
110
126
  STDERR.puts 'Please file a bug on Caterpillar.'
111
127
  raise 'Portal root directory not found at %s' % self.deploy_dir
112
128
  end
113
-
114
- File.join(self.deploy_dir,root_dir,'WEB-INF')
129
+
130
+ return web_inf_dir(root_dir)
115
131
 
116
132
  end
117
133
  end
134
+
135
+ # The rule by which the WEB-INF is constructed regardless of the server.
136
+ def web_inf_dir(root_dir)
137
+ # The @deploy_dir variable does not need checking,
138
+ # as the method deploy_dir() does that.
139
+ #if deploy_dir_defined?
140
+
141
+ return File.join(self.deploy_dir(),root_dir,'WEB-INF')
142
+ end
118
143
 
119
144
  # Reads Liferay portlet descriptor XML files and parses them with Hpricot.
120
145
  def analyze(type=:native)
@@ -1,4 +1,13 @@
1
- module Caterpillar
1
+ # encoding: utf-8
2
+
3
+
4
+ #--
5
+ # (c) Copyright 2008,2009 Mikael Lammentausta
6
+ # See the file LICENSES.txt included with the distribution for
7
+ # software license details.
8
+ #++
9
+
10
+ module Caterpillar # :nodoc:
2
11
  # Portlet navigation on Rails.
3
12
  #
4
13
  # Caterpillar installs a partial 'caterpillar/navigation' into your views,
@@ -1,3 +1,6 @@
1
+ # encoding: utf-8
2
+
3
+
1
4
  #--
2
5
  # (c) Copyright 2008 Mikael Lammentausta
3
6
  # See the file LICENSES.txt included with the distribution for
@@ -1,5 +1,8 @@
1
+ # encoding: utf-8
2
+
3
+
1
4
  #--
2
- # (c) Copyright 2008 Mikael Lammentausta
5
+ # (c) Copyright 2008, 2010 Mikael Lammentausta
3
6
  # See the file LICENSES.txt included with the distribution for
4
7
  # software license details.
5
8
  #++
@@ -11,9 +14,18 @@ module Caterpillar
11
14
 
12
15
  # Creates portlet XML
13
16
  def xml(portlets)
17
+ session =
18
+ begin
19
+ {
20
+ :key => Caterpillar::Security.get_session_key(),
21
+ :secret => Caterpillar::Security.get_secret()
22
+ }
23
+ rescue nil
24
+ end
25
+
14
26
  xml = self.header
15
27
  portlets.each do |p|
16
- xml << self.template(p)
28
+ xml << self.template(p,session)
17
29
  end
18
30
  xml << self.footer
19
31
  return xml
@@ -35,8 +47,6 @@ module Caterpillar
35
47
  'com.celamanzi.liferay.portlets.rails286.Rails286PortletRenderFilter'
36
48
  end
37
49
 
38
- protected
39
-
40
50
  # JSR 286 portlet XML header. Opens portlet-app.
41
51
  def header
42
52
  xml = '<?xml version="1.0" encoding="UTF-8"?>' +"\n"
@@ -54,7 +64,8 @@ module Caterpillar
54
64
  end
55
65
 
56
66
  # portlet.xml template.
57
- def template(portlet)
67
+ # session is a hash containing session key and secret from Rails.
68
+ def template(portlet,session=nil)
58
69
  # add roles
59
70
  # TODO: move into portlet hash
60
71
  # administrator, power-user, user
@@ -78,6 +89,20 @@ module Caterpillar
78
89
  xml << " <portlet-info>\n"
79
90
  xml << " <title>%s</title>\n" % portlet[:title]
80
91
  xml << " </portlet-info>\n"
92
+ # insert session key
93
+ unless session.nil?
94
+ xml << " <init-param>\n"+\
95
+ " <name>session_key</name>\n"+\
96
+ " <value>#{session[:key]}</value>\n"+\
97
+ " </init-param>\n"
98
+ end
99
+ # insert secret
100
+ unless session.nil?
101
+ xml << " <init-param>\n"+\
102
+ " <name>secret</name>\n"+\
103
+ " <value>#{session[:secret]}</value>\n"+\
104
+ " </init-param>\n"
105
+ end
81
106
  roles.each do |role|
82
107
  xml << " <security-role-ref>\n"
83
108
  xml << " <role-name>#{role}</role-name>\n"
@@ -115,4 +140,4 @@ module Caterpillar
115
140
 
116
141
  end # static methods
117
142
  end
118
- end
143
+ end