caterpillar 0.9.0

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