| /* | |
| * 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; | |
| gwt::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 gwt::Value(); | |
| } | |
| gwt::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 gwt::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 gwt::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; | |
| } | |
| gwt::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; | |
| } | |
| gwt::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; | |
| } | |
| gwt::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; | |
| } | |
| gwt::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 gwt::Value& value) { | |
| if (!channel.isConnected()) { | |
| Debug::log(Debug::Debugging) << "Ignoring setProperty after disconnect" | |
| << Debug::flush; | |
| return false; | |
| } | |
| // TODO(jat): error handling? | |
| gwt::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; | |
| } |