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)
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
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
;
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
;
51 * The "basic" name (normally, the interface name, unless several Remote -
52 * derived interfaces are implemented.
54 protected String name
;
57 * The name (without package) of the class, passed as the parameter.
59 protected String implName
;
62 * The proposed name for the stub.
64 protected String stubName
;
67 * The Remote's, implemented by this class.
69 protected Collection implementedRemotes
= new HashSet();
72 * The extra classes that must be imported.
74 protected Collection extraImports
= new HashSet();
77 * The methods we must implement.
79 protected Collection methods
= new HashSet();
82 * The map of all code generator variables.
84 public Properties vars
= new Properties();
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;
94 * If this flag is set (true by default), the compiler emits warnings.
96 protected boolean warnings
= true;
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.
113 packag
= name
= implName
= stubName
= null;
114 implementedRemotes
.clear();
115 extraImports
.clear();
121 * Compile the given class (the instance of Remote), generating the stub and
125 * the class to compile.
127 public synchronized void compile(Class remote
)
133 s
= remote
.getName();
134 int p
= s
.lastIndexOf('.');
143 packag
= s
.substring(0, p
);
144 implName
= name
= s
.substring(p
+ 1);
147 name
= convertStubName(name
);
151 vars
.put("#name", name
);
152 vars
.put("#package", packag
);
153 vars
.put("#implName", implName
);
156 System
.out
.println("Package " + packag
+ ", name " + name
+ " impl "
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
]))
196 if (! remEx
&& !force
)
197 throw new CompilationError(m
[i
].getName() + ", defined in "
199 + ", does not throw "
200 + RemoteException
.class.getName());
202 AbstractMethodGenerator mm
= createMethodGenerator(m
[i
]);
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.
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:
234 Class finalComponent
= nameIt
;
235 while (finalComponent
.isArray())
237 finalComponent
= finalComponent
.getComponentType();
241 StringBuffer brackets
= new StringBuffer();
243 for (int i
= 0; i
< dimension
; i
++)
245 brackets
.append("[]");
248 return name(finalComponent
) + " " + brackets
;
252 String n
= nameIt
.getName();
253 if (! nameIt
.isArray() && ! nameIt
.isPrimitive())
254 if (! n
.startsWith("java.lang")
255 && ! (packag
!= null && n
.startsWith(packag
)))
258 int p
= n
.lastIndexOf('.');
262 return n
.substring(p
+ 1);
267 * Get the RMI-style repository Id for the given class.
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.
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() + "\"");
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");
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
);
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()));
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()
365 template
= getResource("Tie.jav");
367 template
= getResource("ImplTie.jav");
370 HashFinder hashFinder
= new HashFinder();
372 // Find the hash character position:
373 Iterator iter
= methods
.iterator();
374 String
[] names
= new String
[methods
.size()];
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();
401 m
.hashCharPosition
= hashCharPosition
;
403 b
.append(m
.generateTieMethod());
406 vars
.put("#tie_methods", b
.toString());
408 vars
.put("#imports", getImportStatements());
410 String output
= replaceAll(template
, vars
);
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();
434 String ic
= it
.next().toString();
435 imp
.add("import " + ic
+ ";\n");
438 StringBuffer b
= new StringBuffer();
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
)
459 * Set the verbose output mode (false by default)
461 * @param isVerbose the verbose output mode
463 public void setVerbose(boolean isVerbose
)
469 * If this flag is set (true by default), the compiler emits warnings.
471 public void setWarnings(boolean warn
)
477 * Set the error ignore mode.
479 public void setForce(boolean isforce
)
485 * Get the package name.
487 public String
getPackageName()
493 * Get the proposed stub name
495 public String
getStubName()
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());