# $Id: JrexClient.pm,v 1.12 2004/12/06 20:38:14 jkremer Exp $
# Copyright 2004, Sun Microsystems, Inc. All rights reserved.
package Java::JrexClient;
use Java::JavaObject;
use Java::JrexMsg;
use Java::JVM;
use System;
use strict;

sub new {
  my($class, $url, $name, $pass) = @_;

  if (!$url){
	 my $jvm = new Java::JVM();
	 my $port = $jvm->getPort();
	 $url = "http://localhost:".$port."/jrex";
  }

  my $this = { url  => $url,
					name => $name,
					pass => $pass};

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

# create session for java remote execution
sub openSession {
  my ($this) = @_;
  if ($this->{session}){
	 return $this->{session};
  }
  my $cmd =  Java::JrexMsg::new( "openSession", );
  my $msg = $this->callCmd($cmd);
  $this->{msg}     = $msg;
  if ($msg){
	 $this->{session} = $msg->get("session");
  }
  return $this->{session};
}

# close a session freeing all objects.
sub closeSession {
  my ($this, $session)   = @_;
  if (!$session){
	 $session = $this->{session}
  }
  my $cmd      =  Java::JrexMsg::new( "closeSession",
												  { "session" => $session } );
  my $msg      = $this->callCmd($cmd);
  return $this->{error};
}

# create a java object.
sub create {
   my ($this, $class, $args, $sigs) = @_;

	my $cmdArgs = {
						"session" => $this->{session},
						"class"   => $class,
					  };
	if ($args){
	  $cmdArgs->{arg} = $args;
	}
	if ($sigs){
	  $cmdArgs->{sig} = $sigs;
	}
	my $cmd =  Java::JrexMsg::new( "create", $cmdArgs );

	my $msg      = $this->callCmd($cmd);
	if ($msg){
	  return $msg->get("object");
	}
}

sub evalJava {
  my ($this, $code, $args) = @_;

  $args->{_session} = $this->{session};
  return $this->invoke("com.sun.netstorage.fm.storade.agent.devkit.Eval",
									  "eval",
									  [$args, $code]);
}

sub evalJavaObject {
  my ($this, $code, $args) = @_;
  my $object = $this->evalJava($code, $args);
  if ($this->error){
	 die $this->error;
  }
  return new Java::JavaObject($this, $object);
}

sub createObject {
  my ($this, $class, $args, $sigs) = @_;

  my $object = $this->create($class, $args, $sigs);
  if ($this->error){
	 die $this->error;
  }
  return new Java::JavaObject($this, $object);
}

sub getAttribute {
  my ($this, $object, $attribute) = @_;
  my $cmdArgs = {
					  "session"   => $this->{session},
					  "object"    => $object,
					  "attribute" => $attribute
					  };
  my $cmd = Java::JrexMsg::new( "getAttribute", $cmdArgs );
  my $msg = $this->callCmd($cmd);
  if ($msg){
	 return $msg->get("object");
  }
}

sub setAttribute {
  my ($this, $object, $attribute, $value) = @_;
  my $cmdArgs = {
					  "session"   => $this->{session},
					  "object"    => $object,
					  "attribute" => $attribute,
					  "value"     => $value
					  };
  my $cmd = Java::JrexMsg::new( "setAttribute", $cmdArgs );
  my $msg = $this->callCmd($cmd);
}

# invoke a java method.
sub invoke {
  my ($this, $object, $method, $args, $sigs) = @_;

  my $cmdArgs = {
						"session" => $this->{session},
						"object"   => $object,
						"method"   => $method,
					  };
  if ($args){
	 $cmdArgs->{arg} = $args;
  }
  if ($sigs){
	 $cmdArgs->{sig} = $sigs;
  }
  my $cmd =  Java::JrexMsg::new( "invokeMethod", $cmdArgs );
  my $msg = $this->callCmd($cmd);
  $this->{msg} = $msg;
  if ($msg){
	 if ($msg->{error}){
		$this->{error} = $msg->{error};
	 }
	 return $msg->get("object");
  }
  return undef;
}

sub callCmd {
  my ($this, $cmd) = @_;

  use LWP::UserAgent;
  my $ua = LWP::UserAgent->new;

  $this->clear;
  my $req = HTTP::Request->new(POST => $this->{url});
  $req->content_type('application/soap+xml');
  my $soapdoc = $cmd->toXML();

  $req->content($soapdoc);

  if ($this->{name}){
	 $req->authorization_basic($this->{name}, $this->{pass});
  }
  else {
	 eval {
      my $ipcFile = System->get_home() . "/DATA/IPC_Access";
		$req->authorization_basic("peer", "peer");
		if ( -f "$ipcFile"){
		  if (open(O, $ipcFile)){
			 my $line = <O>;
			 chop($line);
			 my $index = rindex($line, ":");
			 my $user = substr($line, 0, $index);
			 my $pass = substr($line, $index+1);
			 $req->authorization_basic($user, $pass);
			 close(O);
		  }
		}
	 };
  }

  my $res = $ua->request($req);

  if (!$res->is_success) {
	 if ($this->{jvm_start}){
		$this->{error} = { "faultcode" => "Client",
								 "faultString" => $res->error_as_HTML,
								 "faultActor"  => "JrexClient"
							  };
		$this->{jvm_start} = undef;
		return;
	 }
	 $this->{jvm_start} = 1;
	 my $jvm = new Java::JVM();
	 $jvm->start();
	 return $this->callCmd($cmd);
  }

  $this->{jvm_start} = undef;

  $this->{response} = $res->content;
  my $soap = Java::JrexMsg::newFromXML( $res->content );
  $this->{error} = $soap->error;
  return $soap;
}

sub deleteObject {
  my ($this, $object) = @_;
  my $cmdArgs = {
					  "session"   => $this->{session},
					  "object"    => $object,
					  };
  my $cmd = Java::JrexMsg::new( "delete", $cmdArgs );
  $this->callCmd($cmd);
}

sub response {
  my ($this) = @_;
  return $this->{response};
}

sub error {
  my ($this) = @_;
  return $this->{error};
}

sub clear {
  my ($this) = @_;
  $this->{error}    = undef;
  $this->{response} = undef;
}

1;
