The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
Changes 127
MANIFEST 12
MANIFEST.SKIP 13
META.yml 85
Makefile.PL 106
README 2373
inc/Module/AutoInstall.pm 13
inc/Module/Install/AutoInstall.pm 223
inc/Module/Install/Base.pm 38
inc/Module/Install/Can.pm 11
inc/Module/Install/Fetch.pm 11
inc/Module/Install/Include.pm 11
inc/Module/Install/Makefile.pm 32134
inc/Module/Install/Metadata.pm 82149
inc/Module/Install/Win32.pm 11
inc/Module/Install/WriteAll.pm 25
inc/Module/Install.pm 79104
lib/Class/Accessor/Grouped.pm 119300
t/accessors.t 6461
t/accessors_ro.t 5661
t/accessors_wo.t 4757
t/accessors_xs.t 829
t/basic.t 11
t/component.t 1010
t/inherited.t 65
t/lib/AccessorGroups.pm 321
t/lib/AccessorGroupsComp.pm 012
t/lib/AccessorGroupsRO.pm 54
t/lib/AccessorGroupsSubclass.pm 06
t/lib/AccessorGroupsWO.pm 54
t/manifest.t 11
t/pod_coverage.t 11
t/pod_spelling.t 370
t/pod_syntax.t 11
t/strict.t 11
t/style_no_tabs.t 11
t/warnings.t 11
37 files changed (This is a version diff) 6161123
@@ -1,5 +1,31 @@
 Revision history for Class::Accessor::Grouped.
 
