# $Id: JavaObject.pm,v 1.2 2005/01/06 16:31:17 jkremer Exp $
# Copyright 2004, Sun Microsystems, Inc. All rights reserved.
package Java::JavaObject;
use Java::JrexClient;
use Java::JrexMsg;
use Java::JVM;
use strict;

use vars qw($AUTOLOAD);

sub new {
  my($class, $client, $className, $args, $sigs) = @_;

  my $this = { "client"    => $client };

  if ( $className =~ /\$(.*)#\d*/ ){
	$this->{object}    = $className;
	$this->{className} = $1;
  }
  else {
	 $this->{className} = $className;
	 $this->{object}    = $client->invoke($className, $args, $sigs );
	 $this->{error}     = $client->error;
  }

  bless $this, "Java::JavaObject";
  return $this;
}

# Return the class name of the java object.
sub class {
  my ($this) = @_;
  return $this->{className};
}

# Assert that there is no errors with the object or
# last client call to the object.
sub assert {
  my ($this) = @_;
  return $this->{error};
}

# Get the perl object handle that is used by the java client.
sub OBJECT {
  my ($this) = @_;
  return $this->{object};
}

# determine if this java object is an instance of the given class.
sub instanceof {
   my ($this, $classname) = @_;
	return ($classname eq $this->{className});
}

sub DESTROY {
  my ($this) = @_;
#	 $client->deleteObject($this->{object});
}

# INVOKE a java method 
# $method - The name of the method on this java object to invoke. The method
#           must be public and if it throws any exceptions they can be caught
#           using an eval block and the error messageg will be available
#           in the $@ variable.
# $args   - An array reference containing all of the arguments to be passed
#           to the method.
# $sigs   - Optional argument that contains a reference to an array of
#           java data type of arguments containing the class name of the
#           arguments. The JREX environment usually guesses at what a good
#           argument type will be and uses the first match.
#           The $sigs argument removes any abiguity.
#           Note that the fully qualified class name including package must
#           be used and for arrays the [L<class>; construct must be used.
#           Example ["java.lang.Integer",
#                     "java.lang.String",
#                    "[Ljava.lang.String;"
#                   ]
sub INVOKE {
  my ($this, $method, $args, $sigs) = @_;
  my $client = $this->{client};
  if (!$client){
	 die { 'faultcode' => 'Client.exception',
			 'faultdetail' => {
                             'error' => 'java.lang.IllegalArgumentException',
									},
          'faultactor' => 'StorADE'
        };
  }
  my $retval = $client->invoke($this->{object}, $method, $args, $sigs);
  my $error = $client->error;
  if ($error){
	 my $fd = $error->{faultdetail};
	 if ($fd->{object}){
		die new Java::JavaObject($this->client, $fd->{object});
	 }
	 die $error;
  }

  if ( $retval =~ /\$(.*)#\d*/ ){
    return new Java::JavaObject($this->client, $retval);
  }
  return $retval;
}

# AUTO invoke a method with the name given by AUTOLOAD.
# The INVOKE method is then called with the input array as the
# argument list and with the default method signiture used.
sub AUTOLOAD {

  my ($this, $args) = @_;

  my $method = $AUTOLOAD;
  $method =~ s/.*:://;

  if ($args){
	 shift @_;
	 $args = \@_;
  }

  return $this->INVOKE($method, $args);
}

1;
