source: main/trunk/package-kits/linux/files/servlet.pl@ 29669

Last change on this file since 29669 was 29669, checked in by Jeremy Symon, 9 years ago

Added command to remove a servlet by name

  • Property svn:executable set to *
File size: 8.6 KB
Line 
1#!/usr/bin/env perl
2
3use strict;
4use warnings;
5use utf8;
6
7use XML::Parser;
8use Data::Dumper;
9use POSIX 'isatty';
10
11# Reads the servlets partial XML file using XML::Parser,
12# Then converts the obtained data structure to a more readable one
13# Example conversion:
14=xml
15<servlet>
16 <servlet-name>library</servlet-name>
17 <description attribute="example">The standard gsdl3 library program</description>
18 <servlet-class>org.greenstone.gsdl3.LibraryServlet</servlet-class>
19 <init-param>
20 <param-name>library_name</param-name>
21 <param-value>library</param-value>
22 </init-param>
23 <init-param>
24 <param-name>site_name</param-name>
25 <param-value>localsite</param-value>
26 </init-param>
27</servlet>
28=cut
29=data_structure
30{
31 'servlet' => {
32 'servlet-class' => 'org.greenstone.gsdl3.LibraryServlet',
33 'servlet-name' => 'library',
34 'description' => {
35 '.value' => 'The standard gsdl3 library program',
36 '.attr' => {
37 'attribute' => 'example'
38 }
39 },
40 'init-param' => [
41 {
42 'param-value' => 'library',
43 'param-name' => 'library_name'
44 },
45 {
46 'param-name' => 'site_name',
47 'param-value' => 'localsite'
48 }
49 ]
50 }
51}
52=cut
53sub read_xml {
54 my $FH = shift;
55 local $/ = undef;
56 my $xml = <$FH>;
57 # The xml needs a root element, so we wrap it in one
58 $xml='<__root__>' . $xml . '</__root__>';
59 # Parse the data using XML::Parser
60 my $data = new XML::Parser (Style => 'Tree')->parse ($xml);
61
62 sub tidy {
63 my %hash;
64 # If the element has attributes, add them to the hash
65 my $attr = shift;
66 if (scalar keys %$attr > 0) {
67 $hash{'.attr'} = $attr;
68 }
69 # Read any child elements or text value
70 while (@_) {
71 my $element = shift;
72 my $value = shift;
73 if ($element eq 0) {
74 $value =~ /^\s*$/ || ($hash{'.value'} .= $value);
75 } else {
76 # If there is more than one of a single tupe of child element,
77 # That child element must become an array
78 if (defined $hash{$element}) {
79 unless (ref $hash{$element} eq 'ARRAY') {
80 $hash{$element} = [ $hash{$element} ];
81 }
82 push @{$hash{$element}}, tidy (@{$value});
83 } else {
84 $hash{$element} = tidy (@{$value});
85 }
86 }
87 }
88 # If the element only has a value, it can become a scalar
89 if (scalar keys %hash == 1 and defined $hash{'.value'}) {
90 return $hash{'.value'};
91 }
92 return \%hash;
93 }
94 return tidy (@{@$data[1]});
95}
96
97# Writes a data structure to an XML file
98sub write_xml {
99 my ($hash, $FH) = @_;
100 select $FH;
101 sub open_tag {
102 my ($indent, $tag, $attr) = @_;
103 print $indent, "<", $tag;
104 if (defined $attr) {
105 for my $key (sort keys %$attr) {
106 print " ", $key, '="', $attr->{$key}, '"';
107 }
108 }
109 print ">";
110 }
111 sub write_element {
112 my ($indent, $hash) = @_;
113 for my $key (sort keys %$hash) {
114 $key eq '.attr' && next;
115 my $val = $hash->{$key};
116 $key eq '.value' && do {
117 print $val, "\n";
118 next;
119 };
120 for (ref $val) {
121 /^ARRAY$/ && do {
122 for my $element (@$val) {
123 open_tag ($indent, $key, $element->{'.attr'});
124 for (ref $element) {
125 /^HASH$/ && do {
126 print "\n";
127 write_element (" $indent", $element);
128 print $indent, "</", $key, ">\n";
129 last;
130 };
131 print $element, "</", $key, ">\n";
132 }
133 }
134 last;
135 };
136 /^HASH$/ && do {
137 open_tag ($indent, $key, $val->{'.attr'});
138 # If the element only has a value with attributes,
139 # it can be formatted on one line
140 if (scalar keys %$val == 2 and defined $val->{'.value'}) {
141 print $val->{'.value'}, "</", $key, ">\n";
142 } else {
143 print "\n";
144 write_element (" $indent", $val);
145 print $indent, "</", $key, ">\n";
146 }
147 last;
148 };
149 open_tag ($indent, $key);
150 print $val;
151 print "</", $key, ">\n";
152 }
153 }
154 }
155 write_element ("", $hash);
156 select STDOUT;
157}
158
159my $hash;
160my %commands;
161# Command structure:
162# key: Case-insensitive name of the command
163# val: Array of info about the command
164# [0]: Description of the command
165# [1]: Function that is run for the command
166# [2]: Number of arguments of the command (if any)
167%commands = (
168 help => [
169 'Prints help about the available commands',
170 sub {
171 for my $cmd (sort keys %commands) {
172 printf "%-10s %s\n", $cmd, $commands{$cmd}[0];
173 }
174 },
175 ],
176 clear => [
177 'Clears the internal state',
178 sub {
179 undef $hash;
180 }
181 ],
182 read => [
183 'Parses XML from a file into the internal state',
184 sub {
185 my $file = shift @ARGV;
186 if ($file eq '-') {
187 if (isatty *STDIN) {
188 print STDERR "Reading XML from STDIN. Press ^D to end\n";
189 }
190 $hash = read_xml *STDIN;
191 } else {
192 open FH, '<', $file;
193 $hash = read_xml *FH;
194 close FH;
195 }
196 },
197 1,
198 ],
199 write => [
200 'Writes the current internal state as XML to a file',
201 sub {
202 my $file = shift @ARGV;
203 if ($file eq '-') {
204 write_xml $hash, *STDOUT;
205 } else {
206 open FH, '>', $file;
207 write_xml $hash, *FH;
208 close FH;
209 }
210 },
211 1,
212 ],
213 debug => [
214 'Dumps the current internal state to stdout',
215 sub {
216 print Dumper $hash;
217 },
218 ],
219 count => [
220 'Returns the number of servlets in the current internal state',
221 sub {
222 my $count = 0;
223 if (defined $hash->{servlet}) {
224 $count = 1;
225 my $servlets = $hash->{servlet};
226 if (ref $servlets eq 'ARRAY') {
227 $count = scalar @{$hash->{servlet}};
228 }
229 }
230 print $count, "\n";
231 },
232 ],
233 list => [
234 'Lists the servlets in the current internal state',
235 sub {
236 if (defined $hash->{servlet}) {
237 my $servlets = $hash->{servlet};
238 if (ref $servlets eq 'ARRAY') {
239 for my $servlet (@{$hash->{servlet}}) {
240 print $servlet->{'servlet-name'}, "\n";
241 }
242 } else {
243 print $servlets->{'servlet-name'}, "\n";
244 }
245 } else {
246 print STDERR "No servlets found. Was valid XML provided?\n";
247 }
248 },
249 ],
250 remove => [
251 'Removes a servlet from the current internal state',
252 sub {
253 my $name = shift @ARGV;
254 if (defined $hash->{servlet}) {
255 my $servlets = $hash->{servlet};
256 if (ref $servlets eq 'ARRAY') {
257 my @array = grep { $_->{'servlet-name'} ne $name } @$servlets;
258 $hash->{servlet} = \@array;
259 } elsif ($servlets->{'servlet-name'} eq $name) {
260 delete $hash->{servlet};
261 }
262 }
263 },
264 1,
265 ],
266);
267
268# Check that all given commands are valid
269my $argc = 0;
270for my $cmd (@ARGV) {
271 if ($argc > 0) {
272 # skip arguments to a previous command
273 $argc --;
274 } elsif (defined $commands{$cmd}) {
275 # get the argument count of a valid command
276 $argc = @{$commands{$cmd}}[2];
277 defined $argc or ($argc = 0);
278 } else {
279 # invalid command
280 print STDERR "Valid commands are:\n";
281 @{$commands{help}}[1]->();
282 die "Invalid command '" . $cmd . "'\n";
283 }
284}
285
286# Run the commands
287while (@ARGV) {
288 @{$commands{lc shift}}[1]->();
289}
Note: See TracBrowser for help on using the repository browser.