[libinline-java-perl] 216/398: Core for 0.40 is ready.
Jonas Smedegaard
dr at jones.dk
Thu Feb 26 11:43:05 UTC 2015
This is an automated email from the git hooks/post-receive script.
js pushed a commit to tag 0.55
in repository libinline-java-perl.
commit af088f3119c3d91cc59fe9853ba157d4a40f0ddf
Author: patrick_leb <>
Date: Fri Mar 21 15:55:48 2003 +0000
Core for 0.40 is ready.
---
Java.pm | 85 ++++++----
Java/JNI.xs | 8 +-
Java/JVM.pm | 2 +-
Java/Makefile.PL | 3 +-
Java/Portable.pm | 26 ++-
Java/Protocol.pm | 28 +++-
Java/sources/InlineJavaArray.java | 2 +
Java/sources/InlineJavaCastException.java | 2 +
Java/sources/InlineJavaClass.java | 4 +-
Java/sources/InlineJavaException.java | 6 +-
.../InlineJavaInvocationTargetException.java | 4 +-
Java/sources/InlineJavaPerlCaller.java | 8 +-
Java/sources/InlineJavaPerlException.java | 12 +-
Java/sources/InlineJavaProtocol.java | 36 ++--
Java/sources/InlineJavaServer.java | 45 +++--
Java/sources/InlineJavaServerThread.java | 30 +++-
Java/sources/InlineJavaTest.java | 8 -
Java/sources/InlineJavaThrown.java | 5 +-
Java/sources/InlineJavaUserClassLink.java | 45 +++++
Java/sources/InlineJavaUserClassLoader.java | 183 ++++++++++++++++++++-
Java/sources/InlineJavaUtils.java | 9 +
Makefile.PL | 43 +++--
t/10_5_shared_fork.t | 21 ++-
t/12_callbacks.t | 35 ++--
24 files changed, 501 insertions(+), 149 deletions(-)
diff --git a/Java.pm b/Java.pm
index 71fb12b..ac275ec 100644
--- a/Java.pm
+++ b/Java.pm
@@ -52,10 +52,6 @@ my $JVM = undef ;
my $INLINES = {} ;
-# Add the directory where our jar file is to the classpath
-$ENV{CLASSPATH} = Inline::Java::Portable::make_classpath(get_jar()) ;
-
-
# This stuff is to control the termination of the Java Interpreter
sub done {
my $signal = shift ;
@@ -174,19 +170,25 @@ sub set_option {
if (! exists($o->{ILSM}->{$name})){
my $val = undef ;
if (($env_or)&&(exists($ENV{"PERL_INLINE_JAVA_$name"}))){
- $val = $ENV{"PERL_INLINE_JAVA_$name"} || '' ;
+ $val = $ENV{"PERL_INLINE_JAVA_$name"} ;
}
elsif (exists($opts->{$name})){
- $val = $opts->{$name} || '' ;
+ $val = $opts->{$name} ;
}
else{
$val = $default ;
}
if ($type eq 'b'){
+ if (! defined($val)){
+ $val = 0 ;
+ }
$val = ($val ? 1 : 0) ;
}
elsif ($type eq 'i'){
+ if ((! defined($val))||($val !~ /\d/)){
+ $val = 0 ;
+ }
$val = int($val) ;
}
@@ -272,6 +274,8 @@ sub build {
"javac" . portable("EXE_EXTENSION")) ;
my $redir = portable("IO_REDIR") ;
+ my $cp = $ENV{CLASSPATH} || '' ;
+ $ENV{CLASSPATH} = make_classpath($o->get_java_config('CLASSPATH'), get_server_jar()) ;
my $cmd = "\"$javac\" -d \"$install_dir\" $source > cmd.out $redir" ;
if ($o->get_config('UNTAINT')){
($cmd) = $cmd =~ /(.*)/ ;
@@ -281,6 +285,7 @@ sub build {
$res and do {
croak $o->compile_error_msg($cmd) ;
} ;
+ $ENV{CLASSPATH} = $cp ;
# When we run the commands, we quote them because in WIN32 you need it if
# the programs are in directories which contain spaces. Unfortunately, in
@@ -300,6 +305,15 @@ sub build {
}
}
}
+ my $modfname = $o->get_api('modfname') ;
+ my $suffix = $o->get_api('suffix') ;
+
+ # Touch the .jdat file.
+ my $jdat = File::Spec->catfile($install_dir, $o->get_api('modfname') . '.' . $o->get_api('suffix')) ;
+ if (! open(Inline::Java::TOUCH, ">$jdat")){
+ croak "Can't create file $jdat" ;
+ }
+ close(Inline::Java::TOUCH) ;
# Go back and clean up
chdir $cwd ;
@@ -358,16 +372,17 @@ sub load {
'auto', $o->get_api('modpname')) ;
# If the JVM is not running, we need to start it here.
- my $cp = $ENV{CLASSPATH} ;
- my @cp = make_classpath() ;
if (! $JVM){
- $ENV{CLASSPATH} = '' ;
- $ENV{CLASSPATH} = make_classpath(get_jar()) ;
+ my $cp = $ENV{CLASSPATH} || '' ;
+ $ENV{CLASSPATH} = get_server_jar() ;
$JVM = new Inline::Java::JVM($o) ;
-
- # Add classpath entries + install to the JVM
+ $ENV{CLASSPATH} = $cp ;
+ # Add CLASSPATH entries + user jar + $install_dir to the JVM classpath
+ my @cp = make_classpath($o->get_java_config('CLASSPATH'), get_user_jar()) ;
my $pc = new Inline::Java::Protocol(undef, $o) ;
+ $pc->AddClassPath(@cp, $install_dir) ;
+
my $st = $pc->ServerType() ;
if ((($st eq "shared")&&(! $o->get_java_config('SHARED_JVM')))||
(($st eq "private")&&($o->get_java_config('SHARED_JVM')))){
@@ -375,10 +390,12 @@ sub load {
}
}
else{
- # Add $install entry to the JVM.
+ # Add $install_dir entry to the JVM classpath.
+ my $pc = new Inline::Java::Protocol(undef, $o) ;
+ $pc->AddClassPath($install_dir) ;
}
- # Add our Inline object to the list.
+ my $study_module_classes = 1 ;
my $prev_o = $INLINES->{$modfname} ;
if (defined($prev_o)){
Inline::Java::debug(2, "module '$modfname' was already loaded, importing binding into new instance") ;
@@ -386,15 +403,17 @@ sub load {
$o->{ILSM}->{data} = [] ;
}
push @{$o->{ILSM}->{data}}, @{$prev_o->{ILSM}->{data}} ;
+ $study_module_classes = 0 ;
}
+ # Add our Inline object to the list.
$INLINES->{$modfname} = $o ;
my $classes = [] ;
if ((defined($o->get_java_config('STUDY')))&&(scalar($o->get_java_config('STUDY')))){
- $classes = $o->_study($o->get_java_config('STUDY')) ;
+ $classes = $o->get_java_config('STUDY') ;
}
- $o->_study($classes, 1) ;
+ $o->_study($classes, $study_module_classes) ;
$o->set_java_config('loaded', 1) ;
Inline::Java::debug(1, "load done.") ;
@@ -406,10 +425,11 @@ sub load {
sub _study {
my $o = shift ;
my $classes = shift ;
+ my $study_module = shift ;
# Then we ask it to give us the public symbols from the classes
# that we got.
- my @lines = $o->report($classes) ;
+ my @lines = $o->report($classes, $study_module) ;
# Now we read up the symbols and bind them to Perl.
$o->bind_jdat($o->load_jdat(@lines)) ;
@@ -421,32 +441,32 @@ sub _study {
sub report {
my $o = shift ;
my $classes = shift ;
- my $load = shift || 0 ;
+ my $study_module = shift || 0 ;
my $install_dir = File::Spec->catdir($o->get_api('install_lib'),
'auto', $o->get_api('modpname')) ;
my $cache = $o->get_api('modfname') . '.' . $o->get_api('suffix') ;
- # If search_dir is valid that means that we are really at module load time,
- # or else we are just studying a specific class via AUTOSTUDY.
- if (($load)&&(! $o->get_java_config('built'))){
+ if (($study_module)&&(! $o->get_java_config('built'))){
# Since we didn't build the module, this means that
# it was up to date. We can therefore use the data
# from the cache
Inline::Java::debug(1, "using jdat cache") ;
my $p = File::Spec->catfile($install_dir, $cache) ;
- if (open(Inline::Java::CACHE, "<$p")){
- my $resp = join("", <Inline::Java::CACHE>) ;
- close(Inline::Java::CACHE) ;
- return split("\n", $resp) ;
- }
- else{
- croak "Can't open $p for reading: $!" ;
+ my $size = (-s $p) || 0 ;
+ if ($size > 0){
+ if (open(Inline::Java::CACHE, "<$p")){
+ my $resp = join("", <Inline::Java::CACHE>) ;
+ close(Inline::Java::CACHE) ;
+ return split("\n", $resp) ;
+ }
+ else{
+ croak "Can't open $p for reading: $!" ;
+ }
}
}
- # Ok, we really have some classes to study.
- if ($load){
+ if ($study_module){
# We need to add the classes that are in the directory or under...
my @cl = Inline::Java::Portable::find_classes_in_dir($install_dir) ;
foreach my $class (@cl){
@@ -467,12 +487,13 @@ sub report {
if (! scalar(@new_classes)){
return () ;
}
-
+
+ # Ok, there are some classes in there that we don't know about.
# Ask for the info on the classes
my $pc = new Inline::Java::Protocol(undef, $o) ;
my $resp = $pc->Report(join(" ", @new_classes)) ;
- if (($load)&&($o->get_java_config('built'))){
+ if (($study_module)&&($o->get_java_config('built'))){
# Update the cache.
Inline::Java::debug(1, "updating jdat cache") ;
my $p = File::Spec->catfile($install_dir, $cache) ;
diff --git a/Java/JNI.xs b/Java/JNI.xs
index 84b6372..076168c 100644
--- a/Java/JNI.xs
+++ b/Java/JNI.xs
@@ -180,15 +180,17 @@ new(CLASS, classpath, embedded, debug)
/* Load the classes that we will use */
- RETVAL->ijs_class = (*(env))->FindClass(env, "InlineJavaServer") ;
+ RETVAL->ijs_class = (*(env))->FindClass(env, "org/perl/inline/java/InlineJavaServer") ;
check_exception(env, "Can't find class InlineJavaServer") ;
RETVAL->string_class = (*(env))->FindClass(env, "java/lang/String") ;
check_exception(env, "Can't find class java.lang.String") ;
/* Get the method ids that are needed later */
- RETVAL->jni_main_mid = (*(env))->GetStaticMethodID(env, RETVAL->ijs_class, "jni_main", "(I)LInlineJavaServer;") ;
+ RETVAL->jni_main_mid = (*(env))->GetStaticMethodID(env, RETVAL->ijs_class, "jni_main",
+ "(I)Lorg/perl/inline/java/InlineJavaServer;") ;
check_exception(env, "Can't find method jni_main in class InlineJavaServer") ;
- RETVAL->process_command_mid = (*(env))->GetMethodID(env, RETVAL->ijs_class, "ProcessCommand", "(Ljava/lang/String;)Ljava/lang/String;") ;
+ RETVAL->process_command_mid = (*(env))->GetMethodID(env, RETVAL->ijs_class, "ProcessCommand",
+ "(Ljava/lang/String;)Ljava/lang/String;") ;
check_exception(env, "Can't find method ProcessCommand in class InlineJavaServer") ;
/* Register the callback function */
diff --git a/Java/JVM.pm b/Java/JVM.pm
index 5bfc461..f6f7f12 100644
--- a/Java/JVM.pm
+++ b/Java/JVM.pm
@@ -74,7 +74,7 @@ sub new {
"java" . Inline::Java::portable("EXE_EXTENSION")) ;
my $shared = ($this->{shared} ? "true" : "false") ;
- my $cmd = "\"$java\" InlineJavaServer $debug $this->{port} $shared" ;
+ my $cmd = "\"$java\" org.perl.inline.java.InlineJavaServer $debug $this->{port} $shared" ;
Inline::Java::debug(1, $cmd) ;
if ($o->get_config('UNTAINT')){
($cmd) = $cmd =~ /(.*)/ ;
diff --git a/Java/Makefile.PL b/Java/Makefile.PL
index 3e8ff86..d06d272 100644
--- a/Java/Makefile.PL
+++ b/Java/Makefile.PL
@@ -127,7 +127,6 @@ sub search {
if ($File::Find::dir =~ /jre/){
if ($file =~ /\.$ext$/){
my $dir = File::Spec->canonpath($File::Find::dir) ;
- print "---> $File::Find::dir\n" ;
$so_dirs{$dir} = 1 ;
}
}
@@ -208,7 +207,7 @@ sub Choose {
}
print "$cnt- $f\n" ;
}
- my $idx = AskSub("Please select from the above list (using the corresponding number) which '$f' to use",
+ my $idx = AskSub("Please select from the above list (using the corresponding number) which '$f' to use:",
$def, sub {(($_[0] >= 1)&&($_[0] <= $cnt))}) ;
$o->{selected} = $o->{choices}->[int($idx) - 1] ;
diff --git a/Java/Portable.pm b/Java/Portable.pm
index fb8a432..425783d 100644
--- a/Java/Portable.pm
+++ b/Java/Portable.pm
@@ -1,7 +1,7 @@
package Inline::Java::Portable ;
@Inline::Java::Portable::ISA = qw(Exporter) ;
- at EXPORT = qw(portable make_classpath get_jar) ;
+ at EXPORT = qw(portable make_classpath get_server_jar get_user_jar) ;
use strict ;
@@ -12,6 +12,7 @@ $Inline::Java::Portable::VERSION = '0.40' ;
use Exporter ;
use Carp ;
use Config ;
+use Cwd ;
use File::Find ;
use File::Spec ;
@@ -61,12 +62,12 @@ sub make_classpath {
$p = portable("SUB_FIX_CLASSPATH", $p) ;
}
- # Remove duplicates, but preserve order
+ # Remove duplicates, remove invalids but preserve order
my @fcp = () ;
my %cp = map {$_ => 1} @cp ;
foreach my $p (@cp){
- if (($p)&&($cp{$p})){
- push @fcp, $p ;
+ if (($p)&&($cp{$p})&&(-e $p)){
+ push @fcp, (-d $p ? Cwd::abs_path($p) : $p) ;
delete $cp{$p} ;
}
}
@@ -78,11 +79,20 @@ sub make_classpath {
}
-sub get_jar {
- return File::Spec->catfile(
+sub get_jar_dir {
+ return File::Spec->catdir(
(File::Spec->splitpath($INC{"Inline/Java.pm"}))[0,1],
- 'Java', 'jar', 'InlineJava.jar'
- ) ;
+ 'Java') ;
+}
+
+
+sub get_server_jar {
+ return File::Spec->catfile(get_jar_dir(), 'InlineJavaServer.jar') ;
+}
+
+
+sub get_user_jar {
+ return File::Spec->catfile(get_jar_dir(), 'InlineJavaUser.jar') ;
}
diff --git a/Java/Protocol.pm b/Java/Protocol.pm
index 52e4646..ee9c660 100644
--- a/Java/Protocol.pm
+++ b/Java/Protocol.pm
@@ -9,6 +9,8 @@ use Inline::Java::Object ;
use Inline::Java::Array ;
use Carp ;
+my %CLASSPATH_ENTRIES = () ;
+
sub new {
my $class = shift ;
@@ -24,6 +26,28 @@ sub new {
}
+sub AddClassPath {
+ my $this = shift ;
+ my @paths = @_ ;
+
+ @paths = map {
+ my $e = $_ ;
+ if ($CLASSPATH_ENTRIES{$e}){
+ return () ;
+ }
+ else{
+ Inline::Java::debug(1, "adding to classpath: '$e'") ;
+ $CLASSPATH_ENTRIES{$e} = 1 ;
+ }
+ $e ;
+ } @paths ;
+
+ my $data = "add_classpath " . join(" ", map {encode($_)} @paths) ;
+
+ return $this->Send($data, 1) ;
+}
+
+
sub ServerType {
my $this = shift ;
@@ -342,7 +366,7 @@ sub DeserializeObject {
if (Inline::Java::Class::ClassIsReference($elem_class)){
if (! Inline::Java::known_to_perl($pkg, $elem_class)){
if (($thrown)||($inline->get_java_config('AUTOSTUDY'))){
- $inline->_study([$elem_class]) ;
+ $inline->_study([$elem_class], 0) ;
}
else{
# Object is not known to Perl, it lives as a
@@ -370,7 +394,7 @@ sub DeserializeObject {
if ($thrown){
Inline::Java::debug(3, "throwing stub...") ;
- my ($msg, $score) = $obj->__isa('IJPerlException') ;
+ my ($msg, $score) = $obj->__isa('org.perl.inline.java.InlineJavaPerlException') ;
if ($msg){
die $obj ;
}
diff --git a/Java/sources/InlineJavaArray.java b/Java/sources/InlineJavaArray.java
index c05c621..c397ab4 100644
--- a/Java/sources/InlineJavaArray.java
+++ b/Java/sources/InlineJavaArray.java
@@ -1,3 +1,5 @@
+package org.perl.inline.java ;
+
import java.util.* ;
import java.lang.reflect.Array ;
diff --git a/Java/sources/InlineJavaCastException.java b/Java/sources/InlineJavaCastException.java
index 798fe21..b799689 100644
--- a/Java/sources/InlineJavaCastException.java
+++ b/Java/sources/InlineJavaCastException.java
@@ -1,3 +1,5 @@
+package org.perl.inline.java ;
+
class InlineJavaCastException extends InlineJavaException {
InlineJavaCastException(String m){
super(m) ;
diff --git a/Java/sources/InlineJavaClass.java b/Java/sources/InlineJavaClass.java
index 861076f..68d3812 100644
--- a/Java/sources/InlineJavaClass.java
+++ b/Java/sources/InlineJavaClass.java
@@ -1,3 +1,5 @@
+package org.perl.inline.java ;
+
import java.util.* ;
@@ -22,7 +24,7 @@ class InlineJavaClass {
}
try {
- Class c = Class.forName(name) ;
+ Class c = Class.forName(name, true, InlineJavaServer.GetInstance().GetUserClassLoader()) ;
return c ;
}
catch (ClassNotFoundException e){
diff --git a/Java/sources/InlineJavaException.java b/Java/sources/InlineJavaException.java
index 2143dac..7e2f3cd 100644
--- a/Java/sources/InlineJavaException.java
+++ b/Java/sources/InlineJavaException.java
@@ -1,5 +1,7 @@
-class InlineJavaException extends Exception {
- InlineJavaException(String s) {
+package org.perl.inline.java ;
+
+public class InlineJavaException extends Exception {
+ public InlineJavaException(String s) {
super(s) ;
}
}
diff --git a/Java/sources/InlineJavaInvocationTargetException.java b/Java/sources/InlineJavaInvocationTargetException.java
index d65b55d..768bb1a 100644
--- a/Java/sources/InlineJavaInvocationTargetException.java
+++ b/Java/sources/InlineJavaInvocationTargetException.java
@@ -1,5 +1,7 @@
+package org.perl.inline.java ;
+
class InlineJavaInvocationTargetException extends InlineJavaException {
- private Throwable t = null ;
+ private Throwable t ;
InlineJavaInvocationTargetException(String m, Throwable _t){
diff --git a/Java/sources/InlineJavaPerlCaller.java b/Java/sources/InlineJavaPerlCaller.java
index 04eaa38..2a14780 100644
--- a/Java/sources/InlineJavaPerlCaller.java
+++ b/Java/sources/InlineJavaPerlCaller.java
@@ -1,9 +1,9 @@
+package org.perl.inline.java ;
+
/*
Callback to Perl...
-
- This class has user visibility so methods must be public.
*/
-class InlineJavaPerlCaller {
+public class InlineJavaPerlCaller {
public InlineJavaPerlCaller(){
}
@@ -14,6 +14,6 @@ class InlineJavaPerlCaller {
public Object CallPerl(String pkg, String method, Object args[], String cast) throws InlineJavaException, InlineJavaPerlException {
- return InlineJavaServer.instance.Callback(pkg, method, args, cast) ;
+ return InlineJavaServer.GetInstance().Callback(pkg, method, args, cast) ;
}
}
diff --git a/Java/sources/InlineJavaPerlException.java b/Java/sources/InlineJavaPerlException.java
index 4f78755..a8bf663 100644
--- a/Java/sources/InlineJavaPerlException.java
+++ b/Java/sources/InlineJavaPerlException.java
@@ -1,13 +1,11 @@
-/*
- This object can have user visibility and therefore
- must have public methods.
-*/
+package org.perl.inline.java ;
-class InlineJavaPerlException extends Exception {
- private Object obj = null ;
+public class InlineJavaPerlException extends Exception {
+ private Object obj ;
- InlineJavaPerlException(Object o) {
+
+ public InlineJavaPerlException(Object o){
obj = o ;
}
diff --git a/Java/sources/InlineJavaProtocol.java b/Java/sources/InlineJavaProtocol.java
index 694ae83..28cdd16 100644
--- a/Java/sources/InlineJavaProtocol.java
+++ b/Java/sources/InlineJavaProtocol.java
@@ -1,3 +1,5 @@
+package org.perl.inline.java ;
+
import java.util.* ;
import java.lang.reflect.* ;
@@ -11,7 +13,7 @@ class InlineJavaProtocol {
private InlineJavaClass ijc ;
private InlineJavaArray ija ;
private String cmd ;
- private String response ;
+ private String response = null ;
InlineJavaProtocol(InlineJavaServer _ijs, String _cmd) {
@@ -39,6 +41,9 @@ class InlineJavaProtocol {
else if (c.equals("get_member")){
GetJavaMember(st) ;
}
+ else if (c.equals("add_classpath")){
+ AddClassPath(st) ;
+ }
else if (c.equals("server_type")){
ServerType(st) ;
}
@@ -133,6 +138,15 @@ class InlineJavaProtocol {
}
+ void AddClassPath(StringTokenizer st) throws InlineJavaException {
+ while (st.hasMoreTokens()){
+ String path = Decode(st.nextToken()) ;
+ InlineJavaServer.GetInstance().GetUserClassLoader().AddClassPath(path) ;
+ }
+ SetResponse(null) ;
+ }
+
+
void ServerType(StringTokenizer st) throws InlineJavaException {
SetResponse(ijs.GetType()) ;
}
@@ -233,7 +247,7 @@ class InlineJavaProtocol {
Object p[] = (Object [])f.get(1) ;
try {
- Object ret = m.invoke(o, p) ;
+ Object ret = InlineJavaServer.GetInstance().GetUserClassLoader().invoke(m, o, p) ;
SetResponse(ret) ;
}
catch (IllegalAccessException e){
@@ -285,7 +299,7 @@ class InlineJavaProtocol {
String msg = "For array of type " + c.getName() + ", element " + member + ": " ;
try {
Object elem = ijc.CastArgument(type, arg) ;
- Array.set(o, idx, elem) ;
+ InlineJavaServer.GetInstance().GetUserClassLoader().array_set(o, idx, elem) ;
SetResponse(null) ;
}
catch (InlineJavaCastException e){
@@ -302,7 +316,7 @@ class InlineJavaProtocol {
Object p = (Object)fl.get(1) ;
try {
- f.set(o, p) ;
+ InlineJavaServer.GetInstance().GetUserClassLoader().set(f, o, p) ;
SetResponse(null) ;
}
catch (IllegalAccessException e){
@@ -335,7 +349,8 @@ class InlineJavaProtocol {
if (ijc.ClassIsArray(c)){
int idx = Integer.parseInt(member) ;
- SetResponse(Array.get(o, idx)) ;
+ Object ret = InlineJavaServer.GetInstance().GetUserClassLoader().array_get(o, idx) ;
+ SetResponse(ret) ;
}
else{
ArrayList fl = ValidateMember(c, member, st) ;
@@ -343,7 +358,7 @@ class InlineJavaProtocol {
Field f = (Field)fl.get(0) ;
String name = f.getName() ;
try {
- Object ret = f.get(o) ;
+ Object ret = InlineJavaServer.GetInstance().GetUserClassLoader().get(f, o) ;
SetResponse(ret) ;
}
catch (IllegalAccessException e){
@@ -377,14 +392,7 @@ class InlineJavaProtocol {
String name = p.getName() ;
Object ret = null ;
try {
- // This will allow usage of the default no-arg constructor
- if (proto.length == 0){
- ret = p.newInstance() ;
- }
- else{
- Constructor con = (Constructor)p.getConstructor(proto) ;
- ret = con.newInstance(args) ;
- }
+ ret = InlineJavaServer.GetInstance().GetUserClassLoader().create(p, args, proto) ;
}
catch (NoSuchMethodException e){
throw new InlineJavaException("Constructor for class " + name + " with signature " + InlineJavaUtils.CreateSignature(proto) + " not found: " + e.getMessage()) ;
diff --git a/Java/sources/InlineJavaServer.java b/Java/sources/InlineJavaServer.java
index da1b0ff..806a24f 100644
--- a/Java/sources/InlineJavaServer.java
+++ b/Java/sources/InlineJavaServer.java
@@ -1,3 +1,5 @@
+package org.perl.inline.java ;
+
import java.net.* ;
import java.io.* ;
import java.util.* ;
@@ -8,11 +10,10 @@ import java.util.* ;
objects.
*/
public class InlineJavaServer {
- static InlineJavaServer instance = null ;
+ private static InlineJavaServer instance = null ;
private int port = 0 ;
private boolean shared_jvm = false ;
-
private InlineJavaUserClassLoader ijucl = null ;
private HashMap thread_objects = new HashMap() ;
private int objid = 1 ;
@@ -28,25 +29,25 @@ public class InlineJavaServer {
// This constructor is used in server mode
public InlineJavaServer(String[] argv){
- init(new Integer(argv[1]).intValue()) ;
+ init(new Integer(argv[0]).intValue()) ;
- port = Integer.parseInt(argv[2]) ;
- shared_jvm = new Boolean(argv[3]).booleanValue() ;
+ port = Integer.parseInt(argv[1]) ;
+ shared_jvm = new Boolean(argv[2]).booleanValue() ;
ServerSocket ss = null ;
try {
ss = new ServerSocket(port) ;
}
catch (IOException e){
- System.err.println("Can't open server socket on port " + String.valueOf(port) +
+ InlineJavaUtils.Fatal("Can't open server socket on port " + String.valueOf(port) +
": " + e.getMessage()) ;
- System.err.flush() ;
- System.exit(1) ;
}
while (true){
try {
- InlineJavaServerThread ijt = new InlineJavaServerThread(this, ss.accept()) ;
+ // For now we pass our own InlineJavaUserClassLoader, but later we can implement
+ // privacy by creating a new one.
+ InlineJavaServerThread ijt = new InlineJavaServerThread(this, ss.accept(), ijucl) ;
ijt.start() ;
if (! shared_jvm){
try {
@@ -75,6 +76,26 @@ public class InlineJavaServer {
}
+ static InlineJavaServer GetInstance(){
+ if (instance == null){
+ InlineJavaUtils.Fatal("No instance of InlineJavaServer has been created!") ;
+ }
+
+ return instance ;
+ }
+
+
+ InlineJavaUserClassLoader GetUserClassLoader(){
+ Thread t = Thread.currentThread() ;
+ if (t instanceof InlineJavaServerThread){
+ return ((InlineJavaServerThread)t).GetUserClassLoader() ;
+ }
+ else{
+ return ijucl ;
+ }
+ }
+
+
String GetType(){
return (shared_jvm ? "shared" : "private") ;
}
@@ -220,10 +241,10 @@ public class InlineJavaServer {
if (t instanceof InlineJavaServerThread){
// Client-server mode
InlineJavaServerThread ijt = (InlineJavaServerThread)t ;
- ijt.bw.write(cmd + "\n") ;
- ijt.bw.flush() ;
+ ijt.GetWriter().write(cmd + "\n") ;
+ ijt.GetWriter().flush() ;
- resp = ijt.br.readLine() ;
+ resp = ijt.GetReader().readLine() ;
}
else{
// JNI mode
diff --git a/Java/sources/InlineJavaServerThread.java b/Java/sources/InlineJavaServerThread.java
index 9a524eb..d3aba87 100644
--- a/Java/sources/InlineJavaServerThread.java
+++ b/Java/sources/InlineJavaServerThread.java
@@ -1,18 +1,23 @@
+package org.perl.inline.java ;
+
import java.io.* ;
import java.net.* ;
import java.util.* ;
class InlineJavaServerThread extends Thread {
- InlineJavaServer ijs ;
- Socket client ;
- BufferedReader br ;
- BufferedWriter bw ;
+ private InlineJavaServer ijs ;
+ private Socket client ;
+ private BufferedReader br ;
+ private BufferedWriter bw ;
+ private InlineJavaUserClassLoader ijucl ;
+
- InlineJavaServerThread(InlineJavaServer _ijs, Socket _client) throws IOException {
+ InlineJavaServerThread(InlineJavaServer _ijs, Socket _client, InlineJavaUserClassLoader _ijucl) throws IOException {
super() ;
client = _client ;
ijs = _ijs ;
+ ijucl = _ijucl ;
br = new BufferedReader(
new InputStreamReader(client.getInputStream())) ;
@@ -21,6 +26,21 @@ class InlineJavaServerThread extends Thread {
}
+ BufferedReader GetReader(){
+ return br ;
+ }
+
+
+ BufferedWriter GetWriter(){
+ return bw ;
+ }
+
+
+ InlineJavaUserClassLoader GetUserClassLoader(){
+ return ijucl ;
+ }
+
+
public void run(){
try {
ijs.AddThread(getName()) ;
diff --git a/Java/sources/InlineJavaTest.java b/Java/sources/InlineJavaTest.java
deleted file mode 100644
index 16f27ae..0000000
--- a/Java/sources/InlineJavaTest.java
+++ /dev/null
@@ -1,8 +0,0 @@
-class InlineJavaTest {
- public static void main(String[] args){
- InlineJavaServer ijs = InlineJavaServer.jni_main(5) ;
- String resp = ijs.ProcessCommand("server_type") ;
-
- System.out.println(resp) ;
- }
-}
diff --git a/Java/sources/InlineJavaThrown.java b/Java/sources/InlineJavaThrown.java
index 92f88bd..38bee49 100644
--- a/Java/sources/InlineJavaThrown.java
+++ b/Java/sources/InlineJavaThrown.java
@@ -1,5 +1,8 @@
+package org.perl.inline.java ;
+
+
class InlineJavaThrown {
- Throwable t = null ;
+ Throwable t ;
InlineJavaThrown(Throwable _t){
t = _t ;
diff --git a/Java/sources/InlineJavaUserClassLink.java b/Java/sources/InlineJavaUserClassLink.java
new file mode 100644
index 0000000..0f2d97a
--- /dev/null
+++ b/Java/sources/InlineJavaUserClassLink.java
@@ -0,0 +1,45 @@
+import java.util.* ;
+import java.lang.reflect.* ;
+
+
+public class InlineJavaUserClassLink {
+ public InlineJavaUserClassLink(){
+ }
+
+
+ public Object invoke(Method m, Object o, Object p[]) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+ return m.invoke(o, p) ;
+ }
+
+
+ public Object get(Field f, Object o) throws IllegalAccessException, IllegalArgumentException {
+ return f.get(o) ;
+ }
+
+
+ public void set(Field f, Object o, Object p) throws IllegalAccessException, IllegalArgumentException {
+ f.set(o, p) ;
+ }
+
+
+ public Object array_get(Object o, Integer idx){
+ return Array.get(o, idx.intValue()) ;
+ }
+
+
+ public void array_set(Object o, Integer idx, Object elem) throws IllegalArgumentException {
+ Array.set(o, idx.intValue(), elem) ;
+ }
+
+
+ public Object create(Class p, Object args[], Class proto[]) throws NoSuchMethodException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+ // This will allow usage of the default no-arg constructor
+ if (proto.length == 0){
+ return p.newInstance() ;
+ }
+ else{
+ Constructor con = (Constructor)p.getConstructor(proto) ;
+ return con.newInstance(args) ;
+ }
+ }
+}
diff --git a/Java/sources/InlineJavaUserClassLoader.java b/Java/sources/InlineJavaUserClassLoader.java
index b8e4f88..b46b0e2 100644
--- a/Java/sources/InlineJavaUserClassLoader.java
+++ b/Java/sources/InlineJavaUserClassLoader.java
@@ -1,20 +1,189 @@
+package org.perl.inline.java ;
+
import java.net.* ;
import java.util.* ;
+import java.io.* ;
+import java.lang.reflect.* ;
-public class InlineJavaUserClassLoader extends URLClassLoader {
+/*
+ This is the ClassLoader that loads the users code. It is also
+ used to pass reflection calls to the InlineJavaUserClassLink
+ so that it will execute them.
+*/
+class InlineJavaUserClassLoader extends URLClassLoader {
private HashMap urls = new HashMap() ;
+ private Object link = null ;
+ private Method invoke = null ;
+ private Method get = null ;
+ private Method set = null ;
+ private Method array_get = null ;
+ private Method array_set = null ;
+ private Method create = null ;
+
public InlineJavaUserClassLoader(){
super(new URL [] {}) ;
}
- public void AddPath(URL u){
- if (urls.get(u) == null){
- urls.put(u, "1") ;
- addURL(u) ;
- }
- }
+ public void AddClassPath(String path) throws InlineJavaException {
+ try {
+ File p = new File(path) ;
+ URL u = p.toURL() ;
+ if (urls.get(u) == null){
+ urls.put(u, "1") ;
+ addURL(u) ;
+ }
+ }
+ catch (MalformedURLException e){
+ throw new InlineJavaException("Can't add invalid classpath entry '" + path + "'") ;
+ }
+ }
+
+
+ synchronized private void check_link() throws InlineJavaException {
+ if (link == null){
+ try {
+ InlineJavaUtils.debug(1, "loading InlineJavaUserClassLink via InlineJavaUserClassLoader") ;
+ Class c = Class.forName("InlineJavaUserClassLink", true, this) ;
+ link = c.newInstance() ;
+
+ invoke = find_method(c, "invoke") ;
+ get = find_method(c, "get") ;
+ set = find_method(c, "set") ;
+ array_get = find_method(c, "array_get") ;
+ array_set = find_method(c, "array_set") ;
+ create = find_method(c, "create") ;
+ }
+ catch (Exception e){
+ throw new InlineJavaException("InlineJavaUserClassLoader can't load InlineJavaUserClassLink: invalid classpath setup (" +
+ e.getClass().getName() + ": " + e.getMessage() + ")") ;
+ }
+ }
+ }
+
+
+ private Method find_method(Class c, String name) throws InlineJavaException {
+ Method ml[] = c.getMethods() ;
+ for (int i = 0 ; i < ml.length ; i++){
+ if (ml[i].getName().equals(name)){
+ return ml[i] ;
+ }
+ }
+
+ throw new InlineJavaException("Can't find method '" + name +
+ "' in class InlineJavaUserClassLink") ;
+ }
+
+
+ private Object invoke_via_link(Method m, Object p[]) throws NoSuchMethodException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InlineJavaException {
+ try {
+ return m.invoke(link, p) ;
+ }
+ catch (IllegalAccessException e){
+ throw new InlineJavaException("Can't invoke method from class InlineJavaUserClassLink: IllegalAccessException") ;
+ }
+ catch (IllegalArgumentException e){
+ throw new InlineJavaException("Can't invoke method from class InlineJavaUserClassLink: IllegalArgumentException") ;
+ }
+ catch (InvocationTargetException e){
+ Throwable t = e.getTargetException() ;
+ if (t instanceof NoSuchMethodException){
+ throw (NoSuchMethodException)t ;
+ }
+ else if (t instanceof InstantiationException){
+ throw (InstantiationException)t ;
+ }
+ else if (t instanceof IllegalAccessException){
+ throw (IllegalAccessException)t ;
+ }
+ if (t instanceof IllegalAccessException){
+ throw (IllegalAccessException)t ;
+ }
+ else if (t instanceof IllegalArgumentException){
+ throw (IllegalArgumentException)t ;
+ }
+ else if (t instanceof InvocationTargetException){
+ throw (InvocationTargetException)t ;
+ }
+ // Not sure if this is really necessary, but...
+ else if (t instanceof RuntimeException){
+ RuntimeException re = (RuntimeException)t ;
+ throw re ;
+ }
+ else{
+ // In theory this case is impossible.
+ throw new InlineJavaException("Unexpected exception of type '" +
+ t.getClass().getName() + "': " + t.getMessage()) ;
+ }
+ }
+ }
+
+
+ public Object invoke(Method m, Object o, Object p[]) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InlineJavaException {
+ check_link() ;
+ try {
+ return invoke_via_link(invoke, new Object [] {m, o, p}) ;
+ }
+ catch (NoSuchMethodException me){/* Impossible */}
+ catch (InstantiationException ie){/* Impossible */}
+ return null ;
+ }
+
+
+ public Object get(Field f, Object o) throws IllegalAccessException, IllegalArgumentException, InlineJavaException {
+ check_link() ;
+ try {
+ return invoke_via_link(get, new Object [] {f, o}) ;
+ }
+ catch (NoSuchMethodException me){/* Impossible */}
+ catch (InstantiationException ie){/* Impossible */}
+ catch (InvocationTargetException e){/* Impossible */}
+ return null ;
+ }
+
+
+ public void set(Field f, Object o, Object p) throws IllegalAccessException, IllegalArgumentException, InlineJavaException {
+ check_link() ;
+ try {
+ invoke_via_link(set, new Object [] {f, o, p}) ;
+ }
+ catch (NoSuchMethodException me){/* Impossible */}
+ catch (InstantiationException ie){/* Impossible */}
+ catch (InvocationTargetException e){/* Impossible */}
+ }
+
+
+ public Object array_get(Object o, int idx) throws InlineJavaException {
+ check_link() ;
+ try {
+ return invoke_via_link(array_get, new Object [] {o, new Integer(idx)}) ;
+ }
+ catch (NoSuchMethodException me){/* Impossible */}
+ catch (InstantiationException ie){/* Impossible */}
+ catch (IllegalAccessException iae){/* Impossible */}
+ catch (IllegalArgumentException iae){/* Impossible */}
+ catch (InvocationTargetException e){/* Impossible */}
+ return null ;
+ }
+
+
+ public void array_set(Object o, int idx, Object elem) throws IllegalArgumentException, InlineJavaException {
+ check_link() ;
+ try {
+ invoke_via_link(array_set, new Object [] {o, new Integer(idx), elem}) ;
+ }
+ catch (NoSuchMethodException me){/* Impossible */}
+ catch (InstantiationException ie){/* Impossible */}
+ catch (IllegalAccessException iae){/* Impossible */}
+ catch (InvocationTargetException e){/* Impossible */}
+ }
+
+
+ public Object create(Class p, Object args[], Class proto[]) throws NoSuchMethodException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InlineJavaException {
+ check_link() ;
+ return invoke_via_link(create, new Object [] {p, args, proto}) ;
+ }
}
diff --git a/Java/sources/InlineJavaUtils.java b/Java/sources/InlineJavaUtils.java
index 7d2173a..0459f01 100644
--- a/Java/sources/InlineJavaUtils.java
+++ b/Java/sources/InlineJavaUtils.java
@@ -1,3 +1,5 @@
+package org.perl.inline.java ;
+
import java.util.* ;
@@ -38,6 +40,13 @@ class InlineJavaUtils {
}
+ static void Fatal(String msg){
+ System.err.println(msg) ;
+ System.err.flush() ;
+ System.exit(1) ;
+ }
+
+
static boolean ReverseMembers() {
String v = System.getProperty("java.version") ;
boolean no_rev = ((v.startsWith("1.2"))||(v.startsWith("1.3"))) ;
diff --git a/Makefile.PL b/Makefile.PL
index 637291f..f255d8e 100644
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -23,14 +23,21 @@ foreach my $arg (@ARGV){
@ARGV = @new_args ;
if (! $jdk_dir){
- print <<NO_J2SDK;
+ my $def_pl = File::Spec->catfile('Java', 'DefaultJ2SDK.pl') ;
+ if (-e $def_pl){
+ require File::Spec->catfile('Java', 'DefaultJ2SDK.pl') ;
+ $jdk_dir = Inline::Java::get_default_j2sdk() ;
+ }
+ else{
+ print <<NO_J2SDK;
A Java 2 SDK is required to install and use Inline::Java. Please
specify your Java 2 SDK installation directory using the J2SDK
option to Makefile.PL as such:
perl Makefile.PL J2SDK=/path/to/your/j2sdk/installation
NO_J2SDK
- exit(1) ;
+ exit(1) ;
+ }
}
elsif (! -d $jdk_dir){
print <<BAD_J2SDK;
@@ -87,19 +94,34 @@ my $jar = File::Spec->catfile($jdk_dir, 'bin', 'jar' . $ext) ;
my $src_dir = File::Spec->catdir('Java', 'sources') ;
my $src = File::Spec->catfile($src_dir, '*.java') ;
my $obj_dir = File::Spec->catdir('Java', 'classes') ;
-my $arch_dir = File::Spec->catdir('Java', 'jar') ;
-my $arch = File::Spec->catfile($arch_dir, 'InlineJava.jar') ;
+my $server_arch = File::Spec->catfile('Java', 'InlineJavaServer.jar') ;
+my $user_arch = File::Spec->catfile('Java', 'InlineJavaUser.jar') ;
+
+sub MY::top_targets {
+ my $this = shift ;
+
+ my $make = <<MAKE ;
+# Added by Inline::Java installation
+# pure_all :: java
+MAKE
+
+ return $make . $this->MM::top_targets() ;
+}
+
sub MY::postamble {
- <<MAKE;
-pure_all :: java
+ my $this = shift ;
+ my $make = <<MAKE ;
+# Added by Inline::Java installation
java ::
\@\$(MKPATH) $obj_dir
- \@\$(MKPATH) $arch_dir
"$javac" -d $obj_dir $src
- "$jar" cf $arch -C $obj_dir .
+ "$jar" cf $server_arch -C $obj_dir org
+ "$jar" cf $user_arch -C $obj_dir InlineJavaUserClassLink.class
MAKE
+
+ return $make ;
}
@@ -125,9 +147,10 @@ WriteMakefile(
PM => {
'Java.pm' => File::Spec->catfile('$(INST_LIBDIR)', 'Java.pm'),
'Java.pod'=> File::Spec->catfile('$(INST_LIBDIR)', 'Java.pod'),
- $arch => File::Spec->catfile('$(INST_LIBDIR)', $arch),
+ $server_arch => File::Spec->catfile('$(INST_LIBDIR)', $server_arch),
+ $user_arch => File::Spec->catfile('$(INST_LIBDIR)', $user_arch),
},
- clean => {FILES => "$def_jdk _Inline_test $obj_dir $arch_dir"},
+ clean => {FILES => "$def_jdk _Inline_test $obj_dir $server_arch $user_arch"},
) ;
diff --git a/t/10_5_shared_fork.t b/t/10_5_shared_fork.t
index d3af20e..df46f66 100755
--- a/t/10_5_shared_fork.t
+++ b/t/10_5_shared_fork.t
@@ -5,10 +5,19 @@ use Test ;
BEGIN {
+ require Inline::Java::Portable ;
if ($ENV{PERL_INLINE_JAVA_JNI}){
plan(tests => 0) ;
exit ;
}
+ elsif (! Inline::Java::Portable::portable('GOT_FORK')){
+ plan(tests => 0) ;
+ exit ;
+ }
+ else{
+ $t10::nb = 10 ;
+ plan(tests => $t10::nb + 1) ;
+ }
}
@@ -22,19 +31,9 @@ use Inline (
) ;
-
-if (! Inline::Java::Portable::portable('GOT_FORK')){
- plan(tests => 0) ;
- exit ;
-}
-
-
-my $nb = 10 ;
-plan(tests => $nb + 1) ;
-
-
$t10::t10::i = 0 ;
+my $nb = $t10::nb ;
my $sum = (($nb) * ($nb + 1)) / 2 ;
for (my $i = 0 ; $i < $nb ; $i++){
if (! fork()){
diff --git a/t/12_callbacks.t b/t/12_callbacks.t
index 6aa7fb6..a8616a9 100755
--- a/t/12_callbacks.t
+++ b/t/12_callbacks.t
@@ -171,6 +171,7 @@ __Java__
import java.io.* ;
+import org.perl.inline.java.* ;
class t15 extends InlineJavaPerlCaller {
class OwnException extends Exception {
@@ -199,7 +200,7 @@ class t15 extends InlineJavaPerlCaller {
return a * b ;
}
- public int silly_mul_via_perl(int a, int b) throws InlineJavaException, PerlException {
+ public int silly_mul_via_perl(int a, int b) throws InlineJavaException, InlineJavaPerlException {
int ret = 0 ;
for (int i = 0 ; i < b ; i++){
ret = add_via_perl(ret, a) ;
@@ -207,44 +208,44 @@ class t15 extends InlineJavaPerlCaller {
return ret ;
}
- public int add_via_perl(int a, int b) throws InlineJavaException, PerlException {
+ public int add_via_perl(int a, int b) throws InlineJavaException, InlineJavaPerlException {
String val = (String)CallPerl("main", "add",
new Object [] {new Integer(a), new Integer(b)}) ;
return new Integer(val).intValue() ;
}
- public int [] incr_via_perl(int a[]) throws InlineJavaException, PerlException {
+ public int [] incr_via_perl(int a[]) throws InlineJavaException, InlineJavaPerlException {
int [] r = (int [])CallPerl("main", "incr",
new Object [] {a}, "[I") ;
return r ;
}
- public void death_via_perl() throws InlineJavaException, PerlException {
+ public void death_via_perl() throws InlineJavaException, InlineJavaPerlException {
InlineJavaPerlCaller c = new InlineJavaPerlCaller() ;
c.CallPerl("main", "death", null) ;
}
- public void except() throws InlineJavaException, PerlException {
- throw new PerlException("test") ;
+ public void except() throws InlineJavaException, InlineJavaPerlException {
+ throw new InlineJavaPerlException("test") ;
}
- public int mul_via_perl(int a, int b) throws InlineJavaException, PerlException {
+ public int mul_via_perl(int a, int b) throws InlineJavaException, InlineJavaPerlException {
String val = (String)CallPerl("main", "mul",
new Object [] {new Integer(a), new Integer(b)}) ;
return new Integer(val).intValue() ;
}
- public int add_via_perl_via_java(int a, int b) throws InlineJavaException, PerlException {
+ public int add_via_perl_via_java(int a, int b) throws InlineJavaException, InlineJavaPerlException {
String val = (String)CallPerl("main", "add_via_java",
new Object [] {new Integer(a), new Integer(b)}) ;
return new Integer(val).intValue() ;
}
- static public int add_via_perl_via_java_t(t15 t, int a, int b) throws InlineJavaException, PerlException {
+ static public int add_via_perl_via_java_t(t15 t, int a, int b) throws InlineJavaException, InlineJavaPerlException {
InlineJavaPerlCaller c = new InlineJavaPerlCaller() ;
String val = (String)c.CallPerl("main", "add_via_java_t",
new Object [] {t, new Integer(a), new Integer(b)}) ;
@@ -253,7 +254,7 @@ class t15 extends InlineJavaPerlCaller {
}
- public int silly_mul_via_perl_via_java(int a, int b) throws InlineJavaException, PerlException {
+ public int silly_mul_via_perl_via_java(int a, int b) throws InlineJavaException, InlineJavaPerlException {
int ret = 0 ;
for (int i = 0 ; i < b ; i++){
String val = (String)CallPerl("main", "add_via_java",
@@ -264,14 +265,14 @@ class t15 extends InlineJavaPerlCaller {
}
- public String cat_via_perl(String a, String b) throws InlineJavaException, PerlException {
+ public String cat_via_perl(String a, String b) throws InlineJavaException, InlineJavaPerlException {
String val = (String)CallPerl("main", "cat",
new Object [] {a, b}) ;
return val ;
}
- public String twister(int max, int cnt, int explode) throws InlineJavaException, PerlException, OwnException {
+ public String twister(int max, int cnt, int explode) throws InlineJavaException, InlineJavaPerlException, OwnException {
if (cnt == max){
if (explode > 0){
throw new OwnException("throw java twister") ;
@@ -288,18 +289,16 @@ class t15 extends InlineJavaPerlCaller {
public void bug() throws InlineJavaException {
- throw new InlineJavaException(
- InlineJavaServer.instance. new InlineJavaException("bug")) ;
+ throw new InlineJavaException("bug") ;
}
- public Object perlt() throws InlineJavaException, PerlException, OwnException {
+ public Object perlt() throws InlineJavaException, InlineJavaPerlException, OwnException {
return CallPerl("main", "t", null) ;
}
- public Object perldummy() throws InlineJavaException, PerlException, OwnException {
+ public Object perldummy() throws InlineJavaException, InlineJavaPerlException, OwnException {
return CallPerl("main", "dummy", null) ;
}
-}
-
+}
\ No newline at end of file
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-perl/packages/libinline-java-perl.git
More information about the Pkg-perl-cvs-commits
mailing list