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 }