package textbender::a::b::rhinohideDemo::RhinohideDemo; # Copyright 2007, Michael Allan. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Textbender Software"), to deal in the Textbender Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicence, and/or sell copies of the Textbender Software, and to permit persons to whom the Textbender Software is furnished to do so, subject to the following conditions: The preceding copyright notice and this permission notice shall be included in all copies or substantial portions of the Textbender Software. THE TEXTBENDER SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE TEXTBENDER SOFTWARE OR THE USE OR OTHER DEALINGS IN THE TEXTBENDER SOFTWARE. use strict; use warnings; =pod =head1 DESCRIPTION Demonstration build of Rhinohide. =head1 EXPORTS =over 4 =cut BEGIN { use Exporter (); our @ISA; @ISA = qw( Exporter ); our @EXPORT_OK; @EXPORT_OK = qw( build_rhinohideDemo ); } our @EXPORT_OK; my $_build_cache_dir; { use textbender::a::b::Build qw( build_cache_root ensure_dir ); $_build_cache_dir = ensure_dir( build_cache_root() . '/textbender/a/b/rhinohideDemo' ); } =pod =item B (target, described in the accompanying F script) =cut sub build_clean() { use File::Path qw( rmtree ); use textbender::a::b::Build qw( build_cache_root out_dir ); print textbender::a::b::Build::call_stack_indentation() . "clean\n"; rmtree( build_cache_root() . "/textbender" ); rmtree( out_dir() ); } =pod =item B (target, described in the accompanying F script) =cut sub build_jar() { use textbender::a::b::Build qw( ensure_dir ); use textbender::a::b::FileSync qw( $from_dir sync_found $to_dir ); print textbender::a::b::Build::call_stack_indentation() . "jar\n"; compile(); # - - - my $manifest_file = $_build_cache_dir . '/jar-manifest'; open FILE, '>', $manifest_file or die; { print FILE 'Class-Path:'; for my $jar( 'rhinohide.jar', 'textbender/o/junit.jar' ) # OPT download speed: junit.jar only needed in the _signed/ deployment, for test pages; not for demo pages { print FILE ' ' . $jar; } print FILE "\n"; close FILE; # ^ beware above: "the last line of a manifest file will not be parsed if it doesn't end with a new line character." } my $jar_file = ensure_dir(out_dir()) . '/rhinohideDemo.jar'; my $manifest_file_last = $manifest_file . '-last'; my $manifest_is_changed; if( !-f $manifest_file_last || system ( "diff --brief $manifest_file $manifest_file_last > /dev/null" )) { $manifest_is_changed = 1; File::Copy::copy( $manifest_file, $manifest_file_last ) or die $!; } else { $manifest_is_changed = 0; } textbender::a::b::Java::jar ( compile_class_outdir(), $jar_file, $manifest_file, $manifest_is_changed ); return $jar_file; } =pod =item B (target, described in the accompanying F script) =cut sub build_rhinohideDemo() { # cf. textbender::a::b::rhinohide::Rhinohide::build_rhinohide() use File::Basename qw( basename ); use textbender::a::b::Build qw( ensure_dir %option out_dir ); use textbender::a::b::FileSync qw( $from_dir sync_found sync_to_file $to_dir ); use textbender::a::b::base::Base(); use textbender::a::b::rhinohide::Rhinohide(); print textbender::a::b::Build::call_stack_indentation() . "rhinohideDemo\n"; # demo files, dependencies, and all the rest of the source # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $from_dir = 'textbender'; $to_dir = out_dir() . '/textbender'; File::Find::find( {follow_fast=>1, no_chdir=>1, wanted=>sub { my $f = $File::Find::name; jar: { $f =~ m'\.jar$' or last jar; $f eq 'textbender/o/junit.jar' and last jar; return; # no other jars are needed } sync_found(); }}, $from_dir ); # test/demo pages # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - File::Find::find( {follow_fast=>1, no_chdir=>1, wanted=>sub { my $outfile = $File::Find::name; # textbender/a/b/rhinohideDemo/_/bar.xht_source.txt $outfile =~ s:_source\.txt$:: or return; # textbender/a/b/rhinohideDemo/_/bar.xht $outfile =~ s:_/([^/]+)$:$1: or return; # textbender/a/b/rhinohideDemo/bar.xht sync_to_file ( $File::Find::name, out_dir() . '/' . $outfile ); }}, 'textbender/a/b/rhinohideDemo' ); # rhinohide.jar # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - textbender::a::b::rhinohide::Rhinohide::build_jar(); # rhinohideDemo.jar # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - build_jar(); # signed copies of jars, for JUnit test applets (JUnit needs reflection) # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - my $signed_out_dir = ensure_dir( out_dir() . '/_signed' ); $from_dir = out_dir(); $to_dir = $signed_out_dir; File::Find::find( {follow_fast=>1, no_chdir=>1, wanted=>sub { my $f = $File::Find::name; $f =~ m'/_signed\b' and return; # avoid endless nest/loop -d $f || $f =~ m'\.jar$' or return; sync_found(); }}, $from_dir ); $option{'sign'} && textbender::a::b::base::Base::sign_all( $signed_out_dir ); } =pod =item B Compiles out-of-sync source files *.java to *.class. Returns the number of files compiled. =cut my $compile__print_count; sub _compile__print_all_source() # File::Find::find wanted sub { # cf. textbender::a::b::Java::_compile__print_all_source() my $file = $File::Find::name; -d $file and return; # skip directories my $outfile = $file; # textbender/foo/bar.java $outfile =~ s:\.java$:.class: or return; # textbender/foo/bar.class -l $file && $file =~ m'/\.\#[^/]+$' and die "\nemacs lock file (do you need to save this buffer?): $_\n"; $outfile = compile_class_outdir() . '/' . $outfile; # /dir/textbender/foo/bar.class if( -f $outfile ) { File::stat::stat($file)->mtime > File::stat::stat($outfile)->mtime or return; } else # finally, filter by path (last because we still want to compile off-path dependencies (pulled in by javac on the last path) that are now out-of-date { $file =~ m:^textbender/a/b/rhinohideDemo/: or return; } print ARGFILE $file; print ARGFILE "\n"; ++$compile__print_count; } sub compile() { # cf. textbender::a::b::Java::_compile() use File::Find (); use textbender::a::b::Console qw( print_score $verbosity ); use textbender::a::b::Build qw( build_cache_root ensure_dir ); use textbender::a::b::Java qw( JDK_dir ); my $compile_class_outdir = ensure_dir( compile_class_outdir() ); my $command = JDK_dir() . '/bin/javac' . ' -sourcepath .' . " -d $compile_class_outdir" . ' -deprecation -g' # Though deprecation warnings are emitted only for single-file compiles, # with or without -deprecation, in 1.4, # . ' -source ' . textbender::a::b::Java::major_version() ## latest is the default in 1.5 # . ' -target ' . textbender::a::b::Java::major_version() ## latest is the default in 1.5 # . ' -verbose' . ' -Xlint' # new in 1.5 . ' -Xlint:-serial'; # because its documentation (especially for @serialField and @serialData) is incomprehensible local *ARGFILE; my $argfile; # source # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $argfile = build_cache_root() . '/textbender/a/b/Java-compile-arg-source'; open ARGFILE, '>', $argfile or die; { $compile__print_count = 0; # thus far File::Find::find ( {follow_fast=>1, no_chdir=>1, wanted=>\&_compile__print_all_source}, 'textbender' ); close ARGFILE; } $compile__print_count or return 0; $command .= ' @' . $argfile; # classpath # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $argfile = build_cache_root() . '/textbender/a/b/Java-compile-arg-classpath'; open ARGFILE, '>', $argfile or die; { print ARGFILE "-classpath $compile_class_outdir"; for my $file ( out_dir() . '/rhinohide.jar', out_dir() . '/textbender/o/junit.jar', JDK_dir() . '/jre/lib/plugin.jar' # for JSObject (in-browser code) ){ print ARGFILE ':'; print ARGFILE $file; } # ` ` ` print ARGFILE "\n"; close ARGFILE; } $command .= ' @' . $argfile; # - - - print textbender::a::b::Build::call_stack_indentation() . "(compile $compile__print_count...\n"; if( $verbosity ) { print "\n$command\n"; print_score( undef, '^' ); } system $command and exit; return $compile__print_count; } =pod =item B Returns the directory to which compiled Java (*.class) files are output. =cut sub compile_class_outdir() { use textbender::a::b::Build qw( build_cache_root ); return build_cache_root() . '/textbender/a/b/rhinohideDemo/compile-out'; } =pod =back =cut 1;