wCMF  3.6
 All Classes Namespaces Files Functions Variables Groups Pages
class.RPCClient.php
Go to the documentation of this file.
1 <?php
2 /**
3  * wCMF - wemove Content Management Framework
4  * Copyright (C) 2005-2014 wemove digital solutions GmbH
5  *
6  * Licensed under the terms of any of the following licenses
7  * at your choice:
8  *
9  * - GNU Lesser General Public License (LGPL)
10  * http://www.gnu.org/licenses/lgpl.html
11  * - Eclipse Public License (EPL)
12  * http://www.eclipse.org/org/documents/epl-v10.php
13  *
14  * See the license.txt file distributed with this work for
15  * additional information.
16  *
17  * $Id$
18  */
19 require_once(BASE."wcmf/lib/util/class.Log.php");
20 require_once(BASE."wcmf/lib/presentation/class.Request.php");
21 require_once(BASE."wcmf/lib/presentation/class.Response.php");
22 
23 /**
24  * @class RPCClient
25  * @ingroup Remoting
26  * @brief RPCClient is used to do calls to other wCMF instances on
27  * the same maschine.
28  *
29  * @author ingo herwig <ingo@wemove.com>
30  */
31 class RPCClient
32 {
33  // constants
34  const SIDS_SESSION_VARNAME = 'RPCClient.sids';
35 
36  private $_serverCli = null;
37  private $_php = null;
38  private $_user = null;
39 
40  /**
41  * Constructor
42  * @param serverCli The command line interface of the other server instance.
43  * @param user The remote user instance.
44  */
45  function __construct($serverCli, $user)
46  {
47  $this->_serverCli = realpath($serverCli);
48  if (!file_exists($this->_serverCli))
49  {
50  WCMFException::throwEx("Could not setup RPCClient: ".$this->_serverCli." not found.",
51  __FILE__, __LINE__);
52  }
53 
54  // locate the php executable
55  $parser = InifileParser::getInstance();
56  if (($this->_php = $parser->getValue('php', 'system')) === false)
57  {
58  WCMFException::throwEx("Could not setup RPCClient:\n".
59  $parser->getErrorMsg(), __FILE__, __LINE__);
60  }
61 
62  // initialize the session variable for storing session
63  $session = &SessionData::getInstance();
64  if (!$session->exist(self::SIDS_SESSION_VARNAME)) {
65  $var = array();
66  $session->set(self::SIDS_SESSION_VARNAME, $var);
67  }
68  $this->_user = $user;
69  }
70  /**
71  * Do a call to the remote server.
72  * @param request A Request instance
73  * @return A Response instance
74  */
75  function call($request)
76  {
77  $response = $this->doRemoteCall($request, false);
78  return $response;
79  }
80  /**
81  * Do a remote call.
82  * @param request The Request instance
83  * @param isLogin True/False wether this request is a login request or not
84  * @return The Response instance
85  */
86  protected function doRemoteCall($request, $isLogin)
87  {
88  // initially login, if no sessionId is set
89  $sessionId = $this->getSessionId();
90  if (!$isLogin && $sessionId == null) {
91  $response = $this->doLogin();
92  if ($response) {
93  $sessionId = $this->getSessionId();
94  }
95  }
96 
97  $jsonResponse = null;
98  $returnValue = -1;
99 
100  $request->setResponseFormat(MSG_FORMAT_JSON);
101  $serializedRequest = base64_encode(serialize($request));
102 
103  $arguments = array(
104  $serializedRequest,
105  $sessionId
106  );
107  $currentDir = getcwd();
108  chdir(dirname($this->_serverCli));
109  if (Log::isDebugEnabled(__CLASS__)) {
110  Log::debug("Do remote call to: ".$this->_serverCli, __CLASS__);
111  Log::debug("Request:\n".$request->toString(), __CLASS__);
112  }
113  // store and reopen the session (see http://bugs.php.net/bug.php?id=44942)
114  session_write_close();
115  exec($this->_php.' '.$this->_serverCli.' '.join(' ', $arguments), $jsonResponse, $returnValue);
116  session_start();
117  if (Log::isDebugEnabled(__CLASS__)) {
118  Log::debug("Response [JSON]:\n".$jsonResponse[0], __CLASS__);
119  }
120  chdir($currentDir);
121 
122  $responseData = JSONUtil::decode($jsonResponse[0], true);
123  $response = new Response('', '', '', $responseData);
124  $response->setFormat(MSG_FORMAT_JSON);
125  Formatter::deserialize($response);
126  if (Log::isDebugEnabled(__CLASS__)) {
127  Log::debug("Response:\n".$response->toString(), __CLASS__);
128  }
129 
130  if (!$response->getValue('success')) {
131  // if the session expired, try to relogin
132  if (strpos('Authorization failed', $response->getValue('errorMsg')) === 0 && !$isLogin) {
133  $this->doLogin($url);
134  }
135  else {
136  $this->handleError($response);
137  }
138  }
139  return $response;
140  }
141  /**
142  * Do the login request. If the request is successful,
143  * the session id will be set.
144  * @return True on success
145  */
146  protected function doLogin()
147  {
148  if ($this->_user)
149  {
150  $request = new Request(
151  'LoginController',
152  '',
153  'dologin',
154  array(
155  'login' => $this->_user->getLogin(),
156  'password' => $this->_user->getPassword(),
157  'password_is_encrypted' => true
158  )
159  );
160  $response = $this->doRemoteCall($request, true);
161  if ($response->getValue('success'))
162  {
163  // store the session id in the session
164  $this->setSessionId($response->getValue('sid'));
165  return true;
166  }
167  }
168  else {
169  WCMFException::throwEx("Remote user required for remote call.", __FILE__, __LINE__);
170  }
171  }
172  /**
173  * Store the session id for our server in the local session
174  * @return The session id or null
175  */
176  protected function setSessionId($sessionId)
177  {
178  $session = SessionData::getInstance();
179  $sids = $session->get(self::SIDS_SESSION_VARNAME);
180  $sids[$this->_serverCli] = $sessionId;
181  $session->set(self::SIDS_SESSION_VARNAME, $sids);
182  }
183  /**
184  * Get the session id for our server from the local session
185  * @return The session id or null
186  */
187  protected function getSessionId()
188  {
189  // check if we already have a session with the server
190  $session = &SessionData::getInstance();
191  $sids = $session->get(self::SIDS_SESSION_VARNAME);
192  if (isset($sids[$this->_serverCli])) {
193  return $sids[$this->_serverCli];
194  }
195  return null;
196  }
197  /**
198  * Error handling method
199  * @param response The Response instance
200  */
201  protected function handleError($response)
202  {
203  $errorMsg = $response->getValue('errorMsg');
204  Log::error("Error in remote call to ".$this->_serverCli.": ".$errorMsg."\n".$response->toString(), __FILE__, __LINE__);
205  WCMFException::throwEx("Error in remote call to ".$this->_serverCli.": ".$errorMsg, __FILE__, __LINE__);
206  }
207 }
208 ?>
const MSG_FORMAT_JSON
call($request)
error($message, $category)
Definition: class.Log.php:69
debug($message, $category)
Definition: class.Log.php:39
RPCClient is used to do calls to other wCMF instances on the same maschine.
setSessionId($sessionId)
Request holds the request values that are used as input to Controller instances. It is typically inst...
throwEx($message, $file='', $line='')
static decode($value, $assoc=false)
__construct($serverCli, $user)
isDebugEnabled($category)
Definition: class.Log.php:89
handleError($response)
const SIDS_SESSION_VARNAME
Response holds the response values that are used as output from Controller instances. It is typically instantiated by the ActionMapper instance and filled during Controller execution.
doRemoteCall($request, $isLogin)
deserialize(&$request)