line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package POOF; |
2
|
|
|
|
|
|
|
|
3
|
6
|
|
|
6
|
|
649
|
use 5.007; |
|
6
|
|
|
|
|
17
|
|
|
6
|
|
|
|
|
293
|
|
4
|
7
|
|
|
5
|
|
457
|
use strict; |
|
5
|
|
|
|
|
9
|
|
|
5
|
|
|
|
|
121
|
|
5
|
7
|
|
|
5
|
|
41
|
use warnings; |
|
5
|
|
|
|
|
558
|
|
|
5
|
|
|
|
|
89
|
|
6
|
|
|
|
|
|
|
|
7
|
5
|
|
|
5
|
|
24
|
use B::Deparse; |
|
5
|
|
|
|
|
18
|
|
|
5
|
|
|
|
|
701
|
|
8
|
5
|
|
|
3
|
|
5947
|
use Attribute::Handlers; |
|
5
|
|
|
|
|
40595
|
|
|
5
|
|
|
|
|
34
|
|
9
|
3
|
|
|
3
|
|
161
|
use Scalar::Util qw(blessed refaddr); |
|
3
|
|
|
|
|
7
|
|
|
3
|
|
|
|
|
415
|
|
10
|
3
|
|
|
3
|
|
24
|
use Carp qw(croak confess cluck); |
|
3
|
|
|
|
|
8
|
|
|
3
|
|
|
|
|
208
|
|
11
|
3
|
|
|
3
|
|
3828
|
use Class::ISA; |
|
3
|
|
|
|
|
10139
|
|
|
3
|
|
|
|
|
93
|
|
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
|
14
|
3
|
|
|
3
|
|
2011
|
use POOF::Properties; |
|
3
|
|
|
|
|
10
|
|
|
3
|
|
|
|
|
113
|
|
15
|
3
|
|
|
3
|
|
27
|
use POOF::DataType; |
|
3
|
|
|
|
|
8
|
|
|
3
|
|
|
|
|
181
|
|
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
our $VERSION = '1.4'; |
18
|
|
|
|
|
|
|
our $TRACE = 0; |
19
|
|
|
|
|
|
|
our $RAISE_EXCEPTION = 'trap'; |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
#------------------------------------------------------------------------------- |
23
|
3
|
|
|
3
|
|
17
|
use constant PROPERTIES => { }; |
|
3
|
|
|
|
|
8
|
|
|
3
|
|
|
|
|
371
|
|
24
|
3
|
|
|
3
|
|
19
|
use constant PROPERTYINDEX => { }; |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
142
|
|
25
|
3
|
|
|
3
|
|
18
|
use constant METHODS => { }; |
|
3
|
|
|
|
|
7
|
|
|
3
|
|
|
|
|
175
|
|
26
|
3
|
|
|
3
|
|
16
|
use constant GROUPS => { }; |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
164
|
|
27
|
3
|
|
|
3
|
|
17
|
use constant PROPBACKREF => { }; |
|
3
|
|
|
|
|
7
|
|
|
3
|
|
|
|
|
237
|
|
28
|
3
|
|
|
3
|
|
16
|
use constant PROPBACKDOOR => { }; |
|
3
|
|
|
|
|
7
|
|
|
3
|
|
|
|
|
140
|
|
29
|
3
|
|
|
3
|
|
17
|
use constant CLASSES => { }; |
|
3
|
|
|
|
|
4
|
|
|
3
|
|
|
|
|
128
|
|
30
|
3
|
|
|
3
|
|
16
|
use constant METHODDISPATCH => { }; |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
240
|
|
31
|
3
|
|
|
3
|
|
17
|
use constant ENCFQCLASSNAMES => { }; |
|
3
|
|
|
|
|
7
|
|
|
3
|
|
|
|
|
151
|
|
32
|
3
|
|
|
3
|
|
17
|
use constant PROCESSEDFILES => { }; |
|
3
|
|
|
|
|
7
|
|
|
3
|
|
|
|
|
417
|
|
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
#------------------------------------------------------------------------------- |
36
|
|
|
|
|
|
|
# access levels |
37
|
3
|
|
|
|
|
21891
|
use constant ACCESSLEVEL => |
38
|
|
|
|
|
|
|
{ |
39
|
|
|
|
|
|
|
'Private' => 0, |
40
|
|
|
|
|
|
|
'Protected' => 1, |
41
|
|
|
|
|
|
|
'Public' => 2, |
42
|
3
|
|
|
3
|
|
18
|
}; |
|
3
|
|
|
|
|
5
|
|
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
#------------------------------------------------------------------------------- |
45
|
|
|
|
|
|
|
sub new |
46
|
|
|
|
|
|
|
{ |
47
|
5
|
|
|
5
|
1
|
1198
|
my $class = shift; |
48
|
5
|
|
|
|
|
13
|
my %args = @_; |
49
|
|
|
|
|
|
|
|
50
|
5
|
50
|
|
|
|
16
|
confess "This class cannot be instantiated as a stand along object, it must be inherited instead" |
51
|
|
|
|
|
|
|
if $class eq 'POOF'; |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
# define main constructor property definition array |
54
|
5
|
|
|
|
|
17
|
my @properties = _processParentProperties($class,{}); |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
# deal with self |
57
|
5
|
|
|
|
|
10
|
foreach my $property (@{ +PROPERTIES->{ $class } }) |
|
5
|
|
|
|
|
12
|
|
58
|
|
|
|
|
|
|
{ |
59
|
15
|
50
|
|
|
|
49
|
if (exists $property->{'name'}) |
60
|
|
|
|
|
|
|
{ |
61
|
|
|
|
|
|
|
# add to Properties.pm constructor args |
62
|
15
|
|
|
|
|
77
|
push(@properties,{ |
63
|
|
|
|
|
|
|
'class' => $class, |
64
|
|
|
|
|
|
|
'name' => $property->{'name'}, |
65
|
|
|
|
|
|
|
'access' => $property->{'data'}->{'access'}, |
66
|
|
|
|
|
|
|
'virtual' => $property->{'data'}->{'virtual'}, |
67
|
|
|
|
|
|
|
'data' => POOF::DataType->new($property->{'data'}), |
68
|
|
|
|
|
|
|
'datadef' => $property->{'data'} |
69
|
|
|
|
|
|
|
}); |
70
|
|
|
|
|
|
|
} |
71
|
|
|
|
|
|
|
} |
72
|
|
|
|
|
|
|
|
73
|
5
|
|
|
|
|
10
|
my $obj; |
74
|
5
|
|
|
|
|
6
|
tie %{$obj}, 'POOF::Properties', \@properties, $class, \&pErrors, \+GROUPS, \+PROPBACKREF, @_; |
|
5
|
|
|
|
|
36
|
|
75
|
3
|
|
|
|
|
5
|
bless $obj,$class; |
76
|
|
|
|
|
|
|
|
77
|
3
|
|
|
|
|
6
|
$obj->{'___refobj___'} = $obj; |
78
|
|
|
|
|
|
|
|
79
|
3
|
50
|
33
|
|
|
9
|
$RAISE_EXCEPTION = $args{'RaiseException'} |
80
|
|
|
|
|
|
|
if exists $args{'RaiseException'} && defined $args{'RaiseException'}; |
81
|
|
|
|
|
|
|
|
82
|
3
|
|
|
|
|
23
|
$obj->_init( @_ ); |
83
|
|
|
|
|
|
|
|
84
|
0
|
|
|
|
|
0
|
return $obj; |
85
|
|
|
|
|
|
|
} |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
sub _processParentProperties |
88
|
|
|
|
|
|
|
{ |
89
|
10
|
|
|
5
|
|
24
|
my $class = shift; |
90
|
10
|
|
|
|
|
48
|
my $seen = shift; |
91
|
10
|
|
|
|
|
31
|
my @properties = @_; |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
# deal with parents |
94
|
10
|
|
|
|
|
45
|
foreach my $parent (reverse Class::ISA::super_path($class)) |
95
|
|
|
|
|
|
|
{ |
96
|
10
|
50
|
|
|
|
225
|
next if $seen->{$parent}++; |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
# process it's parents first |
99
|
5
|
100
|
33
|
|
|
17
|
@properties = _processParentProperties($parent,$seen,@properties) |
100
|
|
|
|
|
|
|
if (exists +PROPERTIES->{ $parent } && $parent ne 'POOF'); |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
# skip any non-defined parent |
103
|
5
|
100
|
|
|
|
17
|
next unless exists +PROPERTIES->{ $parent }; |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
# deal with each parent property |
106
|
0
|
|
|
|
|
0
|
foreach my $property (@{ +PROPERTIES->{ $parent } }) |
|
0
|
|
|
|
|
0
|
|
107
|
|
|
|
|
|
|
{ |
108
|
0
|
50
|
|
|
|
0
|
if (exists $property->{'name'}) |
109
|
|
|
|
|
|
|
{ |
110
|
|
|
|
|
|
|
# add to Properties.pm constructor args |
111
|
0
|
|
|
|
|
0
|
push(@properties,{ |
112
|
|
|
|
|
|
|
'class' => $parent, |
113
|
|
|
|
|
|
|
'name' => $property->{'name'}, |
114
|
|
|
|
|
|
|
'access' => $property->{'data'}->{'access'}, |
115
|
|
|
|
|
|
|
'virtual' => $property->{'data'}->{'virtual'}, |
116
|
|
|
|
|
|
|
'data' => POOF::DataType->new($property->{'data'}), |
117
|
|
|
|
|
|
|
'datadef' => $property->{'data'} |
118
|
|
|
|
|
|
|
}); |
119
|
|
|
|
|
|
|
} |
120
|
|
|
|
|
|
|
} |
121
|
|
|
|
|
|
|
} |
122
|
|
|
|
|
|
|
|
123
|
5
|
|
|
|
|
14
|
return (@properties); |
124
|
|
|
|
|
|
|
} |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
sub _init |
127
|
|
|
|
|
|
|
{ |
128
|
5
|
|
|
5
|
|
6
|
my $obj = shift; |
129
|
5
|
|
|
|
|
11
|
my %args = @_; |
130
|
5
|
|
|
|
|
13
|
return (@_); |
131
|
|
|
|
|
|
|
} |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
#------------------------------------------------------------------------------- |
135
|
|
|
|
|
|
|
# Error handling |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
my $ERRORS; |
138
|
|
|
|
|
|
|
sub pErrors |
139
|
|
|
|
|
|
|
{ |
140
|
0
|
|
|
3
|
1
|
0
|
my $obj = shift; |
141
|
0
|
|
|
|
|
0
|
my ($k,$e) = @_; |
142
|
|
|
|
|
|
|
|
143
|
0
|
0
|
|
|
|
0
|
$e->{'description'} = "$e->{'description'}" |
144
|
|
|
|
|
|
|
if ref($e); |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
return |
147
|
0
|
|
|
|
|
0
|
@_ == 0 |
148
|
0
|
0
|
|
|
|
0
|
? scalar keys %{$ERRORS->{ refaddr($obj) }} |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
149
|
|
|
|
|
|
|
: @_ == 1 |
150
|
|
|
|
|
|
|
? delete $ERRORS->{ refaddr($obj) }->{ $k } |
151
|
|
|
|
|
|
|
: @_ == 2 |
152
|
|
|
|
|
|
|
? $obj->_AddError($k,$e) |
153
|
|
|
|
|
|
|
: undef; |
154
|
|
|
|
|
|
|
} |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
sub pGetErrors |
157
|
|
|
|
|
|
|
{ |
158
|
0
|
|
|
0
|
1
|
0
|
my $obj = shift; |
159
|
|
|
|
|
|
|
return |
160
|
0
|
0
|
|
|
|
0
|
ref $ERRORS->{ refaddr($obj) } |
161
|
|
|
|
|
|
|
? $ERRORS->{ refaddr($obj) } |
162
|
|
|
|
|
|
|
: { }; |
163
|
|
|
|
|
|
|
} |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
sub pAllErrors |
166
|
|
|
|
|
|
|
{ |
167
|
0
|
|
|
0
|
0
|
0
|
my ($obj) = @_; |
168
|
0
|
|
|
|
|
0
|
return scalar(keys %{$obj->pGetAllErrors}); |
|
0
|
|
|
|
|
0
|
|
169
|
|
|
|
|
|
|
} |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
sub pGetAllErrors |
172
|
|
|
|
|
|
|
{ |
173
|
0
|
|
|
0
|
1
|
0
|
my ($obj,$parent) = @_; |
174
|
0
|
|
|
|
|
0
|
my $errors = {}; |
175
|
|
|
|
|
|
|
|
176
|
0
|
0
|
|
|
|
0
|
$parent = |
177
|
|
|
|
|
|
|
$parent |
178
|
|
|
|
|
|
|
? "$parent-" |
179
|
|
|
|
|
|
|
: ''; |
180
|
|
|
|
|
|
|
|
181
|
0
|
0
|
|
|
|
0
|
if ($obj->_Relationship(ref($obj),'POOF::Collection') =~ /^(?:self|child)$/) |
182
|
|
|
|
|
|
|
{ |
183
|
0
|
|
|
|
|
0
|
for(my $i=0; $i<=$#{$obj}; $i++) |
|
0
|
|
|
|
|
0
|
|
184
|
|
|
|
|
|
|
{ |
185
|
|
|
|
|
|
|
# skip non initialized elements of collection |
186
|
0
|
0
|
|
|
|
0
|
next unless exists $obj->[$i]; |
187
|
0
|
0
|
|
|
|
0
|
if ($obj->_Relationship(ref($obj->[$i]),'POOF') =~ /^(?:self|child)$/) |
188
|
|
|
|
|
|
|
{ |
189
|
0
|
|
|
|
|
0
|
my $error = $obj->[$i]->pGetAllErrors("$parent$i"); |
190
|
0
|
0
|
|
|
|
0
|
%{$errors} = (%{$errors},%{$error}) |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
191
|
|
|
|
|
|
|
if $error; |
192
|
|
|
|
|
|
|
} |
193
|
|
|
|
|
|
|
} |
194
|
|
|
|
|
|
|
} |
195
|
|
|
|
|
|
|
else |
196
|
|
|
|
|
|
|
{ |
197
|
0
|
|
|
|
|
0
|
foreach my $prop (@{+PROPERTIES->{ ref($obj) }}) |
|
0
|
|
|
|
|
0
|
|
198
|
|
|
|
|
|
|
{ |
199
|
0
|
0
|
|
|
|
0
|
if ($obj->_Relationship(ref($obj->{$prop->{'name'}}),'POOF') =~ /^(?:self|child)$/) |
200
|
|
|
|
|
|
|
{ |
201
|
0
|
|
|
|
|
0
|
my $error = $obj->{$prop->{'name'}}->pGetAllErrors("$parent$prop->{'name'}"); |
202
|
0
|
0
|
|
|
|
0
|
%{$errors} = (%{$errors},%{$error}) |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
203
|
|
|
|
|
|
|
if $error; |
204
|
|
|
|
|
|
|
} |
205
|
|
|
|
|
|
|
} |
206
|
|
|
|
|
|
|
} |
207
|
|
|
|
|
|
|
|
208
|
0
|
|
|
|
|
0
|
my $myErrors = $obj->pGetErrors; |
209
|
0
|
|
|
|
|
0
|
map { $errors->{"$parent$_"} = $myErrors->{$_} } keys %{$myErrors}; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
210
|
0
|
|
|
|
|
0
|
return $errors; |
211
|
|
|
|
|
|
|
} |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
sub _AddError |
214
|
|
|
|
|
|
|
{ |
215
|
0
|
|
|
0
|
|
0
|
my ($obj,$k,$e) = @_; |
216
|
0
|
0
|
|
|
|
0
|
unless ($RAISE_EXCEPTION eq 'trap') |
217
|
|
|
|
|
|
|
{ |
218
|
0
|
0
|
|
|
|
0
|
my $error_string = "\nException for " . ref($obj) . "->{'$k'}\n" . "-"x50 . "\n" |
219
|
|
|
|
|
|
|
. "\n\tcode = $e->{'code'}" |
220
|
|
|
|
|
|
|
. "\n\tvalue = " . (defined $e->{'value'} ? $e->{'value'} : 'undef') |
221
|
|
|
|
|
|
|
. "\n\tdescription = $e->{'description'}"; |
222
|
|
|
|
|
|
|
|
223
|
0
|
0
|
|
|
|
0
|
if ($RAISE_EXCEPTION eq 'warn') |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
224
|
|
|
|
|
|
|
{ |
225
|
0
|
|
|
|
|
0
|
warn $error_string; |
226
|
|
|
|
|
|
|
} |
227
|
|
|
|
|
|
|
elsif($RAISE_EXCEPTION eq 'print') |
228
|
|
|
|
|
|
|
{ |
229
|
0
|
|
|
|
|
0
|
print $error_string; |
230
|
|
|
|
|
|
|
} |
231
|
|
|
|
|
|
|
elsif($RAISE_EXCEPTION eq 'cluck') |
232
|
|
|
|
|
|
|
{ |
233
|
0
|
|
|
|
|
0
|
cluck $error_string ."\n\tstack = "; |
234
|
|
|
|
|
|
|
} |
235
|
|
|
|
|
|
|
elsif($RAISE_EXCEPTION eq 'confess') |
236
|
|
|
|
|
|
|
{ |
237
|
0
|
|
|
|
|
0
|
confess $error_string ."\n\tstack = "; |
238
|
|
|
|
|
|
|
} |
239
|
|
|
|
|
|
|
elsif($RAISE_EXCEPTION eq 'croak') |
240
|
|
|
|
|
|
|
{ |
241
|
0
|
|
|
|
|
0
|
croak $error_string; |
242
|
|
|
|
|
|
|
} |
243
|
|
|
|
|
|
|
elsif($RAISE_EXCEPTION eq 'die') |
244
|
|
|
|
|
|
|
{ |
245
|
0
|
|
|
|
|
0
|
die $error_string; |
246
|
|
|
|
|
|
|
} |
247
|
|
|
|
|
|
|
} |
248
|
|
|
|
|
|
|
|
249
|
0
|
|
|
|
|
0
|
return $ERRORS->{ refaddr($obj) }->{ $k } = $e; |
250
|
|
|
|
|
|
|
} |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
sub pRaiseException |
253
|
|
|
|
|
|
|
{ |
254
|
0
|
|
|
0
|
0
|
0
|
my ($obj,$val) = @_; |
255
|
|
|
|
|
|
|
return |
256
|
0
|
0
|
|
|
|
0
|
defined $val |
257
|
|
|
|
|
|
|
? $RAISE_EXCEPTION = $val |
258
|
|
|
|
|
|
|
: $RAISE_EXCEPTION; |
259
|
|
|
|
|
|
|
} |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
#------------------------------------------------------------------------------- |
262
|
|
|
|
|
|
|
# Group operations |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
sub pGetPropertiesOfGroups |
265
|
|
|
|
|
|
|
{ |
266
|
0
|
|
|
0
|
1
|
0
|
my $obj = shift; |
267
|
0
|
|
|
|
|
0
|
my %props; |
268
|
0
|
|
|
|
|
0
|
@props{ $obj->pGetNamesOfGroup(@_) } = $obj->pGetValuesOfGroup(@_); |
269
|
0
|
|
|
|
|
0
|
return (%props); |
270
|
|
|
|
|
|
|
} |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
sub pGetGroups |
273
|
|
|
|
|
|
|
{ |
274
|
0
|
|
|
0
|
1
|
0
|
my ($obj) = @_; |
275
|
0
|
|
|
|
|
0
|
return (keys %{ +GROUPS->{ ref $obj } }); |
|
0
|
|
|
|
|
0
|
|
276
|
|
|
|
|
|
|
} |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
sub pGetNamesOfGroup |
279
|
|
|
|
|
|
|
{ |
280
|
2
|
|
|
2
|
1
|
3
|
my ($obj,$group) = @_; |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
return |
283
|
2
|
|
|
|
|
10
|
defined $group && exists +GROUPS->{ ref $obj }->{ $group } |
284
|
2
|
50
|
33
|
|
|
13
|
? (@{ +GROUPS->{ ref $obj }->{ $group } }) |
285
|
|
|
|
|
|
|
: (); |
286
|
|
|
|
|
|
|
} |
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
sub pGroup |
289
|
|
|
|
|
|
|
{ |
290
|
2
|
|
|
2
|
1
|
3
|
my ($obj,$group) = @_; |
291
|
2
|
|
|
|
|
8
|
return $obj->pGetNamesOfGroup($group); |
292
|
|
|
|
|
|
|
} |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
sub pGroupEncoded |
295
|
|
|
|
|
|
|
{ |
296
|
0
|
|
|
0
|
1
|
0
|
my ($obj,$group) = @_; |
297
|
0
|
|
|
|
|
0
|
return (map { $obj->_encodeFullyQualifyClassName . '-' . $_ } $obj->pGetNamesOfGroup($group)); |
|
0
|
|
|
|
|
0
|
|
298
|
|
|
|
|
|
|
} |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
sub pPropertyNamesEncoded |
301
|
|
|
|
|
|
|
{ |
302
|
0
|
|
|
0
|
1
|
0
|
my ($obj,$refObj,@names) = @_; |
303
|
0
|
|
|
|
|
0
|
my $class = ref $refObj; |
304
|
0
|
|
|
|
|
0
|
return (map { $obj->_encodeFullyQualifyClassName($refObj) . '-' . $_ } @names ); |
|
0
|
|
|
|
|
0
|
|
305
|
|
|
|
|
|
|
} |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
sub pGetValuesOfGroup |
308
|
|
|
|
|
|
|
{ |
309
|
0
|
|
|
0
|
1
|
0
|
my ($obj,$group) = @_; |
310
|
|
|
|
|
|
|
return |
311
|
0
|
|
|
|
|
0
|
defined $group && $obj->pGetNamesOfGroup($group) |
312
|
0
|
0
|
0
|
|
|
0
|
? (@{$obj}{ $obj->pGetNamesOfGroup($group) }) |
313
|
|
|
|
|
|
|
: (); |
314
|
|
|
|
|
|
|
} |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
sub pValidGroupName |
317
|
|
|
|
|
|
|
{ |
318
|
0
|
0
|
|
0
|
1
|
0
|
my $obj = ref $_[0] ? +shift : undef; |
319
|
0
|
|
|
|
|
0
|
my ($name) = @_; |
320
|
|
|
|
|
|
|
return |
321
|
0
|
0
|
|
|
|
0
|
$name !~ /^\s*$/ |
322
|
|
|
|
|
|
|
? 1 |
323
|
|
|
|
|
|
|
: 0; |
324
|
|
|
|
|
|
|
} |
325
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
#------------------------------------------------------------------------------- |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
sub pSetPropertyDeeply |
330
|
|
|
|
|
|
|
{ |
331
|
0
|
|
|
0
|
1
|
0
|
my ($obj,$ref,$val,@path) = @_; |
332
|
0
|
|
|
|
|
0
|
my $level = shift @path; |
333
|
|
|
|
|
|
|
|
334
|
0
|
0
|
|
|
|
0
|
if (@path) |
335
|
|
|
|
|
|
|
{ |
336
|
|
|
|
|
|
|
# look ahead to see if this is a collection |
337
|
0
|
0
|
0
|
|
|
0
|
if (ref($ref->{$level}) && $obj->_Relationship($ref->{$level},'POOF::Collection') =~ /^(?:self|child)$/o ) |
338
|
|
|
|
|
|
|
{ |
339
|
|
|
|
|
|
|
# it's a collection |
340
|
0
|
|
|
|
|
0
|
$obj->pSetPropertyDeeply($ref->{$level}->[ shift @path ],$val,@path); |
341
|
|
|
|
|
|
|
} |
342
|
|
|
|
|
|
|
else |
343
|
|
|
|
|
|
|
{ |
344
|
|
|
|
|
|
|
# no it's not |
345
|
0
|
|
|
|
|
0
|
$obj->pSetPropertyDeeply($ref->{$level},$val,@path) |
346
|
|
|
|
|
|
|
} |
347
|
|
|
|
|
|
|
} |
348
|
|
|
|
|
|
|
else |
349
|
|
|
|
|
|
|
{ |
350
|
0
|
|
|
|
|
0
|
$ref->{$level} = $val; |
351
|
|
|
|
|
|
|
} |
352
|
|
|
|
|
|
|
} |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
sub pGetPropertyDeeply |
355
|
|
|
|
|
|
|
{ |
356
|
0
|
|
|
0
|
1
|
0
|
my ($obj,$ref,@path) = @_; |
357
|
0
|
|
|
|
|
0
|
my $level = shift @path; |
358
|
|
|
|
|
|
|
return |
359
|
0
|
0
|
|
|
|
0
|
scalar (@path) |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
360
|
|
|
|
|
|
|
? ref($ref) eq 'ARRAY' |
361
|
|
|
|
|
|
|
? $obj->pGetPropertyDeeply($ref->[$level],@path) |
362
|
|
|
|
|
|
|
: $obj->pGetPropertyDeeply($ref->{$level},@path) |
363
|
|
|
|
|
|
|
: ref($ref) eq 'ARRAY' |
364
|
|
|
|
|
|
|
? $ref->[$level] |
365
|
|
|
|
|
|
|
: $ref->{$level}; |
366
|
|
|
|
|
|
|
} |
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
sub pInstantiate |
369
|
|
|
|
|
|
|
{ |
370
|
0
|
|
|
0
|
0
|
0
|
my ($obj,$prop) = @_; |
371
|
|
|
|
|
|
|
return |
372
|
0
|
|
|
|
|
0
|
$obj->pPropertyDefinition($prop)->{'otype'}->new |
373
|
|
|
|
|
|
|
( |
374
|
|
|
|
|
|
|
$obj->pGetPropertiesOfGroups('Application'), |
375
|
|
|
|
|
|
|
RaiseException => $POOF::RAISE_EXCEPTION |
376
|
|
|
|
|
|
|
); |
377
|
|
|
|
|
|
|
} |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
sub pReInstantiateSelf |
380
|
|
|
|
|
|
|
{ |
381
|
0
|
|
|
0
|
0
|
0
|
my ($obj,%args) = @_; |
382
|
|
|
|
|
|
|
return |
383
|
0
|
|
|
|
|
0
|
ref($obj)->new( |
384
|
|
|
|
|
|
|
$obj->pGetPropertiesOfGroups('Application'), |
385
|
|
|
|
|
|
|
%args |
386
|
|
|
|
|
|
|
); |
387
|
|
|
|
|
|
|
} |
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
#------------------------------------------------------------------------------- |
390
|
|
|
|
|
|
|
# property definitions |
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
sub pPropertyEnumOptions |
393
|
|
|
|
|
|
|
{ |
394
|
0
|
|
|
0
|
1
|
0
|
my ($obj,$propName) = @_; |
395
|
0
|
0
|
|
|
|
0
|
confess "There are no properties associated with " . ref($obj) |
396
|
|
|
|
|
|
|
unless exists +PROPBACKREF->{ ref($obj) }; |
397
|
0
|
|
|
|
|
0
|
return +PROPBACKREF->{ ref($obj) }->EnumOptions($propName); |
398
|
|
|
|
|
|
|
} |
399
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
sub pPropertyDefinition |
401
|
|
|
|
|
|
|
{ |
402
|
0
|
|
|
0
|
1
|
0
|
my ($obj,$propName) = @_; |
403
|
0
|
0
|
|
|
|
0
|
confess "There are no properties associated with " . ref($obj) |
404
|
|
|
|
|
|
|
unless exists +PROPBACKREF->{ ref($obj) }; |
405
|
|
|
|
|
|
|
|
406
|
0
|
|
|
|
|
0
|
return +PROPBACKREF->{ ref($obj) }->Definition($propName); |
407
|
|
|
|
|
|
|
} |
408
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
#------------------------------------------------------------------------------- |
410
|
|
|
|
|
|
|
our $AUTOLOAD; |
411
|
|
|
|
|
|
|
sub AUTOLOAD |
412
|
|
|
|
|
|
|
{ |
413
|
0
|
|
|
0
|
|
0
|
my $obj = shift; |
414
|
|
|
|
|
|
|
|
415
|
0
|
|
|
|
|
0
|
my $name = $AUTOLOAD; |
416
|
0
|
|
|
|
|
0
|
$name =~ s/.*://; # strip fully-qualified portion |
417
|
|
|
|
|
|
|
|
418
|
0
|
0
|
|
|
|
0
|
my $super = |
419
|
|
|
|
|
|
|
$AUTOLOAD =~ /\:SUPER\:/o |
420
|
|
|
|
|
|
|
? 1 |
421
|
|
|
|
|
|
|
: 0; |
422
|
|
|
|
|
|
|
|
423
|
0
|
|
0
|
|
|
0
|
my $class = ref($obj) || confess "$obj is not an object"; |
424
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
# TDB: handle super correctly, if the parent does not have the method |
426
|
|
|
|
|
|
|
# then try his parent and so on until we hit the top, if no method |
427
|
|
|
|
|
|
|
# is found then throw and exeption. |
428
|
0
|
|
|
|
|
0
|
my $package = |
429
|
|
|
|
|
|
|
$super |
430
|
0
|
0
|
|
|
|
0
|
? shift @{[ Class::ISA::super_path( $class ) ]} |
431
|
|
|
|
|
|
|
: $class; |
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
# just return undef if we are dealing with built in methods like DESTROY |
434
|
0
|
0
|
|
|
|
0
|
return if $name eq 'DESTROY'; |
435
|
|
|
|
|
|
|
|
436
|
0
|
0
|
|
|
|
0
|
if ($TRACE) |
437
|
|
|
|
|
|
|
{ |
438
|
3
|
|
|
3
|
|
214
|
no warnings; |
|
3
|
|
|
|
|
21
|
|
|
3
|
|
|
|
|
4655
|
|
439
|
0
|
|
|
|
|
0
|
warn qq|$AUTOLOAD for ($package) called from | . (caller(0))[0] . "\n"; |
440
|
0
|
|
|
|
|
0
|
warn qq|$AUTOLOAD for ($package) called from | . (caller(1))[0] . "\n"; |
441
|
0
|
|
|
|
|
0
|
warn qq|$AUTOLOAD for ($package) called from | . (caller(2))[0] . "\n"; |
442
|
0
|
|
|
|
|
0
|
warn qq|$AUTOLOAD for ($package) called from | . (caller(3))[0] . "\n"; |
443
|
0
|
|
|
|
|
0
|
warn qq|$AUTOLOAD for ($package) called from | . (caller(4))[0] . "\n"; |
444
|
0
|
|
|
|
|
0
|
warn "\twith " . scalar(@_) . " parameters\n"; |
445
|
|
|
|
|
|
|
} |
446
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
# make sure we apply the inheritance rules the first time a class is used. |
449
|
0
|
0
|
|
|
|
0
|
$obj->_BuildMethodDispatch( $package ) |
450
|
|
|
|
|
|
|
unless exists +METHODDISPATCH->{ $package }; |
451
|
|
|
|
|
|
|
|
452
|
0
|
0
|
0
|
|
|
0
|
confess "$name method does not exist in class $package" |
453
|
|
|
|
|
|
|
unless ( |
454
|
|
|
|
|
|
|
exists +METHODDISPATCH->{ $package }->{ $name } |
455
|
|
|
|
|
|
|
and exists +METHODDISPATCH->{ $package }->{ $name }->{'code'} |
456
|
|
|
|
|
|
|
); |
457
|
|
|
|
|
|
|
|
458
|
0
|
|
|
|
|
0
|
my $method = +METHODDISPATCH->{ $package }->{ $name }->{'code'}; |
459
|
0
|
|
|
|
|
0
|
my $access = +METHODDISPATCH->{ $package }->{ $name }->{'access'}; |
460
|
|
|
|
|
|
|
|
461
|
0
|
0
|
|
|
|
0
|
$access = |
462
|
|
|
|
|
|
|
exists ACCESSLEVEL->{ $access } |
463
|
|
|
|
|
|
|
? ACCESSLEVEL->{ $access } |
464
|
|
|
|
|
|
|
: ACCESSLEVEL->{ 'Public' }; |
465
|
|
|
|
|
|
|
|
466
|
0
|
|
|
|
|
0
|
my $context = $obj->_AccessContext; |
467
|
|
|
|
|
|
|
|
468
|
0
|
0
|
|
|
|
0
|
confess "Illegal access of method $name" |
469
|
|
|
|
|
|
|
unless $access >= $context; |
470
|
|
|
|
|
|
|
|
471
|
0
|
|
|
|
|
0
|
return &{$method}($obj,@_); |
|
0
|
|
|
|
|
0
|
|
472
|
|
|
|
|
|
|
} |
473
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
|
475
|
|
|
|
|
|
|
sub _BuildMethodDispatch |
476
|
|
|
|
|
|
|
{ |
477
|
0
|
|
|
0
|
|
0
|
my $obj = shift; |
478
|
0
|
|
|
|
|
0
|
my $package = shift; |
479
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
# get all parents |
481
|
0
|
|
|
|
|
0
|
my @parents = Class::ISA::super_path($package); |
482
|
|
|
|
|
|
|
|
483
|
|
|
|
|
|
|
# go through each class on the chain |
484
|
0
|
|
|
|
|
0
|
foreach my $parent (reverse @parents) |
485
|
|
|
|
|
|
|
{ |
486
|
|
|
|
|
|
|
# non-defined parent will simply get and empty hash |
487
|
|
|
|
|
|
|
# and we'll skip to the next parent |
488
|
0
|
0
|
|
|
|
0
|
unless (exists +METHODS->{ $parent }) |
489
|
|
|
|
|
|
|
{ |
490
|
0
|
|
|
|
|
0
|
+METHODDISPATCH->{ $parent } = { }; |
491
|
0
|
|
|
|
|
0
|
next; |
492
|
|
|
|
|
|
|
} |
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
# deal with each parent methods |
495
|
0
|
|
|
|
|
0
|
foreach my $name (keys %{ +METHODS->{ $parent } }) |
|
0
|
|
|
|
|
0
|
|
496
|
|
|
|
|
|
|
{ |
497
|
0
|
|
|
|
|
0
|
my $method = +METHODS->{ $parent }->{ $name }; |
498
|
|
|
|
|
|
|
# skip any private property since they are not accessible |
499
|
|
|
|
|
|
|
# from this context, they are only accessible from the class in |
500
|
|
|
|
|
|
|
# which they are defined. |
501
|
0
|
0
|
|
|
|
0
|
next if $method->{'access'} eq 'Private'; |
502
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
# croak if a method is redefined and it's not marked at virtual |
504
|
0
|
0
|
0
|
|
|
0
|
confess "A non-virtual $name has been redefined in $parent" |
505
|
|
|
|
|
|
|
if (exists +METHODDISPATCH->{ $package }->{ $name } |
506
|
|
|
|
|
|
|
and +METHODDISPATCH->{ $package }->{ $name }->{'virtual'} != 1); |
507
|
|
|
|
|
|
|
|
508
|
|
|
|
|
|
|
# add method to dispatch table |
509
|
0
|
|
|
|
|
0
|
+METHODDISPATCH->{ $package }->{ $name } = $method; |
510
|
|
|
|
|
|
|
} |
511
|
|
|
|
|
|
|
} |
512
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
# deal with each method in this package |
514
|
0
|
|
|
|
|
0
|
foreach my $name (keys %{ +METHODS->{ $package } }) |
|
0
|
|
|
|
|
0
|
|
515
|
|
|
|
|
|
|
{ |
516
|
0
|
|
|
|
|
0
|
my $method = +METHODS->{ $package }->{ $name }; |
517
|
|
|
|
|
|
|
|
518
|
|
|
|
|
|
|
# croak if a method is redefined and it's not marked at virtual |
519
|
0
|
0
|
0
|
|
|
0
|
confess "A non-virtual $name has been redefined in $package" |
520
|
|
|
|
|
|
|
if (exists +METHODDISPATCH->{ $package }->{ $name } |
521
|
|
|
|
|
|
|
and +METHODDISPATCH->{ $package }->{ $name }->{'virtual'} != 1); |
522
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
# add method to dispatch table |
524
|
0
|
|
|
|
|
0
|
+METHODDISPATCH->{ $package }->{ $name } = $method; |
525
|
|
|
|
|
|
|
} |
526
|
|
|
|
|
|
|
} |
527
|
|
|
|
|
|
|
|
528
|
|
|
|
|
|
|
|
529
|
|
|
|
|
|
|
sub _AccessContext |
530
|
|
|
|
|
|
|
{ |
531
|
0
|
|
|
0
|
|
0
|
my ($obj) = @_; |
532
|
0
|
|
|
|
|
0
|
my $self = ref($obj); |
533
|
|
|
|
|
|
|
|
534
|
0
|
|
|
|
|
0
|
my ($caller) = (caller(1))[0]; |
535
|
|
|
|
|
|
|
|
536
|
0
|
|
|
|
|
0
|
my $relationship = $obj->_Relationship($caller,$self); |
537
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
return |
539
|
0
|
0
|
|
|
|
0
|
$relationship eq 'self' |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
540
|
|
|
|
|
|
|
? 0 # 'private' |
541
|
|
|
|
|
|
|
: $relationship eq 'child' |
542
|
|
|
|
|
|
|
? 1 # 'protected' |
543
|
|
|
|
|
|
|
: $relationship eq 'parent' |
544
|
|
|
|
|
|
|
? 1 # 'protected' This is wierd shit, but I'm too tired now to fix it. |
545
|
|
|
|
|
|
|
: 2 # 'public'; |
546
|
|
|
|
|
|
|
} |
547
|
|
|
|
|
|
|
|
548
|
|
|
|
|
|
|
sub _CallerContext |
549
|
|
|
|
|
|
|
{ |
550
|
0
|
|
|
0
|
|
0
|
my ($obj) = @_; |
551
|
0
|
0
|
|
|
|
0
|
$obj->Trace if $TRACE; |
552
|
0
|
|
|
|
|
0
|
return (caller(1))[0]; |
553
|
|
|
|
|
|
|
} |
554
|
|
|
|
|
|
|
|
555
|
|
|
|
|
|
|
sub _Relationship |
556
|
|
|
|
|
|
|
{ |
557
|
0
|
|
|
0
|
|
0
|
my $obj = shift; |
558
|
0
|
0
|
|
|
|
0
|
my ($class1,$class2) = map { $_ ? ref $_ ? ref $_ : $_ : '' } @_; |
|
0
|
0
|
|
|
|
0
|
|
559
|
|
|
|
|
|
|
|
560
|
0
|
0
|
|
|
|
0
|
return 'self' if $class1 eq $class2; |
561
|
|
|
|
|
|
|
|
562
|
0
|
|
|
|
|
0
|
my %family1 = map { $_ => 1 } Class::ISA::super_path( $class1 ); |
|
0
|
|
|
|
|
0
|
|
563
|
0
|
|
|
|
|
0
|
my %family2 = map { $_ => 1 } Class::ISA::super_path( $class2 ); |
|
0
|
|
|
|
|
0
|
|
564
|
|
|
|
|
|
|
|
565
|
|
|
|
|
|
|
return |
566
|
0
|
0
|
|
|
|
0
|
exists $family1{ $class2 } |
|
|
0
|
|
|
|
|
|
567
|
|
|
|
|
|
|
? 'child' |
568
|
|
|
|
|
|
|
: exists $family2{ $class1 } |
569
|
|
|
|
|
|
|
? 'parent' |
570
|
|
|
|
|
|
|
: 'unrelated'; |
571
|
|
|
|
|
|
|
} |
572
|
|
|
|
|
|
|
|
573
|
|
|
|
|
|
|
|
574
|
|
|
|
|
|
|
sub _DumpAccessContext |
575
|
|
|
|
|
|
|
{ |
576
|
0
|
|
|
0
|
|
0
|
my $obj = shift; |
577
|
0
|
|
|
|
|
0
|
my %caller; |
578
|
|
|
|
|
|
|
|
579
|
0
|
|
|
|
|
0
|
for(2 .. 5) |
580
|
|
|
|
|
|
|
{ |
581
|
0
|
|
|
|
|
0
|
@caller{ qw( |
582
|
|
|
|
|
|
|
0-package |
583
|
|
|
|
|
|
|
1-filename |
584
|
|
|
|
|
|
|
2-line |
585
|
|
|
|
|
|
|
3-subr |
586
|
|
|
|
|
|
|
4-has_args |
587
|
|
|
|
|
|
|
5-wantarray |
588
|
|
|
|
|
|
|
6-evaltext |
589
|
|
|
|
|
|
|
7-is_required |
590
|
|
|
|
|
|
|
8-hints |
591
|
|
|
|
|
|
|
9-bitmask |
592
|
|
|
|
|
|
|
) } = caller($_); |
593
|
|
|
|
|
|
|
|
594
|
0
|
0
|
|
|
|
0
|
last unless defined $caller{'0-package'}; |
595
|
|
|
|
|
|
|
|
596
|
0
|
|
|
|
|
0
|
warn "\ncaller $_\n" . "-"x50 . "\n"; |
597
|
0
|
|
|
|
|
0
|
$obj->_DumpCaller(\%caller); |
598
|
|
|
|
|
|
|
} |
599
|
|
|
|
|
|
|
} |
600
|
|
|
|
|
|
|
|
601
|
|
|
|
|
|
|
sub _DumpCore |
602
|
|
|
|
|
|
|
{ |
603
|
0
|
|
|
0
|
|
0
|
my ($obj) = @_; |
604
|
|
|
|
|
|
|
|
605
|
|
|
|
|
|
|
#warn "Dumping Core\n"; |
606
|
|
|
|
|
|
|
#warn "-"x50 . "\n"; |
607
|
|
|
|
|
|
|
#warn "METHODS: ",Dumper( +METHODDISPATCH), "\n"; |
608
|
|
|
|
|
|
|
#warn "PROPERTYINDEX: ",Dumper( +PROPERTYINDEX), "\n"; |
609
|
|
|
|
|
|
|
#warn "PROPERTIES: ",Dumper( +PROPERTIES), "\n"; |
610
|
|
|
|
|
|
|
} |
611
|
|
|
|
|
|
|
|
612
|
|
|
|
|
|
|
|
613
|
|
|
|
|
|
|
#------------------------------------------------------------------------------- |
614
|
|
|
|
|
|
|
# function attribute handlers |
615
|
|
|
|
|
|
|
|
616
|
3
|
|
|
3
|
1
|
26
|
sub Method : ATTR(CODE,BEGIN) { _processFile(@_) } |
|
3
|
|
|
6
|
|
6
|
|
|
3
|
|
|
|
|
33
|
|
|
6
|
|
|
|
|
790
|
|
617
|
3
|
|
|
3
|
0
|
2024
|
sub Property : ATTR(CODE,BEGIN) { _processFile(@_) } |
|
3
|
|
|
14
|
|
8
|
|
|
3
|
|
|
|
|
19
|
|
|
14
|
|
|
|
|
2330
|
|
618
|
3
|
|
|
3
|
1
|
1082
|
sub Private : ATTR(CODE,BEGIN) { _processFile(@_) } |
|
3
|
|
|
2
|
|
8
|
|
|
3
|
|
|
|
|
98
|
|
|
2
|
|
|
|
|
109
|
|
619
|
3
|
|
|
3
|
1
|
1429
|
sub Protected : ATTR(CODE,BEGIN) { _processFile(@_) } |
|
3
|
|
|
0
|
|
6
|
|
|
3
|
|
|
|
|
14
|
|
|
0
|
|
|
|
|
0
|
|
620
|
3
|
|
|
3
|
1
|
1729
|
sub Public : ATTR(CODE,BEGIN) { _processFile(@_) } |
|
3
|
|
|
17
|
|
7
|
|
|
3
|
|
|
|
|
13
|
|
|
17
|
|
|
|
|
944
|
|
621
|
3
|
|
|
3
|
1
|
1464
|
sub Virtual : ATTR(CODE,BEGIN) { _processFile(@_) } |
|
3
|
|
|
6
|
|
7
|
|
|
3
|
|
|
|
|
13
|
|
|
6
|
|
|
|
|
272
|
|
622
|
3
|
|
|
3
|
0
|
1358
|
sub Doc : ATTR(CODE,BEGIN) { _processFile(@_) } |
|
3
|
|
|
0
|
|
9
|
|
|
3
|
|
|
|
|
13
|
|
|
0
|
|
|
|
|
0
|
|
623
|
|
|
|
|
|
|
|
624
|
|
|
|
|
|
|
|
625
|
|
|
|
|
|
|
sub _processFile |
626
|
|
|
|
|
|
|
{ |
627
|
45
|
|
|
45
|
|
91
|
my ($package, $symbol, $referent, $attr, $data, $phase) = @_; |
628
|
|
|
|
|
|
|
|
629
|
45
|
100
|
|
|
|
164
|
return if $package =~ /POOF::TEMPORARYNAMESPACE/; |
630
|
|
|
|
|
|
|
|
631
|
|
|
|
|
|
|
# convert package name to a path |
632
|
22
|
50
|
|
|
|
30
|
my ($filename) = map { exists $INC{"$_.pm"} ? $INC{"$_.pm"} : $0 } map { s!::!/!go; $_ } ($package); |
|
22
|
|
|
|
|
98
|
|
|
22
|
|
|
|
|
77
|
|
|
22
|
|
|
|
|
53
|
|
633
|
|
|
|
|
|
|
|
634
|
|
|
|
|
|
|
# just return if we already processed this file |
635
|
22
|
100
|
|
|
|
103
|
return if +PROCESSEDFILES->{$filename}++; |
636
|
|
|
|
|
|
|
|
637
|
3
|
|
|
|
|
6
|
my $source; |
638
|
|
|
|
|
|
|
my $exception; |
639
|
|
|
|
|
|
|
|
640
|
|
|
|
|
|
|
# read source from file and untaint it |
641
|
3
|
50
|
|
|
|
277
|
open(SOURCEFILE,$filename) || confess "Could not open $filename\n"; |
642
|
|
|
|
|
|
|
{ |
643
|
3
|
|
|
|
|
8
|
local $/ = undef; |
|
3
|
|
|
|
|
17
|
|
644
|
3
|
|
|
|
|
186
|
=~ /(.*)/ms; # put untainted code in $1 |
645
|
3
|
|
|
|
|
22
|
$source = $1; |
646
|
|
|
|
|
|
|
} |
647
|
3
|
|
|
|
|
39
|
close(SOURCEFILE); |
648
|
|
|
|
|
|
|
|
649
|
|
|
|
|
|
|
# let's rename the packages so we don't brack perl's inheritance stuff |
650
|
3
|
|
|
|
|
22
|
$source =~ s/^package\s+/package POOF::TEMPORARYNAMESPACE/g; |
651
|
|
|
|
|
|
|
|
652
|
|
|
|
|
|
|
# now let's evaluate the source using the same nasty string eval which is |
653
|
|
|
|
|
|
|
# the reason we have to jump through hoops here (caramba!). |
654
|
|
|
|
|
|
|
{ |
655
|
|
|
|
|
|
|
# creating block to squelch perl's complaining |
656
|
3
|
|
|
3
|
|
4763
|
no strict 'refs'; |
|
3
|
|
|
|
|
8
|
|
|
3
|
|
|
|
|
226
|
|
|
3
|
|
|
|
|
36
|
|
657
|
3
|
|
|
3
|
|
17
|
no warnings 'redefine'; |
|
3
|
|
|
|
|
7
|
|
|
3
|
|
|
|
|
2047
|
|
658
|
3
|
|
|
3
|
|
47
|
eval $source; |
|
3
|
|
|
3
|
|
8
|
|
|
3
|
|
|
3
|
|
617
|
|
|
3
|
|
|
3
|
|
18
|
|
|
3
|
|
|
2
|
|
5
|
|
|
3
|
|
|
4
|
|
223
|
|
|
3
|
|
|
|
|
19
|
|
|
3
|
|
|
|
|
14
|
|
|
3
|
|
|
|
|
333
|
|
|
3
|
|
|
|
|
16
|
|
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
468
|
|
|
2
|
|
|
|
|
18
|
|
|
3
|
|
|
|
|
480
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
659
|
3
|
100
|
|
|
|
220
|
if($@) |
660
|
|
|
|
|
|
|
{ |
661
|
1
|
|
|
|
|
2
|
$exception = $@; |
662
|
1
|
|
|
|
|
10
|
my ($error,$file) = split /\(eval \d+\)/, $exception; |
663
|
1
|
|
|
|
|
5
|
my ($replace,$line) = split /\] line /, $file; |
664
|
1
|
50
|
|
|
|
7
|
$exception = qq|$error [$filename]| . ($line ? " line $line" : $replace); |
665
|
1
|
|
|
|
|
56
|
die $exception; |
666
|
|
|
|
|
|
|
} |
667
|
|
|
|
|
|
|
} |
668
|
|
|
|
|
|
|
|
669
|
|
|
|
|
|
|
# split source into packages but keep the keyword package in each piece; |
670
|
2
|
|
|
|
|
22
|
my @packages = map { "package $_" } split(/^package\s+/,$source); |
|
4
|
|
|
|
|
19
|
|
671
|
|
|
|
|
|
|
|
672
|
|
|
|
|
|
|
# process each package one at a time |
673
|
2
|
|
|
|
|
7
|
foreach my $package (@packages) |
674
|
|
|
|
|
|
|
{ |
675
|
4
|
100
|
|
|
|
20
|
next unless $package =~ m/^package\s+([^\s]+)\s*;/; |
676
|
2
|
|
|
|
|
5
|
my $tempclass = $1; |
677
|
2
|
|
|
|
|
5
|
my $class = $tempclass; |
678
|
|
|
|
|
|
|
|
679
|
2
|
|
|
|
|
297
|
$class =~ s/POOF::TEMPORARYNAMESPACE//g; |
680
|
|
|
|
|
|
|
|
681
|
|
|
|
|
|
|
# identify all properties and methods by steping through each line one at a time |
682
|
2
|
|
|
|
|
549
|
my @lines = split(/(?:\x0A|\x0D\x0A)/o,$package); |
683
|
2
|
|
|
|
|
14
|
foreach (@lines) |
684
|
|
|
|
|
|
|
{ |
685
|
191
|
|
|
|
|
352
|
s/#.*$//; |
686
|
191
|
100
|
|
|
|
445
|
if(/\bsub\b\s*([^\s\{\(\:]+)\s*:\s*([^\{]+)\s*(\{|$)?/o) |
687
|
|
|
|
|
|
|
{ |
688
|
|
|
|
|
|
|
|
689
|
9
|
|
|
|
|
19
|
chomp(); |
690
|
9
|
50
|
|
|
|
40
|
my ($sub,$end) = ($1,$3 ? $3 : ''); |
691
|
9
|
|
|
|
|
30
|
my %attrs = map { $_ => 1 } map { _trim($_) } split(/\s+/,$2); |
|
21
|
|
|
|
|
51
|
|
|
21
|
|
|
|
|
98
|
|
692
|
|
|
|
|
|
|
|
693
|
|
|
|
|
|
|
# classify into property or method |
694
|
9
|
100
|
|
|
|
38
|
if (exists $attrs{'Method'}) # process method |
|
|
50
|
|
|
|
|
|
695
|
|
|
|
|
|
|
{ |
696
|
|
|
|
|
|
|
# determine access |
697
|
3
|
|
|
|
|
11
|
my $access = _determineAccess(%attrs); |
698
|
|
|
|
|
|
|
# determine virtual |
699
|
3
|
|
|
|
|
9
|
my $virtual = _determineVirtual(%attrs); |
700
|
|
|
|
|
|
|
|
701
|
|
|
|
|
|
|
# creating block to squelch perl's complaining |
702
|
|
|
|
|
|
|
{ |
703
|
3
|
|
|
3
|
|
22
|
no strict 'refs'; |
|
3
|
|
|
|
|
69
|
|
|
3
|
|
|
|
|
105
|
|
|
3
|
|
|
|
|
98
|
|
704
|
3
|
|
|
3
|
|
20
|
no warnings 'redefine'; |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
440
|
|
705
|
3
|
|
|
|
|
4
|
+METHODS->{ $class }->{ $sub }->{'code'} = \&{$class . '::' . $sub}; |
|
3
|
|
|
|
|
38
|
|
706
|
|
|
|
|
|
|
} |
707
|
|
|
|
|
|
|
|
708
|
|
|
|
|
|
|
# handle access |
709
|
3
|
|
|
|
|
1573
|
+METHODS->{ $class }->{ $sub }->{'access'} = $access; |
710
|
|
|
|
|
|
|
|
711
|
|
|
|
|
|
|
# handle virtual |
712
|
3
|
|
|
|
|
15
|
+METHODS->{ $class }->{ $sub }->{'virtual'} = $virtual; |
713
|
|
|
|
|
|
|
|
714
|
|
|
|
|
|
|
## handle documentation |
715
|
|
|
|
|
|
|
#+METHODS->{ $class }->{ $sub }->{'doc'} = $doc; |
716
|
|
|
|
|
|
|
|
717
|
|
|
|
|
|
|
} |
718
|
|
|
|
|
|
|
elsif(exists $attrs{'Property'}) # process property |
719
|
|
|
|
|
|
|
{ |
720
|
|
|
|
|
|
|
|
721
|
|
|
|
|
|
|
# determine access |
722
|
6
|
|
|
|
|
27
|
my $access = _determineAccess(%attrs); |
723
|
|
|
|
|
|
|
# determine virtual |
724
|
6
|
|
|
|
|
18
|
my $virtual = _determineVirtual(%attrs); |
725
|
|
|
|
|
|
|
|
726
|
6
|
|
|
|
|
10
|
my $objdef; |
727
|
|
|
|
|
|
|
# creating block to squelch perl's complaining |
728
|
|
|
|
|
|
|
{ |
729
|
3
|
|
|
3
|
|
17
|
no strict 'refs'; |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
104
|
|
|
6
|
|
|
|
|
8
|
|
730
|
3
|
|
|
3
|
|
15
|
no warnings 'redefine'; |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
1309
|
|
731
|
|
|
|
|
|
|
|
732
|
6
|
|
|
|
|
170
|
$objdef = |
733
|
6
|
|
|
|
|
251
|
ref(&{$tempclass . '::' . $sub}) eq 'HASH' |
734
|
0
|
|
|
|
|
0
|
? &{$tempclass . '::' . $sub} |
735
|
6
|
50
|
|
|
|
13
|
: { &{$tempclass . '::' . $sub} }; |
736
|
|
|
|
|
|
|
} |
737
|
|
|
|
|
|
|
# this should return the hash that defines the property |
738
|
6
|
50
|
|
|
|
18
|
%{$objdef} || confess "Properties must be defined by returning a hash ref with their attributes"; |
|
6
|
|
|
|
|
20
|
|
739
|
|
|
|
|
|
|
|
740
|
6
|
50
|
|
|
|
21
|
unless (exists +PROPERTYINDEX->{ $class }->{ $sub }) |
741
|
|
|
|
|
|
|
{ |
742
|
6
|
|
|
|
|
13
|
push(@{ +PROPERTIES->{ $class } },{ 'name' => $sub }); |
|
6
|
|
|
|
|
73
|
|
743
|
6
|
|
|
|
|
10
|
+PROPERTYINDEX->{ $class }->{ $sub } = $#{ +PROPERTIES->{ $class } }; |
|
6
|
|
|
|
|
23
|
|
744
|
|
|
|
|
|
|
|
745
|
|
|
|
|
|
|
# handle groups |
746
|
6
|
100
|
66
|
|
|
40
|
if (exists $objdef->{'groups'} && ref($objdef->{'groups'}) eq 'ARRAY') |
747
|
|
|
|
|
|
|
{ |
748
|
3
|
|
|
|
|
2
|
foreach my $group (@{$objdef->{'groups'}}) |
|
3
|
|
|
|
|
9
|
|
749
|
|
|
|
|
|
|
{ |
750
|
|
|
|
|
|
|
#confess "Invalid group name ($group} used in property $sub" |
751
|
|
|
|
|
|
|
# unless ValidGroupName($group); |
752
|
|
|
|
|
|
|
} |
753
|
|
|
|
|
|
|
} |
754
|
|
|
|
|
|
|
|
755
|
6
|
|
|
|
|
11
|
+PROPERTIES->{ $class }->[ +PROPERTYINDEX->{ $class }->{ $sub } ]->{ 'data' } = { %{$objdef},access => $access, virtual => $virtual }; |
|
6
|
|
|
|
|
63
|
|
756
|
|
|
|
|
|
|
} |
757
|
|
|
|
|
|
|
} |
758
|
|
|
|
|
|
|
else |
759
|
|
|
|
|
|
|
{ |
760
|
|
|
|
|
|
|
# just skip, they might be using a non POOF function attribute or a Doc attribute |
761
|
0
|
|
|
|
|
0
|
next; |
762
|
|
|
|
|
|
|
} |
763
|
|
|
|
|
|
|
} |
764
|
|
|
|
|
|
|
|
765
|
|
|
|
|
|
|
} |
766
|
|
|
|
|
|
|
|
767
|
|
|
|
|
|
|
{ |
768
|
3
|
|
|
3
|
|
17
|
no strict 'refs'; |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
90
|
|
|
2
|
|
|
|
|
5
|
|
769
|
3
|
|
|
3
|
|
14
|
no warnings 'redefine'; |
|
3
|
|
|
|
|
11
|
|
|
3
|
|
|
|
|
2304
|
|
770
|
2
|
|
|
|
|
141
|
my $table = eval '\\%' . $class . '::'; |
771
|
2
|
|
|
|
|
6
|
foreach my $item (keys %{$table}) |
|
2
|
|
|
|
|
10
|
|
772
|
|
|
|
|
|
|
{ |
773
|
20
|
100
|
100
|
|
|
172
|
if (exists +PROPERTYINDEX->{ $class }->{ $item } || exists +METHODS->{ $class }->{ $item }) |
774
|
|
|
|
|
|
|
{ |
775
|
5
|
|
|
|
|
9
|
*{ $table->{$item} } = undef; |
|
5
|
|
|
|
|
506
|
|
776
|
|
|
|
|
|
|
} |
777
|
|
|
|
|
|
|
} |
778
|
|
|
|
|
|
|
} |
779
|
|
|
|
|
|
|
} |
780
|
|
|
|
|
|
|
} |
781
|
|
|
|
|
|
|
|
782
|
|
|
|
|
|
|
sub _determineAccess |
783
|
|
|
|
|
|
|
{ |
784
|
9
|
|
|
11
|
|
20
|
my %attrs = @_; |
785
|
|
|
|
|
|
|
# go from most secure to least secure |
786
|
|
|
|
|
|
|
return |
787
|
9
|
50
|
|
|
|
51
|
exists $attrs{'Private'} |
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
788
|
|
|
|
|
|
|
? 'Private' |
789
|
|
|
|
|
|
|
: exists $attrs{'Protected'} |
790
|
|
|
|
|
|
|
? 'Protected' |
791
|
|
|
|
|
|
|
: exists $attrs{'Public'} |
792
|
|
|
|
|
|
|
? 'Public' |
793
|
|
|
|
|
|
|
: 'Protected'; # will default to procted if nothing has been specified |
794
|
|
|
|
|
|
|
} |
795
|
|
|
|
|
|
|
|
796
|
|
|
|
|
|
|
sub _determineVirtual |
797
|
|
|
|
|
|
|
{ |
798
|
9
|
|
|
11
|
|
20
|
my %attrs = @_; |
799
|
|
|
|
|
|
|
# we make a distinction between properties and methods as they have different defaults |
800
|
|
|
|
|
|
|
return |
801
|
9
|
50
|
|
|
|
47
|
exists $attrs{'Property'} |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
802
|
|
|
|
|
|
|
? exists $attrs{'Virtual'} |
803
|
|
|
|
|
|
|
? 1 |
804
|
|
|
|
|
|
|
: exists $attrs{'NonVirtual'} |
805
|
|
|
|
|
|
|
? 0 |
806
|
|
|
|
|
|
|
: 0 # Properties default to Virtual |
807
|
|
|
|
|
|
|
: exists $attrs{'Method'} |
808
|
|
|
|
|
|
|
? exists $attrs{'Virtual'} |
809
|
|
|
|
|
|
|
? 1 |
810
|
|
|
|
|
|
|
: 0 # Methods default to NonVirtual |
811
|
|
|
|
|
|
|
: 0; |
812
|
|
|
|
|
|
|
} |
813
|
|
|
|
|
|
|
|
814
|
|
|
|
|
|
|
sub _trim |
815
|
|
|
|
|
|
|
{ |
816
|
21
|
|
|
21
|
|
26
|
my ($dat) = @_; |
817
|
21
|
|
|
|
|
71
|
$dat =~ s/^\s*//go; |
818
|
21
|
|
|
|
|
97
|
$dat =~ s/\s*$//go; |
819
|
21
|
|
|
|
|
49
|
return $dat; |
820
|
|
|
|
|
|
|
} |
821
|
|
|
|
|
|
|
|
822
|
|
|
|
|
|
|
sub log2file |
823
|
|
|
|
|
|
|
{ |
824
|
0
|
0
|
|
2
|
0
|
|
open(FH,">>/tmp/debug_log") || die "Could not open debug_log to write\n($!)\n"; |
825
|
0
|
|
|
|
|
|
print FH join(' ', @_) . "\n"; |
826
|
0
|
|
|
|
|
|
close(FH) |
827
|
|
|
|
|
|
|
} |
828
|
|
|
|
|
|
|
|
829
|
|
|
|
|
|
|
|
830
|
|
|
|
|
|
|
|
831
|
|
|
|
|
|
|
|
832
|
|
|
|
|
|
|
1; |
833
|
|
|
|
|
|
|
__END__ |