| /* | 
 |  * Copyright 2008 Google Inc. | 
 |  * | 
 |  * Licensed under the Apache License, Version 2.0 (the "License"); you may not | 
 |  * use this file except in compliance with the License. You may obtain a copy of | 
 |  * the License at | 
 |  * | 
 |  * http://www.apache.org/licenses/LICENSE-2.0 | 
 |  * | 
 |  * Unless required by applicable law or agreed to in writing, software | 
 |  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | 
 |  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | 
 |  * License for the specific language governing permissions and limitations under | 
 |  * the License. | 
 |  */ | 
 |  | 
 | #include <string> | 
 |  | 
 | #include "Debug.h" | 
 | #include "FreeValueMessage.h" | 
 | #include "HostChannel.h" | 
 | #include "InvokeMessage.h" | 
 | #include "InvokeSpecialMessage.h" | 
 | #include "ReturnMessage.h" | 
 | #include "ServerMethods.h" | 
 | #include "scoped_ptr/scoped_ptr.h" | 
 |  | 
 | using std::string; | 
 |  | 
 | Value ServerMethods::getProperty(HostChannel& channel, SessionHandler* handler, int objectRef, | 
 |     int dispatchId) { | 
 |   if (!channel.isConnected()) { | 
 |     Debug::log(Debug::Debugging) << "Ignoring getProperty after disconnect" | 
 |         << Debug::flush; | 
 |     return Value(); | 
 |   } | 
 |   Value args[2]; | 
 |   args[0].setInt(objectRef); | 
 |   args[1].setInt(dispatchId); | 
 |   if (!InvokeSpecialMessage::send(channel, SPECIAL_GET_PROPERTY, 2, args)) { | 
 |     Debug::log(Debug::Error) << "  failed to send invoke of GetProperty(disp=" << dispatchId | 
 |         << ", obj=" << objectRef << ")" << Debug::flush; | 
 |     return Value(); | 
 |   } | 
 |   scoped_ptr<ReturnMessage> retMsg(channel.reactToMessagesWhileWaitingForReturn(handler)); | 
 |   if (!retMsg.get()) { | 
 |     Debug::log(Debug::Error) << "getProperty: get return value failed for GetProperty(disp=" | 
 |         << dispatchId << ", obj=" << objectRef << ")" << Debug::flush; | 
 |     return Value(); | 
 |   } | 
 |   return retMsg->getReturnValue(); | 
 | } | 
 |  | 
 | int ServerMethods::hasMethod(HostChannel& channel, SessionHandler* handler, int classId, | 
 |     const std::string& name) { | 
 |   if (name != "toString" && name.find("::") == string::npos) { | 
 |     // only JSNI-style names and toString are valid | 
 |     return -1; | 
 |   } | 
 |   if (!channel.isConnected()) { | 
 |     Debug::log(Debug::Debugging) << "Ignoring hasMethod after disconnect" | 
 |         << Debug::flush; | 
 |     return -2; | 
 |   } | 
 |   Value arg; | 
 |   arg.setString(name); | 
 |   if (!InvokeSpecialMessage::send(channel, SPECIAL_HAS_METHOD, 1, &arg)) { | 
 |     Debug::log(Debug::Error) << "hasMethod: invoke(hasMethod) failed" << Debug::flush; | 
 |     return -2; | 
 |   } | 
 |   scoped_ptr<ReturnMessage> retMsg(channel.reactToMessagesWhileWaitingForReturn(handler)); | 
 |   if (!retMsg.get()) { | 
 |     Debug::log(Debug::Error) << "hasMethod: get return value failed" << Debug::flush; | 
 |     return -2; | 
 |   } | 
 |   Value retval = retMsg->getReturnValue(); | 
 |   // TODO(jat): better error handling? | 
 |   return retval.isInt() ? retval.getInt() : -2; | 
 | } | 
 |  | 
 | int ServerMethods::hasProperty(HostChannel& channel, SessionHandler* handler, int classId, | 
 |     const std::string& name) { | 
 |   if (name != "toString" && name.find("::") == string::npos) { | 
 |     // only JSNI-style names and toString are valid | 
 |     return -1; | 
 |   } | 
 |   if (!channel.isConnected()) { | 
 |     Debug::log(Debug::Debugging) << "Ignoring hasProperty after disconnect" | 
 |         << Debug::flush; | 
 |     return -2; | 
 |   } | 
 |   Value arg; | 
 |   arg.setString(name); | 
 |   if (!InvokeSpecialMessage::send(channel, SPECIAL_HAS_PROPERTY, 1, &arg)) { | 
 |     Debug::log(Debug::Error) << "hasProperty: invoke(hasProperty) failed" << Debug::flush; | 
 |     return -2; | 
 |   } | 
 |   scoped_ptr<ReturnMessage> retMsg(channel.reactToMessagesWhileWaitingForReturn(handler)); | 
 |   if (!retMsg.get()) { | 
 |     Debug::log(Debug::Error) << "hasProperty: get return value failed" << Debug::flush; | 
 |     return -2; | 
 |   } | 
 |   Value retval = retMsg->getReturnValue(); | 
 |   // TODO(jat): better error handling? | 
 |   return retval.isInt() ? retval.getInt() : -2; | 
 | } | 
 |  | 
 | bool ServerMethods::setProperty(HostChannel& channel, SessionHandler* handler, int objectRef, | 
 |     int dispatchId, const Value& value) { | 
 |   if (!channel.isConnected()) { | 
 |     Debug::log(Debug::Debugging) << "Ignoring setProperty after disconnect" | 
 |         << Debug::flush; | 
 |     return false; | 
 |   } | 
 |   // TODO(jat): error handling? | 
 |   Value args[3]; | 
 |   args[0].setInt(objectRef); | 
 |   args[1].setInt(dispatchId); | 
 |   args[2] = value; | 
 |   if (!InvokeSpecialMessage::send(channel, SPECIAL_SET_PROPERTY, 3, args)) { | 
 |     Debug::log(Debug::Error) << "  failed to send invoke of SetProperty(disp=" << dispatchId | 
 |         << ", obj=" << objectRef << ")" << Debug::flush; | 
 |     return false; | 
 |   } | 
 |   scoped_ptr<ReturnMessage> retMsg(channel.reactToMessagesWhileWaitingForReturn(handler)); | 
 |   if (!retMsg.get()) { | 
 |     Debug::log(Debug::Error) << "setProperty: get return value failed for SetProperty(disp=" | 
 |         << dispatchId << ", obj=" << objectRef << ")" << Debug::flush; | 
 |     return false; | 
 |   } | 
 |   // TODO: use the returned exception? | 
 |   return !retMsg.get()->isException(); | 
 | } | 
 |  | 
 | bool ServerMethods::freeJava(HostChannel& channel, SessionHandler* handler, int idCount, | 
 |       const int* ids) { | 
 |   // If we are disconnected, assume the server will free all of these anyway. | 
 |   // This deals with the problem of getting finalizers called after the channel is dropped. | 
 |   if (!channel.isConnected()) { | 
 |     Debug::log(Debug::Debugging) << "Ignoring freeJava after disconnect" | 
 |         << Debug::flush; | 
 |     return true; | 
 |   } | 
 |   if (!FreeValueMessage::send(channel, idCount, ids)) { | 
 |     Debug::log(Debug::Error) << "  failed to send FreeValues message" << Debug::flush; | 
 |     return false; | 
 |   } | 
 |   return true; | 
 | } |