caterpillar 0.9.0

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,235 @@
1
+ #--
2
+ # (c) Copyright 2008 Mikael Lammentausta
3
+ # See the file LICENSES.txt included with the distribution for
4
+ # software license details.
5
+ #++
6
+
7
+ module Caterpillar
8
+ # Creates liferay-portlet XML and liferay-display XML.
9
+ # The latter optionally combines your production portlet display configuration.
10
+ class Liferay
11
+
12
+ # Liferay version
13
+ attr_accessor :version
14
+
15
+ # The location of Liferay's WEB-INF folder for XML analyzation
16
+ attr_accessor :WEB_INF
17
+
18
+ def initialize(version='5.1.1')
19
+ @version = version
20
+ end
21
+
22
+ def analyze(type)
23
+ raise 'Configure WEB-INF' unless self.WEB_INF
24
+ require 'hpricot'
25
+ return nil unless type==:native
26
+
27
+ portlets = []
28
+
29
+ f=File.open(self.WEB_INF+'/portlet-custom.xml','r')
30
+ portlet_xml = Hpricot.XML(f.read)
31
+ f.close
32
+
33
+ f=File.open(self.WEB_INF+'/liferay-display.xml','r')
34
+ display_xml = Hpricot.XML(f.read)
35
+ f.close
36
+
37
+ (portlet_xml/'portlet').each do |portlet|
38
+ _p = {
39
+ :name => (portlet/'portlet-name').innerHTML,
40
+ :title => (portlet/'display-name').innerHTML
41
+ }
42
+
43
+ # horribly ineffective
44
+ display_xml.search("//category").each do |c|
45
+ _p.update(:category => c['name'] ) if (c/"//portlet[@id='#{_p[:name]}']").any?
46
+ end
47
+
48
+ portlets << _p
49
+ end
50
+ return portlets
51
+ end
52
+
53
+ # liferay-portlet XML
54
+ def portletapp_xml(portlets)
55
+ doctype = 'liferay-portlet-app'
56
+ xml = self.xml_header(doctype)
57
+ portlets.each do |p|
58
+ xml << self.portletapp_template(p)
59
+ end
60
+ xml << self.portlet_xml_footer(doctype)
61
+ return xml
62
+ end
63
+
64
+ # liferay-display XML
65
+ def display_xml(portlets)
66
+ xml = self.xml_header('display')
67
+
68
+ categories = []
69
+ Util.categorize(portlets).each_pair do |category,portlets|
70
+ categories << category
71
+ xml << self.display_template(category,portlets)
72
+ end
73
+
74
+ # include other native Liferay categories
75
+ if self.WEB_INF
76
+ require 'hpricot'
77
+
78
+ filename = self.WEB_INF+'/liferay-display.xml'
79
+ f=File.open(filename,'r')
80
+ doc = Hpricot.XML(f.read)
81
+ f.close
82
+ (doc/:category).each do |el|
83
+ unless categories.include?(el.attributes['name'])
84
+ xml << ' ' + el.to_original_html + "\n"
85
+ end
86
+ end
87
+ end
88
+
89
+ xml << self.portlet_xml_footer('display')
90
+ return xml
91
+ end
92
+
93
+ protected
94
+
95
+ # common XML header
96
+ def xml_header(doctype)
97
+ version = self.dtd_version(doctype)
98
+ xml = '<?xml version="1.0" encoding="UTF-8"?>'
99
+ xml << "\n"
100
+ xml << '<!DOCTYPE %s PUBLIC' % doctype
101
+ case doctype
102
+ when 'liferay-portlet-app'
103
+ xml << ' "-//Liferay//DTD Portlet Application %s//EN"' % version
104
+ xml << ' "http://www.liferay.com/dtd/%s_%s.dtd">' % [
105
+ doctype, version.gsub('.','_') ]
106
+ when 'display'
107
+ xml << ' "-//Liferay//DTD Display %s//EN"' % version
108
+ xml << ' "http://www.liferay.com/dtd/liferay-%s_%s.dtd">' % [
109
+ doctype, version.gsub('.','_') ]
110
+ end
111
+ xml << "\n\n"
112
+ xml << '<%s>' % doctype
113
+ xml << "\n"
114
+ return xml
115
+ end
116
+
117
+ # common XML footer
118
+ def portlet_xml_footer(doctype)
119
+ '</%s>' % doctype
120
+ end
121
+
122
+ # TODO: DTD version detection based on self.version
123
+ def dtd_version(type)
124
+ case type
125
+ when 'liferay-portlet-app'
126
+ '5.1.0'
127
+ when 'display'
128
+ '5.1.0'
129
+ end
130
+ end
131
+
132
+ def portletapp_template(portlet)
133
+ xml = " <portlet>\n"
134
+ xml << " <portlet-name>%s</portlet-name>\n" % portlet[:name]
135
+ xml << " <icon>/%s/images/icon.png</icon>\n" % portlet[:servlet]
136
+ # can there be several portlet instances on the same page?
137
+ xml << " <instanceable>true</instanceable>\n"
138
+ # include javascripts?
139
+ portlet[:javascripts].each do |js|
140
+ xml << " <header-portal-javascript>"
141
+ xml << "/%s/javascripts/%s" % [portlet[:servlet],js]
142
+ xml << "</header-portal-javascript>\n"
143
+ end
144
+ xml << " </portlet>\n\n"
145
+ end
146
+
147
+ def display_template(category,portlets)
148
+ xml = ' <category name="%s">' % category +"\n"
149
+
150
+ portlets.each do |p|
151
+ xml << ' <portlet id="%s" />' % p[:name]
152
+ xml << "\n"
153
+ end
154
+ xml << " </category>\n\n"
155
+
156
+ return xml
157
+ end
158
+
159
+ public
160
+
161
+ # tables that are skipped when creating fixtures
162
+ def skip_fixture_tables
163
+ [
164
+ "country","cyrususer","cyrusvirtual",
165
+ "documentlibrary_fsentry","documentlibrary_binval","documentlibrary_node","documentlibrary_prop","documentlibrary_refs",
166
+ "expandocolumn",
167
+ "expandorow",
168
+ "expandotable",
169
+ "expandovalue",
170
+ "image",
171
+ "chat_entry",
172
+ "chat_status",
173
+ "journalcontentsearch",
174
+ "journalfeed",
175
+ "journalstructure",
176
+ "journaltemplate",
177
+ "listtype",
178
+ "mbban",
179
+ "mbmessageflag",
180
+ "mbstatsuser",
181
+ "membershiprequest",
182
+ "orglabor",
183
+ "passwordpolicyrel",
184
+ "passwordpolicy",
185
+ "passwordtracker",
186
+ "pluginsetting",
187
+ "pollschoice",
188
+ "pollsquestion",
189
+ "pollsvote",
190
+ "quartz_blob_triggers",
191
+ "quartz_calendars",
192
+ "quartz_cron_triggers",
193
+ "quartz_fired_triggers",
194
+ "quartz_job_details",
195
+ "quartz_job_listeners",
196
+ "quartz_locks",
197
+ "quartz_paused_trigger_grps",
198
+ "quartz_scheduler_state",
199
+ "quartz_simple_triggers",
200
+ "quartz_trigger_listeners",
201
+ "quartz_triggers",
202
+ "ratingsentry",
203
+ "ratingsstats",
204
+ "region",
205
+ "release_",
206
+ "scframeworkversion",
207
+ "scframeworkversi_scproductvers",
208
+ "schema_migrations",
209
+ "sclicenses_scproductentries",
210
+ "sclicense",
211
+ "scproductentry",
212
+ "scproductscreenshot",
213
+ "scproductversion",
214
+ "servicecomponent",
215
+ "sessions",
216
+ "shoppingcart",
217
+ "shoppingcategory",
218
+ "shoppingcoupon",
219
+ "shoppingitemfield",
220
+ "shoppingitemprice",
221
+ "shoppingitem",
222
+ "shoppingorderitem",
223
+ "shoppingorder",
224
+ "socialactivity",
225
+ "socialrelation",
226
+ "subscription",
227
+ "tasksproposal",
228
+ "tasksreview",
229
+ "webdavprops",
230
+ "website"
231
+ ]
232
+ end
233
+
234
+ end
235
+ end
@@ -0,0 +1,8 @@
1
+ require 'active_record'
2
+
3
+ module Caterpillar
4
+ # This model does not appear in the lportal database. This is created by a migration and contains the portlet id => name mappings.
5
+ class LiferayPortlet < ActiveRecord::Base
6
+ set_table_name :lportal_portlets
7
+ end
8
+ end
@@ -0,0 +1,40 @@
1
+ module Caterpillar
2
+ # Portlet navigation on Rails.
3
+ #
4
+ # Caterpillar installs a partial 'caterpillar/navigation' into your views,
5
+ # along with an image and a CSS file.
6
+ # You need to add a filter 'caterpillar' which you will only load in
7
+ # development environment - in production the portlet container will be the
8
+ # 'window manager'. This partial helps you to navigate between your portlets.
9
+ #
10
+ # This will go to your ApplicationController:
11
+ # if RAILS_ENV=='development'
12
+ # before_filter :caterpillar
13
+ # end
14
+ #
15
+ # def caterpillar # :nodoc:
16
+ # @caterpillar_navigation = Caterpillar::Navigation.rails
17
+ # @caterpillar_navigation_defaults = {
18
+ # :uid => 13904,
19
+ # :gid => 13912
20
+ # }
21
+ # end
22
+ #
23
+ # This will go the body of your layout:
24
+ # <% if @caterpillar_navigation -%>
25
+ # <%= stylesheet_link_tag 'caterpillar/caterpillar' %>
26
+ # <%= javascript_include_tag 'caterpillar/caterpillar' %>
27
+ # <%= render :partial => "caterpillar/navigation" %>
28
+ # <% end -%>
29
+ #
30
+ class Navigation
31
+
32
+ # Method for formulating the portlets hash in Rails environment
33
+ def self.rails
34
+ config = Util.eval_configuration
35
+ config.routes = Util.parse_routes(config)
36
+ return Util.categorize(Parser.new(config).portlets)
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,110 @@
1
+ #--
2
+ # (c) Copyright 2008 Mikael Lammentausta
3
+ # See the file LICENSES.txt included with the distribution for
4
+ # software license details.
5
+ #++
6
+
7
+ module Caterpillar
8
+ # Portlet configuration and route parser.
9
+ class Parser
10
+
11
+ def initialize(config)
12
+ @config = config
13
+ @routes = config.routes
14
+ end
15
+
16
+ # Updates the portlets hash from the routes and configuration options.
17
+ # Changes the path variables to a format supported by the Rails-portlet.
18
+ def portlets(routes=@routes)
19
+ raise 'No configuration' unless @config
20
+ raise 'No routes provided' unless routes
21
+ portlets = []
22
+
23
+ @config.instances.flatten.each do |portlet|
24
+
25
+ ### route to path
26
+ if portlet[:path]
27
+ # take user-given path & do not parse routes
28
+ path = portlet[:path]
29
+ #
30
+ # parse the requirements - controller & action
31
+ # ( this is too difficult -- no navigation for user-given paths )
32
+ #
33
+ # builder = ActionController::Routing::RouteBuilder.new
34
+ # req_path = builder.segments_for_route_path(path)
35
+ # r = ActionController::Routing::Routes.recognize_path(req_path, { :method => :get })
36
+ # puts r.inspect
37
+
38
+ portlet.update( :reqs => {} )
39
+ portlet.update( :vars => [] )
40
+
41
+ else
42
+ begin
43
+ _r = routes.select{
44
+ |route| route[:name]==portlet[:name].to_sym
45
+ }
46
+ path = _r.first[:path] # take only the first segments
47
+ raise if path.nil?
48
+ rescue
49
+ STDERR.puts ' !! no route for %s' % portlet[:name]
50
+ next
51
+ end
52
+
53
+ ### requirements - controller & action
54
+ portlet.update( :reqs => _r.first[:reqs] )
55
+
56
+ ### variables
57
+ portlet.update( :vars => _r.first[:vars] )
58
+
59
+ # delete the route from routes
60
+ _r.each do |r|
61
+ routes.delete(r)
62
+ end
63
+ end
64
+ # fix path variables to be replaced by rails-portlet at runtime
65
+ path.gsub!(/:uid/,'%UID%')
66
+ path.gsub!(/:gid/,'%GID%')
67
+ # TODO: notify user of unsupported variables
68
+ portlet.update( :path => path )
69
+
70
+ ### javascripts
71
+ # append portlet's javascripts to global javascripts
72
+ javascripts = (portlet[:javascripts].nil? ?
73
+ @config.javascripts : @config.javascripts + portlet[:javascripts].to_a)
74
+ portlet.update( :javascripts => javascripts.flatten )
75
+
76
+ portlets << portlet
77
+ end
78
+
79
+ # leftover named routes
80
+ if @config.include_all_named_routes==true
81
+ portlets << routes
82
+ portlets.flatten!
83
+ end
84
+
85
+ # sanity check
86
+ portlets.each do |portlet|
87
+ ### hostname
88
+ portlet.update( :host => @config.host ) unless portlet[:host]
89
+
90
+ ### servlet
91
+ portlet.update( :servlet => @config.servlet ) unless portlet[:servlet]
92
+
93
+ ### category
94
+ portlet.update( :category => @config.category ) unless portlet[:category]
95
+
96
+ ### title
97
+ _title = portlet[:title] || portlet[:name].to_s.gsub('_',' ').capitalize
98
+ # strip illegal characters
99
+ title = _title.gsub(/ä/,'a').gsub(/ö/,'o').gsub(/Ä/,'A').gsub(/Ö/,'O')
100
+ portlet.update( :title => title )
101
+
102
+ ### javascripts
103
+ portlet.update( :javascripts => @config.javascripts ) unless portlet[:javascripts]
104
+ end
105
+
106
+ return portlets
107
+ end
108
+
109
+ end
110
+ end
@@ -0,0 +1,98 @@
1
+ #--
2
+ # (c) Copyright 2008 Mikael Lammentausta
3
+ # See the file LICENSES.txt included with the distribution for
4
+ # software license details.
5
+ #++
6
+
7
+ module Caterpillar
8
+ # Formulates generic JSR286 portlet XML
9
+ class Portlet
10
+ class << self
11
+
12
+ # Creates portlet XML
13
+ def xml(portlets)
14
+ xml = self.header
15
+ portlets.each do |p|
16
+ xml << self.template(p)
17
+ end
18
+ xml << self.footer
19
+ return xml
20
+ end
21
+
22
+ def debug(config,routes) # :nodoc:
23
+ routes.select{|r| !r[:name].empty?}.each do |route|
24
+ puts '%s: %s' % [route[:name], route[:path]]
25
+ end
26
+ end
27
+
28
+ # Rails-portlet Java class
29
+ def portlet_class
30
+ 'com.celamanzi.liferay.portlets.rails286.Rails286Portlet'
31
+ end
32
+
33
+ # Rails-portlet Java class
34
+ def portlet_filter_class
35
+ 'com.celamanzi.liferay.portlets.rails286.Rails286PortletRenderFilter'
36
+ end
37
+
38
+ protected
39
+
40
+ def header
41
+ xml = '<?xml version="1.0" encoding="UTF-8"?>'
42
+ xml << "\n"
43
+ xml << '<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
44
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
45
+ xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd">'
46
+ xml << "\n\n"
47
+ return xml
48
+ end
49
+
50
+ def footer
51
+ '</portlet-app>' + "\n"
52
+ end
53
+
54
+ # portlet.xml template.
55
+ def template(portlet)
56
+ xml = " <!-- %s -->\n" % portlet[:title]
57
+ xml << " <portlet>\n"
58
+ xml << " <portlet-name>%s</portlet-name>\n" % portlet[:name]
59
+ xml << " <portlet-class>%s</portlet-class>\n" % self.portlet_class
60
+ xml << " <supports>\n"
61
+ xml << " <mime-type>text/html</mime-type>\n"
62
+ xml << " <portlet-mode>view</portlet-mode>\n"
63
+ ### edit mode
64
+ xml << " <portlet-mode>edit</portlet-mode>\n" if portlet[:edit]==true
65
+ xml << " </supports>\n"
66
+ xml << " <portlet-info>\n"
67
+ xml << " <title>%s</title>\n" % portlet[:title]
68
+ xml << " </portlet-info>\n"
69
+ xml << " </portlet>\n"
70
+ xml << ""
71
+ xml << " <filter>\n"
72
+ xml << " <filter-name>%s_filter</filter-name>\n" % portlet[:name]
73
+ xml << " <filter-class>%s</filter-class>\n" % self.portlet_filter_class
74
+ xml << " <lifecycle>RENDER_PHASE</lifecycle>\n"
75
+ xml << " <init-param>\n"
76
+ xml << " <name>host</name>\n"
77
+ xml << " <value>%s</value>\n" % portlet[:host] || ""
78
+ xml << " </init-param>\n"
79
+ xml << " <init-param>\n"
80
+ xml << " <name>servlet</name>\n"
81
+ xml << " <value>%s</value>\n" % portlet[:servlet]
82
+ xml << " </init-param>\n"
83
+ xml << " <init-param>\n"
84
+ xml << " <name>route</name>\n"
85
+ xml << " <value>%s</value>\n" % portlet[:path].gsub(/&/,"&amp;")
86
+ xml << " </init-param>\n"
87
+ xml << " </filter>\n"
88
+ xml << ""
89
+ xml << " <filter-mapping>\n"
90
+ xml << " <filter-name>%s_filter</filter-name>\n" % portlet[:name]
91
+ xml << " <portlet-name>%s</portlet-name>\n" % portlet[:name]
92
+ xml << " </filter-mapping>\n"
93
+ xml << "\n"
94
+ end
95
+
96
+ end # static methods
97
+ end
98
+ end