1 /* LocalDelegate.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.Poa;
40 
41 import gnu.CORBA.CDR.AbstractCdrOutput;
42 import gnu.CORBA.IOR;
43 import gnu.CORBA.IorProvider;
44 import gnu.CORBA.StreamBasedRequest;
45 
46 import org.omg.CORBA.ARG_INOUT;
47 import org.omg.CORBA.Bounds;
48 import org.omg.CORBA.Context;
49 import org.omg.CORBA.ContextList;
50 import org.omg.CORBA.ExceptionList;
51 import org.omg.CORBA.NO_IMPLEMENT;
52 import org.omg.CORBA.NVList;
53 import org.omg.CORBA.NamedValue;
54 import org.omg.CORBA.OBJECT_NOT_EXIST;
55 import org.omg.CORBA.ORB;
56 import org.omg.CORBA.Request;
57 import org.omg.CORBA.TypeCodePackage.BadKind;
58 import org.omg.CORBA.UnknownUserException;
59 import org.omg.CORBA.portable.ApplicationException;
60 import org.omg.CORBA.portable.InputStream;
61 import org.omg.CORBA.portable.InvokeHandler;
62 import org.omg.CORBA.portable.ObjectImpl;
63 import org.omg.CORBA.portable.OutputStream;
64 import org.omg.CORBA.portable.RemarshalException;
65 import org.omg.PortableServer.ServantLocatorPackage.CookieHolder;
66 
67 import java.util.Arrays;
68 
69 /**
70  * A local delegate, transferring all object requests to the locally available
71  * servant. This class is involved in handling the method invocations on the
72  * local object, obtained by POA.create_reference_with_id.
73  *
74  * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org)
75  */
76 public class LocalDelegate
77   extends org.omg.CORBA_2_3.portable.Delegate
78   implements IorProvider
79 {
80   /**
81    * The same servant as an invocation handler.
82    */
83   gnuServantObject object;
84 
85   String operation;
86 
87   public final gnuPOA poa;
88 
89   final byte[] Id;
90 
91   /**
92    * Create a local delegate, forwarding requests to the servant that must also
93    * be an invocation handler.
94    */
LocalDelegate(gnuServantObject an_object, gnuPOA a_poa, byte[] an_id)95   public LocalDelegate(gnuServantObject an_object, gnuPOA a_poa, byte[] an_id)
96   {
97     object = an_object;
98     poa = a_poa;
99     Id = an_id;
100   }
101 
102   /**
103    * Get the IOR of the connected object.
104    */
getIor()105   public IOR getIor()
106   {
107     return object.getIor();
108   }
109 
request(org.omg.CORBA.Object target, String method)110   public Request request(org.omg.CORBA.Object target, String method)
111   {
112     operation = method;
113 
114     LocalRequest rq = new LocalRequest(object, poa, Id);
115     rq.setOperation(method);
116     rq.setORB(orb(target));
117     return rq;
118   }
119 
release(org.omg.CORBA.Object target)120   public void release(org.omg.CORBA.Object target)
121   {
122   }
123 
is_equivalent(org.omg.CORBA.Object target, org.omg.CORBA.Object other)124   public boolean is_equivalent(org.omg.CORBA.Object target,
125     org.omg.CORBA.Object other)
126   {
127     if (target == other)
128       return true;
129     else if (target instanceof ObjectImpl && other instanceof ObjectImpl)
130       {
131         org.omg.CORBA.portable.Delegate a = null;
132         org.omg.CORBA.portable.Delegate b = null;
133         try
134           {
135             a = ((ObjectImpl) target)._get_delegate();
136             b = ((ObjectImpl) other)._get_delegate();
137           }
138         catch (Exception ex)
139           {
140             // Unable to get one of the delegates.
141             return false;
142           }
143         if (a instanceof LocalDelegate && b instanceof LocalDelegate)
144           {
145             byte[] k1 = ((LocalDelegate) a).Id;
146             byte[] k2 = ((LocalDelegate) b).Id;
147             return Arrays.equals(k1, k2);
148           }
149         else
150           return false;
151       }
152     else
153       return false;
154   }
155 
156   /**
157    * Always return false.
158    */
non_existent(org.omg.CORBA.Object target)159   public boolean non_existent(org.omg.CORBA.Object target)
160   {
161     return false;
162   }
163 
164   /**
165    * Get hash code.
166    */
hash(org.omg.CORBA.Object target, int maximum)167   public int hash(org.omg.CORBA.Object target, int maximum)
168   {
169     return hashCode() % maximum;
170   }
171 
172   /**
173    * Check if this object could be named by the given repository id.
174    *
175    * @param idl_id the repository id to check.
176    *
177    * @return true if it is one of the possible repository ids of this object.
178    */
is_a(org.omg.CORBA.Object a_servant, String idl_id)179   public boolean is_a(org.omg.CORBA.Object a_servant, String idl_id)
180   {
181     String[] maybe = object._ids();
182     for (int i = 0; i < maybe.length; i++)
183       {
184         if (maybe[i].equals(idl_id))
185           return true;
186       }
187     return false;
188   }
189 
190   /**
191    * Return <code>this</code>.
192    */
duplicate(org.omg.CORBA.Object target)193   public org.omg.CORBA.Object duplicate(org.omg.CORBA.Object target)
194   {
195     return target;
196   }
197 
198   /**
199    * Create request for using with DII.
200    */
create_request(org.omg.CORBA.Object target, Context context, String method, NVList parameters, NamedValue returns, ExceptionList exceptions, ContextList ctx_list)201   public Request create_request(org.omg.CORBA.Object target, Context context,
202     String method, NVList parameters, NamedValue returns,
203     ExceptionList exceptions, ContextList ctx_list)
204   {
205     operation = method;
206 
207     LocalRequest rq = new LocalRequest(object, poa, Id);
208     rq.setOperation(method);
209     rq.set_args(parameters);
210     rq.set_result(returns);
211     rq.set_exceptions(exceptions);
212     rq.set_context_list(ctx_list);
213     return rq;
214   }
215 
216   /**
217    * Create request for using with DII.
218    */
create_request(org.omg.CORBA.Object target, Context context, String method, NVList parameters, NamedValue returns)219   public Request create_request(org.omg.CORBA.Object target, Context context,
220     String method, NVList parameters, NamedValue returns)
221   {
222     operation = method;
223 
224     LocalRequest rq = new LocalRequest(object, poa, Id);
225     rq.setOperation(method);
226     rq.set_args(parameters);
227     rq.set_result(returns);
228     return rq;
229   }
230 
231   /**
232    * Not in use.
233    */
get_interface_def(org.omg.CORBA.Object target)234   public org.omg.CORBA.Object get_interface_def(org.omg.CORBA.Object target)
235   {
236     throw new NO_IMPLEMENT();
237   }
238 
239   /**
240    * Create a request to invoke the method of this CORBA object.
241    *
242    * @param operation the name of the method to invoke.
243    * @param response_expected specifies if this is one way message or the
244    * response to the message is expected.
245    *
246    * @return the stream where the method arguments should be written.
247    */
request( org.omg.CORBA.Object target, String method, boolean response_expected)248   public org.omg.CORBA.portable.OutputStream request(
249     org.omg.CORBA.Object target, String method, boolean response_expected)
250   {
251     operation = method;
252 
253     // Check if the object is not explicitly deactivated.
254     AOM.Obj e = poa.aom.get(Id);
255     if (e != null && e.isDeactiveted())
256       {
257         if (poa.servant_activator != null || poa.servant_locator != null)
258           {
259             // This will force the subsequent activation.
260             object.setServant(null);
261             e.setServant(null);
262             e.setDeactivated(false);
263           }
264         else
265           throw new OBJECT_NOT_EXIST("Deactivated");
266       }
267 
268     LocalRequest rq = new LocalRequest(object, poa, Id);
269     rq.setOperation(method);
270     rq.setORB(orb(target));
271     return rq.getParameterStream();
272   }
273 
274   /**
275    * Return the associated invocation handler.
276    */
getHandler(String method, CookieHolder cookie)277   public InvokeHandler getHandler(String method, CookieHolder cookie)
278   {
279     return object.getHandler(method, cookie, false);
280   }
281 
282   /**
283    * Return the ORB of the associated POA. The parameter is not in use.
284    */
orb(org.omg.CORBA.Object target)285   public ORB orb(org.omg.CORBA.Object target)
286   {
287     return poa.orb();
288   }
289 
290   /**
291    * Make an invocation.
292    *
293    * @param target not in use.
294    * @param output the stream request that should be returned by
295    * {@link #m_request} in this method.
296    * @throws ApplicationException if the use exception is thrown by the servant
297    * method.
298    */
invoke(org.omg.CORBA.Object target, OutputStream output)299   public InputStream invoke(org.omg.CORBA.Object target, OutputStream output)
300     throws ApplicationException
301   {
302     try
303       {
304         StreamBasedRequest sr = (StreamBasedRequest) output;
305 
306         LocalRequest lr = (LocalRequest) sr.request;
307         InvokeHandler handler = lr.object.getHandler(lr.operation(), lr.cookie,
308           false);
309 
310         if (handler instanceof DynamicImpHandler)
311           {
312             // The local request known how to handle it, but the different
313             // method must be called.
314             lr.invoke();
315 
316             // The encapsulation will inherit orb, endian, charsets, etc.
317             AbstractCdrOutput buf = sr.createEncapsulation();
318 
319             // Write all request parameters to the buffer stream.
320             if (lr.env().exception() != null)
321               {
322                 try
323                   {
324                     UnknownUserException uex = (UnknownUserException) lr.env().exception();
325                     throw new ApplicationException(uex.except.type().id(),
326                       uex.except.create_input_stream());
327                   }
328                 catch (BadKind ex)
329                   {
330                     InternalError ierr = new InternalError();
331                     ierr.initCause(ex);
332                     throw ierr;
333                   }
334               }
335             if (lr.return_value() != null)
336               lr.return_value().write_value(buf);
337 
338             NamedValue a;
339             try
340               {
341                 for (int i = 0; i < lr.arguments().count(); i++)
342                   {
343                     a = lr.arguments().item(i);
344                     if (a.flags() == ARG_INOUT.value
345                       || a.flags() == ARG_INOUT.value)
346                       {
347                         a.value().write_value(buf);
348                       }
349                   }
350               }
351             catch (Bounds ex)
352               {
353                 InternalError ierr = new InternalError();
354                 ierr.initCause(ex);
355                 throw ierr;
356               }
357 
358             return buf.create_input_stream();
359           }
360         else
361           {
362             LocalRequest lrq = (LocalRequest) sr.request;
363             return lrq.s_invoke(handler);
364           }
365       }
366     catch (gnuForwardRequest f)
367       {
368         try
369           {
370             return ((ObjectImpl) f.forward_reference)._invoke(f.forward_reference._request(
371               operation, true));
372           }
373         catch (RemarshalException e)
374           {
375             // Never thrown in this place by Classpath implementation.
376             throw new NO_IMPLEMENT();
377           }
378       }
379   }
380 
releaseReply(org.omg.CORBA.Object target, InputStream input)381   public void releaseReply(org.omg.CORBA.Object target, InputStream input)
382   {
383     release(target);
384   }
385 }
386