1 /* gnuDelegate.java -- 2 Copyright (C) 2005 Free Software Foundation, Inc. 3 4 This file is part of GNU Classpath. 5 6 GNU Classpath is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2, or (at your option) 9 any later version. 10 11 GNU Classpath is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GNU Classpath; see the file COPYING. If not, write to the 18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19 02110-1301 USA. 20 21 Linking this library statically or dynamically with other modules is 22 making a combined work based on this library. Thus, the terms and 23 conditions of the GNU General Public License cover the whole 24 combination. 25 26 As a special exception, the copyright holders of this library give you 27 permission to link this library with independent modules to produce an 28 executable, regardless of the license terms of these independent 29 modules, and to copy and distribute the resulting executable under 30 terms of your choice, provided that you also meet, for each linked 31 independent module, the terms and conditions of the license of that 32 module. An independent module is a module which is not derived from 33 or based on this library. If you modify this library, you may extend 34 this exception to your version of the library, but you are not 35 obligated to do so. If you do not wish to do so, delete this 36 exception statement from your version. */ 37 38 39 package gnu.CORBA; 40 41 import gnu.CORBA.CDR.BufferredCdrInput; 42 import gnu.CORBA.GIOP.ReplyHeader; 43 44 import org.omg.CORBA.CompletionStatus; 45 import org.omg.CORBA.Context; 46 import org.omg.CORBA.ContextList; 47 import org.omg.CORBA.ExceptionList; 48 import org.omg.CORBA.MARSHAL; 49 import org.omg.CORBA.NVList; 50 import org.omg.CORBA.NamedValue; 51 import org.omg.CORBA.ORB; 52 import org.omg.CORBA.Request; 53 import org.omg.CORBA.portable.ApplicationException; 54 import org.omg.CORBA.portable.InputStream; 55 import org.omg.CORBA.portable.OutputStream; 56 import org.omg.CORBA.portable.RemarshalException; 57 import org.omg.PortableInterceptor.ForwardRequest; 58 59 import java.io.IOException; 60 61 import java.net.Socket; 62 63 /** 64 * The Classpath implementation of the {@link Delegate} functionality in the 65 * case, when the object was constructed from an IOR object. The IOR can be 66 * constructed from the stringified object reference. 67 * 68 * There is an different instance of this delegate for each CORBA object. 69 * 70 * @author Audrius Meskauskas (AudriusA@Bioinformatics.org) 71 */ 72 public class IorDelegate extends SimpleDelegate 73 { 74 /** 75 * Contructs an instance of object using the given IOR. 76 */ IorDelegate(ORB an_orb, IOR an_ior)77 public IorDelegate(ORB an_orb, IOR an_ior) 78 { 79 super(an_orb, an_ior); 80 } 81 82 /** 83 * Creates the request to invoke the method on this object. 84 * 85 * @param target the object, for that the operation must be invoked. 86 * @param context context (null allowed) 87 * @param operation the method name 88 * @param parameters the method parameters 89 * @param returns the return value holder 90 * @param exceptions the exceptions that can be thrown by the method 91 * @param ctx_list the context list (null allowed) 92 * 93 * @return the created request. 94 */ create_request(org.omg.CORBA.Object target, Context context, String operation, NVList parameters, NamedValue returns )95 public Request create_request(org.omg.CORBA.Object target, Context context, 96 String operation, NVList parameters, NamedValue returns 97 ) 98 { 99 gnuRequest request = getRequestInstance(target); 100 101 request.setIor(getIor()); 102 request.set_target(target); 103 104 request.setOperation(operation); 105 request.set_args(parameters); 106 request.m_context = context; 107 request.set_result(returns); 108 request.setORB(orb); 109 110 return request; 111 } 112 113 /** 114 * Creates the request to invoke the method on this object. 115 * 116 * @param target the object, for that the operation must be invoked. 117 * @param context context (null allowed) 118 * @param operation the method name 119 * @param parameters the method parameters 120 * @param returns the return value holder 121 * 122 * @return the created request. 123 */ create_request(org.omg.CORBA.Object target, Context context, String operation, NVList parameters, NamedValue returns, ExceptionList exceptions, ContextList ctx_list )124 public Request create_request(org.omg.CORBA.Object target, Context context, 125 String operation, NVList parameters, NamedValue returns, 126 ExceptionList exceptions, ContextList ctx_list 127 ) 128 { 129 gnuRequest request = getRequestInstance(target); 130 131 request.setIor(ior); 132 request.set_target(target); 133 134 request.setOperation(operation); 135 request.set_args(parameters); 136 request.m_context = context; 137 request.set_result(returns); 138 request.set_exceptions(exceptions); 139 request.set_context_list(ctx_list); 140 request.setORB(orb); 141 142 return request; 143 } 144 145 /** 146 * Get the instance of request. 147 */ getRequestInstance(org.omg.CORBA.Object target)148 protected gnuRequest getRequestInstance(org.omg.CORBA.Object target) 149 { 150 return new gnuRequest(); 151 } 152 153 /** 154 * Invoke operation on the given object, als handling temproray and permanent 155 * redirections. The ReplyHeader.LOCATION_FORWARD will cause to resend the 156 * request to the new direction. The ReplyHeader.LOCATION_FORWARD_PERM will 157 * cause additionally to remember the new location by this delegate, so 158 * subsequent calls will be immediately delivered to the new target. 159 * 160 * @param target the target object. 161 * @param output the output stream, previously returned by 162 * {@link #request(org.omg.CORBA.Object, String, boolean)}. 163 * 164 * @return the input stream, to read the response from or null for a one-way 165 * request. 166 * 167 * @throws SystemException if the SystemException has been thrown on the 168 * remote side (the exact type and the minor code matches the data of the 169 * remote exception that has been thrown). 170 * 171 * @throws org.omg.CORBA.portable.ApplicationException as specified. 172 * @throws org.omg.CORBA.portable.RemarshalException as specified. 173 */ invoke(org.omg.CORBA.Object target, OutputStream output)174 public InputStream invoke(org.omg.CORBA.Object target, OutputStream output) 175 throws ApplicationException, RemarshalException 176 { 177 StreamBasedRequest request = (StreamBasedRequest) output; 178 Forwardings: while (true) 179 { 180 try 181 { 182 if (request.response_expected) 183 { 184 RawReply response = request.request.submit(); 185 186 // Read reply header. 187 ReplyHeader rh = response.header.create_reply_header(); 188 BufferredCdrInput input = response.getStream(); 189 input.setOrb(orb); 190 rh.read(input); 191 request.request.m_rph = rh; 192 193 boolean moved_permanently = false; 194 195 switch (rh.reply_status) 196 { 197 case ReplyHeader.NO_EXCEPTION: 198 if (request.request.m_interceptor != null) 199 request.request.m_interceptor.receive_reply(request.request.m_info); 200 if (response.header.version.since_inclusive(1, 2)) 201 input.align(8); 202 return input; 203 204 case ReplyHeader.SYSTEM_EXCEPTION: 205 if (response.header.version.since_inclusive(1, 2)) 206 input.align(8); 207 showException(request, input); 208 209 throw ObjectCreator.readSystemException(input, 210 rh.service_context); 211 212 case ReplyHeader.USER_EXCEPTION: 213 if (response.header.version.since_inclusive(1, 2)) 214 input.align(8); 215 showException(request, input); 216 217 throw new ApplicationException( 218 request.request.m_exception_id, input); 219 220 case ReplyHeader.LOCATION_FORWARD_PERM: 221 moved_permanently = true; 222 223 case ReplyHeader.LOCATION_FORWARD: 224 if (response.header.version.since_inclusive(1, 2)) 225 input.align(8); 226 227 IOR forwarded = new IOR(); 228 try 229 { 230 forwarded._read_no_endian(input); 231 } 232 catch (IOException ex) 233 { 234 MARSHAL t = new MARSHAL("Cant read forwarding info", 235 5102, CompletionStatus.COMPLETED_NO); 236 t.initCause(ex); 237 throw t; 238 } 239 240 gnuRequest prev = request.request; 241 gnuRequest r = getRequestInstance(target); 242 243 r.m_interceptor = prev.m_interceptor; 244 r.m_slots = prev.m_slots; 245 246 r.m_args = prev.m_args; 247 r.m_context = prev.m_context; 248 r.m_context_list = prev.m_context_list; 249 r.m_environment = prev.m_environment; 250 r.m_exceptions = prev.m_exceptions; 251 r.m_operation = prev.m_operation; 252 r.m_parameter_buffer = prev.m_parameter_buffer; 253 r.m_parameter_buffer.request = r; 254 r.m_result = prev.m_result; 255 r.m_target = prev.m_target; 256 r.oneWay = prev.oneWay; 257 r.m_forward_ior = forwarded; 258 259 if (r.m_interceptor != null) 260 r.m_interceptor.receive_other(r.m_info); 261 262 r.setIor(forwarded); 263 264 IorObject it = new IorObject(orb, 265 forwarded); 266 267 r.m_target = it; 268 269 request.request = r; 270 271 IOR prev_ior = getIor(); 272 273 setIor(forwarded); 274 275 try 276 { 277 return invoke(it, request); 278 } 279 finally 280 { 281 if (!moved_permanently) 282 setIor(prev_ior); 283 } 284 285 default: 286 throw new MARSHAL("Unknow reply status: " 287 + rh.reply_status, 8000 + rh.reply_status, 288 CompletionStatus.COMPLETED_NO); 289 } 290 } 291 else 292 { 293 request.request.send_oneway(); 294 return null; 295 } 296 } 297 catch (ForwardRequest forwarded) 298 { 299 ForwardRequest fw = forwarded; 300 Forwarding2: while (true) 301 { 302 try 303 { 304 gnuRequest prev = request.request; 305 gnuRequest r = getRequestInstance(target); 306 307 r.m_interceptor = prev.m_interceptor; 308 r.m_args = prev.m_args; 309 r.m_context = prev.m_context; 310 r.m_context_list = prev.m_context_list; 311 r.m_environment = prev.m_environment; 312 r.m_exceptions = prev.m_exceptions; 313 r.m_operation = prev.m_operation; 314 r.m_parameter_buffer = prev.m_parameter_buffer; 315 r.m_parameter_buffer.request = r; 316 r.m_result = prev.m_result; 317 r.m_target = prev.m_target; 318 r.oneWay = prev.oneWay; 319 320 r.m_forwarding_target = fw.forward; 321 322 if (r.m_interceptor != null) 323 r.m_interceptor.receive_other(r.m_info); 324 325 r.m_target = fw.forward; 326 request.request = r; 327 break Forwarding2; 328 } 329 catch (ForwardRequest e) 330 { 331 forwarded = e; 332 } 333 } 334 } 335 } 336 } 337 338 /** 339 * Show exception to interceptor. 340 */ showException(StreamBasedRequest request, BufferredCdrInput input)341 void showException(StreamBasedRequest request, BufferredCdrInput input) 342 throws ForwardRequest 343 { 344 input.mark(2048); 345 request.request.m_exception_id = input.read_string(); 346 input.reset(); 347 348 if (request.request.m_interceptor != null) 349 request.request.m_interceptor.receive_exception(request.request.m_info); 350 } 351 352 /** 353 * Create a request to invoke the method of this CORBA object. 354 * 355 * @param target the CORBA object, to that this operation must be applied. 356 * @param operation the name of the method to invoke. 357 * 358 * @return the request. 359 */ request(org.omg.CORBA.Object target, String operation)360 public Request request(org.omg.CORBA.Object target, String operation) 361 { 362 gnuRequest request = getRequestInstance(target); 363 364 request.setIor(ior); 365 request.set_target(target); 366 367 request.setOperation(operation); 368 request.setORB(orb); 369 370 return request; 371 } 372 373 /** 374 * Create a request to invoke the method of this CORBA object. 375 * 376 * @param target the CORBA object, to that this operation must be applied. 377 * @param operation the name of the method to invoke. 378 * @param response_expected specifies if this is one way message or the 379 * response to the message is expected. 380 * 381 * @return the stream where the method arguments should be written. 382 */ request(org.omg.CORBA.Object target, String operation, boolean response_expected )383 public OutputStream request(org.omg.CORBA.Object target, String operation, 384 boolean response_expected 385 ) 386 { 387 gnuRequest request = getRequestInstance(target); 388 389 request.setIor(ior); 390 request.set_target(target); 391 request.setOperation(operation); 392 393 StreamBasedRequest out = request.getParameterStream(); 394 out.response_expected = response_expected; 395 request.setORB(orb); 396 out.setOrb(orb); 397 398 return out; 399 } 400 401 /** 402 * If there is an opened cache socket to access this object, close that 403 * socket. 404 * 405 * @param target The target is not used, this delegate requires a single 406 * instance per object. 407 */ release(org.omg.CORBA.Object target)408 public void release(org.omg.CORBA.Object target) 409 { 410 String key = ior.Internet.host + ":" + ior.Internet.port; 411 412 Socket socket = SocketRepository.get_socket(key); 413 try 414 { 415 if (socket != null) 416 { 417 socket.close(); 418 } 419 } 420 catch (IOException ex) 421 { 422 // do nothing, then. 423 } 424 } 425 426 /** 427 * Reset the remote_ior flag, forcing to check if the object is local on the 428 * next getRequestInstance call. 429 */ setIor(IOR an_ior)430 public void setIor(IOR an_ior) 431 { 432 super.setIor(an_ior); 433 } 434 435 /** 436 * Checks if the ior is local so far it is easy. 437 */ is_local(org.omg.CORBA.Object self)438 public boolean is_local(org.omg.CORBA.Object self) 439 { 440 return false; 441 } 442 }