Source code: gnu/classpath/tools/rmi/rmic/RmiMethodGenerator.java
1 /* MethodGenerator.java -- Generates methods for rmi compiler.
2 Copyright (C) 2006 Free Software Foundation
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
27
28 package gnu.classpath.tools.rmi.rmic;
29
30 import gnu.classpath.tools.AbstractMethodGenerator;
31 import gnu.java.rmi.server.RMIHashes;
32
33 import java.lang.reflect.Method;
34 import java.util.Properties;
35
36 /**
37 * Keeps information about the single method and generates the code fragments,
38 * related to that method.
39 *
40 * @author Audrius Meskauskas, Lithuania (audriusa@Bioinformatics.org)
41 */
42 public class RmiMethodGenerator
43 implements AbstractMethodGenerator
44 {
45 /**
46 * The method being defined.
47 */
48 Method method;
49
50 /**
51 * The parent code generator.
52 */
53 RmicCompiler rmic;
54
55 /**
56 * Create the new method generator for the given method.
57 *
58 * @param aMethod the related method.
59 * @param aRmic the Rmic generator instance, where more class - related
60 * information is defined.
61 */
62 public RmiMethodGenerator(Method aMethod, RmicCompiler aRmic)
63 {
64 method = aMethod;
65 rmic = aRmic;
66 if (method.getParameterTypes().length == 0)
67 rmic.addZeroSizeObjecArray = true;
68 }
69
70 /**
71 * Get the method parameter declaration.
72 *
73 * @return the string - method parameter declaration.
74 */
75 public String getArgumentList()
76 {
77 StringBuffer b = new StringBuffer();
78
79 Class[] args = method.getParameterTypes();
80
81 for (int i = 0; i < args.length; i++)
82 {
83 b.append(rmic.name(args[i]));
84 b.append(" p" + i);
85 if (i < args.length - 1)
86 b.append(", ");
87 }
88 return b.toString();
89 }
90
91 /**
92 * Get the method parameter list only (no type declarations). This is used to
93 * generate the method invocations statement.
94 *
95 * @return the string - method parameter list.
96 */
97 public String getArgumentNames()
98 {
99 StringBuffer b = new StringBuffer();
100
101 Class[] args = method.getParameterTypes();
102
103 for (int i = 0; i < args.length; i++)
104 {
105 b.append(" p" + i);
106 if (i < args.length - 1)
107 b.append(", ");
108 }
109 return b.toString();
110 }
111
112 /**
113 * Get the list of exceptions, thrown by this method.
114 *
115 * @return the list of exceptions.
116 */
117 public String getThrows()
118 {
119 StringBuffer b = new StringBuffer();
120
121 Class[] args = method.getExceptionTypes();
122
123 for (int i = 0; i < args.length; i++)
124 {
125 b.append(rmic.name(args[i]));
126 if (i < args.length - 1)
127 b.append(", ");
128 }
129 return b.toString();
130 }
131
132 /**
133 * Generate this method for the Stub class.
134 *
135 * @return the method body for the stub class.
136 */
137 public String generateStubMethod()
138 {
139 String templateName;
140
141 Properties vars = new Properties(rmic.vars);
142 vars.put("#return_type", rmic.name(method.getReturnType()));
143 vars.put("#method_name", method.getName());
144 vars.put("#method_hash", getMethodHashCode());
145 vars.put("#argument_list", getArgumentList());
146 vars.put("#object_arg_list", getArgListAsObjectArray());
147 vars.put("#declaring_class", rmic.name(method.getDeclaringClass()));
148 vars.put("#class_arg_list", getArgListAsClassArray());
149
150 String thr = getThrows();
151 if (thr.length() > 0)
152 vars.put("#throws", "\n throws " + thr);
153 else
154 vars.put("#throws", "");
155
156 if (method.getReturnType().equals(void.class))
157 templateName = "Stub_12MethodVoid.jav";
158 else
159 {
160 templateName = "Stub_12Method.jav";
161 vars.put("#return_statement", getReturnStatement());
162 }
163
164 String template = rmic.getResource(templateName);
165 String generated = rmic.replaceAll(template, vars);
166 return generated;
167 }
168
169 /**
170 * Generate sentences for Reading and Defining Arguments.
171 *
172 * @return the sequence of sentences for reading and defining arguments.
173 */
174 public String getStaticMethodDeclarations()
175 {
176 StringBuffer b = new StringBuffer();
177 Class[] args = method.getParameterTypes();
178
179 for (int i = 0; i < args.length; i++)
180 {
181 b.append(" ");
182 b.append(rmic.name(args[i]));
183 b.append(" ");
184 b.append("p" + i);
185 b.append(" = ");
186 if (i < args.length - 1)
187 b.append("\n");
188 }
189 return b.toString();
190 }
191
192 /**
193 * Get the write statement for writing parameters inside the stub.
194 *
195 * @return the write statement.
196 */
197 public String getArgListAsObjectArray()
198 {
199 Class[] args = method.getParameterTypes();
200
201 if (args.length==0)
202 return "NO_ARGS";
203
204 StringBuffer b = new StringBuffer("new Object[] {");
205
206 for (int i = 0; i < args.length; i++)
207 {
208 if (!args[i].isPrimitive())
209 b.append("p"+i);
210 else
211 {
212 b.append("new "+rmic.name(WrapUnWrapper.getWrappingClass(args[i])));
213 b.append("(p"+i+")");
214 }
215 if (i<args.length-1)
216 b.append(", ");
217 }
218 b.append("}");
219 return b.toString();
220 }
221
222 /**
223 * Get the return statement, assuming that the returned object is placed into
224 * the variable "result".
225 */
226 public String getReturnStatement()
227 {
228 Class r = method.getReturnType();
229 if (r.equals(void.class))
230 return "";
231 else
232 {
233 if (r.isPrimitive())
234 {
235 String wcd = rmic.name(WrapUnWrapper.getWrappingClass(r));
236 return "return ((" + wcd + ") result)."
237 + WrapUnWrapper.getUnwrappingMethod(r) + ";";
238 }
239 else
240 return "return (" + rmic.name(r) + ") result;";
241 }
242 }
243
244 /**
245 * Get argument list as class array.
246 */
247 public String getArgListAsClassArray()
248 {
249 StringBuffer b = new StringBuffer();
250 Class[] args = method.getParameterTypes();
251
252 for (int i = 0; i < args.length; i++)
253 {
254 b.append(rmic.name(args[i]));
255 b.append(".class");
256 if (i < args.length - 1)
257 b.append(", ");
258 }
259 return b.toString();
260 }
261
262 /**
263 * RMI ties (previously named Skeletons) are no longer used since v 1.2. This
264 * method should never be called.
265 */
266 public String generateTieMethod()
267 {
268 throw new InternalError();
269 }
270
271 /**
272 * Get the method hash code.
273 */
274 public String getMethodHashCode()
275 {
276 return RMIHashes.getMethodHash(method)+"L";
277 }
278
279 /**
280 * Additional processing of the stub name (nothing to do for JRMP stubs).
281 */
282 public String convertStubName(String name)
283 {
284 return name;
285 }
286
287 }