+
+0.09008 Sun Oct 11 07:41:56 2010
+    - Put back a private undocumented method that the DBIC-CDBI compat
+      layer relies on :(
+    - Fix corner case segfaults with C::XSA and old 5.8 perls
+
+0.09007 Sat Oct  9 10:22:56 2010 (DELETED)
+    - Fix corner case when get/set_simple overrides are circumvented
+      iff Class::XSAccessor is present
+
+0.09006 Fri Sep 10 23:55:00 2010
+    - Fix bugs in ro/wo accessor generation when XSAccessor is
+      being used
+    - Better Class::XSAccessor usage control - introducing
+      $ENV{CAG_USE_XS} and $Class::Accessor::Grouped::USE_XS
+
+0.09005 Wed Sep  1 04:00:00 2010
+    - Again, remove Class::XSAccessor for Win32 sine it still breaks
+
+0.09004 Wed Aug 11 04:23:15 2010
+    - Changed the way Class::XSAccessor is invoked if available
+      (recommended by C::XSA author)
+    - Modified internal cache names to avoid real accessor clashes
+    - Some micro-optimizations for get_inherited
+    - Fixed field names with a single quote in them (patch from Jason Plum)
+
 0.09003 Fri Apr 23 23:00:19 2010
     - use Class::XSAccessor if available for 'simple' accessors, except on
       MSWin32, with documentation
@@ -33,7 +59,7 @@ Revision history for Class::Accessor::Grouped.
     - Tweak code for pure speed while fixing performance issue when assigning @_
     under Perl 5.10.0
 
-0.07000 
+0.07000
     - Altered get_inherited to return undef rather than () when no value
         set for Class::Data::(Inheritable|Accessor) compatiblity
     - Fixed spelling test error
@@ -24,7 +24,9 @@ t/basic.t
 t/component.t
 t/inherited.t
 t/lib/AccessorGroups.pm
+t/lib/AccessorGroupsComp.pm
 t/lib/AccessorGroupsRO.pm
+t/lib/AccessorGroupsSubclass.pm
 t/lib/AccessorGroupsWO.pm
 t/lib/BaseInheritedGroups.pm
 t/lib/ExtraInheritedGroups.pm
@@ -33,7 +35,6 @@ t/lib/NotReallyAClass.pm
 t/lib/SuperInheritedGroups.pm
 t/manifest.t
 t/pod_coverage.t
-t/pod_spelling.t
 t/pod_syntax.t
 t/strict.t
 t/style_no_tabs.t
@@ -37,4 +37,6 @@ Build.bat
 \b\.#
 
 # Avoid author test files.
-\bpod-spelling.t$
+\bpod_spelling.t$
+
+^benchmark
@@ -4,11 +4,12 @@ author:
   - 'Matt S. Trout <mst@shadowcatsystems.co.uk>'
 build_requires:
   ExtUtils::MakeMaker: 6.42
-  Sub::Identify: 0
+  Test::Exception: 0
+  Test::More: 0.94
 configure_requires:
   ExtUtils::MakeMaker: 6.42
 distribution_type: module
-generated_by: 'Module::Install version 0.94'
+generated_by: 'Module::Install version 1.00'
 license: perl
 meta-spec:
   url: http://module-build.sourceforge.net/META-spec-v1.4.html
@@ -18,10 +19,6 @@ no_index:
   directory:
     - inc
     - t
-provides:
-  Class::Accessor::Grouped:
-    file: lib/Class/Accessor/Grouped.pm
-    version: 0.09003
 requires:
   Carp: 0
   Class::Inspector: 0
@@ -31,5 +28,5 @@ requires:
   perl: 5.6.1
 resources:
   license: http://dev.perl.org/licenses/
-  repository: http://dev.catalyst.perl.org/repos/bast/trunk/Class-Accessor-Grouped/
-version: 0.09003
+  repository: http://dev.catalyst.perl.org/repos/bast/Class-Accessor-Grouped/trunk
+version: 0.09008
@@ -1,7 +1,7 @@
-# $Id: Makefile.PL 7804 2009-10-20 23:19:14Z caelum $
+# $Id: /mirror/Class-Accessor-Grouped/trunk/Makefile.PL 9763 2010-10-08T16:59:29.986835Z rabbit  $
 use strict;
 use warnings;
-use inc::Module::Install 0.91;
+use inc::Module::Install 1;
 
 name 'Class-Accessor-Grouped';
 license 'perl';
@@ -14,23 +14,19 @@ requires 'MRO::Compat';
 requires 'Class::Inspector';
 requires 'Sub::Name' => '0.04';
 
-# removed due to segfaults, see _hasXS()
-#requires 'Class::XSAccessor';
-
-test_requires 'Sub::Identify';
+test_requires 'Test::More' => '0.94';
+test_requires 'Test::Exception';
 
 clean_files "Class-Accessor-Grouped-* t/var";
 
 if (-e 'MANIFEST.SKIP') {
     system('pod2text lib/Class/Accessor/Grouped.pm > README');
+    realclean_files 'README';
 }
 
-realclean_files 'README';
-
-auto_provides;
 auto_install;
 
 resources repository =>
-'http://dev.catalyst.perl.org/repos/bast/trunk/Class-Accessor-Grouped/';
+'http://dev.catalyst.perl.org/repos/bast/Class-Accessor-Grouped/trunk';
 
 WriteAll;
@@ -42,25 +42,28 @@ METHODS
     value rather than getting the value.
 
   make_group_accessor
-    Arguments: $group, $field
-        Returns: $sub (\CODE)
+    Arguments: $group, $field, $method
+        Returns: \&accessor_coderef ?
 
-    Returns a single accessor in a given group; called by mk_group_accessors
-    for each entry in @fieldspec.
+    Called by mk_group_accessors for each entry in @fieldspec. Either
+    returns a coderef which will be installed at "&__PACKAGE__::$method", or
+    returns "undef" if it elects to install the coderef on its own.
 
   make_group_ro_accessor
-    Arguments: $group, $field
-        Returns: $sub (\CODE)
+    Arguments: $group, $field, $method
+        Returns: \&accessor_coderef ?
 
-    Returns a single read-only accessor in a given group; called by
-    mk_group_ro_accessors for each entry in @fieldspec.
+    Called by mk_group_ro_accessors for each entry in @fieldspec. Either
+    returns a coderef which will be installed at "&__PACKAGE__::$method", or
+    returns "undef" if it elects to install the coderef on its own.
 
   make_group_wo_accessor
-    Arguments: $group, $field
-        Returns: $sub (\CODE)
+    Arguments: $group, $field, $method
+        Returns: \&accessor_coderef ?
 
-    Returns a single write-only accessor in a given group; called by
-    mk_group_wo_accessors for each entry in @fieldspec.
+    Called by mk_group_wo_accessors for each entry in @fieldspec. Either
+    returns a coderef which will be installed at "&__PACKAGE__::$method", or
+    returns "undef" if it elects to install the coderef on its own.
 
   get_simple
     Arguments: $field
@@ -128,21 +131,68 @@ METHODS
     Returns a list of 'parent' or 'super' class names that the current class
     inherited from.
 
-Performance
-    You can speed up accessors of type 'simple' by installing
-    Class::XSAccessor. Note however that the use of this module is disabled
-    by default on Win32 systems, as it causes yet unresolved segfaults. If
-    you are a Win32 user, and want to try this module with
-    Class::XSAccessor, set $Class::Accessor::Grouped::hasXS to a true value
-    before registering your accessors (e.g. in a "BEGIN" block)
+PERFORMANCE
+    To provide total flexibility Class::Accessor::Grouped calls methods
+    internally while performing get/set actions, which makes it noticeably
+    slower than similar modules. To compensate, this module will
+    automatically use the insanely fast Class::XSAccessor to generate the
+    "simple"-group accessors, if Class::XSAccessor >= 1.06 is available on
+    your system.
+
+  Benchmark
+    This is the result of a set/get/set loop benchmark on perl 5.12.1 with
+    thread support, showcasing most popular accessor builders: Moose, Mouse,
+    CAF, CAF_XS and XSA:
+
+                Rate     CAG   moOse     CAF HANDMADE  CAF_XS moUse_XS CAG_XS     XSA
+     CAG      1777/s      --    -27%    -29%     -36%    -62%     -67%   -72%    -73%
+     moOse    2421/s     36%      --     -4%     -13%    -48%     -55%   -61%    -63%
+     CAF      2511/s     41%      4%      --     -10%    -47%     -53%   -60%    -61%
+     HANDMADE 2791/s     57%     15%     11%       --    -41%     -48%   -56%    -57%
+     CAF_XS   4699/s    164%     94%     87%      68%      --     -13%   -25%    -28%
+     moUse_XS 5375/s    203%    122%    114%      93%     14%       --   -14%    -18%
+     CAG_XS   6279/s    253%    159%    150%     125%     34%      17%     --     -4%
+     XSA      6515/s    267%    169%    159%     133%     39%      21%     4%      --
+
+    Benchmark program is available in the root of the repository
+    <http://search.cpan.org/dist/Class-Accessor-Grouped/>:
+
+  Notes on Class::XSAccessor
+    You can force (or disable) the use of Class::XSAccessor before creating
+    a particular "simple" accessor by either manipulating the global
+    variable $Class::Accessor::Grouped::USE_XS to true or false (preferably
+    with localization, or you can do so before runtime via the "CAG_USE_XS"
+    environment variable.
+
+    Since Class::XSAccessor has no knowledge of "get_simple" and
+    "set_simple" this module does its best to detect if you are overriding
+    one of these methods and will fall back to using the perl version of the
+    accessor in order to maintain consistency. However be aware that if you
+    enable use of "Class::XSAccessor" (automatically or explicitly), create
+    an object, invoke a simple accessor on that object, and then manipulate
+    the symbol table to install a "get/set_simple" override - you get to
+    keep all the pieces.
+
+    While Class::XSAccessor works surprisingly well for the amount of black
+    magic it tries to pull off, it's still black magic. At present (Sep
+    2010) the module is known to have problems on Windows under heavy
+    thread-stress (e.g. Win32+Apache+mod_perl). Thus for the time being
+    Class::XSAccessor will not be used automatically if you are running
+    under "MSWin32".
 
 AUTHORS
-    Matt S. Trout <mst@shadowcatsystems.co.uk> Christopher H. Laco
-    <claco@chrislaco.com>
+    Matt S. Trout <mst@shadowcatsystems.co.uk>
 
-    With contributions from:
+    Christopher H. Laco <claco@chrislaco.com>
 
-    Guillermo Roditi <groditi@cpan.org>
+CONTRIBUTORS
+    Caelum: Rafael Kitover <rkitover@cpan.org>
+
+    groditi: Guillermo Roditi <groditi@cpan.org>
+
+    Jason Plum <jason.plum@bmmsi.com>
+
+    ribasushi: Peter Rabbitson <ribasushi@cpan.org>
 
 COPYRIGHT & LICENSE
     Copyright (c) 2006-2010 Matt S. Trout <mst@shadowcatsystems.co.uk>
@@ -253,6 +253,8 @@ sub import {
     # import to main::
     no strict 'refs';
     *{'main::WriteMakefile'} = \&Write if caller(0) eq 'main';
+
+    return (@Existing, @Missing);
 }
 
 sub _running_under {
@@ -815,4 +817,4 @@ END_MAKE
 
 __END__
 
-#line 1069
+#line 1071
@@ -6,7 +6,7 @@ use Module::Install::Base ();
 
 use vars qw{$VERSION @ISA $ISCORE};
 BEGIN {
-	$VERSION = '0.94';
+	$VERSION = '1.00';
 	@ISA     = 'Module::Install::Base';
 	$ISCORE  = 1;
 }
@@ -37,12 +37,33 @@ sub auto_install {
     $self->include('Module::AutoInstall');
     require Module::AutoInstall;
 
-    Module::AutoInstall->import(
+    my @features_require = Module::AutoInstall->import(
         (@config ? (-config => \@config) : ()),
         (@core   ? (-core   => \@core)   : ()),
         $self->features,
     );
 
+    my %seen;
+    my @requires = map @$_, map @$_, grep ref, $self->requires;
+    while (my ($mod, $ver) = splice(@requires, 0, 2)) {
+        $seen{$mod}{$ver}++;
+    }
+    my @build_requires = map @$_, map @$_, grep ref, $self->build_requires;
+    while (my ($mod, $ver) = splice(@build_requires, 0, 2)) {
+        $seen{$mod}{$ver}++;
+    }
+    my @configure_requires = map @$_, map @$_, grep ref, $self->configure_requires;
+    while (my ($mod, $ver) = splice(@configure_requires, 0, 2)) {
+        $seen{$mod}{$ver}++;
+    }
+
+    my @deduped;
+    while (my ($mod, $ver) = splice(@features_require, 0, 2)) {
+        push @deduped, $mod => $ver unless $seen{$mod}{$ver}++;
+    }
+
+    $self->requires(@deduped);
+
     $self->makemaker_args( Module::AutoInstall::_make_args() );
 
     my $class = ref($self);
@@ -4,7 +4,7 @@ package Module::Install::Base;
 use strict 'vars';
 use vars qw{$VERSION};
 BEGIN {
-	$VERSION = '0.94';
+	$VERSION = '1.00';
 }
 
 # Suspend handler for "redefined" warnings
@@ -51,13 +51,18 @@ sub admin {
 #line 106
 
 sub is_admin {
-	$_[0]->admin->VERSION;
+	! $_[0]->admin->isa('Module::Install::Base::FakeAdmin');
 }
 
 sub DESTROY {}
 
 package Module::Install::Base::FakeAdmin;
 
+use vars qw{$VERSION};
+BEGIN {
+	$VERSION = $Module::Install::Base::VERSION;
+}
+
 my $fake;
 
 sub new {
@@ -75,4 +80,4 @@ BEGIN {
 
 1;
 
-#line 154
+#line 159
@@ -9,7 +9,7 @@ use Module::Install::Base ();
 
 use vars qw{$VERSION @ISA $ISCORE};
 BEGIN {
-	$VERSION = '0.94';
+	$VERSION = '1.00';
 	@ISA     = 'Module::Install::Base';
 	$ISCORE  = 1;
 }
@@ -6,7 +6,7 @@ use Module::Install::Base ();
 
 use vars qw{$VERSION @ISA $ISCORE};
 BEGIN {
-	$VERSION = '0.94';
+	$VERSION = '1.00';
 	@ISA     = 'Module::Install::Base';
 	$ISCORE  = 1;
 }
@@ -6,7 +6,7 @@ use Module::Install::Base ();
 
 use vars qw{$VERSION @ISA $ISCORE};
 BEGIN {
-	$VERSION = '0.94';
+	$VERSION = '1.00';
 	@ISA     = 'Module::Install::Base';
 	$ISCORE  = 1;
 }
@@ -4,10 +4,11 @@ package Module::Install::Makefile;
 use strict 'vars';
 use ExtUtils::MakeMaker   ();
 use Module::Install::Base ();
+use Fcntl qw/:flock :seek/;
 
 use vars qw{$VERSION @ISA $ISCORE};
 BEGIN {
-	$VERSION = '0.94';
+	$VERSION = '1.00';
 	@ISA     = 'Module::Install::Base';
 	$ISCORE  = 1;
 }
@@ -25,8 +26,8 @@ sub prompt {
 		die "Caught an potential prompt infinite loop ($c[1]|$c[2]|$_[0])";
 	}
 
-	# In automated testing, always use defaults
-	if ( $ENV{AUTOMATED_TESTING} and ! $ENV{PERL_MM_USE_DEFAULT} ) {
+	# In automated testing or non-interactive session, always use defaults
+	if ( ($ENV{AUTOMATED_TESTING} or -! -t STDIN) and ! $ENV{PERL_MM_USE_DEFAULT} ) {
 		local $ENV{PERL_MM_USE_DEFAULT} = 1;
 		goto &ExtUtils::MakeMaker::prompt;
 	} else {
@@ -45,10 +46,90 @@ sub makemaker {
 	( @_ < 2 or $makemaker >= eval($_[1]) ) ? $makemaker : 0
 }
 
+# Ripped from ExtUtils::MakeMaker 6.56, and slightly modified
+# as we only need to know here whether the attribute is an array
+# or a hash or something else (which may or may not be appendable).
+my %makemaker_argtype = (
+ C                  => 'ARRAY',
+ CONFIG             => 'ARRAY',
+# CONFIGURE          => 'CODE', # ignore
+ DIR                => 'ARRAY',
+ DL_FUNCS           => 'HASH',
+ DL_VARS            => 'ARRAY',
+ EXCLUDE_EXT        => 'ARRAY',
+ EXE_FILES          => 'ARRAY',
+ FUNCLIST           => 'ARRAY',
+ H                  => 'ARRAY',
+ IMPORTS            => 'HASH',
+ INCLUDE_EXT        => 'ARRAY',
+ LIBS               => 'ARRAY', # ignore ''
+ MAN1PODS           => 'HASH',
+ MAN3PODS           => 'HASH',
+ META_ADD           => 'HASH',
+ META_MERGE         => 'HASH',
+ PL_FILES           => 'HASH',
+ PM                 => 'HASH',
+ PMLIBDIRS          => 'ARRAY',
+ PMLIBPARENTDIRS    => 'ARRAY',
+ PREREQ_PM          => 'HASH',
+ CONFIGURE_REQUIRES => 'HASH',
+ SKIP               => 'ARRAY',
+ TYPEMAPS           => 'ARRAY',
+ XS                 => 'HASH',
+# VERSION            => ['version',''],  # ignore
+# _KEEP_AFTER_FLUSH  => '',
+
+ clean      => 'HASH',
+ depend     => 'HASH',
+ dist       => 'HASH',
+ dynamic_lib=> 'HASH',
+ linkext    => 'HASH',
+ macro      => 'HASH',
+ postamble  => 'HASH',
+ realclean  => 'HASH',
+ test       => 'HASH',
+ tool_autosplit => 'HASH',
+
+ # special cases where you can use makemaker_append
+ CCFLAGS   => 'APPENDABLE',
+ DEFINE    => 'APPENDABLE',
+ INC       => 'APPENDABLE',
+ LDDLFLAGS => 'APPENDABLE',
+ LDFROM    => 'APPENDABLE',
+);
+
 sub makemaker_args {
-	my $self = shift;
+	my ($self, %new_args) = @_;
 	my $args = ( $self->{makemaker_args} ||= {} );
-	%$args = ( %$args, @_ );
+	foreach my $key (keys %new_args) {
+		if ($makemaker_argtype{$key}) {
+			if ($makemaker_argtype{$key} eq 'ARRAY') {
+				$args->{$key} = [] unless defined $args->{$key};
+				unless (ref $args->{$key} eq 'ARRAY') {
+					$args->{$key} = [$args->{$key}]
+				}
+				push @{$args->{$key}},
+					ref $new_args{$key} eq 'ARRAY'
+						? @{$new_args{$key}}
+						: $new_args{$key};
+			}
+			elsif ($makemaker_argtype{$key} eq 'HASH') {
+				$args->{$key} = {} unless defined $args->{$key};
+				foreach my $skey (keys %{ $new_args{$key} }) {
+					$args->{$key}{$skey} = $new_args{$key}{$skey};
+				}
+			}
+			elsif ($makemaker_argtype{$key} eq 'APPENDABLE') {
+				$self->makemaker_append($key => $new_args{$key});
+			}
+		}
+		else {
+			if (defined $args->{$key}) {
+				warn qq{MakeMaker attribute "$key" is overriden; use "makemaker_append" to append values\n};
+			}
+			$args->{$key} = $new_args{$key};
+		}
+	}
 	return $args;
 }
 
@@ -58,8 +139,8 @@ sub makemaker_append {
 	my $self = shift;
 	my $name = shift;
 	my $args = $self->makemaker_args;
-	$args->{name} = defined $args->{$name}
-		? join( ' ', $args->{name}, @_ )
+	$args->{$name} = defined $args->{$name}
+		? join( ' ', $args->{$name}, @_ )
 		: join( ' ', @_ );
 }
 
@@ -100,28 +181,22 @@ sub inc {
 	$self->makemaker_args( INC => shift );
 }
 
-my %test_dir = ();
-
 sub _wanted_t {
-	/\.t$/ and -f $_ and $test_dir{$File::Find::dir} = 1;
 }
 
 sub tests_recursive {
 	my $self = shift;
-	if ( $self->tests ) {
-		die "tests_recursive will not work if tests are already defined";
-	}
 	my $dir = shift || 't';
 	unless ( -d $dir ) {
 		die "tests_recursive dir '$dir' does not exist";
 	}
-	%test_dir = ();
+	my %tests = map { $_ => 1 } split / /, ($self->tests || '');
 	require File::Find;
-	File::Find::find( \&_wanted_t, $dir );
-	if ( -d 'xt' and ($Module::Install::AUTHOR or $ENV{RELEASE_TESTING}) ) {
-		File::Find::find( \&_wanted_t, 'xt' );
-	}
-	$self->tests( join ' ', map { "$_/*.t" } sort keys %test_dir );
+	File::Find::find(
+        sub { /\.t$/ and -f $_ and $tests{"$File::Find::dir/*.t"} = 1 },
+        $dir
+    );
+	$self->tests( join ' ', sort keys %tests );
 }
 
 sub write {
@@ -158,13 +233,24 @@ sub write {
 	my $args = $self->makemaker_args;
 	$args->{DISTNAME} = $self->name;
 	$args->{NAME}     = $self->module_name || $self->name;
-	$args->{VERSION}  = $self->version;
 	$args->{NAME}     =~ s/-/::/g;
+	$args->{VERSION}  = $self->version or die <<'EOT';
+ERROR: Can't determine distribution version. Please specify it
+explicitly via 'version' in Makefile.PL, or set a valid $VERSION
+in a module, and provide its file path via 'version_from' (or
+'all_from' if you prefer) in Makefile.PL.
+EOT
+
 	$DB::single = 1;
 	if ( $self->tests ) {
+		my @tests = split ' ', $self->tests;
+		my %seen;
 		$args->{test} = {
-			TESTS => $self->tests,
+			TESTS => (join ' ', grep {!$seen{$_}++} @tests),
 		};
+    } elsif ( $Module::Install::ExtraTests::use_extratests ) {
+        # Module::Install::ExtraTests doesn't set $self->tests and does its own tests via harness.
+        # So, just ignore our xt tests here.
 	} elsif ( -d 'xt' and ($Module::Install::AUTHOR or $ENV{RELEASE_TESTING}) ) {
 		$args->{test} = {
 			TESTS => join( ' ', map { "$_/*.t" } grep { -d $_ } qw{ t xt } ),
@@ -172,7 +258,7 @@ sub write {
 	}
 	if ( $] >= 5.005 ) {
 		$args->{ABSTRACT} = $self->abstract;
-		$args->{AUTHOR}   = $self->author;
+		$args->{AUTHOR}   = join ', ', @{$self->author || []};
 	}
 	if ( $self->makemaker(6.10) ) {
 		$args->{NO_META}   = 1;
@@ -184,6 +270,9 @@ sub write {
 	unless ( $self->is_admin ) {
 		delete $args->{SIGN};
 	}
+	if ( $self->makemaker(6.31) and $self->license ) {
+		$args->{LICENSE} = $self->license;
+	}
 
 	my $prereq = ($args->{PREREQ_PM} ||= {});
 	%$prereq = ( %$prereq,
@@ -208,13 +297,22 @@ sub write {
 	# Remove any reference to perl, BUILD_REQUIRES doesn't support it
 	delete $args->{BUILD_REQUIRES}->{perl};
 
-	# Delete bundled dists from prereq_pm
-	my $subdirs = ($args->{DIR} ||= []);
+	# Delete bundled dists from prereq_pm, add it to Makefile DIR
+	my $subdirs = ($args->{DIR} || []);
 	if ($self->bundles) {
+		my %processed;
 		foreach my $bundle (@{ $self->bundles }) {
-			my ($file, $dir) = @$bundle;
-			push @$subdirs, $dir if -d $dir;
-			delete $build_prereq->{$file}; #Delete from build prereqs only
+			my ($mod_name, $dist_dir) = @$bundle;
+			delete $prereq->{$mod_name};
+			$dist_dir = File::Basename::basename($dist_dir); # dir for building this module
+			if (not exists $processed{$dist_dir}) {
+				if (-d $dist_dir) {
+					# List as sub-directory to be processed by make
+					push @$subdirs, $dist_dir;
+				}
+				# Else do nothing: the module is already present on the system
+				$processed{$dist_dir} = undef;
+			}
 		}
 	}
 
@@ -233,7 +331,10 @@ sub write {
 		}
 	}
 
-	$args->{INSTALLDIRS} = $self->installdirs;
+	if ($self->installdirs) {
+		warn qq{old INSTALLDIRS (probably set by makemaker_args) is overriden by installdirs\n} if $args->{INSTALLDIRS};
+		$args->{INSTALLDIRS} = $self->installdirs;
+	}
 
 	my %args = map {
 		( $_ => $args->{$_} ) } grep {defined($args->{$_} )
@@ -264,9 +365,9 @@ sub fix_up_makefile {
 		. ($self->postamble || '');
 
 	local *MAKEFILE;
-	open MAKEFILE, "< $makefile_name" or die "fix_up_makefile: Couldn't open $makefile_name: $!";
+	open MAKEFILE, "+< $makefile_name" or die "fix_up_makefile: Couldn't open $makefile_name: $!";
+	eval { flock MAKEFILE, LOCK_EX };
 	my $makefile = do { local $/; <MAKEFILE> };
-	close MAKEFILE or die $!;
 
 	$makefile =~ s/\b(test_harness\(\$\(TEST_VERBOSE\), )/$1'inc', /;
 	$makefile =~ s/( -I\$\(INST_ARCHLIB\))/ -Iinc$1/g;
@@ -286,7 +387,8 @@ sub fix_up_makefile {
 	# XXX - This is currently unused; not sure if it breaks other MM-users
 	# $makefile =~ s/^pm_to_blib\s+:\s+/pm_to_blib :: /mg;
 
-	open  MAKEFILE, "> $makefile_name" or die "fix_up_makefile: Couldn't open $makefile_name: $!";
+	seek MAKEFILE, 0, SEEK_SET;
+	truncate MAKEFILE, 0;
 	print MAKEFILE  "$preamble$makefile$postamble" or die $!;
 	close MAKEFILE  or die $!;
 
@@ -310,4 +412,4 @@ sub postamble {
 
 __END__
 
-#line 439
+#line 541
@@ -6,7 +6,7 @@ use Module::Install::Base ();
 
 use vars qw{$VERSION @ISA $ISCORE};
 BEGIN {
-	$VERSION = '0.94';
+	$VERSION = '1.00';
 	@ISA     = 'Module::Install::Base';
 	$ISCORE  = 1;
 }
@@ -19,7 +19,6 @@ my @scalar_keys = qw{
 	name
 	module_name
 	abstract
-	author
 	version
 	distribution_type
 	tests
@@ -43,8 +42,11 @@ my @resource_keys = qw{
 
 my @array_keys = qw{
 	keywords
+	author
 };
 
+*authors = \&author;
+
 sub Meta              { shift          }
 sub Meta_BooleanKeys  { @boolean_keys  }
 sub Meta_ScalarKeys   { @scalar_keys   }
@@ -176,43 +178,6 @@ sub perl_version {
 	$self->{values}->{perl_version} = $version;
 }
 
-#Stolen from M::B
-my %license_urls = (
-    perl         => 'http://dev.perl.org/licenses/',
-    apache       => 'http://apache.org/licenses/LICENSE-2.0',
-    artistic     => 'http://opensource.org/licenses/artistic-license.php',
-    artistic_2   => 'http://opensource.org/licenses/artistic-license-2.0.php',
-    lgpl         => 'http://opensource.org/licenses/lgpl-license.php',
-    lgpl2        => 'http://opensource.org/licenses/lgpl-2.1.php',
-    lgpl3        => 'http://opensource.org/licenses/lgpl-3.0.html',
-    bsd          => 'http://opensource.org/licenses/bsd-license.php',
-    gpl          => 'http://opensource.org/licenses/gpl-license.php',
-    gpl2         => 'http://opensource.org/licenses/gpl-2.0.php',
-    gpl3         => 'http://opensource.org/licenses/gpl-3.0.html',
-    mit          => 'http://opensource.org/licenses/mit-license.php',
-    mozilla      => 'http://opensource.org/licenses/mozilla1.1.php',
-    open_source  => undef,
-    unrestricted => undef,
-    restrictive  => undef,
-    unknown      => undef,
-);
-
-sub license {
-	my $self = shift;
-	return $self->{values}->{license} unless @_;
-	my $license = shift or die(
-		'Did not provide a value to license()'
-	);
-	$self->{values}->{license} = $license;
-
-	# Automatically fill in license URLs
-	if ( $license_urls{$license} ) {
-		$self->resources( license => $license_urls{$license} );
-	}
-
-	return 1;
-}
-
 sub all_from {
 	my ( $self, $file ) = @_;
 
@@ -242,7 +207,7 @@ sub all_from {
 	$self->name_from($file)         unless $self->name;
 	$self->version_from($file)      unless $self->version;
 	$self->perl_version_from($file) unless $self->perl_version;
-	$self->author_from($pod)        unless $self->author;
+	$self->author_from($pod)        unless @{$self->author || []};
 	$self->license_from($pod)       unless $self->license;
 	$self->abstract_from($pod)      unless $self->abstract;
 
@@ -352,6 +317,9 @@ sub version_from {
 	require ExtUtils::MM_Unix;
 	my ( $self, $file ) = @_;
 	$self->version( ExtUtils::MM_Unix->parse_version($file) );
+
+	# for version integrity check
+	$self->makemaker_args( VERSION_FROM => $file );
 }
 
 sub abstract_from {
@@ -362,7 +330,7 @@ sub abstract_from {
 			{ DISTNAME => $self->name },
 			'ExtUtils::MM_Unix'
 		)->parse_abstract($file)
-	 );
+	);
 }
 
 # Add both distribution and module name
@@ -428,54 +396,146 @@ sub author_from {
 		([^\n]*)
 	/ixms) {
 		my $author = $1 || $2;
-		$author =~ s{E<lt>}{<}g;
-		$author =~ s{E<gt>}{>}g;
+
+		# XXX: ugly but should work anyway...
+		if (eval "require Pod::Escapes; 1") {
+			# Pod::Escapes has a mapping table.
+			# It's in core of perl >= 5.9.3, and should be installed
+			# as one of the Pod::Simple's prereqs, which is a prereq
+			# of Pod::Text 3.x (see also below).
+			$author =~ s{ E<( (\d+) | ([A-Za-z]+) )> }
+			{
+				defined $2
+				? chr($2)
+				: defined $Pod::Escapes::Name2character_number{$1}
+				? chr($Pod::Escapes::Name2character_number{$1})
+				: do {
+					warn "Unknown escape: E<$1>";
+					"E<$1>";
+				};
+			}gex;
+		}
+		elsif (eval "require Pod::Text; 1" && $Pod::Text::VERSION < 3) {
+			# Pod::Text < 3.0 has yet another mapping table,
+			# though the table name of 2.x and 1.x are different.
+			# (1.x is in core of Perl < 5.6, 2.x is in core of
+			# Perl < 5.9.3)
+			my $mapping = ($Pod::Text::VERSION < 2)
+				? \%Pod::Text::HTML_Escapes
+				: \%Pod::Text::ESCAPES;
+			$author =~ s{ E<( (\d+) | ([A-Za-z]+) )> }
+			{
+				defined $2
+				? chr($2)
+				: defined $mapping->{$1}
+				? $mapping->{$1}
+				: do {
+					warn "Unknown escape: E<$1>";
+					"E<$1>";
+				};
+			}gex;
+		}
+		else {
+			$author =~ s{E<lt>}{<}g;
+			$author =~ s{E<gt>}{>}g;
+		}
 		$self->author($author);
 	} else {
 		warn "Cannot determine author info from $_[0]\n";
 	}
 }
 
+#Stolen from M::B
+my %license_urls = (
+    perl         => 'http://dev.perl.org/licenses/',
+    apache       => 'http://apache.org/licenses/LICENSE-2.0',
+    apache_1_1   => 'http://apache.org/licenses/LICENSE-1.1',
+    artistic     => 'http://opensource.org/licenses/artistic-license.php',
+    artistic_2   => 'http://opensource.org/licenses/artistic-license-2.0.php',
+    lgpl         => 'http://opensource.org/licenses/lgpl-license.php',
+    lgpl2        => 'http://opensource.org/licenses/lgpl-2.1.php',
+    lgpl3        => 'http://opensource.org/licenses/lgpl-3.0.html',
+    bsd          => 'http://opensource.org/licenses/bsd-license.php',
+    gpl          => 'http://opensource.org/licenses/gpl-license.php',
+    gpl2         => 'http://opensource.org/licenses/gpl-2.0.php',
+    gpl3         => 'http://opensource.org/licenses/gpl-3.0.html',
+    mit          => 'http://opensource.org/licenses/mit-license.php',
+    mozilla      => 'http://opensource.org/licenses/mozilla1.1.php',
+    open_source  => undef,
+    unrestricted => undef,
+    restrictive  => undef,
+    unknown      => undef,
+);
+
+sub license {
+	my $self = shift;
+	return $self->{values}->{license} unless @_;
+	my $license = shift or die(
+		'Did not provide a value to license()'
+	);
+	$license = __extract_license($license) || lc $license;
+	$self->{values}->{license} = $license;
+
+	# Automatically fill in license URLs
+	if ( $license_urls{$license} ) {
+		$self->resources( license => $license_urls{$license} );
+	}
+
+	return 1;
+}
+
 sub _extract_license {
-	if (
-		$_[0] =~ m/
-		(
-			=head \d \s+
-			(?:licen[cs]e|licensing|copyrights?|legal)\b
-			.*?
-		)
-		(=head\\d.*|=cut.*|)
-		\z
-	/ixms ) {
-		my $license_text = $1;
-		my @phrases      = (
-			'under the same (?:terms|license) as (?:perl|the perl programming language)' => 'perl', 1,
-			'under the terms of (?:perl|the perl programming language) itself' => 'perl', 1,
-			'Artistic and GPL'                   => 'perl',        1,
-			'GNU general public license'         => 'gpl',         1,
-			'GNU public license'                 => 'gpl',         1,
-			'GNU lesser general public license'  => 'lgpl',        1,
-			'GNU lesser public license'          => 'lgpl',        1,
-			'GNU library general public license' => 'lgpl',        1,
-			'GNU library public license'         => 'lgpl',        1,
-			'BSD license'                        => 'bsd',         1,
-			'Artistic license'                   => 'artistic',    1,
-			'GPL'                                => 'gpl',         1,
-			'LGPL'                               => 'lgpl',        1,
-			'BSD'                                => 'bsd',         1,
-			'Artistic'                           => 'artistic',    1,
-			'MIT'                                => 'mit',         1,
-			'proprietary'                        => 'proprietary', 0,
-		);
-		while ( my ($pattern, $license, $osi) = splice(@phrases, 0, 3) ) {
-			$pattern =~ s#\s+#\\s+#gs;
-			if ( $license_text =~ /\b$pattern\b/i ) {
-			        return $license;
-			}
+	my $pod = shift;
+	my $matched;
+	return __extract_license(
+		($matched) = $pod =~ m/
+			(=head \d \s+ L(?i:ICEN[CS]E|ICENSING)\b.*?)
+			(=head \d.*|=cut.*|)\z
+		/xms
+	) || __extract_license(
+		($matched) = $pod =~ m/
+			(=head \d \s+ (?:C(?i:OPYRIGHTS?)|L(?i:EGAL))\b.*?)
+			(=head \d.*|=cut.*|)\z
+		/xms
+	);
+}
+
+sub __extract_license {
+	my $license_text = shift or return;
+	my @phrases      = (
+		'(?:under )?the same (?:terms|license) as (?:perl|the perl (?:\d )?programming language)' => 'perl', 1,
+		'(?:under )?the terms of (?:perl|the perl programming language) itself' => 'perl', 1,
+		'Artistic and GPL'                   => 'perl',         1,
+		'GNU general public license'         => 'gpl',          1,
+		'GNU public license'                 => 'gpl',          1,
+		'GNU lesser general public license'  => 'lgpl',         1,
+		'GNU lesser public license'          => 'lgpl',         1,
+		'GNU library general public license' => 'lgpl',         1,
+		'GNU library public license'         => 'lgpl',         1,
+		'GNU Free Documentation license'     => 'unrestricted', 1,
+		'GNU Affero General Public License'  => 'open_source',  1,
+		'(?:Free)?BSD license'               => 'bsd',          1,
+		'Artistic license'                   => 'artistic',     1,
+		'Apache (?:Software )?license'       => 'apache',       1,
+		'GPL'                                => 'gpl',          1,
+		'LGPL'                               => 'lgpl',         1,
+		'BSD'                                => 'bsd',          1,
+		'Artistic'                           => 'artistic',     1,
+		'MIT'                                => 'mit',          1,
+		'Mozilla Public License'             => 'mozilla',      1,
+		'Q Public License'                   => 'open_source',  1,
+		'OpenSSL License'                    => 'unrestricted', 1,
+		'SSLeay License'                     => 'unrestricted', 1,
+		'zlib License'                       => 'open_source',  1,
+		'proprietary'                        => 'proprietary',  0,
+	);
+	while ( my ($pattern, $license, $osi) = splice(@phrases, 0, 3) ) {
+		$pattern =~ s#\s+#\\s+#gs;
+		if ( $license_text =~ /\b$pattern\b/i ) {
+			return $license;
 		}
-	} else {
-	        return;
 	}
+	return '';
 }
 
 sub license_from {
@@ -556,8 +616,15 @@ sub _perl_version {
 	return $v;
 }
 
-
-
+sub add_metadata {
+    my $self = shift;
+    my %hash = @_;
+    for my $key (keys %hash) {
+        warn "add_metadata: $key is not prefixed with 'x_'.\n" .
+             "Use appopriate function to add non-private metadata.\n" unless $key =~ /^x_/;
+        $self->{values}->{$key} = $hash{$key};
+    }
+}
 
 
 ######################################################################
@@ -6,7 +6,7 @@ use Module::Install::Base ();
 
 use vars qw{$VERSION @ISA $ISCORE};
 BEGIN {
-	$VERSION = '0.94';
+	$VERSION = '1.00';
 	@ISA     = 'Module::Install::Base';
 	$ISCORE  = 1;
 }
@@ -6,7 +6,7 @@ use Module::Install::Base ();
 
 use vars qw{$VERSION @ISA $ISCORE};
 BEGIN {
-	$VERSION = '0.94';;
+	$VERSION = '1.00';
 	@ISA     = qw{Module::Install::Base};
 	$ISCORE  = 1;
 }
@@ -26,7 +26,10 @@ sub WriteAll {
 
 	$self->check_nmake if $args{check_nmake};
 	unless ( $self->makemaker_args->{PL_FILES} ) {
-		$self->makemaker_args( PL_FILES => {} );
+		# XXX: This still may be a bit over-defensive...
+		unless ($self->makemaker(6.25)) {
+			$self->makemaker_args( PL_FILES => {} ) if -f 'Build.PL';
+		}
 	}
 
 	# Until ExtUtils::MakeMaker support MYMETA.yml, make sure
@@ -19,6 +19,9 @@ package Module::Install;
 
 use 5.005;
 use strict 'vars';
+use Cwd        ();
+use File::Find ();
+use File::Path ();
 
 use vars qw{$VERSION $MAIN};
 BEGIN {
@@ -28,7 +31,7 @@ BEGIN {
 	# This is not enforced yet, but will be some time in the next few
 	# releases once we can make sure it won't clash with custom
 	# Module::Install extensions.
-	$VERSION = '0.94';
+	$VERSION = '1.00';
 
 	# Storage for the pseudo-singleton
 	$MAIN    = undef;
@@ -38,18 +41,25 @@ BEGIN {
 
 }
 
+sub import {
+	my $class = shift;
+	my $self  = $class->new(@_);
+	my $who   = $self->_caller;
 
-
-
-
-# Whether or not inc::Module::Install is actually loaded, the
-# $INC{inc/Module/Install.pm} is what will still get set as long as
-# the caller loaded module this in the documented manner.
-# If not set, the caller may NOT have loaded the bundled version, and thus
-# they may not have a MI version that works with the Makefile.PL. This would
-# result in false errors or unexpected behaviour. And we don't want that.
-my $file = join( '/', 'inc', split /::/, __PACKAGE__ ) . '.pm';
-unless ( $INC{$file} ) { die <<"END_DIE" }
+	#-------------------------------------------------------------
+	# all of the following checks should be included in import(),
+	# to allow "eval 'require Module::Install; 1' to test
+	# installation of Module::Install. (RT #51267)
+	#-------------------------------------------------------------
+
+	# Whether or not inc::Module::Install is actually loaded, the
+	# $INC{inc/Module/Install.pm} is what will still get set as long as
+	# the caller loaded module this in the documented manner.
+	# If not set, the caller may NOT have loaded the bundled version, and thus
+	# they may not have a MI version that works with the Makefile.PL. This would
+	# result in false errors or unexpected behaviour. And we don't want that.
+	my $file = join( '/', 'inc', split /::/, __PACKAGE__ ) . '.pm';
+	unless ( $INC{$file} ) { die <<"END_DIE" }
 
 Please invoke ${\__PACKAGE__} with:
 
@@ -61,26 +71,28 @@ not:
 
 END_DIE
 
-
-
-
-
-# If the script that is loading Module::Install is from the future,
-# then make will detect this and cause it to re-run over and over
-# again. This is bad. Rather than taking action to touch it (which
-# is unreliable on some platforms and requires write permissions)
-# for now we should catch this and refuse to run.
-if ( -f $0 ) {
-	my $s = (stat($0))[9];
-
-	# If the modification time is only slightly in the future,
-	# sleep briefly to remove the problem.
-	my $a = $s - time;
-	if ( $a > 0 and $a < 5 ) { sleep 5 }
-
-	# Too far in the future, throw an error.
-	my $t = time;
-	if ( $s > $t ) { die <<"END_DIE" }
+	# This reportedly fixes a rare Win32 UTC file time issue, but
+	# as this is a non-cross-platform XS module not in the core,
+	# we shouldn't really depend on it. See RT #24194 for detail.
+	# (Also, this module only supports Perl 5.6 and above).
+	eval "use Win32::UTCFileTime" if $^O eq 'MSWin32' && $] >= 5.006;
+
+	# If the script that is loading Module::Install is from the future,
+	# then make will detect this and cause it to re-run over and over
+	# again. This is bad. Rather than taking action to touch it (which
+	# is unreliable on some platforms and requires write permissions)
+	# for now we should catch this and refuse to run.
+	if ( -f $0 ) {
+		my $s = (stat($0))[9];
+
+		# If the modification time is only slightly in the future,
+		# sleep briefly to remove the problem.
+		my $a = $s - time;
+		if ( $a > 0 and $a < 5 ) { sleep 5 }
+
+		# Too far in the future, throw an error.
+		my $t = time;
+		if ( $s > $t ) { die <<"END_DIE" }
 
 Your installer $0 has a modification time in the future ($s > $t).
 
@@ -89,15 +101,12 @@ This is known to create infinite loops in make.
 Please correct this, then run $0 again.
 
 END_DIE
-}
-
-
-
+	}
 
 
-# Build.PL was formerly supported, but no longer is due to excessive
-# difficulty in implementing every single feature twice.
-if ( $0 =~ /Build.PL$/i ) { die <<"END_DIE" }
+	# Build.PL was formerly supported, but no longer is due to excessive
+	# difficulty in implementing every single feature twice.
+	if ( $0 =~ /Build.PL$/i ) { die <<"END_DIE" }
 
 Module::Install no longer supports Build.PL.
 
@@ -107,23 +116,42 @@ Please remove all Build.PL files and only use the Makefile.PL installer.
 
 END_DIE
 
+	#-------------------------------------------------------------
 
+	# To save some more typing in Module::Install installers, every...
+	# use inc::Module::Install
+	# ...also acts as an implicit use strict.
+	$^H |= strict::bits(qw(refs subs vars));
 
+	#-------------------------------------------------------------
 
+	unless ( -f $self->{file} ) {
+		foreach my $key (keys %INC) {
+			delete $INC{$key} if $key =~ /Module\/Install/;
+		}
 
-# To save some more typing in Module::Install installers, every...
-# use inc::Module::Install
-# ...also acts as an implicit use strict.
-$^H |= strict::bits(qw(refs subs vars));
-
+		local $^W;
+		require "$self->{path}/$self->{dispatch}.pm";
+		File::Path::mkpath("$self->{prefix}/$self->{author}");
+		$self->{admin} = "$self->{name}::$self->{dispatch}"->new( _top => $self );
+		$self->{admin}->init;
+		@_ = ($class, _self => $self);
+		goto &{"$self->{name}::import"};
+	}
 
+	local $^W;
+	*{"${who}::AUTOLOAD"} = $self->autoload;
+	$self->preload;
 
+	# Unregister loader and worker packages so subdirs can use them again
+	delete $INC{'inc/Module/Install.pm'};
+	delete $INC{'Module/Install.pm'};
 
+	# Save to the singleton
+	$MAIN = $self;
 
-use Cwd        ();
-use File::Find ();
-use File::Path ();
-use FindBin;
+	return 1;
+}
 
 sub autoload {
 	my $self = shift;
@@ -136,7 +164,21 @@ sub autoload {
 			# Delegate back to parent dirs
 			goto &$code unless $cwd eq $pwd;
 		}
-		$$sym =~ /([^:]+)$/ or die "Cannot autoload $who - $sym";
+		unless ($$sym =~ s/([^:]+)$//) {
+			# XXX: it looks like we can't retrieve the missing function
+			# via $$sym (usually $main::AUTOLOAD) in this case.
+			# I'm still wondering if we should slurp Makefile.PL to
+			# get some context or not ...
+			my ($package, $file, $line) = caller;
+			die <<"EOT";
+Unknown function is found at $file line $line.
+Execution of $file aborted due to runtime errors.
+
+If you're a contributor to a project, you may need to install
+some Module::Install extensions from CPAN (or other repository).
+If you're a user of a module, please contact the author.
+EOT
+		}
 		my $method = $1;
 		if ( uc($method) eq $method ) {
 			# Do nothing
@@ -152,33 +194,6 @@ sub autoload {
 	};
 }
 
-sub import {
-	my $class = shift;
-	my $self  = $class->new(@_);
-	my $who   = $self->_caller;
-
-	unless ( -f $self->{file} ) {
-		require "$self->{path}/$self->{dispatch}.pm";
-		File::Path::mkpath("$self->{prefix}/$self->{author}");
-		$self->{admin} = "$self->{name}::$self->{dispatch}"->new( _top => $self );
-		$self->{admin}->init;
-		@_ = ($class, _self => $self);
-		goto &{"$self->{name}::import"};
-	}
-
-	*{"${who}::AUTOLOAD"} = $self->autoload;
-	$self->preload;
-
-	# Unregister loader and worker packages so subdirs can use them again
-	delete $INC{"$self->{file}"};
-	delete $INC{"$self->{path}.pm"};
-
-	# Save to the singleton
-	$MAIN = $self;
-
-	return 1;
-}
-
 sub preload {
 	my $self = shift;
 	unless ( $self->{extensions} ) {
@@ -204,6 +219,7 @@ sub preload {
 
 	my $who = $self->_caller;
 	foreach my $name ( sort keys %seen ) {
+		local $^W;
 		*{"${who}::$name"} = sub {
 			${"${who}::AUTOLOAD"} = "${who}::$name";
 			goto &{"${who}::AUTOLOAD"};
@@ -214,12 +230,18 @@ sub preload {
 sub new {
 	my ($class, %args) = @_;
 
+	delete $INC{'FindBin.pm'};
+	{
+		# to suppress the redefine warning
+		local $SIG{__WARN__} = sub {};
+		require FindBin;
+	}
+
 	# ignore the prefix on extension modules built from top level.
 	my $base_path = Cwd::abs_path($FindBin::Bin);
 	unless ( Cwd::abs_path(Cwd::cwd()) eq $base_path ) {
 		delete $args{prefix};
 	}
-
 	return $args{_self} if $args{_self};
 
 	$args{dispatch} ||= 'Admin';
@@ -272,8 +294,10 @@ END_DIE
 sub load_extensions {
 	my ($self, $path, $top) = @_;
 
+	my $should_reload = 0;
 	unless ( grep { ! ref $_ and lc $_ eq lc $self->{prefix} } @INC ) {
 		unshift @INC, $self->{prefix};
+		$should_reload = 1;
 	}
 
 	foreach my $rv ( $self->find_extensions($path) ) {
@@ -281,12 +305,13 @@ sub load_extensions {
 		next if $self->{pathnames}{$pkg};
 
 		local $@;
-		my $new = eval { require $file; $pkg->can('new') };
+		my $new = eval { local $^W; require $file; $pkg->can('new') };
 		unless ( $new ) {
 			warn $@ if $@;
 			next;
 		}
-		$self->{pathnames}{$pkg} = delete $INC{$file};
+		$self->{pathnames}{$pkg} =
+			$should_reload ? delete $INC{$file} : $INC{$file};
 		push @{$self->{extensions}}, &{$new}($pkg, _top => $top );
 	}
 
@@ -2,34 +2,183 @@ package Class::Accessor::Grouped;
 use strict;
 use warnings;
 use Carp ();
-use Class::Inspector ();
 use Scalar::Util ();
 use MRO::Compat;
 use Sub::Name ();
 
-our $VERSION = '0.09003';
+our $VERSION = '0.09008';
 $VERSION = eval $VERSION;
 
-# Class::XSAccessor is segfaulting on win32, so be careful
-# Win32 users can set $hasXS to try to use it anyway
+# when changing minimum version don't forget to adjust L</PERFROMANCE> as well
+our $__minimum_xsa_version = '1.06';
 
-our $hasXS;
+our $USE_XS;
+# the unless defined is here so that we can override the value
+# before require/use, *regardless* of the state of $ENV{CAG_USE_XS}
+$USE_XS = $ENV{CAG_USE_XS}
+    unless defined $USE_XS;
 
-sub _hasXS {
+my ($xsa_loaded, $xsa_autodetected);
 
-  if (not defined $hasXS) {
-    $hasXS = 0;
+my $load_xsa = sub {
+    return if $xsa_loaded++;
+    require Class::XSAccessor;
+    Class::XSAccessor->VERSION($__minimum_xsa_version);
+};
+
+my $use_xs = sub {
+    if (defined $USE_XS) {
+        $load_xsa->() if ($USE_XS && ! $xsa_loaded);
+        return $USE_XS;
+    }
 
+    $xsa_autodetected = 1;
+    $USE_XS = 0;
+
+    # Class::XSAccessor is segfaulting on win32, in some
+    # esoteric heavily-threaded scenarios
+    # Win32 users can set $USE_XS/CAG_USE_XS to try to use it anyway
     if ($^O ne 'MSWin32') {
-      eval {
-        require Class::XSAccessor;
-        $hasXS = 1;
-      };
+        local $@;
+        eval { $load_xsa->(); $USE_XS = 1 };
     }
-  }
 
-  return $hasXS;
-}
+    return $USE_XS;
+};
+
+my $maker_type_map = {
+  rw => {
+    xsa => 'accessors',
+    cag => 'make_group_accessor',
+  },
+  ro => {
+    xsa => 'getters',
+    cag => 'make_group_ro_accessor',
+  },
+  wo => {
+    xsa => 'setters',
+    cag => 'make_group_wo_accessor',
+  },
+};
+
+# When installing an XSA simple accessor, we need to make sure we are not
+# short-circuiting a (compile or runtime) get_simple/set_simple override.
+# What we do here is install a lazy first-access check, which will decide
+# the ultimate coderef being placed in the accessor slot
+
+my $no_xsa_classes_warned;
+my $add_xs_accessor = sub {
+    my ($class, $group, $field, $name, $type) = @_;
+
+    Class::XSAccessor->import({
+        replace => 1,
+        class => $class,
+        $maker_type_map->{$type}{xsa} => {
+            $name => $field,
+        },
+    });
+
+    my $xs_cref = $class->can($name);
+
+    my $pp_cref = do {
+        my $cag_method = $maker_type_map->{$type}{cag};
+        local $USE_XS = 0;
+        $class->$cag_method ($group, $field, $name, $type);
+    };
+
+    # can't use pkg_gen to track this stuff, as it doesn't
+    # detect superclass mucking
+    my $original_getter = __PACKAGE__->can ("get_$group");
+    my $original_setter = __PACKAGE__->can ("set_$group");
+
+    return sub {
+        my $self = $_[0];
+        my $current_class = Scalar::Util::blessed( $self ) || $self;
+
+        my $final_cref;
+        if (
+            $current_class->can("get_$group") == $original_getter
+                &&
+            $current_class->can("set_$group") == $original_setter
+        ) {
+            # nothing has changed, might as well use the XS crefs
+            #
+            # note that by the time this code executes, we already have
+            # *objects* (since XSA works on 'simple' only by definition).
+            # If someone is mucking with the symbol table *after* there
+            # are some objects already - look! many, shiny pieces! :)
+            $final_cref = $xs_cref;
+        }
+        else {
+            $final_cref = $pp_cref;
+            if ($USE_XS and ! $xsa_autodetected and ! $no_xsa_classes_warned->{$current_class}++) {
+
+                # not using Carp since the line where this happens doesn't mean much
+                warn 'Explicitly requested use of Class::XSAccessor disabled for objects of class '
+                   . "'$current_class' due to an overriden get_$group and/or set_$group\n";
+            }
+        }
+
+        # installing an XSA cref that was originally created on a class
+        # different than $current_class is perfectly safe as per
+        # C::XSA's author
+        my $fq_meth = "${current_class}::${name}";
+
+        no strict qw/refs/;
+        no warnings qw/redefine/;
+
+        *$fq_meth = Sub::Name::subname($fq_meth, $final_cref);
+
+        # older perls segfault if the cref behind the goto throws
+        # http://rt.perl.org/rt3/Public/Bug/Display.html?id=35878
+        return $final_cref->(@_) if ($] < 5.008009);
+
+        goto $final_cref;
+    };
+};
+
+# Yes this method is undocumented
+# Yes it should be a private coderef like the one above it
+# No we can't do that (yet) because the DBIC-CDBI compat layer overrides it
+# %$*@!?&!&#*$!!!
+sub _mk_group_accessors {
+    my($self, $maker, $group, @fields) = @_;
+    my $class = Scalar::Util::blessed $self || $self;
+
+    no strict 'refs';
+    no warnings 'redefine';
+
+    # So we don't have to do lots of lookups inside the loop.
+    $maker = $self->can($maker) unless ref $maker eq 'CODE';
+
+    foreach (@fields) {
+        if( $_ eq 'DESTROY' ) {
+            Carp::carp("Having a data accessor named DESTROY in ".
+                       "'$class' is unwise.");
+        }
+
+        my ($name, $field) = (ref $_)
+            ? (@$_)
+            : ($_, $_)
+        ;
+
+        my $alias = "_${name}_accessor";
+
+        for my $meth ($name, $alias) {
+
+            # the maker may elect to not return anything, meaning it already
+            # installed the coderef for us
+            my $cref = $self->$maker($group, $field, $meth)
+                or next;
+
+            my $fq_meth = join('::', $class, $meth);
+
+            *$fq_meth = Sub::Name::subname($fq_meth, $cref);
+                #unless defined &{$class."\:\:$field"}
+        }
+    }
+};
+
 
 =head1 NAME
 
@@ -76,55 +225,6 @@ sub mk_group_accessors {
   return;
 }
 
-
-{
-    no strict 'refs';
-    no warnings 'redefine';
-
-    sub _mk_group_accessors {
-        my($self, $maker, $group, @fields) = @_;
-        my $class = Scalar::Util::blessed $self || $self;
-
-        # So we don't have to do lots of lookups inside the loop.
-        $maker = $self->can($maker) unless ref $maker;
-        
-        my $hasXS = _hasXS();
-
-        foreach my $field (@fields) {
-            if( $field eq 'DESTROY' ) {
-                Carp::carp("Having a data accessor named DESTROY  in ".
-                             "'$class' is unwise.");
-            }
-
-            my $name = $field;
-
-            ($name, $field) = @$field if ref $field;
-            
-            my $alias = "_${name}_accessor";
-            my $full_name = join('::', $class, $name);
-            my $full_alias = join('::', $class, $alias);
-            
-            if ( $hasXS && $group eq 'simple' ) {
-                require Class::XSAccessor;
-                Class::XSAccessor::newxs_accessor("${class}::${name}", $field, 0);
-                Class::XSAccessor::newxs_accessor("${class}::${alias}", $field, 0);
-                
-                # XXX: is the alias accessor really necessary?
-            }
-            else {
-                my $accessor = $self->$maker($group, $field);
-                my $alias_accessor = $self->$maker($group, $field);
-                
-                *$full_name = Sub::Name::subname($full_name, $accessor);
-                  #unless defined &{$class."\:\:$field"}
-                
-                *$full_alias = Sub::Name::subname($full_alias, $alias_accessor);
-                  #unless defined &{$class."\:\:$alias"}
-            }
-        }
-    }
-}
-
 =head2 mk_group_ro_accessors
 
 =over 4
@@ -173,55 +273,72 @@ sub mk_group_wo_accessors {
 
 =over 4
 
-=item Arguments: $group, $field
+=item Arguments: $group, $field, $method
 
-Returns: $sub (\CODE)
+Returns: \&accessor_coderef ?
 
 =back
 
-Returns a single accessor in a given group; called by mk_group_accessors
-for each entry in @fieldspec.
+Called by mk_group_accessors for each entry in @fieldspec. Either returns
+a coderef which will be installed at C<&__PACKAGE__::$method>, or returns
+C<undef> if it elects to install the coderef on its own.
 
 =cut
 
 sub make_group_accessor {
-    my ($class, $group, $field) = @_;
+    my ($class, $group, $field, $name) = @_;
+
+    if ( $group eq 'simple' && $use_xs->() ) {
+        return $add_xs_accessor->(@_, 'rw');
+    }
 
     my $set = "set_$group";
     my $get = "get_$group";
 
+    $field =~ s/'/\\'/g;
+
     # eval for faster fastiness
-    return eval "sub {
+    my $code = eval "sub {
         if(\@_ > 1) {
             return shift->$set('$field', \@_);
         }
         else {
             return shift->$get('$field');
         }
-    };"
+    };";
+    Carp::croak $@ if $@;
+
+    return $code;
 }
 
 =head2 make_group_ro_accessor
 
 =over 4
 
-=item Arguments: $group, $field
+=item Arguments: $group, $field, $method
 
-Returns: $sub (\CODE)
+Returns: \&accessor_coderef ?
 
 =back
 
-Returns a single read-only accessor in a given group; called by
-mk_group_ro_accessors for each entry in @fieldspec.
+Called by mk_group_ro_accessors for each entry in @fieldspec. Either returns
+a coderef which will be installed at C<&__PACKAGE__::$method>, or returns
+C<undef> if it elects to install the coderef on its own.
 
 =cut
 
 sub make_group_ro_accessor {
-    my($class, $group, $field) = @_;
+    my($class, $group, $field, $name) = @_;
+
+    if ( $group eq 'simple' && $use_xs->() ) {
+        return $add_xs_accessor->(@_, 'ro');
+    }
 
     my $get = "get_$group";
 
-    return eval "sub {
+    $field =~ s/'/\\'/g;
+
+    my $code = eval "sub {
         if(\@_ > 1) {
             my \$caller = caller;
             Carp::croak(\"'\$caller' cannot alter the value of '$field' on \".
@@ -230,30 +347,40 @@ sub make_group_ro_accessor {
         else {
             return shift->$get('$field');
         }
-    };"
+    };";
+    Carp::croak $@ if $@;
+
+    return $code;
 }
 
 =head2 make_group_wo_accessor
 
 =over 4
 
-=item Arguments: $group, $field
+=item Arguments: $group, $field, $method
 
-Returns: $sub (\CODE)
+Returns: \&accessor_coderef ?
 
 =back
 
-Returns a single write-only accessor in a given group; called by
-mk_group_wo_accessors for each entry in @fieldspec.
+Called by mk_group_wo_accessors for each entry in @fieldspec. Either returns
+a coderef which will be installed at C<&__PACKAGE__::$method>, or returns
+C<undef> if it elects to install the coderef on its own.
 
 =cut
 
 sub make_group_wo_accessor {
-    my($class, $group, $field) = @_;
+    my($class, $group, $field, $name) = @_;
+
+    if ( $group eq 'simple' && $use_xs->() ) {
+        return $add_xs_accessor->(@_, 'wo')
+    }
 
     my $set = "set_$group";
 
-    return eval "sub {
+    $field =~ s/'/\\'/g;
+
+    my $code = eval "sub {
         unless (\@_ > 1) {
             my \$caller = caller;
             Carp::croak(\"'\$caller' cannot access the value of '$field' on \".
@@ -262,7 +389,10 @@ sub make_group_wo_accessor {
         else {
             return shift->$set('$field', \@_);
         }
-    };"
+    };";
+    Carp::croak $@ if $@;
+
+    return $code;
 }
 
 =head2 get_simple
@@ -325,32 +455,33 @@ instances.
 sub get_inherited {
     my $class;
 
-    if (Scalar::Util::blessed $_[0]) {
-        my $reftype = Scalar::Util::reftype $_[0];
-        $class = ref $_[0];
-
-        if ($reftype eq 'HASH' && exists $_[0]->{$_[1]}) {
-            return $_[0]->{$_[1]};
-        } elsif ($reftype ne 'HASH') {
-            Carp::croak('Cannot get inherited value on an object instance that is not hash-based');
-        };
-    } else {
+    if ( defined( $class = Scalar::Util::blessed $_[0] ) ) {
+        if (Scalar::Util::reftype $_[0] eq 'HASH') {
+          return $_[0]->{$_[1]} if exists $_[0]->{$_[1]};
+        }
+        else {
+          Carp::croak('Cannot get inherited value on an object instance that is not hash-based');
+        }
+    }
+    else {
         $class = $_[0];
-    };
+    }
 
     no strict 'refs';
-    no warnings qw/uninitialized/;
-    return ${$class.'::__cag_'.$_[1]} if defined(${$class.'::__cag_'.$_[1]});
+    no warnings 'uninitialized';
+
+    my $cag_slot = '::__cag_'. $_[1];
+    return ${$class.$cag_slot} if defined(${$class.$cag_slot});
 
     # we need to be smarter about recalculation, as @ISA (thus supers) can very well change in-flight
-    my $pkg_gen = mro::get_pkg_gen ($class);
-    if ( ${$class.'::__cag_pkg_gen'} != $pkg_gen ) {
-        @{$class.'::__cag_supers'} = $_[0]->get_super_paths;
-        ${$class.'::__cag_pkg_gen'} = $pkg_gen;
-    };
+    my $cur_gen = mro::get_pkg_gen ($class);
+    if ( $cur_gen != ${$class.'::__cag_pkg_gen__'} ) {
+        @{$class.'::__cag_supers__'} = $_[0]->get_super_paths;
+        ${$class.'::__cag_pkg_gen__'} = $cur_gen;
+    }
 
-    foreach (@{$class.'::__cag_supers'}) {
-        return ${$_.'::__cag_'.$_[1]} if defined(${$_.'::__cag_'.$_[1]});
+    for (@{$class.'::__cag_supers__'}) {
+        return ${$_.$cag_slot} if defined(${$_.$cag_slot});
     };
 
     return undef;
@@ -377,7 +508,7 @@ hash-based object.
 =cut
 
 sub set_inherited {
-    if (Scalar::Util::blessed $_[0]) {
+    if (defined Scalar::Util::blessed $_[0]) {
         if (Scalar::Util::reftype $_[0] eq 'HASH') {
             return $_[0]->{$_[1]} = $_[2];
         } else {
@@ -438,6 +569,7 @@ it. This method will die if the specified class could not be loaded.
 sub set_component_class {
     if ($_[2]) {
         local $^W = 0;
+        require Class::Inspector;
         if (Class::Inspector->installed($_[2]) && !Class::Inspector->loaded($_[2])) {
             eval "use $_[2]";
 
@@ -455,30 +587,79 @@ Returns a list of 'parent' or 'super' class names that the current class inherit
 =cut
 
 sub get_super_paths {
-    my $class = Scalar::Util::blessed $_[0] || $_[0];
-
-    return @{mro::get_linear_isa($class)};
+    return @{mro::get_linear_isa( ref($_[0]) || $_[0] )};
 };
 
 1;
 
-=head1 Performance
-
-You can speed up accessors of type 'simple' by installing L<Class::XSAccessor>.
-Note however that the use of this module is disabled by default on Win32
-systems, as it causes yet unresolved segfaults. If you are a Win32 user, and
-want to try this module with L<Class::XSAccessor>, set
-C<$Class::Accessor::Grouped::hasXS> to a true value B<before> registering
-your accessors (e.g. in a C<BEGIN> block)
+=head1 PERFORMANCE
+
+To provide total flexibility L<Class::Accessor::Grouped> calls methods
+internally while performing get/set actions, which makes it noticeably
+slower than similar modules. To compensate, this module will automatically
+use the insanely fast L<Class::XSAccessor> to generate the C<simple>-group
+accessors, if L<< Class::XSAccessor >= 1.06|Class::XSAccessor >> is
+available on your system.
+
+=head2 Benchmark
+
+This is the result of a set/get/set loop benchmark on perl 5.12.1 with
+thread support, showcasing most popular accessor builders: L<Moose>, L<Mouse>,
+L<CAF|Class::Accessor::Fast>, L<CAF_XS|Class::Accessor::Fast::XS>
+and L<XSA|Class::XSAccessor>:
+
+            Rate     CAG   moOse     CAF HANDMADE  CAF_XS moUse_XS CAG_XS     XSA
+ CAG      1777/s      --    -27%    -29%     -36%    -62%     -67%   -72%    -73%
+ moOse    2421/s     36%      --     -4%     -13%    -48%     -55%   -61%    -63%
+ CAF      2511/s     41%      4%      --     -10%    -47%     -53%   -60%    -61%
+ HANDMADE 2791/s     57%     15%     11%       --    -41%     -48%   -56%    -57%
+ CAF_XS   4699/s    164%     94%     87%      68%      --     -13%   -25%    -28%
+ moUse_XS 5375/s    203%    122%    114%      93%     14%       --   -14%    -18%
+ CAG_XS   6279/s    253%    159%    150%     125%     34%      17%     --     -4%
+ XSA      6515/s    267%    169%    159%     133%     39%      21%     4%      --
+
+Benchmark program is available in the root of the
+L<repository|http://search.cpan.org/dist/Class-Accessor-Grouped/>:
+
+=head2 Notes on Class::XSAccessor
+
+You can force (or disable) the use of L<Class::XSAccessor> before creating a
+particular C<simple> accessor by either manipulating the global variable
+C<$Class::Accessor::Grouped::USE_XS> to true or false (preferably with
+L<localization|perlfunc/local>, or you can do so before runtime via the
+C<CAG_USE_XS> environment variable.
+
+Since L<Class::XSAccessor> has no knowledge of L</get_simple> and
+L</set_simple> this module does its best to detect if you are overriding
+one of these methods and will fall back to using the perl version of the
+accessor in order to maintain consistency. However be aware that if you
+enable use of C<Class::XSAccessor> (automatically or explicitly), create
+an object, invoke a simple accessor on that object, and B<then> manipulate
+the symbol table to install a C<get/set_simple> override - you get to keep
+all the pieces.
+
+While L<Class::XSAccessor> works surprisingly well for the amount of black
+magic it tries to pull off, it's still black magic. At present (Sep 2010)
+the module is known to have problems on Windows under heavy thread-stress
+(e.g. Win32+Apache+mod_perl). Thus for the time being L<Class::XSAccessor>
+will not be used automatically if you are running under C<MSWin32>.
 
 =head1 AUTHORS
 
 Matt S. Trout <mst@shadowcatsystems.co.uk>
+
 Christopher H. Laco <claco@chrislaco.com>
 
-With contributions from:
+=head1 CONTRIBUTORS
+
+Caelum: Rafael Kitover <rkitover@cpan.org>
+
+groditi: Guillermo Roditi <groditi@cpan.org>
+
+Jason Plum <jason.plum@bmmsi.com>
+
+ribasushi: Peter Rabbitson <ribasushi@cpan.org>
 
-Guillermo Roditi <groditi@cpan.org>
 
 =head1 COPYRIGHT & LICENSE
 
@@ -2,100 +2,97 @@ use Test::More tests => 62;
 use strict;
 use warnings;
 use lib 't/lib';
-use Sub::Identify qw/sub_name sub_fullname/;;
+use B qw/svref_2object/;
 
+# we test the pure-perl versions only, but allow overrides
+# from the accessor_xs test-umbrella
+# Also make sure a rogue envvar will not interfere with
+# things
+my $use_xs;
 BEGIN {
-    # Disable XSAccessor to test pure-Perl accessors
-    $Class::Accessor::Grouped::hasXS = 0;
-    
-    require AccessorGroups;
-}
+    $Class::Accessor::Grouped::USE_XS = 0
+        unless defined $Class::Accessor::Grouped::USE_XS;
+    $ENV{CAG_USE_XS} = 1;
+    $use_xs = $Class::Accessor::Grouped::USE_XS;
+};
 
-my $class = AccessorGroups->new;
+use AccessorGroupsSubclass;
 
 {
-    my $warned = 0;
+    my $obj = AccessorGroupsSubclass->new;
+    my $class = ref $obj;
+    my $name = 'multiple1';
+    my $alias = "_${name}_accessor";
 
+    for my $meth ($name, $alias) {
+        my $cv = svref_2object( $obj->can($meth) );
+        is($cv->GV->NAME, $meth, "$meth accessor is named");
+        is($cv->GV->STASH->NAME, 'AccessorGroups', "$meth class correct");
+    }
+
+    my $warned = 0;
     local $SIG{__WARN__} = sub {
         if  (shift =~ /DESTROY/i) {
             $warned++;
         };
     };
 
-    $class->mk_group_accessors('warnings', 'DESTROY');
+    no warnings qw/once/;
+    local *AccessorGroupsSubclass::DESTROY = sub {};
 
+    $class->mk_group_accessors('warnings', 'DESTROY');
     ok($warned);
-
-    # restore non-accessorized DESTROY
-    no warnings;
-    *AccessorGroups::DESTROY = sub {};
 };
 
-{
-  my $class_name = ref $class;
-  my $name = 'multiple1';
-  my $alias = "_${name}_accessor";
-  my $accessor = $class->can($name);
-  my $alias_accessor = $class->can($alias);
-  isnt(sub_name($accessor), '__ANON__', 'accessor is named');
-  isnt(sub_name($alias_accessor), '__ANON__', 'alias is named');
-  is(sub_fullname($accessor), join('::',$class_name,$name), 'accessor FQ name');
-  is(sub_fullname($alias_accessor), join('::',$class_name,$alias), 'alias FQ name');
-}
-
-foreach (qw/singlefield multiple1 multiple2/) {
-    my $name = $_;
-    my $alias = "_${name}_accessor";
-
-    can_ok($class, $name, $alias);
 
-    is($class->$name, undef);
-    is($class->$alias, undef);
-
-    # get/set via name
-    is($class->$name('a'), 'a');
-    is($class->$name, 'a');
-    is($class->{$name}, 'a');
-
-    # alias gets same as name
-    is($class->$alias, 'a');
-
-    # get/set via alias
-    is($class->$alias('b'), 'b');
-    is($class->$alias, 'b');
-    is($class->{$name}, 'b');
-
-    # alias gets same as name
-    is($class->$name, 'b');
+my $obj = AccessorGroupsSubclass->new;
+
+my $test_accessors = {
+    singlefield => {
+        is_xs => $use_xs,
+        has_extra => 1,
+    },
+    multiple1 => {
+    },
+    multiple2 => {
+    },
+    lr1name => {
+        custom_field => 'lr1;field',
+    },
+    lr2name => {
+        custom_field => "lr2'field",
+    },
 };
 
-foreach (qw/lr1 lr2/) {
-    my $name = "$_".'name';
+
+for my $name (sort keys %$test_accessors) {
     my $alias = "_${name}_accessor";
-    my $field = "$_".'field';
+    my $field = $test_accessors->{$name}{custom_field} || $name;
+    my $extra = $test_accessors->{$name}{has_extra};
 
-    can_ok($class, $name, $alias);
-    ok(!$class->can($field));
+    can_ok($obj, $name, $alias);
+    ok(!$obj->can($field))
+      if $field ne $name;
 
-    is($class->$name, undef);
-    is($class->$alias, undef);
+    is($obj->$name, undef);
+    is($obj->$alias, undef);
 
     # get/set via name
-    is($class->$name('c'), 'c');
-    is($class->$name, 'c');
-    is($class->{$field}, 'c');
+    is($obj->$name('a'), 'a');
+    is($obj->$name, 'a');
+    is($obj->{$field}, $extra ? 'a Extra tackled on' : 'a');
 
     # alias gets same as name
-    is($class->$alias, 'c');
+    is($obj->$alias, 'a');
 
     # get/set via alias
-    is($class->$alias('d'), 'd');
-    is($class->$alias, 'd');
-    is($class->{$field}, 'd');
+    is($obj->$alias('b'), 'b');
+    is($obj->$alias, 'b');
+    is($obj->{$field}, $extra ? 'b Extra tackled on' : 'b');
 
     # alias gets same as name
-    is($class->$name, 'd');
+    is($obj->$name, 'b');
 };
 
+# important
 1;
-
@@ -1,10 +1,24 @@
 use Test::More tests => 48;
+use Test::Exception;
 use strict;
 use warnings;
 use lib 't/lib';
+
+# we test the pure-perl versions only, but allow overrides
+# from the accessor_xs test-umbrella
+# Also make sure a rogue envvar will not interfere with
+# things
+my $use_xs;
+BEGIN {
+    $Class::Accessor::Grouped::USE_XS = 0
+        unless defined $Class::Accessor::Grouped::USE_XS;
+    $ENV{CAG_USE_XS} = 1;
+    $use_xs = $Class::Accessor::Grouped::USE_XS;
+};
+
 use AccessorGroupsRO;
 
-my $class = AccessorGroupsRO->new;
+my $obj = AccessorGroupsRO->new;
 
 {
     my $warned = 0;
@@ -15,77 +29,68 @@ my $class = AccessorGroupsRO->new;
         };
     };
 
-    $class->mk_group_ro_accessors('warnings', 'DESTROY');
+    no warnings qw/once/;
+    local *AccessorGroupsRO::DESTROY = sub {};
 
-    ok($warned);
+    $obj->mk_group_ro_accessors('warnings', 'DESTROY');
 
-    # restore non-accessorized DESTROY
-    no warnings;
-    *AccessorGroupsRO::DESTROY = sub {};
+    ok($warned);
 };
 
-foreach (qw/singlefield multiple1 multiple2/) {
-    my $name = $_;
-    my $alias = "_${name}_accessor";
-
-    can_ok($class, $name, $alias);
-
-    is($class->$name, undef);
-    is($class->$alias, undef);
-
-    # get via name
-    $class->{$name} = 'a';
-    is($class->$name, 'a');
-
-    # alias gets same as name
-    is($class->$alias, 'a');
-
-    # die on set via name/alias
-    eval {
-        $class->$name('b');
-    };
-    ok($@ =~ /cannot alter/);
-
-    eval {
-        $class->$alias('b');
-    };
-    ok($@ =~ /cannot alter/);
-
-    # value should be unchanged
-    is($class->$name, 'a');
-    is($class->$alias, 'a');
+my $test_accessors = {
+    singlefield => {
+        is_xs => $use_xs,
+    },
+    multiple1 => {
+    },
+    multiple2 => {
+    },
+    lr1name => {
+        custom_field => 'lr1;field',
+    },
+    lr2name => {
+        custom_field => "lr2'field",
+    },
 };
 
-foreach (qw/lr1 lr2/) {
-    my $name = "$_".'name';
+for my $name (sort keys %$test_accessors) {
+
     my $alias = "_${name}_accessor";
-    my $field = "$_".'field';
+    my $field = $test_accessors->{$name}{custom_field} || $name;
+
+    can_ok($obj, $name, $alias);
 
-    can_ok($class, $name, $alias);
-    ok(!$class->can($field));
+    ok(!$obj->can($field))
+      if $field ne $name;
 
-    is($class->$name, undef);
-    is($class->$alias, undef);
+    is($obj->$name, undef);
+    is($obj->$alias, undef);
 
     # get via name
-    $class->{$field} = 'c';
-    is($class->$name, 'c');
+    $obj->{$field} = 'a';
+    is($obj->$name, 'a');
 
     # alias gets same as name
-    is($class->$alias, 'c');
+    is($obj->$alias, 'a');
+
+    my $ro_regex = $test_accessors->{$name}{is_xs}
+        ? qr/Usage\:.+$name.*\(self\)/
+        : qr/cannot alter the value of '\Q$field\E'/
+    ;
 
     # die on set via name/alias
-    eval {
-        $class->$name('d');
-    };
-    ok($@ =~ /cannot alter/);
+    throws_ok {
+        $obj->$name('b');
+    } $ro_regex;
 
-    eval {
-        $class->$alias('d');
-    };
-    ok($@ =~ /cannot alter/);
+    throws_ok {
+        $obj->$alias('b');
+    } $ro_regex;
 
     # value should be unchanged
-    is($class->$name, 'c');
-    is($class->$alias, 'c');
+    is($obj->$name, 'a');
+    is($obj->$alias, 'a');
 };
+
+#important
+1;
@@ -1,10 +1,24 @@
 use Test::More tests => 38;
+use Test::Exception;
 use strict;
 use warnings;
 use lib 't/lib';
+
+# we test the pure-perl versions only, but allow overrides
+# from the accessor_xs test-umbrella
+# Also make sure a rogue envvar will not interfere with
+# things
+my $use_xs;
+BEGIN {
+    $Class::Accessor::Grouped::USE_XS = 0
+        unless defined $Class::Accessor::Grouped::USE_XS;
+    $ENV{CAG_USE_XS} = 1;
+    $use_xs = $Class::Accessor::Grouped::USE_XS;
+};
+
 use AccessorGroupsWO;
 
-my $class = AccessorGroupsWO->new;
+my $obj = AccessorGroupsWO->new;
 
 {
     my $warned = 0;
@@ -15,65 +29,61 @@ my $class = AccessorGroupsWO->new;
         };
     };
 
-    $class->mk_group_wo_accessors('warnings', 'DESTROY');
+    no warnings qw/once/;
+    local *AccessorGroupsWO::DESTROY = sub {};
 
+    $obj->mk_group_wo_accessors('warnings', 'DESTROY');
     ok($warned);
-
-    # restore non-accessorized DESTROY
-    no warnings;
-    *AccessorGroupsWO::DESTROY = sub {};
 };
 
-foreach (qw/singlefield multiple1 multiple2/) {
-    my $name = $_;
-    my $alias = "_${name}_accessor";
-
-    can_ok($class, $name, $alias);
-
-    # set via name
-    is($class->$name('a'), 'a');
-    is($class->{$name}, 'a');
-
-    # alias sets same as name
-    is($class->$alias('b'), 'b');
-    is($class->{$name}, 'b');
-
-    # die on get via name/alias
-    eval {
-        $class->$name;
-    };
-    ok($@ =~ /cannot access/);
-
-    eval {
-        $class->$alias;
-    };
-    ok($@ =~ /cannot access/);
+my $test_accessors = {
+    singlefield => {
+        is_xs => $use_xs,
+    },
+    multiple1 => {
+    },
+    multiple2 => {
+    },
+    lr1name => {
+        custom_field => 'lr1;field',
+    },
+    lr2name => {
+        custom_field => "lr2'field",
+    },
 };
 
-foreach (qw/lr1 lr2/) {
-    my $name = "$_".'name';
+for my $name (sort keys %$test_accessors) {
+
     my $alias = "_${name}_accessor";
-    my $field = "$_".'field';
+    my $field = $test_accessors->{$name}{custom_field} || $name;
 
-    can_ok($class, $name, $alias);
-    ok(!$class->can($field));
+    can_ok($obj, $name, $alias);
+
+    ok(!$obj->can($field))
+      if $field ne $name;
 
     # set via name
-    is($class->$name('c'), 'c');
-    is($class->{$field}, 'c');
+    is($obj->$name('a'), 'a');
+    is($obj->{$field}, 'a');
 
     # alias sets same as name
-    is($class->$alias('d'), 'd');
-    is($class->{$field}, 'd');
+    is($obj->$alias('b'), 'b');
+    is($obj->{$field}, 'b');
+
+    my $wo_regex = $test_accessors->{$name}{is_xs}
+        ? qr/Usage\:.+$name.*\(self, newvalue\)/
+        : qr/cannot access the value of '\Q$field\E'/
+    ;
 
     # die on get via name/alias
-    eval {
-        $class->$name;
-    };
-    ok($@ =~ /cannot access/);
+    throws_ok {
+        $obj->$name;
+    } $wo_regex;
 
-    eval {
-        $class->$alias;
-    };
-    ok($@ =~ /cannot access/);
+    throws_ok {
+        $obj->$alias;
+    } $wo_regex;
 };
+
+# important
+1;
\ No newline at end of file
@@ -2,17 +2,38 @@ use strict;
 use warnings;
 use FindBin qw($Bin);
 use File::Spec::Functions;
+use File::Spec::Unix (); # need this for %INC munging
 use Test::More;
 use lib 't/lib';
 
 BEGIN {
-    # Enable XSAccessor check
-    $Class::Accessor::Grouped::hasXS = undef;
-    
-    require AccessorGroups;
+    require Class::Accessor::Grouped;
+    my $xsa_ver = $Class::Accessor::Grouped::__minimum_xsa_version;
+    eval {
+        require Class::XSAccessor;
+        Class::XSAccessor->VERSION ($xsa_ver);
+    };
+    plan skip_all => "Class::XSAccessor >= $xsa_ver not available"
+      if $@;
 }
- 
-plan skip_all => 'Class::XSAccessor not available'
-    unless Class::Accessor::Grouped::_hasXS();
 
-require( catfile($Bin, 'accessors.t') );
\ No newline at end of file
+# rerun the regular 3 tests under XSAccessor
+$Class::Accessor::Grouped::USE_XS = 1;
+for my $tname (qw/accessors.t accessors_ro.t accessors_wo.t/) {
+
+  subtest "$tname with USE_XS (pass $_)" => sub {
+    my $tfn = catfile($Bin, $tname);
+
+    delete $INC{$_} for (
+      qw/AccessorGroups.pm AccessorGroupsRO.pm AccessorGroupsSubclass.pm AccessorGroupsWO.pm/,
+      File::Spec::Unix->catfile ($tfn),
+    );
+
+    local $SIG{__WARN__} = sub { warn @_ unless $_[0] =~ /subroutine .+ redefined/i };
+
+    do($tfn);
+
+  } for (1 .. 2);
+}
+
+done_testing;
@@ -1,5 +1,5 @@
 #!perl -wT
-# $Id: basic.t 3252 2007-05-06 02:24:39Z claco $
+# $Id: /mirror/Class-Accessor-Grouped/trunk/t/basic.t 3253 2007-05-06T02:24:39.381139Z claco  $
 use strict;
 use warnings;
 
@@ -1,18 +1,18 @@
 use Test::More tests => 8;
+use Test::Exception;
 use strict;
 use warnings;
 use lib 't/lib';
 use Class::Inspector;
-use AccessorGroups;
+use AccessorGroupsComp;
 
-is(AccessorGroups->result_class, undef);
+is(AccessorGroupsComp->result_class, undef);
 
 ## croak on set where class can't be loaded and it's a physical class
-my $dying = AccessorGroups->new;
-eval {
+my $dying = AccessorGroupsComp->new;
+throws_ok {
     $dying->result_class('NotReallyAClass');
-};
-ok($@ =~ /Could not load result_class 'NotReallyAClass'/);
+} qr/Could not load result_class 'NotReallyAClass'/;
 is($dying->result_class, undef);
 
 
@@ -22,10 +22,10 @@ $dying->result_class('JunkiesNeverInstalled');
 is($dying->result_class, 'JunkiesNeverInstalled');
 
 ok(!Class::Inspector->loaded('BaseInheritedGroups'));
-AccessorGroups->result_class('BaseInheritedGroups');
+AccessorGroupsComp->result_class('BaseInheritedGroups');
 ok(Class::Inspector->loaded('BaseInheritedGroups'));
-is(AccessorGroups->result_class, 'BaseInheritedGroups');
+is(AccessorGroupsComp->result_class, 'BaseInheritedGroups');
 
 ## unset it
-AccessorGroups->result_class(undef);
-is(AccessorGroups->result_class, undef);
\ No newline at end of file
+AccessorGroupsComp->result_class(undef);
+is(AccessorGroupsComp->result_class, undef);
@@ -1,4 +1,5 @@
 use Test::More tests => 36;
+use Test::Exception;
 use strict;
 use warnings;
 use lib 't/lib';
@@ -57,15 +58,13 @@ is(BaseInheritedGroups->basefield, 'All Your Base');
 # croak on get/set on non hash-based object
 my $dying = NotHashBased->new;
 
-eval {
+throws_ok {
     $dying->killme;
-};
-ok($@ =~ /Cannot get.*is not hash-based/);
+} qr/Cannot get.*is not hash-based/;
 
-eval {
+throws_ok {
     $dying->killme('foo');
-};
-ok($@ =~ /Cannot set.*is not hash-based/);
+} qr/Cannot set.*is not hash-based/;
 
 # make sure we're get defined items, even 0, ''
 BaseInheritedGroups->basefield('base');
@@ -4,12 +4,30 @@ use warnings;
 use base 'Class::Accessor::Grouped';
 
 __PACKAGE__->mk_group_accessors('simple', 'singlefield');
-__PACKAGE__->mk_group_accessors('simple', qw/multiple1 multiple2/);
-__PACKAGE__->mk_group_accessors('simple', [qw/lr1name lr1field/], [qw/lr2name lr2field/]);
-__PACKAGE__->mk_group_accessors('component_class', 'result_class');
+__PACKAGE__->mk_group_accessors('multiple', qw/multiple1 multiple2/);
+__PACKAGE__->mk_group_accessors('listref', [qw/lr1name lr1;field/], [qw/lr2name lr2'field/]);
+
+sub get_simple {
+  my $v = shift->SUPER::get_simple (@_);
+  $v =~ s/ Extra tackled on$// if $v;
+  $v;
+}
+
+sub set_simple {
+  my ($self, $f, $v) = @_;
+  $v .= ' Extra tackled on' if $f eq 'singlefield';
+  $self->SUPER::set_simple ($f, $v);
+  $_[2];
+}
 
 sub new {
     return bless {}, shift;
 };
 
+foreach (qw/multiple listref/) {
+    no strict 'refs';
+    *{"get_$_"} = __PACKAGE__->can('get_simple');
+    *{"set_$_"} = __PACKAGE__->can('set_simple');
+};
+
 1;
@@ -0,0 +1,12 @@
+package AccessorGroupsComp;
+use strict;
+use warnings;
+use base 'Class::Accessor::Grouped';
+
+__PACKAGE__->mk_group_accessors('component_class', 'result_class');
+
+sub new {
+    return bless {}, shift;
+};
+
+1;
@@ -3,18 +3,17 @@ use strict;
 use warnings;
 use base 'Class::Accessor::Grouped';
 
-__PACKAGE__->mk_group_ro_accessors('single', 'singlefield');
+__PACKAGE__->mk_group_ro_accessors('simple', 'singlefield');
 __PACKAGE__->mk_group_ro_accessors('multiple', qw/multiple1 multiple2/);
-__PACKAGE__->mk_group_ro_accessors('listref', [qw/lr1name lr1field/], [qw/lr2name lr2field/]);
+__PACKAGE__->mk_group_ro_accessors('listref', [qw/lr1name lr1;field/], [qw/lr2name lr2'field/]);
 
 sub new {
     return bless {}, shift;
 };
 
-foreach (qw/single multiple listref/) {
+foreach (qw/multiple listref/) {
     no strict 'refs';
-
-    *{"get_$_"} = \&Class::Accessor::Grouped::get_simple;
+    *{"get_$_"} = __PACKAGE__->can ('get_simple');
 };
 
 1;
@@ -0,0 +1,6 @@
+package AccessorGroupsSubclass;
+use strict;
+use warnings;
+use base 'AccessorGroups';
+
+1;
@@ -3,18 +3,17 @@ use strict;
 use warnings;
 use base 'Class::Accessor::Grouped';
 
-__PACKAGE__->mk_group_wo_accessors('single', 'singlefield');
+__PACKAGE__->mk_group_wo_accessors('simple', 'singlefield');
 __PACKAGE__->mk_group_wo_accessors('multiple', qw/multiple1 multiple2/);
-__PACKAGE__->mk_group_wo_accessors('listref', [qw/lr1name lr1field/], [qw/lr2name lr2field/]);
+__PACKAGE__->mk_group_wo_accessors('listref', [qw/lr1name lr1;field/], [qw/lr2name lr2'field/]);
 
 sub new {
     return bless {}, shift;
 };
 
-foreach (qw/single multiple listref/) {
+foreach (qw/multiple listref/) {
     no strict 'refs';
-
-    *{"set_$_"} = \&Class::Accessor::Grouped::set_simple;
+    *{"set_$_"} = __PACKAGE__->can('set_simple');
 };
 
 1;
@@ -1,5 +1,5 @@
 #!perl -wT
-# $Id: manifest.t 5159 2008-11-18 02:10:02Z claco $
+# $Id: /mirror/Class-Accessor-Grouped/trunk/t/manifest.t 5160 2008-11-18T02:10:02.602151Z claco  $
 use strict;
 use warnings;
 
@@ -1,5 +1,5 @@
 #!perl -wT
-# $Id: pod_coverage.t 3252 2007-05-06 02:24:39Z claco $
+# $Id: /mirror/Class-Accessor-Grouped/trunk/t/pod_coverage.t 3253 2007-05-06T02:24:39.381139Z claco  $
 use strict;
 use warnings;
 
@@ -1,37 +0,0 @@
-#!perl -w
-# $Id: pod_spelling.t 7003 2009-07-08 02:24:06Z claco $
-use strict;
-use warnings;
-
-BEGIN {
-    use lib 't/lib';
-    use Test::More;
-
-    plan skip_all => 'set TEST_AUTHOR to enable this test' unless $ENV{TEST_AUTHOR};
-
-    eval 'use Test::Spelling 0.11';
-    plan skip_all => 'Test::Spelling 0.11 not installed' if $@;
-};
-
-set_spell_cmd('aspell list');
-
-add_stopwords(<DATA>);
-
-all_pod_files_spelling_ok();
-
-__DATA__
-Bowden
-Raygun
-Roditi
-isa
-mst
-behaviour
-further
-overridable
-Laco
-Pauley
-claco
-stylings
-fieldspec
-listref
-getters
@@ -1,5 +1,5 @@
 #!perl -wT
-# $Id: pod_syntax.t 3252 2007-05-06 02:24:39Z claco $
+# $Id: /mirror/Class-Accessor-Grouped/trunk/t/pod_syntax.t 3253 2007-05-06T02:24:39.381139Z claco  $
 use strict;
 use warnings;
 
@@ -1,5 +1,5 @@
 #!perl -wT
-# $Id: strict.t 3289 2007-05-11 01:34:21Z claco $
+# $Id: /mirror/Class-Accessor-Grouped/trunk/t/strict.t 3290 2007-05-11T01:34:21.515012Z claco  $
 use strict;
 use warnings;
 
@@ -1,5 +1,5 @@
 #!perl -wT
-# $Id: style_no_tabs.t 3252 2007-05-06 02:24:39Z claco $
+# $Id: /mirror/Class-Accessor-Grouped/trunk/t/style_no_tabs.t 3253 2007-05-06T02:24:39.381139Z claco  $
 use strict;
 use warnings;
 
@@ -1,5 +1,5 @@
 #!perl -wT
-# $Id: warnings.t 3289 2007-05-11 01:34:21Z claco $
+# $Id: /mirror/Class-Accessor-Grouped/trunk/t/warnings.t 3290 2007-05-11T01:34:21.515012Z claco  $
 use strict;
 use warnings;