File Coverage

blib/lib/Lim.pm
Criterion Covered Total %
statement 17 85 20.0
branch 0 38 0.0
condition 0 12 0.0
subroutine 9 16 56.2
pod 12 12 100.0
total 38 163 23.3


line stmt bran cond sub pod time code
1             package Lim;
2              
3 7     7   43851 use common::sense;
  7         24  
  7         62  
4 7     7   441 use Carp;
  7         16  
  7         584  
5              
6 7     7   6091 use YAML::Any ();
  7         7937  
  7         15461  
7              
8             =encoding utf8
9              
10             =head1 NAME
11              
12             Lim - Framework for RESTful JSON/XML, JSON-RPC, XML-RPC and SOAP
13              
14             =head1 VERSION
15              
16             Version 0.19
17              
18             =cut
19              
20             our $VERSION = '0.19';
21             our $CONFIG = {
22             log => {
23             obj_debug => 1,
24             rpc_debug => 1,
25             debug => 1,
26             info => 1,
27             warn => 1,
28             err => 1
29             },
30             prefix => ['', '/usr', '/usr/local'],
31             rpc => {
32             srv_listen => 10,
33             timeout => 30,
34             call_timeout => 300,
35             transport => {
36             http => {
37             host => undef,
38             port => 5353
39             }
40             },
41             protocol => {
42             http => {
43             webroot => '/usr/share/lim/html'
44             }
45             },
46             tls => {
47             method => 'any',
48             verify => 1,
49             verify_require_client_cert => 1,
50             ca_path => '/etc/lim/ssl/certs'
51             }
52             },
53             agent => {
54             config_file => '',
55             uri => []
56             },
57             cli => {
58             history_length => 1000,
59             history_file => defined $ENV{HOME} ? $ENV{HOME}.($ENV{HOME} =~ /\/$/o ? '' : '/').'.lim_history' : '',
60             config_file => defined $ENV{HOME} ? $ENV{HOME}.($ENV{HOME} =~ /\/$/o ? '' : '/').'.limrc' : '',
61             editor => $ENV{EDITOR},
62             host => 'localhost',
63             port => 5353
64             },
65             plugin => {
66             load => {}
67             }
68             };
69              
70             =head1 SYNOPSIS
71              
72             =over 4
73              
74             use Lim;
75              
76             =back
77              
78             =head1 DESCRIPTION
79              
80             L provides a framework for calling plugins over multiple protocols.
81              
82             It uses AnyEvent for async operations and SOAP::Lite, XMLRPC::Lite and JSON::XS
83             for processing protocol messages.
84              
85             There are 3 parts in Lim that can work independenly, a Server part, a Client
86             part and a CLI part.
87              
88             All plugins are also divded into these 3 parts and use the base classes
89             L, L and L.
90              
91             The built in Server part is called L and can be started with
92             lim-agentd. It will use L to load all available plugins on
93             the system and serve their Server part to L if available.
94              
95             The built in CLI part is called L and can be started with lim-cli.
96             It will use L to load all available plugins on the system and
97             use their CLI part if available.
98              
99             =head1 METHODS
100              
101             =over 4
102              
103             =item Lim::OBJ_DEBUG
104              
105             Semi constant sub that controls if object debugging information should sent to
106             the log.
107              
108             =cut
109              
110 44     44 1 507 sub OBJ_DEBUG { 1 }
111              
112             =item Lim::RPC_DEBUG
113              
114             Semi constant sub that controls if RPC debugging information should sent to the
115             log.
116              
117             =cut
118              
119 16     16 1 235 sub RPC_DEBUG { 1 }
120              
121             =item Lim::DEBUG
122              
123             Semi constant sub that controls if debugging information should sent to the log.
124              
125             Common usage:
126             Lim::DEBUG and $self->{logger}->debug(...);
127              
128             =cut
129              
130 2     2 1 25 sub DEBUG { 1 }
131              
132             =item Lim::INFO
133              
134             Semi constant sub that controls if informational logs should sent to the log.
135              
136             Common usage:
137             Lim::INFO and $self->{logger}->info(...);
138              
139             =cut
140              
141 0     0 1 0 sub INFO { 1 }
142              
143             =item Lim::WARN
144              
145             Semi constant sub that controls if warnings should sent to the log.
146              
147             Common usage:
148             Lim::WARN and $self->{logger}->warn(...);
149              
150             =cut
151              
152 4     4 1 84 sub WARN { 1 }
153              
154             =item Lim::ERR
155              
156             Semi constant sub that controls if errors should sent to the log.
157              
158             Common usage:
159             Lim::ERR and $self->{logger}->error(...);
160              
161             =cut
162              
163 0     0 1 0 sub ERR { 1 }
164              
165             =item Lim::Config ->{}
166              
167             Return a hash reference to the configuration.
168              
169             =cut
170              
171 4     4 1 52 sub Config (){ $CONFIG }
172              
173             =item Lim::MergeConfig($config)
174              
175             Try and merge the given hash reference C<$config> into Lim's configuration.
176              
177             =cut
178              
179             sub MergeConfig {
180 0 0   0 1   if (ref($_[0]) eq 'HASH') {
181 0           my @merge = ([$_[0], $CONFIG]);
182              
183 0           while (defined (my $merge = shift(@merge))) {
184 0           my ($from, $to) = @$merge;
185 0           foreach my $key (keys %$from) {
186 0 0         if (exists $to->{$key}) {
187 0 0         unless (ref($from->{$key}) eq ref($to->{$key})) {
188             # TODO display what entry is missmatching
189 0           confess __PACKAGE__, 'Can not merge config, entries type missmatch';
190             }
191 0 0         if (ref($from->{$key}) eq 'HASH') {
192 0           push(@merge, [$from->{$key}, $to->{$key}]);
193 0           next;
194             }
195             }
196 0           $to->{$key} = $from->{$key};
197             }
198             }
199             }
200 0           return;
201             }
202              
203             =item Lim::LoadConfig($filename)
204              
205             Load the given configuration C<$filename> in YAML format and merge it into Lim's
206             configuration.
207              
208             =cut
209              
210             sub LoadConfig {
211 0     0 1   my ($filename) = @_;
212            
213 0 0 0       if (defined $filename and -r $filename) {
214 0           my $yaml;
215            
216 0 0         Lim::DEBUG and Log::Log4perl->get_logger->debug('Loading config ', $filename);
217 0           eval {
218 0           $yaml = YAML::Any::LoadFile($filename);
219             };
220 0 0         if ($@) {
221 0           confess __PACKAGE__, ': Unable to read configuration file ', $filename, ': ', $@, "\n";
222             }
223 0           Lim::MergeConfig($yaml);
224 0           return 1;
225             }
226 0           return;
227             }
228              
229             =item Lim::LoadConfigDirectory($directory)
230              
231             Load the given configuration in directory C<$directory> and merge it into Lim's
232             configuration.
233              
234             =cut
235              
236             sub LoadConfigDirectory {
237 0     0 1   my ($directory) = @_;
238            
239 0 0 0       if (defined $directory and -d $directory) {
240 0 0         unless(opendir(CONFIGS, $directory)) {
241 0           confess __PACKAGE__, ': Unable to read configurations in directory ', $directory, ': ', $!, "\n";
242             }
243              
244 0           foreach my $entry (sort readdir(CONFIGS)) {
245 0           my $yaml;
246            
247 0 0 0       unless(-r $directory.'/'.$entry and $entry =~ /\.yaml$/o) {
248 0           next;
249             }
250            
251 0 0         Lim::DEBUG and Log::Log4perl->get_logger->debug('Loading config ', $entry, ' from directory ', $directory);
252 0           eval {
253 0           $yaml = YAML::Any::LoadFile($directory.'/'.$entry);
254             };
255 0 0         if ($@) {
256 0           confess __PACKAGE__, ': Unable to read configuration file ', $entry, ' from directory ', $directory, ': ', $@, "\n";
257             }
258 0           Lim::MergeConfig($yaml);
259             }
260 0           closedir(CONFIGS);
261 0           return 1;
262             }
263 0           return;
264             }
265              
266             =item Lim::ParseOptions(@options)
267              
268             Parse options given at command line and add them into configuration. Option
269             subgroups are seperated by . (for example log.obj_debug=0).
270              
271             =cut
272              
273             sub ParseOptions {
274 0     0 1   foreach my $option (@_) {
275 0           my ($name, $value) = split(/=/o, $option, 2);
276 0 0 0       unless ($name and defined $value) {
277 0           confess __PACKAGE__, ': Invalid or unknown option: ', $option, "\n";
278             }
279            
280 0           my @parts = split(/\./o, $name);
281 0           my $ref = $CONFIG;
282 0           while (defined(my $part = shift(@parts))) {
283 0 0         unless (scalar @parts) {
284 0 0         if ($part =~ /^(.+)\[\]$/o) {
285 0           $part = $1;
286            
287 0 0         if (exists $ref->{$part}) {
288 0 0         if (ref($ref->{$part}) eq 'ARRAY') {
289 0           push(@{$ref->{$part}}, $value);
  0            
290             }
291             else {
292 0           $ref->{$part} = [ $ref->{$part}, $value ];
293             }
294             }
295             else {
296 0           $ref->{$part} = [ $value ];
297             }
298             }
299             else {
300 0           $ref->{$part} = $value;
301             }
302 0           last;
303             }
304            
305 0 0         unless (exists $ref->{$part}) {
306 0           $ref->{$part} = {};
307             }
308 0           $ref = $ref->{$part};
309             }
310             }
311             }
312              
313             =item Lim::UpdateConfig
314              
315             Used after L and/or L to update and do post
316             configuration tasks.
317              
318             =cut
319              
320             sub UpdateConfig {
321 0     0 1   foreach my $key (keys %{$CONFIG->{log}}) {
  0            
322             {
323 7     7   111 no warnings;
  7         15  
  7         1209  
  0            
324 0 0         eval 'sub '.uc($key).' {'.($CONFIG->{log}->{$key} ? '1' : '0').'}';
325             }
326             }
327             }
328              
329             =back
330              
331             =head1 AUTHOR
332              
333             Jerry Lundström, C<< >>
334              
335             =head1 BUGS
336              
337             Please report any bugs or feature requests to L.
338              
339             =head1 SUPPORT
340              
341             You can find documentation for this module with the perldoc command.
342              
343             perldoc Lim
344              
345             You can also look for information at:
346              
347             =over 4
348              
349             =item * Lim issue tracker (report bugs here)
350              
351             L
352              
353             =back
354              
355             =head1 ACKNOWLEDGEMENTS
356              
357             =head1 LICENSE AND COPYRIGHT
358              
359             Copyright 2012-2013 Jerry Lundström.
360              
361             This program is free software; you can redistribute it and/or modify it
362             under the terms of either: the GNU General Public License as published
363             by the Free Software Foundation; or the Artistic License.
364              
365             See http://dev.perl.org/licenses/ for more information.
366              
367              
368             =cut
369              
370             1; # End of Lim