gnuRequest.java 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424
  1. /* gnuRequest.java --
  2. Copyright (C) 2005 Free Software Foundation, Inc.
  3. This file is part of GNU Classpath.
  4. GNU Classpath is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2, or (at your option)
  7. any later version.
  8. GNU Classpath is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNU Classpath; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  15. 02110-1301 USA.
  16. Linking this library statically or dynamically with other modules is
  17. making a combined work based on this library. Thus, the terms and
  18. conditions of the GNU General Public License cover the whole
  19. combination.
  20. As a special exception, the copyright holders of this library give you
  21. permission to link this library with independent modules to produce an
  22. executable, regardless of the license terms of these independent
  23. modules, and to copy and distribute the resulting executable under
  24. terms of your choice, provided that you also meet, for each linked
  25. independent module, the terms and conditions of the license of that
  26. module. An independent module is a module which is not derived from
  27. or based on this library. If you modify this library, you may extend
  28. this exception to your version of the library, but you are not
  29. obligated to do so. If you do not wish to do so, delete this
  30. exception statement from your version. */
  31. package gnu.CORBA;
  32. import gnu.CORBA.CDR.BufferredCdrInput;
  33. import gnu.CORBA.CDR.BufferedCdrOutput;
  34. import gnu.CORBA.GIOP.MessageHeader;
  35. import gnu.CORBA.GIOP.ReplyHeader;
  36. import gnu.CORBA.GIOP.RequestHeader;
  37. import gnu.CORBA.GIOP.CodeSetServiceContext;
  38. import gnu.CORBA.Interceptor.gnuClientRequestInfo;
  39. import gnu.CORBA.Poa.ORB_1_4;
  40. import org.omg.CORBA.ARG_IN;
  41. import org.omg.CORBA.ARG_INOUT;
  42. import org.omg.CORBA.ARG_OUT;
  43. import org.omg.CORBA.Any;
  44. import org.omg.CORBA.BAD_INV_ORDER;
  45. import org.omg.CORBA.BAD_PARAM;
  46. import org.omg.CORBA.Bounds;
  47. import org.omg.CORBA.COMM_FAILURE;
  48. import org.omg.CORBA.CompletionStatus;
  49. import org.omg.CORBA.Context;
  50. import org.omg.CORBA.ContextList;
  51. import org.omg.CORBA.Environment;
  52. import org.omg.CORBA.ExceptionList;
  53. import org.omg.CORBA.INV_POLICY;
  54. import org.omg.CORBA.MARSHAL;
  55. import org.omg.CORBA.NO_IMPLEMENT;
  56. import org.omg.CORBA.NO_RESOURCES;
  57. import org.omg.CORBA.NVList;
  58. import org.omg.CORBA.NamedValue;
  59. import org.omg.CORBA.ORB;
  60. import org.omg.CORBA.Policy;
  61. import org.omg.CORBA.Request;
  62. import org.omg.CORBA.SystemException;
  63. import org.omg.CORBA.TypeCode;
  64. import org.omg.CORBA.UnknownUserException;
  65. import org.omg.CORBA.portable.ObjectImpl;
  66. import org.omg.IOP.ServiceContext;
  67. import org.omg.IOP.TAG_CODE_SETS;
  68. import org.omg.IOP.TAG_INTERNET_IOP;
  69. import org.omg.IOP.TaggedComponent;
  70. import org.omg.IOP.TaggedProfile;
  71. import org.omg.PortableInterceptor.ClientRequestInfo;
  72. import org.omg.PortableInterceptor.ClientRequestInterceptorOperations;
  73. import org.omg.PortableInterceptor.ForwardRequest;
  74. import org.omg.PortableInterceptor.InvalidSlot;
  75. import java.io.IOException;
  76. import java.io.InputStream;
  77. import java.io.OutputStream;
  78. import java.net.Socket;
  79. import java.util.ArrayList;
  80. /**
  81. * The implementation of the CORBA request.
  82. *
  83. * @author Audrius Meskauskas (AudriusA@Bioinformatics.org)
  84. */
  85. public class gnuRequest extends Request implements Cloneable
  86. {
  87. /**
  88. * The maximal supported GIOP version.
  89. */
  90. public static Version MAX_SUPPORTED = new Version(1, 2);
  91. /**
  92. * The initial pause that the Request makes when the required port is not
  93. * available.
  94. */
  95. public static int PAUSE_INITIAL = 50;
  96. /**
  97. * The number of repretetive attempts to get a required port, if it is not
  98. * immediately available.
  99. */
  100. public static int PAUSE_STEPS = 12;
  101. /**
  102. * The maximal pausing interval between two repetetive attempts. The interval
  103. * doubles after each unsuccessful attempt, but will not exceed this value.
  104. */
  105. public static int PAUSE_MAX = 1000;
  106. /**
  107. * The interceptor, listening the major request submission points.
  108. */
  109. ClientRequestInterceptorOperations m_interceptor;
  110. /**
  111. * The request info, used by interceptor.
  112. */
  113. ClientRequestInfo m_info = new gnuClientRequestInfo(this);
  114. /**
  115. * The empty byte array.
  116. */
  117. private static final RawReply EMPTY =
  118. new RawReply(null, new MessageHeader(), new byte[ 0 ]);
  119. /**
  120. * The context holder for methods ctx(Context) and ctx().
  121. */
  122. protected Context m_context;
  123. /**
  124. * The context list for method contexts().
  125. */
  126. protected ContextList m_context_list;
  127. /**
  128. * The request environment for holding the exception the has possibly been
  129. * thrown by the method being invoked.
  130. */
  131. protected Environment m_environment = new gnuEnvironment();
  132. /**
  133. * The list of all exceptions that can be thrown by the method being invoked.
  134. */
  135. protected ExceptionList m_exceptions = new gnuExceptionList();
  136. /**
  137. * The result, returned by the invoked method (function).
  138. */
  139. protected NamedValue m_result = new gnuNamedValue();
  140. /**
  141. * The exception id, received from the server, null if none.
  142. */
  143. protected String m_exception_id;
  144. /**
  145. * The thrown system exception.
  146. */
  147. protected SystemException m_sys_ex;
  148. /**
  149. * The invocation target.
  150. */
  151. protected org.omg.CORBA.Object m_target;
  152. /**
  153. * The name of the method being invoked.
  154. */
  155. protected String m_operation;
  156. /**
  157. * This field temporary remembers the value of the forwarded ior reference. If
  158. * it is not null, the request was forwarded and the effective target is not
  159. * the same as the default target.
  160. */
  161. public IOR m_forward_ior;
  162. /**
  163. * Is set when object, and not IOR is directly available.
  164. */
  165. public org.omg.CORBA.Object m_forwarding_target;
  166. /**
  167. * The flag, indicating that the request has been sent and the result is
  168. * already received.
  169. */
  170. protected boolean complete;
  171. /**
  172. * The flag, indicating that the response to this request must be ignored
  173. * (used with {@link #send_oneway()}).
  174. */
  175. protected boolean oneWay;
  176. /**
  177. * The flag, indicating that the request has been sent and no result is yet
  178. * received.
  179. */
  180. protected boolean running;
  181. /**
  182. * The request arguments.
  183. */
  184. protected gnuNVList m_args = new gnuNVList();
  185. /**
  186. * The request arguments in the case when they are directly written into the
  187. * parameter buffer.
  188. */
  189. protected StreamBasedRequest m_parameter_buffer;
  190. /**
  191. * The array of slots.
  192. */
  193. protected Any[] m_slots;
  194. /**
  195. * The request header currently in use.
  196. */
  197. protected RequestHeader m_rqh;
  198. /**
  199. * The reply header currently in use.
  200. */
  201. protected ReplyHeader m_rph;
  202. /**
  203. * The IOR of the target.
  204. */
  205. private IOR ior;
  206. /**
  207. * The ORB of the target.
  208. */
  209. private ORB orb;
  210. /**
  211. * The encoding, used to send the message.
  212. *
  213. * The default encoding is inherited from the set IOR (that string reference
  214. * can be encoded in either Big or Little endian). If the IOR encoding is not
  215. * known (for example, by obtaining the reference from the naming service),
  216. * the Big Endian is used.
  217. */
  218. private boolean Big_endian = true;
  219. /**
  220. * Set the IOR data, sufficient to find the invocation target. This also sets
  221. * default endian encoding for invocations.
  222. *
  223. * @see IOR.parse(String)
  224. */
  225. public void setIor(IOR an_ior)
  226. {
  227. ior = an_ior;
  228. setBigEndian(ior.Big_Endian);
  229. }
  230. /**
  231. * Used when redirecting request to another target.
  232. */
  233. gnuRequest redirected;
  234. /**
  235. * Get the IOR data, sufficient to find the invocation target.
  236. *
  237. * @return the IOR data.
  238. */
  239. public IOR getIor()
  240. {
  241. return ior;
  242. }
  243. /**
  244. * Set the ORB, related to the invocation target.
  245. */
  246. public void setORB(ORB an_orb)
  247. {
  248. orb = an_orb;
  249. // Take the interceptor from the ORB.
  250. if (orb instanceof OrbRestricted)
  251. m_interceptor = ((OrbRestricted) orb).iClient;
  252. if (m_interceptor != null && orb instanceof ORB_1_4)
  253. {
  254. m_slots = ((ORB_1_4) orb).ic_current.clone_slots();
  255. }
  256. }
  257. /**
  258. * Set the encoding that will be used to send the message. The default
  259. * encoding is inherited from the set IOR (that string reference can be
  260. * encoded in either Big or Little endian). If the IOR encoding is not known
  261. * (for example, by obtaining the reference from the naming service), the Big
  262. * Endian is used.
  263. *
  264. * @param use_big_endian true to use the Big Endian, false to use the Little
  265. * Endian encoding.
  266. */
  267. public void setBigEndian(boolean use_big_endian)
  268. {
  269. Big_endian = use_big_endian;
  270. }
  271. /**
  272. * The the method name to invoke.
  273. *
  274. * @param operation the method name.
  275. */
  276. public void setOperation(String operation)
  277. {
  278. m_operation = operation;
  279. }
  280. /**
  281. * Get the parameter stream, where the invocation arguments should be written
  282. * if they are written into the stream directly.
  283. */
  284. public StreamBasedRequest getParameterStream()
  285. {
  286. m_parameter_buffer = new StreamBasedRequest();
  287. m_parameter_buffer.request = this;
  288. m_parameter_buffer.setVersion(ior.Internet.version);
  289. m_parameter_buffer.setCodeSet(CodeSetServiceContext.negotiate(ior.Internet.CodeSets));
  290. m_parameter_buffer.setOrb(orb);
  291. m_parameter_buffer.setBigEndian(Big_endian);
  292. // For the old iiop versions, it is important to set the size
  293. // correctly.
  294. if (ior.Internet.version.until_inclusive(1, 1))
  295. {
  296. BufferedCdrOutput measure = new BufferedCdrOutput();
  297. measure.setOffset(12);
  298. if (m_rqh == null)
  299. m_rqh = new gnu.CORBA.GIOP.v1_0.RequestHeader();
  300. m_rqh.operation = m_operation;
  301. m_rqh.object_key = ior.key;
  302. m_rqh.write(measure);
  303. m_parameter_buffer.setOffset(12 + measure.buffer.size());
  304. }
  305. return m_parameter_buffer;
  306. }
  307. /**
  308. * Creates a shallow copy of this request.
  309. */
  310. public gnuRequest Clone()
  311. {
  312. try
  313. {
  314. return (gnuRequest) clone();
  315. }
  316. catch (CloneNotSupportedException ex)
  317. {
  318. throw new Unexpected(ex);
  319. }
  320. }
  321. /** {@inheritDoc} */
  322. public Any add_in_arg()
  323. {
  324. gnuNamedValue v = new gnuNamedValue();
  325. v.setFlags(ARG_IN.value);
  326. m_args.add(v);
  327. return v.value();
  328. }
  329. /** {@inheritDoc} */
  330. public Any add_inout_arg()
  331. {
  332. gnuNamedValue v = new gnuNamedValue();
  333. v.setFlags(ARG_INOUT.value);
  334. m_args.add(v);
  335. return v.value();
  336. }
  337. /** {@inheritDoc} */
  338. public Any add_named_in_arg(String name)
  339. {
  340. gnuNamedValue v = new gnuNamedValue();
  341. v.setFlags(ARG_IN.value);
  342. v.setName(name);
  343. m_args.add(v);
  344. return v.value();
  345. }
  346. /** {@inheritDoc} */
  347. public Any add_named_inout_arg(String name)
  348. {
  349. gnuNamedValue v = new gnuNamedValue();
  350. v.setFlags(ARG_INOUT.value);
  351. v.setName(name);
  352. m_args.add(v);
  353. return v.value();
  354. }
  355. /** {@inheritDoc} */
  356. public Any add_named_out_arg(String name)
  357. {
  358. gnuNamedValue v = new gnuNamedValue();
  359. v.setFlags(ARG_OUT.value);
  360. v.setName(name);
  361. m_args.add(v);
  362. return v.value();
  363. }
  364. /** {@inheritDoc} */
  365. public Any add_out_arg()
  366. {
  367. gnuNamedValue v = new gnuNamedValue();
  368. v.setFlags(ARG_OUT.value);
  369. m_args.add(v);
  370. return v.value();
  371. }
  372. /** {@inheritDoc} */
  373. public NVList arguments()
  374. {
  375. return m_args;
  376. }
  377. /** {@inheritDoc} */
  378. public ContextList contexts()
  379. {
  380. return m_context_list;
  381. }
  382. /** {@inheritDoc} */
  383. public Context ctx()
  384. {
  385. return m_context;
  386. }
  387. /** {@inheritDoc} */
  388. public void ctx(Context a_context)
  389. {
  390. m_context = a_context;
  391. }
  392. /** {@inheritDoc} */
  393. public Environment env()
  394. {
  395. return m_environment;
  396. }
  397. /** {@inheritDoc} */
  398. public ExceptionList exceptions()
  399. {
  400. return m_exceptions;
  401. }
  402. /** {@inheritDoc} */
  403. public void get_response() throws org.omg.CORBA.WrongTransaction
  404. {
  405. /**
  406. * The response is ready after it is received. FIXME implement context
  407. * checks and any other functionality, if required.
  408. */
  409. }
  410. /**
  411. * Submit the request, suspending the current thread until the answer is
  412. * received.
  413. *
  414. * This implementation requires to set the IOR property ({@link #setIOR(IOR)}
  415. * before calling this method.
  416. *
  417. * @throws BAD_INV_ORDER, minor code 0, if the IOR has not been previously
  418. * set.
  419. *
  420. * @throws SystemException if this exception has been thrown on remote side.
  421. * The exact exception type and the minor code are the same as they have been
  422. * for the exception, thrown on remoted side.
  423. */
  424. public synchronized void invoke() throws BAD_INV_ORDER
  425. {
  426. waitWhileBusy();
  427. complete = false;
  428. running = true;
  429. if (ior == null)
  430. throw new BAD_INV_ORDER("Set IOR property first");
  431. try
  432. {
  433. Forwardings:
  434. while (true)
  435. {
  436. try
  437. {
  438. p_invoke();
  439. break Forwardings;
  440. }
  441. catch (ForwardRequest e)
  442. {
  443. try
  444. {
  445. ObjectImpl impl = (ObjectImpl) e.forward;
  446. SimpleDelegate delegate =
  447. (SimpleDelegate) impl._get_delegate();
  448. ior = delegate.getIor();
  449. }
  450. catch (Exception ex)
  451. {
  452. BAD_PARAM bad =
  453. new BAD_PARAM("Unsupported forwarding target");
  454. bad.initCause(ex);
  455. throw bad;
  456. }
  457. }
  458. }
  459. }
  460. finally
  461. {
  462. running = false;
  463. complete = true;
  464. }
  465. }
  466. /** {@inheritDoc} */
  467. public String operation()
  468. {
  469. return m_operation;
  470. }
  471. /**
  472. * Get the orb, related to the invocation target.
  473. */
  474. public ORB orb()
  475. {
  476. return orb;
  477. }
  478. /** {@inheritDoc} */
  479. public boolean poll_response()
  480. {
  481. return complete && !running;
  482. }
  483. /** {@inheritDoc} */
  484. public NamedValue result()
  485. {
  486. return m_result;
  487. }
  488. /**
  489. * {@inheritDoc}
  490. *
  491. */
  492. public Any return_value()
  493. {
  494. return m_result.value();
  495. }
  496. /** {@inheritDoc} */
  497. public synchronized void send_deferred()
  498. {
  499. waitWhileBusy();
  500. new Thread()
  501. {
  502. public void run()
  503. {
  504. invoke();
  505. }
  506. }.start();
  507. }
  508. /**
  509. * Send a request and forget about it, not waiting for a response. This can be
  510. * done also for methods that normally are expected to return some values.
  511. *
  512. * TODO It is generally recommended to reuse the threads. Reuse?
  513. */
  514. public void send_oneway()
  515. {
  516. final gnuRequest cloned = Clone();
  517. cloned.oneWay = true;
  518. new Thread()
  519. {
  520. public void run()
  521. {
  522. cloned.invoke();
  523. }
  524. }.start();
  525. }
  526. /**
  527. * Set the argument list. This field is initialised as empty non null instance
  528. * by default, so the method is only used in cases when the direct replacement
  529. * is desired.
  530. *
  531. * @param a_args the argument list.
  532. */
  533. public void set_args(NVList a_args)
  534. {
  535. if (a_args instanceof gnuNVList)
  536. m_args = (gnuNVList) a_args;
  537. else
  538. {
  539. try
  540. {
  541. // In case if this is another implementation of the NVList.
  542. m_args.list.clear();
  543. for (int i = 0; i < a_args.count(); i++)
  544. {
  545. m_args.add(a_args.item(i));
  546. }
  547. }
  548. catch (Bounds ex)
  549. {
  550. Unexpected.error(ex);
  551. }
  552. }
  553. }
  554. /**
  555. * Set the context list that is later returned by the method
  556. * {@link #contexts()}.
  557. *
  558. * @param a_context_list a new context list.
  559. */
  560. public void set_context_list(ContextList a_context_list)
  561. {
  562. m_context_list = a_context_list;
  563. }
  564. /**
  565. * Set the exception container. This field is initialised as empty non null
  566. * instance by default, so the method is only used in cases when the direct
  567. * replacement is desired.
  568. *
  569. * @param a_environment the new exception container.
  570. */
  571. public void set_environment(Environment a_environment)
  572. {
  573. m_environment = a_environment;
  574. }
  575. /**
  576. * Set the list of exceptions. This field is initialised as empty non null
  577. * instance by default, so the method is only used in cases when the direct
  578. * replacement is desired.
  579. *
  580. * @param a_exceptions a list of exceptions.
  581. */
  582. public void set_exceptions(ExceptionList a_exceptions)
  583. {
  584. m_exceptions = a_exceptions;
  585. }
  586. /**
  587. * Set the operation name.
  588. *
  589. * @param a_operation the operation name.
  590. */
  591. public void set_operation(String a_operation)
  592. {
  593. m_operation = a_operation;
  594. }
  595. /**
  596. * Set the named value, returned as result. This field is initialised as empty
  597. * non null instance by default, so the method is only used in cases when the
  598. * direct replacement is desired.
  599. *
  600. * @param a_result the result keeper.
  601. */
  602. public void set_result(NamedValue a_result)
  603. {
  604. m_result = a_result;
  605. }
  606. /**
  607. * Set the type of the named value, returned as a result. Instantiates a new
  608. * instance of the result value.
  609. */
  610. public void set_return_type(TypeCode returns)
  611. {
  612. if (m_result == null || !returns.equal(m_result.value().type()))
  613. {
  614. m_result = new gnuNamedValue();
  615. m_result.value().type(returns);
  616. }
  617. }
  618. /**
  619. * Set the invocation target.
  620. *
  621. * @param a_target the CORBA object for that the method will be invoked.
  622. */
  623. public void set_target(org.omg.CORBA.Object a_target)
  624. {
  625. m_target = a_target;
  626. }
  627. /**
  628. * Do the actual invocation. This implementation requires to set the IOR
  629. * property ({@link #setIOR(IOR)} before calling this method.
  630. *
  631. * @throws BAD_INV_ORDER, minor code 0, if the IOR has not been previously set
  632. * or if the direct argument addition is mixed with the direct
  633. * argument writing into the output stream.
  634. * @return the server response in binary form.
  635. */
  636. public synchronized RawReply submit()
  637. throws ForwardRequest
  638. {
  639. gnu.CORBA.GIOP.MessageHeader header = new gnu.CORBA.GIOP.MessageHeader();
  640. header.setBigEndian(Big_endian);
  641. // The byte order will be Big Endian by default.
  642. header.message_type = gnu.CORBA.GIOP.MessageHeader.REQUEST;
  643. header.version = useVersion(ior.Internet.version);
  644. RequestHeader rh = header.create_request_header();
  645. rh.operation = m_operation;
  646. rh.object_key = ior.key;
  647. // Update interceptor.
  648. m_rqh = rh;
  649. if (m_interceptor != null)
  650. m_interceptor.send_request(m_info);
  651. // Prepare the submission.
  652. BufferedCdrOutput request_part = new BufferedCdrOutput();
  653. request_part.setOffset(header.getHeaderSize());
  654. request_part.setVersion(header.version);
  655. request_part.setCodeSet(CodeSetServiceContext.negotiate(ior.Internet.CodeSets));
  656. request_part.setOrb(orb);
  657. request_part.setBigEndian(header.isBigEndian());
  658. // This also sets the stream encoding to the encoding, specified
  659. // in the header.
  660. rh.write(request_part);
  661. if (m_args != null && m_args.count() > 0)
  662. {
  663. write_parameters(header, request_part);
  664. if (m_parameter_buffer != null)
  665. throw new BAD_INV_ORDER("Please either add parameters or "
  666. + "write them into stream, but not both " + "at once.");
  667. }
  668. if (m_parameter_buffer != null)
  669. {
  670. write_parameter_buffer(header, request_part);
  671. }
  672. // Now the message size is available.
  673. header.message_size = request_part.buffer.size();
  674. Socket socket = null;
  675. java.lang.Object key = ior.Internet.host + ":" + ior.Internet.port;
  676. synchronized (SocketRepository.class)
  677. {
  678. socket = SocketRepository.get_socket(key);
  679. }
  680. try
  681. {
  682. long pause = PAUSE_INITIAL;
  683. if (socket == null)
  684. {
  685. // The IOException may be thrown under very heavy parallel
  686. // load. For some time, just wait, exceptiong the socket to free.
  687. Open: for (int i = 0; i < PAUSE_STEPS; i++)
  688. {
  689. try
  690. {
  691. if (orb instanceof OrbFunctional)
  692. socket = ((OrbFunctional) orb).socketFactory.
  693. createClientSocket(
  694. ior.Internet.host, ior.Internet.port);
  695. else
  696. socket = new Socket(ior.Internet.host, ior.Internet.port);
  697. break Open;
  698. }
  699. catch (IOException ex)
  700. {
  701. try
  702. {
  703. // Expecting to free a socket via finaliser.
  704. System.gc();
  705. Thread.sleep(pause);
  706. pause = pause * 2;
  707. if (pause > PAUSE_MAX)
  708. pause = PAUSE_MAX;
  709. }
  710. catch (InterruptedException iex)
  711. {
  712. }
  713. }
  714. }
  715. }
  716. if (socket == null)
  717. throw new NO_RESOURCES(ior.Internet.host + ":" + ior.Internet.port
  718. + " in use");
  719. socket.setKeepAlive(true);
  720. OutputStream socketOutput = socket.getOutputStream();
  721. // Write the message header.
  722. header.write(socketOutput);
  723. // Write the request header and parameters (if present).
  724. request_part.buffer.writeTo(socketOutput);
  725. socketOutput.flush();
  726. if (!socket.isClosed() && !oneWay)
  727. {
  728. MessageHeader response_header = new MessageHeader();
  729. InputStream socketInput = socket.getInputStream();
  730. response_header.read(socketInput);
  731. byte[] r;
  732. if (orb instanceof OrbFunctional)
  733. {
  734. OrbFunctional fo = (OrbFunctional) orb;
  735. r = response_header.readMessage(socketInput, socket,
  736. fo.TOUT_WHILE_READING, fo.TOUT_AFTER_RECEIVING);
  737. }
  738. else
  739. r = response_header.readMessage(socketInput, null, 0, 0);
  740. return new RawReply(orb, response_header, r);
  741. }
  742. else
  743. return EMPTY;
  744. }
  745. catch (IOException io_ex)
  746. {
  747. COMM_FAILURE m = new COMM_FAILURE("Unable to open a socket at "
  748. + ior.Internet.host + ":" + ior.Internet.port, 0xC9,
  749. CompletionStatus.COMPLETED_NO);
  750. m.initCause(io_ex);
  751. throw m;
  752. }
  753. finally
  754. {
  755. try
  756. {
  757. if (socket != null && !socket.isClosed())
  758. {
  759. socket.setSoTimeout(OrbFunctional.TANDEM_REQUESTS);
  760. SocketRepository.put_socket(key, socket);
  761. }
  762. }
  763. catch (IOException scx)
  764. {
  765. InternalError ierr = new InternalError();
  766. ierr.initCause(scx);
  767. throw ierr;
  768. }
  769. }
  770. }
  771. /** {@inheritDoc} */
  772. public org.omg.CORBA.Object target()
  773. {
  774. return m_target;
  775. }
  776. /**
  777. * Get the used version. Normally, it is better to respond using the same
  778. * version as it is specified in IOR, but not above the maximal supported
  779. * version.
  780. */
  781. public Version useVersion(Version desired)
  782. {
  783. if (desired.until_inclusive(MAX_SUPPORTED.major, MAX_SUPPORTED.minor))
  784. return desired;
  785. else
  786. return MAX_SUPPORTED;
  787. }
  788. /**
  789. * Wait while the response to request, submitted using
  790. * {@link #send_deferred()} or {@link #invoke()} (from other thread) is
  791. * returned.
  792. *
  793. * FIXME It is possible to rewrite this using Object.wait() and
  794. * Object.notify(), but be sure to prepare the test as well.
  795. */
  796. public synchronized void waitWhileBusy()
  797. {
  798. // Waiting constants.
  799. long wait = 10;
  800. long increment = 2;
  801. long max = 5000;
  802. while (running)
  803. {
  804. try
  805. {
  806. Thread.sleep(wait);
  807. if (wait < max)
  808. wait = wait * increment;
  809. }
  810. catch (InterruptedException ex)
  811. {
  812. }
  813. }
  814. }
  815. /**
  816. * Do actual invocation. This method recursively calls itself if the
  817. * redirection is detected.
  818. */
  819. private void p_invoke()
  820. throws SystemException, ForwardRequest
  821. {
  822. RawReply response = submit();
  823. // If this is a one way message, do not care about the response.
  824. if (oneWay && response == EMPTY)
  825. return;
  826. if (m_rph == null)
  827. m_rph = response.header.create_reply_header();
  828. BufferredCdrInput input = response.getStream();
  829. input.setOrb(orb);
  830. m_rph.read(input);
  831. // The stream must be aligned sinve v1.2, but only once.
  832. boolean align = response.header.version.since_inclusive(1, 2);
  833. switch (m_rph.reply_status)
  834. {
  835. case ReplyHeader.NO_EXCEPTION:
  836. NamedValue arg;
  837. // Read return value, if set.
  838. if (m_result != null)
  839. {
  840. if (align)
  841. {
  842. input.align(8);
  843. align = false;
  844. }
  845. m_result.value().read_value(input, m_result.value().type());
  846. }
  847. // Read returned parameters, if set.
  848. if (m_args != null)
  849. for (int i = 0; i < m_args.count(); i++)
  850. {
  851. try
  852. {
  853. arg = m_args.item(i);
  854. // Both ARG_INOUT and ARG_OUT have this binary flag set.
  855. if ((arg.flags() & ARG_OUT.value) != 0)
  856. {
  857. if (align)
  858. {
  859. input.align(8);
  860. align = false;
  861. }
  862. arg.value().read_value(input, arg.value().type());
  863. }
  864. }
  865. catch (Bounds ex)
  866. {
  867. Unexpected.error(ex);
  868. }
  869. }
  870. if (m_interceptor != null)
  871. m_interceptor.receive_reply(m_info);
  872. break;
  873. case ReplyHeader.SYSTEM_EXCEPTION:
  874. if (align)
  875. {
  876. input.align(8);
  877. align = false;
  878. }
  879. readExceptionId(input);
  880. m_sys_ex = ObjectCreator.readSystemException(input,
  881. m_rph.service_context);
  882. m_environment.exception(m_sys_ex);
  883. if (m_interceptor != null)
  884. m_interceptor.receive_exception(m_info);
  885. throw m_sys_ex;
  886. case ReplyHeader.USER_EXCEPTION:
  887. if (align)
  888. {
  889. input.align(8);
  890. align = false;
  891. }
  892. readExceptionId(input);
  893. // Prepare an Any that will hold the exception.
  894. gnuAny exc = new gnuAny();
  895. exc.setOrb(orb);
  896. exc.insert_Streamable(new StreamHolder(input));
  897. UnknownUserException unuex = new UnknownUserException(exc);
  898. m_environment.exception(unuex);
  899. if (m_interceptor != null)
  900. m_interceptor.receive_exception(m_info);
  901. break;
  902. case ReplyHeader.LOCATION_FORWARD_PERM:
  903. case ReplyHeader.LOCATION_FORWARD:
  904. if (response.header.version.since_inclusive(1, 2))
  905. input.align(8);
  906. IOR forwarded = new IOR();
  907. try
  908. {
  909. forwarded._read_no_endian(input);
  910. }
  911. catch (IOException ex)
  912. {
  913. new MARSHAL("Cant read forwarding info", 5103,
  914. CompletionStatus.COMPLETED_NO);
  915. }
  916. setIor(forwarded);
  917. m_forward_ior = forwarded;
  918. if (m_interceptor != null)
  919. m_interceptor.receive_other(m_info);
  920. // Repeat with the forwarded information.
  921. p_invoke();
  922. return;
  923. default:
  924. throw new MARSHAL("Unknow reply status", 8100 + m_rph.reply_status,
  925. CompletionStatus.COMPLETED_NO);
  926. }
  927. }
  928. /**
  929. * Read exception id without changing the stream pointer position.
  930. */
  931. void readExceptionId(BufferredCdrInput input)
  932. {
  933. input.mark(2048);
  934. m_exception_id = input.read_string();
  935. input.reset();
  936. }
  937. /**
  938. * Write the operation parameters.
  939. *
  940. * @param header the message header
  941. * @param request_part the stream to write parameters into
  942. *
  943. * @throws MARSHAL if the attempt to write the parameters has failde.
  944. */
  945. protected void write_parameter_buffer(MessageHeader header,
  946. BufferedCdrOutput request_part
  947. ) throws MARSHAL
  948. {
  949. try
  950. {
  951. if (header.version.since_inclusive(1, 2))
  952. {
  953. request_part.align(8);
  954. }
  955. m_parameter_buffer.buffer.writeTo(request_part);
  956. }
  957. catch (IOException ex)
  958. {
  959. MARSHAL m = new MARSHAL("Unable to write method arguments to CDR output.");
  960. m.minor = Minor.CDR;
  961. throw m;
  962. }
  963. }
  964. /**
  965. * Write the operation parameters.
  966. *
  967. * @param header the message header
  968. * @param request_part the stream to write parameters into
  969. *
  970. * @throws MARSHAL if the attempt to write the parameters has failde.
  971. */
  972. protected void write_parameters(MessageHeader header,
  973. BufferedCdrOutput request_part
  974. ) throws MARSHAL
  975. {
  976. // Align after 1.2, but only once.
  977. boolean align = header.version.since_inclusive(1, 2);
  978. NamedValue para;
  979. try
  980. {
  981. // Write parameters now.
  982. for (int i = 0; i < m_args.count(); i++)
  983. {
  984. para = m_args.item(i);
  985. // This bit is set both for ARG_IN and ARG_INOUT
  986. if ((para.flags() & ARG_IN.value) != 0)
  987. {
  988. if (align)
  989. {
  990. request_part.align(8);
  991. align = false;
  992. }
  993. para.value().write_value(request_part);
  994. }
  995. }
  996. }
  997. catch (Bounds ex)
  998. {
  999. InternalError ierr = new InternalError();
  1000. ierr.initCause(ex);
  1001. throw ierr;
  1002. }
  1003. }
  1004. /* **************Implementation of the request info operations. ***** */
  1005. /**
  1006. * Add context to request.
  1007. */
  1008. public void add_request_service_context(ServiceContext service_context,
  1009. boolean replace
  1010. )
  1011. {
  1012. m_rqh.addContext(service_context, replace);
  1013. }
  1014. /**
  1015. * Get the Internet profile as an effective profile.
  1016. */
  1017. public TaggedProfile effective_profile()
  1018. {
  1019. BufferedCdrOutput buf = new BufferedCdrOutput(512);
  1020. buf.setOrb(orb);
  1021. ior.Internet.write(buf);
  1022. TaggedProfile p = new TaggedProfile();
  1023. p.tag = TAG_INTERNET_IOP.value;
  1024. p.profile_data = buf.buffer.toByteArray();
  1025. return p;
  1026. }
  1027. /**
  1028. * Return either target or forwarded targed.
  1029. */
  1030. public org.omg.CORBA.Object effective_target()
  1031. {
  1032. return new IorObject(orb, ior);
  1033. }
  1034. /**
  1035. * Get effective component with the give id from the Internet profile.
  1036. */
  1037. public TaggedComponent get_effective_component(int id)
  1038. throws BAD_PARAM
  1039. {
  1040. if (id == TAG_CODE_SETS.value)
  1041. {
  1042. // Codesets are encoded separately.
  1043. BufferedCdrOutput buf = new BufferedCdrOutput(512);
  1044. buf.setOrb(orb);
  1045. ior.Internet.CodeSets.write(buf);
  1046. TaggedComponent t = new TaggedComponent();
  1047. t.tag = TAG_CODE_SETS.value;
  1048. t.component_data = buf.buffer.toByteArray();
  1049. return t;
  1050. }
  1051. else
  1052. {
  1053. for (int i = 0; i < ior.Internet.components.size(); i++)
  1054. {
  1055. TaggedComponent c =
  1056. (TaggedComponent) ior.Internet.components.get(i);
  1057. if (c.tag == id)
  1058. return c;
  1059. }
  1060. }
  1061. throw new BAD_PARAM("No component " + id + " in the Internet profile", 28,
  1062. CompletionStatus.COMPLETED_MAYBE
  1063. );
  1064. }
  1065. /**
  1066. * Get all components with the given id from the internet profile.
  1067. */
  1068. public TaggedComponent[] get_effective_components(int id)
  1069. throws BAD_PARAM
  1070. {
  1071. if (id == TAG_CODE_SETS.value)
  1072. return new TaggedComponent[] { get_effective_component(TAG_CODE_SETS.value) };
  1073. else
  1074. {
  1075. ArrayList components = new ArrayList(ior.Internet.components.size());
  1076. for (int i = 0; i < ior.Internet.components.size(); i++)
  1077. {
  1078. TaggedComponent c =
  1079. (TaggedComponent) ior.Internet.components.get(i);
  1080. if (c.tag == id)
  1081. components.add(c);
  1082. }
  1083. if (components.size() == 0)
  1084. throw new BAD_PARAM("No component " + id +
  1085. " in the Internet profile", 28, CompletionStatus.COMPLETED_MAYBE
  1086. );
  1087. else
  1088. {
  1089. TaggedComponent[] t = new TaggedComponent[ components.size() ];
  1090. for (int i = 0; i < t.length; i++)
  1091. t [ i ] = (TaggedComponent) components.get(i);
  1092. return t;
  1093. }
  1094. }
  1095. }
  1096. /**
  1097. * This should be not implemented up till jdk 1.5 inclusive.
  1098. */
  1099. public Policy get_request_policy(int type) throws INV_POLICY
  1100. {
  1101. throw new NO_IMPLEMENT();
  1102. }
  1103. /** @inheritDoc */
  1104. public String received_exception_id()
  1105. {
  1106. return m_exception_id;
  1107. }
  1108. /** @inheritDoc */
  1109. public Any received_exception()
  1110. {
  1111. if (m_exception_id == null)
  1112. return null;
  1113. if (m_sys_ex != null)
  1114. {
  1115. Any a = orb.create_any();
  1116. ObjectCreator.insertSysException(a, m_sys_ex);
  1117. return a;
  1118. }
  1119. Exception mex = m_environment.exception();
  1120. UnknownUserException ex = (UnknownUserException) mex;
  1121. if (ex == null)
  1122. return null;
  1123. else
  1124. return ex.except;
  1125. }
  1126. /**
  1127. * Return the forwarded reference, null if none.
  1128. */
  1129. public org.omg.CORBA.Object forward_reference()
  1130. {
  1131. if (m_forwarding_target != null)
  1132. return m_forwarding_target;
  1133. if (m_forward_ior != null)
  1134. return new IorObject(orb, m_forward_ior);
  1135. else
  1136. return null;
  1137. }
  1138. /**
  1139. * Get the slot from the slot array inside this request.
  1140. */
  1141. public Any get_slot(int id) throws InvalidSlot
  1142. {
  1143. try
  1144. {
  1145. return m_slots [ id ];
  1146. }
  1147. catch (Exception e)
  1148. {
  1149. throw new InvalidSlot("slot id " + id + ":" + e);
  1150. }
  1151. }
  1152. /**
  1153. * Get the reply status.
  1154. */
  1155. public short reply_status()
  1156. {
  1157. if (m_rph == null)
  1158. throw new BAD_INV_ORDER("Request not yet sent", 14,
  1159. CompletionStatus.COMPLETED_NO
  1160. );
  1161. return (short) m_rph.reply_status;
  1162. }
  1163. /**
  1164. * Get the request id.
  1165. */
  1166. public int request_id()
  1167. {
  1168. return m_rqh.request_id;
  1169. }
  1170. /**
  1171. * Return true if the response is expected.
  1172. */
  1173. public boolean response_expected()
  1174. {
  1175. return !oneWay;
  1176. }
  1177. /**
  1178. * Determines how far the request shall progress before control is returned to
  1179. * the client. However up till JDK 1.5 inclusive this method always returns
  1180. * SYNC_WITH_TRANSPORT.
  1181. *
  1182. * @return {@link org.omg.Messaging.SYNC_WITH_TRANSPORT.value (1), always.
  1183. *
  1184. * @specnote as defined in the Suns 1.5 JDK API.
  1185. */
  1186. public short sync_scope()
  1187. {
  1188. return org.omg.Messaging.SYNC_WITH_TRANSPORT.value;
  1189. }
  1190. /** @inheritDoc */
  1191. public ServiceContext get_request_service_context(int ctx_name)
  1192. throws BAD_PARAM
  1193. {
  1194. return gnu.CORBA.GIOP.ServiceContext.findContext(ctx_name,
  1195. m_rqh.service_context
  1196. );
  1197. }
  1198. /** @inheritDoc */
  1199. public ServiceContext get_reply_service_context(int ctx_name)
  1200. throws BAD_PARAM
  1201. {
  1202. if (m_rph == null)
  1203. throw new BAD_INV_ORDER("Reply context not yet available");
  1204. return gnu.CORBA.GIOP.ServiceContext.findContext(ctx_name,
  1205. m_rph.service_context
  1206. );
  1207. }
  1208. /** @inheritDoc */
  1209. public String[] operation_context()
  1210. {
  1211. return ice_contexts();
  1212. }
  1213. /**
  1214. * Get contexts as required by interceptor.
  1215. */
  1216. public String[] ice_contexts()
  1217. {
  1218. if (m_context_list == null)
  1219. return new String[ 0 ];
  1220. else
  1221. {
  1222. try
  1223. {
  1224. String[] cn = new String[ m_context_list.count() ];
  1225. for (int i = 0; i < cn.length; i++)
  1226. cn [ i ] = m_context_list.item(i);
  1227. return cn;
  1228. }
  1229. catch (Bounds e)
  1230. {
  1231. throw new Unexpected(e);
  1232. }
  1233. }
  1234. }
  1235. /**
  1236. * Check if the call is done via DII.
  1237. */
  1238. public void checkDii()
  1239. {
  1240. if (m_parameter_buffer != null)
  1241. throw new NO_RESOURCES("The invocation method provides " +
  1242. "no access to this resource. DII call required.", 1,
  1243. CompletionStatus.COMPLETED_MAYBE
  1244. );
  1245. }
  1246. }