That highly depends on what you mean by "a package with the name $name".
Although Perl has the keyword package, it doesn't have a first or even second class object which is a "package".
I see. This makes it more tricky.
Right now, Class::MixinFactory works as follows: The creation function
gets an array of names, say qw(Abc Xyz), and assumes that files Abc.pm Xyz.pm.
Conceptionally, each of these modules is supposed to define a so-called mixin (which is
done by defining the functions in those modules within packages Abc and Xyz, respectively).
These "mixins" are not real classes (they don't have any constructor
are nevere "blessed"); MixinFactory now makes out of these mixin-classes
a new class (with a class/package name created at runtime), and this new class combines
all the functions of the individual classes (plus a few more added by MixinFactory).
Everything works fine if it is really setup that way, but consider the case if, due
to an error, MixinFactory gets the list
qw(Abc Uvw)
or
qw(Abc xYz)
instead of
qw(Abc Xyz)
This can happen, because the names inside the qw() list actually come from
an outside source (I know that this is a security hole, but let's aside this
issue for the moment). The first case would still be harmless: MixinFactory
would find that a file with the name Uvw.pm does not exist, and throw an
exception, which we catch.
The second case would be harmless on Unix, for the same reason: MixinFactory
would find that a file with the name xYz.pm does not exist, and again throw
an exception.
The second case causes trouble, however, when you are on Windows. In Windows
you can open successfully the file "xYz.pm",
despite the "real" name of the file is "Xyz.pm", because
Windows is not case sensitive. However, when MixinFactory tries to create
the mixin class, it wants to make a mixin out of Abc and xYz, but the functions
are defined in package Xyz, and it terminates the program.
Since we have control over the mixin modules, we can ensure that a module
Xyz.pm indeed contains a package of the right spelling, Xyz, so it would be
sufficient to protect agains a missspelling in upper/lower case on Windows.
But I think this is not easy either, isn't it?
Ronald
--
Ronald Fischer <ynnor@mm.st>
| [reply] [d/l] [select] |
Considering that one can have a file Abc.pm
sub Abc::foo { ... }
sub Abc::bar { ... }
without any package statement, or even:
BEGIN {
my $package = ... Complicated expression ...;
eval <<"EOT"
package ${package};
sub foo { ... }
sub bar { ... }
EOT
}
I think you can forget about catching all possible cases.
Considering that the majority of the people will write package Abc; near the top of the file, and all you seem to want is earlier program termination, why not perform a check that will catch the majority of the error, and let the few cases where 1) the author doesn't use "package Abc", and 2) the author miscapitalizes the package name, and 3) the author uses a case insensitive file system die sometime later (due to missing subroutines)? | [reply] [d/l] [select] |
I think you can forget about catching all possible cases.
Considering that the majority of the people will write package Abc; near the top of the file, and all you seem to want is earlier program termination,...
Actually, I don't want to terminate earlier; I want to throw an exception (which will
be handled by our central exception handler) and continue with the next task (which
hopefully will go well); the problem with the MixinFactory was that it did not terminate
with an exception, but terminate ungracefully.
But this is a minor issue. Basically, I agree with you; and especially since we have control
about how the "good" files look like, I will follow your advice and, instead of respecting
all pathological cases, require that a good mixin module has to have a package declaration
of a certain form near the top of the file; and I will reject everything modules which
don't match this pattern.
--
Ronald Fischer <ynnor@mm.st>
| [reply] |
It seems your problem is that Windows is not case sensitive when opening files. But its file systems are case preserving so you can overcome this by testing that the case of the file that was loaded is the same as the case of the mixin name. Testing the file name would address the root cause of the problem and avoid dependence on the internals of the mixins.
Retreiving the case of the file isn't elegant, but it is easy enough - just read the directory to find the file name.
But a quick review of the MixinFactory::Factory->class() method, combined with your control over the mixin modules to ensure they have package statements with package names corresponding to their file names suggests that either of your proposed tests should be adequate.
| [reply] |