Imported GNU Classpath 0.90
[official-gcc.git] / libjava / classpath / tools / gnu / classpath / tools / giop / grmic / GiopRmicCompiler.java
blob4beba1c9fd7f8de44fa3347c47cb0ab54302df80
1 /* GiopRmicCompiler -- Central GIOP-based RMI stub and tie compiler class.
2 Copyright (C) 2006 Free Software Foundation
4 This file is part of GNU Classpath.
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.
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.
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.
22 package gnu.classpath.tools.giop.grmic;
24 import gnu.classpath.tools.AbstractMethodGenerator;
26 import java.lang.reflect.Method;
27 import java.rmi.Remote;
28 import java.rmi.RemoteException;
29 import java.util.ArrayList;
30 import java.util.Collection;
31 import java.util.Collections;
32 import java.util.Comparator;
33 import java.util.HashSet;
34 import java.util.Iterator;
35 import java.util.Properties;
36 import java.util.TreeSet;
38 /**
39 * Provides the extended rmic functionality to generate the POA - based classes
40 * for GIOP (javax.rmi.CORBA package).
42 * @author Audrius Meskauskas, Lithuania (audriusa@Bioinformatics.org)
44 public class GiopRmicCompiler
45 extends Generator implements Comparator
47 /** The package name. */
48 protected String packag;
50 /**
51 * The "basic" name (normally, the interface name, unless several Remote -
52 * derived interfaces are implemented.
54 protected String name;
56 /**
57 * The name (without package) of the class, passed as the parameter.
59 protected String implName;
61 /**
62 * The proposed name for the stub.
64 protected String stubName;
66 /**
67 * The Remote's, implemented by this class.
69 protected Collection implementedRemotes = new HashSet();
71 /**
72 * The extra classes that must be imported.
74 protected Collection extraImports = new HashSet();
76 /**
77 * The methods we must implement.
79 protected Collection methods = new HashSet();
81 /**
82 * The map of all code generator variables.
84 public Properties vars = new Properties();
86 /**
87 * If this flag is set (true by default), the compiler generates the Servant
88 * based classes. If set to false, the compiler generates the old style
89 * ObjectImpl based classes.
91 protected boolean poaMode = true;
93 /**
94 * If this flag is set (true by default), the compiler emits warnings.
96 protected boolean warnings = true;
98 /**
99 * Verbose output
101 protected boolean verbose = false;
104 * Force mode - do not check the exceptions
106 protected boolean force = false;
109 * Clear data, preparing for the next compilation.
111 public void reset()
113 packag = name = implName = stubName = null;
114 implementedRemotes.clear();
115 extraImports.clear();
116 methods.clear();
117 vars.clear();
121 * Compile the given class (the instance of Remote), generating the stub and
122 * tie for it.
124 * @param remote
125 * the class to compile.
127 public synchronized void compile(Class remote)
129 reset();
130 String s;
132 // Get the package.
133 s = remote.getName();
134 int p = s.lastIndexOf('.');
135 if (p < 0)
137 // Root package.
138 packag = "";
139 implName = name = s;
141 else
143 packag = s.substring(0, p);
144 implName = name = s.substring(p + 1);
147 name = convertStubName(name);
149 stubName = name;
151 vars.put("#name", name);
152 vars.put("#package", packag);
153 vars.put("#implName", implName);
155 if (verbose)
156 System.out.println("Package " + packag + ", name " + name + " impl "
157 + implName);
159 // Get the implemented remotes.
160 Class[] interfaces = remote.getInterfaces();
162 for (int i = 0; i < interfaces.length; i++)
164 if (Remote.class.isAssignableFrom(interfaces[i]))
166 if (! interfaces[i].equals(Remote.class))
168 implementedRemotes.add(interfaces[i]);
173 vars.put("#idList", getIdList(implementedRemotes));
175 // Collect and process methods.
176 Iterator iter = implementedRemotes.iterator();
178 while (iter.hasNext())
180 Class c = (Class) iter.next();
181 Method[] m = c.getMethods();
183 // Check if throws RemoteException.
184 for (int i = 0; i < m.length; i++)
186 Class[] exc = m[i].getExceptionTypes();
187 boolean remEx = false;
189 for (int j = 0; j < exc.length; j++)
191 if (RemoteException.class.isAssignableFrom(exc[j]))
193 remEx = true;
194 break;
196 if (! remEx && !force)
197 throw new CompilationError(m[i].getName() + ", defined in "
198 + c.getName()
199 + ", does not throw "
200 + RemoteException.class.getName());
202 AbstractMethodGenerator mm = createMethodGenerator(m[i]);
203 methods.add(mm);
209 * Create the method generator for the given method.
211 * @param m the method
213 * @return the created method generator
215 protected AbstractMethodGenerator createMethodGenerator(Method m)
217 return new MethodGenerator(m, this);
221 * Get the name of the given class. The class is added to imports, if not
222 * already present and not from java.lang and not from the current package.
224 * @param nameIt
225 * the class to name
226 * @return the name of class as it should appear in java language
228 public String name(Class nameIt)
230 if (nameIt.isArray())
232 // Mesure dimensions:
233 int dimension = 0;
234 Class finalComponent = nameIt;
235 while (finalComponent.isArray())
237 finalComponent = finalComponent.getComponentType();
238 dimension++;
241 StringBuffer brackets = new StringBuffer();
243 for (int i = 0; i < dimension; i++)
245 brackets.append("[]");
248 return name(finalComponent) + " " + brackets;
250 else
252 String n = nameIt.getName();
253 if (! nameIt.isArray() && ! nameIt.isPrimitive())
254 if (! n.startsWith("java.lang")
255 && ! (packag != null && n.startsWith(packag)))
256 extraImports.add(n);
258 int p = n.lastIndexOf('.');
259 if (p < 0)
260 return n;
261 else
262 return n.substring(p + 1);
267 * Get the RMI-style repository Id for the given class.
269 * @param c
270 * the interface, for that the repository Id must be created.
271 * @return the repository id
273 public String getId(Class c)
275 return "RMI:" + c.getName() + ":0000000000000000";
279 * Get repository Id string array declaration.
281 * @param remotes
282 * the collection of interfaces
283 * @return the fully formatted string array.
285 public String getIdList(Collection remotes)
287 StringBuffer b = new StringBuffer();
289 // Keep the Ids sorted, ensuring, that the same order will be preserved
290 // between compilations.
291 TreeSet sortedIds = new TreeSet();
293 Iterator iter = remotes.iterator();
294 while (iter.hasNext())
296 sortedIds.add(getId((Class) iter.next()));
299 iter = sortedIds.iterator();
300 while (iter.hasNext())
302 b.append(" \"" + iter.next() + "\"");
303 if (iter.hasNext())
304 b.append(", \n");
306 return b.toString();
310 * Generate stub. Can only be called from {@link #compile}.
312 * @return the string, containing the text of the generated stub.
314 public String generateStub()
316 String template = getResource("Stub.jav");
318 // Generate methods.
319 StringBuffer b = new StringBuffer();
320 Iterator iter = methods.iterator();
321 while (iter.hasNext())
323 AbstractMethodGenerator m = (AbstractMethodGenerator) iter.next();
324 b.append(m.generateStubMethod());
327 vars.put("#stub_methods", b.toString());
328 vars.put("#imports", getImportStatements());
329 vars.put("#interfaces", getAllInterfaces());
331 String output = replaceAll(template, vars);
332 return output;
336 * Get the list of all interfaces, implemented by the class, that are
337 * derived from Remote.
339 * @return the string - all interfaces.
341 public String getAllInterfaces()
343 StringBuffer b = new StringBuffer();
344 Iterator iter = implementedRemotes.iterator();
346 while (iter.hasNext())
348 b.append(name((Class) iter.next()));
349 if (iter.hasNext())
350 b.append(", ");
353 return b.toString();
357 * Generate Tie. Can only be called from {@link #compile}.
359 * @return the string, containing the text of the generated Tie.
361 public String generateTie()
363 String template;
364 if (poaMode)
365 template = getResource("Tie.jav");
366 else
367 template = getResource("ImplTie.jav");
369 // Generate methods.
370 HashFinder hashFinder = new HashFinder();
372 // Find the hash character position:
373 Iterator iter = methods.iterator();
374 String[] names = new String[methods.size()];
375 int p = 0;
377 for (int i = 0; i < names.length; i++)
378 names[i] = ((MethodGenerator) iter.next()).getGiopMethodName();
380 int hashCharPosition = hashFinder.findHashCharPosition(names);
382 iter = methods.iterator();
383 while (iter.hasNext())
384 ((MethodGenerator) iter.next()).hashCharPosition = hashCharPosition;
386 vars.put("#hashCharPos", Integer.toString(hashCharPosition));
388 ArrayList sortedMethods = new ArrayList(methods);
389 Collections.sort(sortedMethods, this);
391 iter = sortedMethods.iterator();
393 StringBuffer b = new StringBuffer();
395 MethodGenerator prev = null;
397 while (iter.hasNext())
399 MethodGenerator m = (MethodGenerator) iter.next();
400 m.previous = prev;
401 m.hashCharPosition = hashCharPosition;
402 prev = m;
403 b.append(m.generateTieMethod());
406 vars.put("#tie_methods", b.toString());
408 vars.put("#imports", getImportStatements());
410 String output = replaceAll(template, vars);
411 return output;
414 public int compare(Object a, Object b)
416 MethodGenerator g1 = (MethodGenerator) a;
417 MethodGenerator g2 = (MethodGenerator) b;
419 return g1.getHashChar() - g2.getHashChar();
423 * Import the extra classes, used as the method parameters and return values.
425 * @return the additional import block.
427 protected String getImportStatements()
429 TreeSet imp = new TreeSet();
431 Iterator it = extraImports.iterator();
432 while (it.hasNext())
434 String ic = it.next().toString();
435 imp.add("import " + ic + ";\n");
438 StringBuffer b = new StringBuffer();
439 it = imp.iterator();
441 while (it.hasNext())
443 b.append(it.next());
445 return b.toString();
449 * If this flag is set (true by default), the compiler generates the Servant
450 * based classes. If set to false, the compiler generates the old style
451 * ObjectImpl based classes.
453 public void setPoaMode(boolean mode)
455 poaMode = mode;
459 * Set the verbose output mode (false by default)
461 * @param isVerbose the verbose output mode
463 public void setVerbose(boolean isVerbose)
465 verbose = isVerbose;
469 * If this flag is set (true by default), the compiler emits warnings.
471 public void setWarnings(boolean warn)
473 warnings = warn;
477 * Set the error ignore mode.
479 public void setForce(boolean isforce)
481 force = isforce;
485 * Get the package name.
487 public String getPackageName()
489 return packag;
493 * Get the proposed stub name
495 public String getStubName()
497 return stubName;
501 * Additional processing of the stub name.
503 public String convertStubName(String name)
505 // Drop the Impl suffix, if one exists.
506 if (name.endsWith("Impl"))
507 return name.substring(0, name.length() - "Impl".length());
508 else
509 return name;