summaryrefslogtreecommitdiff
path: root/TAO/TAO_IDL/be/be_visitor_operation/amh_rh_ss.cpp
blob: cb5790d5e41c831d36743c0dbfff8eb3d3960272 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
//=============================================================================
/**
 *  @file   amh_rh_ss.cpp
 *
 *  Creates code for AMH-RH operations.
 *
 *  @author Mayur Deshpande <mayur@ics.uci.edu>
 */
//=============================================================================

#include "operation.h"

be_visitor_amh_rh_operation_ss::be_visitor_amh_rh_operation_ss (
    be_visitor_context *ctx)
  : be_visitor_operation (ctx)
{
}

be_visitor_amh_rh_operation_ss::~be_visitor_amh_rh_operation_ss ()
{
}

int
be_visitor_amh_rh_operation_ss::visit_operation (be_operation *node)
{
  // Nothing to be done for oneway operations.
  if (node->flags () == AST_Operation::OP_oneway)
    {
      return 0;
    }

  /// These are not for the server side.
  if (node->is_sendc_ami ())
    {
      return 0;
    }

  // Output stream.
  TAO_OutStream *os = this->ctx_->stream ();

  UTL_Scope *s =
    this->ctx_->attribute ()
      ? this->ctx_->attribute ()->defined_in ()
      : node->defined_in ();

  be_interface *intf = dynamic_cast<be_interface*> (s);

  if (intf == nullptr)
    {
      be_porttype *pt = dynamic_cast<be_porttype*> (s);

      if (pt == nullptr)
        {
          ACE_ERROR_RETURN ((LM_ERROR,
                             ACE_TEXT ("be_visitor_amh_rh_operation_sh::")
                             ACE_TEXT ("visit_operation - ")
                             ACE_TEXT ("bad scope\n")),
                            -1);
        }
      else
        {
          intf = this->ctx_->interface ();
        }
    }

  char *buf = nullptr;
  intf->compute_full_name ("TAO_", "", buf);
  ACE_CString response_handler_implementation_name ("POA_");
  response_handler_implementation_name += buf;
  // buf was allocated by ACE_OS::strdup, so we need to use free instead
  // of delete.
  ACE_OS::free (buf);
  buf = nullptr;

  // Step 1 : Generate return type: always void
  *os << be_nl_2 << "// TAO_IDL - Generated from" << be_nl
      << "// " << __FILE__ << ":" << __LINE__ << be_nl_2;

  *os << "void" << be_nl
      << response_handler_implementation_name.c_str () << "::";

  // Check if we are an attribute node in disguise
  if (this->ctx_->attribute ())
    {
      // now check if we are a "get" or "set" operation
      if (node->nmembers () == 1) // set
        {
          *os << "_set_";
        }
      else
        {
          *os << "_get_";
        }
    }

  *os << this->ctx_->port_prefix ().c_str ()
      << node->local_name ();

  // Step 2 : Generate the params of the method
  be_visitor_context ctx (*this->ctx_);

  // Set the substate because response handler operations without
  // parameters don't use the environment parameter in the body.
  ctx.sub_state (TAO_CodeGen::TAO_AMH_RESPONSE_HANDLER_OPERATION);

  be_visitor_operation_arglist visitor (&ctx);

  if (node->accept (&visitor) == -1)
    {
      ACE_ERROR_RETURN ((LM_ERROR,
                         "(%N:%l) be_visitor_amh_rh_operation_ss::"
                         "visit_operation - "
                         "codegen for argument list failed\n"),
                        -1);
    }

  int is_an_exception_reply = 0;

  // Find out if the operation is one of the *_excep() operations, the
  // conditions are:
  // 1) The local_name ends in _excep()
  // 2) There is exactly one argument
  // 3) The argument takes an implied valuetype generated from the
  //    original interface
  // 4) The implied valuetype ends in ExceptionHolder
  const char *last_underbar = ACE_OS::strrchr (node->full_name (), '_');

  if (last_underbar != nullptr
      && ACE_OS::strcmp (last_underbar, "_excep") == 0)
    {
      if (node->nmembers () == 1)
        {
          UTL_ScopeActiveIterator i (node,
                                     UTL_Scope::IK_decls);

          if (!i.is_done ())
            {
              be_argument *argument =
                dynamic_cast<be_argument*> (i.item ());
              be_valuetype *vt =
                dynamic_cast<be_valuetype*> (argument->field_type ());

              if (vt != nullptr
                  && vt->original_interface () == intf->original_interface ())
                {
                  const char *last_E =
                    ACE_OS::strrchr (vt->full_name (), 'E');

                  if (last_E != nullptr
                      && ACE_OS::strcmp (last_E, "ExceptionHolder") == 0)
                    {
                      is_an_exception_reply = 1;
                    }
                }
            }
        }
    }

  if (is_an_exception_reply)
    {
      // Remove the trailing '_excep' from the operation name, we know
      // there is one from the checks above...
      ACE_CString operation_name (node->local_name ()->get_string ());
      ACE_CString::size_type const idx = operation_name.rfind ('_');
      ACE_ASSERT (idx != ACE_CString::npos);
      operation_name[idx] = '\0';

      *os << be_nl << "{" << be_idt_nl
          << "try" << be_nl
          << "{" << be_idt_nl
          << "holder->raise_" << operation_name.c_str ()
          << " ();" << be_uidt_nl
          << "}" << be_nl
          << "catch (const ::CORBA::Exception& ex)"
          << be_nl
          << "{" << be_idt_nl
          << "this->_tao_rh_send_exception (ex);" << be_uidt_nl
          << "}" << be_uidt_nl
          << "}";
    }
  else
    {
      // Step 3: Generate actual code for the method
      *os << be_nl << "{" << be_idt_nl
          << "this->_tao_rh_init_reply ();" << be_nl_2;

      this->marshal_params (node);

      *os << be_nl
          << "this->_tao_rh_send_reply ();" << be_uidt_nl
          << "}";
    }

  return 0;
}


int
be_visitor_amh_rh_operation_ss::marshal_params (be_operation *node)
{
  TAO_OutStream *os = this->ctx_->stream ();
  be_visitor_context ctx;

  // Now make sure that we have some in and inout parameters. Otherwise, there
  // is nothing to be marshaled out.
  if (this->has_param_type (node, AST_Argument::dir_IN) ||
      this->has_param_type (node, AST_Argument::dir_INOUT))
    {
      // marshal the in and inout arguments
      *os << "if (!(" << be_idt << be_idt_nl;

      // Marshal each in and inout argument.
      ctx = *this->ctx_;
      ctx.state (TAO_CodeGen::TAO_OPERATION_ARG_INVOKE_CS);
      ctx.sub_state (TAO_CodeGen::TAO_CDR_OUTPUT);
      be_visitor_operation_argument_invoke visitor (&ctx);

      if (node->accept (&visitor) == -1)
        {
          ACE_ERROR_RETURN ((LM_ERROR,
                             "(%N:%l) be_visitor_amh_rh_operation_ss::"
                             "gen_demarshal_params - "
                             "codegen for demarshal failed\n"),
                            -1);
        }

      *os << be_uidt_nl << "))" << be_nl
          << "{" << be_idt_nl;

      // If marshaling fails, raise exception.
      if (this->gen_raise_exception ("::CORBA::MARSHAL",
                                     "") == -1)
        {
          ACE_ERROR_RETURN ((LM_ERROR,
                             "(%N:%l) gen_raise_exception failed\n"),
                            -1);
        }

      *os << be_uidt_nl
          << "}" << be_uidt_nl;
    }

  return 0;
}