src/share/classes/com/sun/corba/se/impl/presentation/rmi/IDLTypesUtil_save.sjava

changeset 519
6b5db99e194c
parent 355
9cdcc0152526
equal deleted inserted replaced
518:0717fc6f2960 519:6b5db99e194c
1 /*
2 * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.corba.se.impl.presentation.rmi ;
27
28 import java.lang.reflect.Method;
29 import java.lang.reflect.Field;
30 import java.util.Set;
31 import java.util.HashSet;
32 import java.util.Iterator;
33
34 /**
35 * Utility class for testing RMI/IDL Types as defined in
36 * Section 1.2 of The Java Language to IDL Mapping. Note that
37 * these are static checks only. Runtime checks, such as those
38 * described in Section 1.2.3, #3, are not covered.
39 */
40 public class IDLTypesUtil {
41
42 public static final String JAVA_GET_PROPERTY_PREFIX = "get";
43 public static final String JAVA_SET_PROPERTY_PREFIX = "set";
44 public static final String JAVA_IS_PROPERTY_PREFIX = "is";
45
46 public static final int VALID_TYPE = 0;
47 public static final int INVALID_TYPE = 1;
48
49 /**
50 * Validate a class to ensure it conforms to the rules for a
51 * Java RMI/IIOP interface.
52 *
53 * @throws IDLTypeException if not a valid RMI/IIOP interface.
54 */
55 public void validateRemoteInterface(Class c) throws IDLTypeException
56 {
57 if( c == null ) {
58 throw new IllegalArgumentException();
59 }
60
61 if( !c.isInterface() ) {
62 String msg = "Class " + c + " must be a java interface.";
63 throw new IDLTypeException(msg);
64 }
65
66 if( !java.rmi.Remote.class.isAssignableFrom(c) ) {
67 String msg = "Class " + c + " must extend java.rmi.Remote, " +
68 "either directly or indirectly.";
69 throw new IDLTypeException(msg);
70 }
71
72 // Get all methods, including super-interface methods.
73 Method[] methods = c.getMethods();
74
75 for(int i = 0; i < methods.length; i++) {
76 Method next = methods[i];
77 validateExceptions(next);
78 }
79
80 // Removed because of bug 4989053
81 // validateDirectInterfaces(c);
82 validateConstants(c);
83
84 return;
85 }
86
87 public boolean isRemoteInterface(Class c)
88 {
89 boolean remoteInterface = true;
90 try {
91 validateRemoteInterface(c);
92 } catch(IDLTypeException ite) {
93 remoteInterface = false;
94 }
95
96 return remoteInterface;
97 }
98
99 /**
100 * Section 1.2.2 Primitive Types
101 */
102 public boolean isPrimitive(Class c)
103 {
104 if( c == null ) {
105 throw new IllegalArgumentException();
106 }
107
108 return c.isPrimitive();
109 }
110
111 /**
112 * Section 1.2.4
113 */
114 public boolean isValue(Class c)
115 {
116 if( c == null ) {
117 throw new IllegalArgumentException();
118 }
119
120 return
121 (!c.isInterface() &&
122 java.io.Serializable.class.isAssignableFrom(c) &&
123 !java.rmi.Remote.class.isAssignableFrom(c));
124 }
125
126 /**
127 * Section 1.2.5
128 */
129 public boolean isArray(Class c)
130 {
131 boolean arrayType = false;
132
133 if( c == null ) {
134 throw new IllegalArgumentException();
135 }
136
137 if( c.isArray() ) {
138 Class componentType = c.getComponentType();
139 arrayType =
140 (isPrimitive(componentType) || isRemoteInterface(componentType) ||
141 isEntity(componentType) || isException(componentType) ||
142 isValue(componentType) || isObjectReference(componentType) );
143 }
144
145 return arrayType;
146 }
147
148 /**
149 * Section 1.2.6
150 */
151 public boolean isException(Class c)
152 {
153 if( c == null ) {
154 throw new IllegalArgumentException();
155 }
156
157 // Must be a checked exception, not including RemoteException or
158 // its subclasses.
159 return isCheckedException(c) && !isRemoteException(c) && isValue(c);
160 }
161
162 public boolean isRemoteException(Class c)
163 {
164 if( c == null ) {
165 throw new IllegalArgumentException();
166 }
167
168 return java.rmi.RemoteException.class.isAssignableFrom(c) ;
169 }
170
171 public boolean isCheckedException(Class c)
172 {
173 if( c == null ) {
174 throw new IllegalArgumentException();
175 }
176
177 return Throwable.class.isAssignableFrom(c) &&
178 !RuntimeException.class.isAssignableFrom(c) &&
179 !Error.class.isAssignableFrom(c) ;
180 }
181
182 /**
183 * Section 1.2.7
184 */
185 public boolean isObjectReference(Class c)
186 {
187 if( c == null ) {
188 throw new IllegalArgumentException();
189 }
190
191 return (c.isInterface() &&
192 org.omg.CORBA.Object.class.isAssignableFrom(c));
193 }
194
195 /**
196 * Section 1.2.8
197 */
198 public boolean isEntity(Class c)
199 {
200 if( c == null ) {
201 throw new IllegalArgumentException();
202 }
203
204 Class superClass = c.getSuperclass();
205 return (!c.isInterface() &&
206 (superClass != null) &&
207 (org.omg.CORBA.portable.IDLEntity.class.isAssignableFrom(c)));
208 }
209
210 public String javaPropertyPrefixToIDL( String javaPrefix )
211 {
212 return "_" + javaPrefix + "_" ;
213 }
214
215 /**
216 * Return the property type if given method is legal property accessor as defined in
217 * Section 1.3.4.3 of Java2IDL spec. Result is one of: JAVA_GET_PROPERTY_PREFIX,
218 * JAVA_SET_PROPERTY_PREFIX, JAVA_IS_PROPERTY_PREFIX.
219 */
220 public String propertyAccessorMethodType(Method m, Class c) {
221
222 String methodName = m.getName();
223 Class returnType = m.getReturnType();
224 Class[] parameters = m.getParameterTypes();
225 Class[] exceptionTypes = m.getExceptionTypes();
226 String propertyType = null;
227
228 if( methodName.startsWith(JAVA_GET_PROPERTY_PREFIX) ) {
229
230 if((parameters.length == 0) && (returnType != Void.TYPE) &&
231 !hasCorrespondingReadProperty(m, c, JAVA_IS_PROPERTY_PREFIX) {
232 propertyType = JAVA_GET_PROPERTY_PREFIX;
233 }
234
235 } else if( methodName.startsWith(JAVA_SET_PROPERTY_PREFIX) ) {
236
237 if((returnType == Void.TYPE) && (parameters.length == 1)) {
238 if (hasCorrespondingReadProperty(m, c, JAVA_GET_PROPERTY_PREFIX) ||
239 hasCorrespondingReadProperty(m, c, JAVA_IS_PROPERTY_PREFIX)) {
240 propertyType = JAVA_SET_PROPERTY_PREFIX;
241 }
242 }
243
244 } else if( methodName.startsWith(JAVA_IS_PROPERTY_PREFIX) ) {
245 if((parameters.length == 0) && (returnType == Boolean.TYPE)) {
246 propertyType = JAVA_IS_PROPERTY_PREFIX;
247 }
248 }
249
250 // Some final checks that apply to all properties.
251 if( propertyType != null ) {
252 if(!validPropertyExceptions(m) ||
253 (methodName.length() <= propertyType.length())) {
254 propertyType = null;
255 }
256 }
257
258 return propertyType ;
259 }
260
261 private boolean hasCorrespondingReadProperty
262 (Method writeProperty, Class c, String readPropertyPrefix) {
263
264 String writePropertyMethodName = writeProperty.getName();
265 Class[] writePropertyParameters = writeProperty.getParameterTypes();
266 boolean foundReadProperty = false;
267
268 try {
269 // Look for a valid corresponding Read property
270 String readPropertyMethodName =
271 writePropertyMethodName.replaceFirst
272 (JAVA_SET_PROPERTY_PREFIX, readPropertyPrefix);
273 Method readPropertyMethod = c.getMethod(readPropertyMethodName,
274 new Class[] {});
275 foundReadProperty =
276 ((propertyAccessorMethodType(readPropertyMethod, c) != null) &&
277 (readPropertyMethod.getReturnType() ==
278 writePropertyParameters[0]));
279 } catch(Exception e) {
280 // ignore. this means we didn't find a corresponding get property.
281 }
282
283 return foundReadProperty;
284 }
285
286 public String getAttributeNameForProperty(String propertyName) {
287 String attributeName = null;
288 String prefix = null;
289
290 if( propertyName.startsWith(JAVA_GET_PROPERTY_PREFIX) ) {
291 prefix = JAVA_GET_PROPERTY_PREFIX;
292 } else if( propertyName.startsWith(JAVA_SET_PROPERTY_PREFIX) ) {
293 prefix = JAVA_SET_PROPERTY_PREFIX;
294 } else if( propertyName.startsWith(JAVA_IS_PROPERTY_PREFIX) ) {
295 prefix = JAVA_IS_PROPERTY_PREFIX;
296 }
297
298 if( (prefix != null) && (prefix.length() < propertyName.length()) ) {
299 String remainder = propertyName.substring(prefix.length());
300 if( (remainder.length() >= 2) &&
301 Character.isUpperCase(remainder.charAt(0)) &&
302 Character.isUpperCase(remainder.charAt(1)) ) {
303 // don't set the first letter to lower-case if the
304 // first two are upper-case
305 attributeName = remainder;
306 } else {
307 attributeName = Character.toLowerCase(remainder.charAt(0)) +
308 remainder.substring(1);
309 }
310 }
311
312 return attributeName;
313 }
314
315 /**
316 * Return IDL Type name for primitive types as defined in
317 * Section 1.3.3 of Java2IDL spec or null if not a primitive type.
318 */
319 public IDLType getPrimitiveIDLTypeMapping(Class c) {
320
321 if( c == null ) {
322 throw new IllegalArgumentException();
323 }
324
325 if( c.isPrimitive() ) {
326 if( c == Void.TYPE ) {
327 return new IDLType( c, "void" ) ;
328 } else if( c == Boolean.TYPE ) {
329 return new IDLType( c, "boolean" ) ;
330 } else if( c == Character.TYPE ) {
331 return new IDLType( c, "wchar" ) ;
332 } else if( c == Byte.TYPE ) {
333 return new IDLType( c, "octet" ) ;
334 } else if( c == Short.TYPE ) {
335 return new IDLType( c, "short" ) ;
336 } else if( c == Integer.TYPE ) {
337 return new IDLType( c, "long" ) ;
338 } else if( c == Long.TYPE ) {
339 return new IDLType( c, "long_long" ) ;
340 } else if( c == Float.TYPE ) {
341 return new IDLType( c, "float" ) ;
342 } else if( c == Double.TYPE ) {
343 return new IDLType( c, "double" ) ;
344 }
345 }
346
347 return null;
348 }
349
350 /**
351 * Return IDL Type name for special case type mappings as defined in
352 * Table 1-1 of Java2IDL spec or null if given class is not a special
353 * type.
354 */
355 public IDLType getSpecialCaseIDLTypeMapping(Class c) {
356
357 if( c == null ) {
358 throw new IllegalArgumentException();
359 }
360
361 if( c == java.lang.Object.class ) {
362 return new IDLType( c, new String[] { "java", "lang" },
363 "Object" ) ;
364 } else if( c == java.lang.String.class ) {
365 return new IDLType( c, new String[] { "CORBA" },
366 "WStringValue" ) ;
367 } else if( c == java.lang.Class.class ) {
368 return new IDLType( c, new String[] { "javax", "rmi", "CORBA" },
369 "ClassDesc" ) ;
370 } else if( c == java.io.Serializable.class ) {
371 return new IDLType( c, new String[] { "java", "io" },
372 "Serializable" ) ;
373 } else if( c == java.io.Externalizable.class ) {
374 return new IDLType( c, new String[] { "java", "io" },
375 "Externalizable" ) ;
376 } else if( c == java.rmi.Remote.class ) {
377 return new IDLType( c, new String[] { "java", "rmi" },
378 "Remote" ) ;
379 } else if( c == org.omg.CORBA.Object.class ) {
380 return new IDLType( c, "Object" ) ;
381 } else {
382 return null;
383 }
384 }
385
386 /**
387 * Implements 1.2.3 #2 and #4
388 */
389 private void validateExceptions(Method method) throws IDLTypeException {
390
391 Class[] exceptions = method.getExceptionTypes();
392
393 boolean declaresRemoteExceptionOrSuperClass = false;
394
395 // Section 1.2.3, #2
396 for(int eIndex = 0; eIndex < exceptions.length; eIndex++) {
397 Class exception = exceptions[eIndex];
398 if( isRemoteExceptionOrSuperClass(exception) ) {
399 declaresRemoteExceptionOrSuperClass = true;
400 break;
401 }
402 }
403
404 if( !declaresRemoteExceptionOrSuperClass ) {
405 String msg = "Method '" + method + "' must throw at least one " +
406 "exception of type java.rmi.RemoteException or one of its " +
407 "super-classes";
408 throw new IDLTypeException(msg);
409 }
410
411 // Section 1.2.3, #4
412 // See also bug 4972402
413 // For all exceptions E in exceptions,
414 // (isCheckedException(E) => (isValue(E) || RemoteException.isAssignableFrom( E ) )
415 for(int eIndex = 0; eIndex < exceptions.length; eIndex++) {
416 Class exception = exceptions[eIndex];
417
418 if (isCheckedException(exception) && !isValue(exception) &&
419 !isRemoteException(exception))
420 {
421 String msg = "Exception '" + exception + "' on method '" +
422 method + "' is not a allowed RMI/IIOP exception type";
423 throw new IDLTypeException(msg);
424 }
425 }
426
427 return;
428 }
429
430 /**
431 * Returns true if the method's throw clause conforms to the exception
432 * restrictions for properties as defined in Section 1.3.4.3 of
433 * Java2IDL spec. This means that for all exceptions E declared on the
434 * method, E isChecked => RemoteException.isAssignableFrom( E ).
435 */
436 private boolean validPropertyExceptions(Method method)
437 {
438 Class[] exceptions = method.getExceptionTypes();
439
440 for(int eIndex = 0; eIndex < exceptions.length; eIndex++) {
441 Class exception = exceptions[eIndex];
442
443 if (isCheckedException(exception) && !isRemoteException(exception))
444 return false ;
445 }
446
447 return true;
448 }
449
450 /**
451 * Implements Section 1.2.3, #2.
452 */
453 private boolean isRemoteExceptionOrSuperClass(Class c) {
454 return
455 ((c == java.rmi.RemoteException.class) ||
456 (c == java.io.IOException.class) ||
457 (c == java.lang.Exception.class) ||
458 (c == java.lang.Throwable.class));
459 }
460
461 /**
462 * Implements Section 1.2.3, #5.
463 */
464 private void validateDirectInterfaces(Class c) throws IDLTypeException {
465
466 Class[] directInterfaces = c.getInterfaces();
467
468 if( directInterfaces.length < 2 ) {
469 return;
470 }
471
472 Set allMethodNames = new HashSet();
473 Set currentMethodNames = new HashSet();
474
475 for(int i = 0; i < directInterfaces.length; i++) {
476 Class next = directInterfaces[i];
477 Method[] methods = next.getMethods();
478
479 // Comparison is based on method names only. First collect
480 // all methods from current interface, eliminating duplicate
481 // names.
482 currentMethodNames.clear();
483 for(int m = 0; m < methods.length; m++) {
484 currentMethodNames.add(methods[m].getName());
485 }
486
487 // Now check each method against list of all unique method
488 // names processed so far.
489 for(Iterator iter=currentMethodNames.iterator(); iter.hasNext();) {
490 String methodName = (String) iter.next();
491 if( allMethodNames.contains(methodName) ) {
492 String msg = "Class " + c + " inherits method " +
493 methodName + " from multiple direct interfaces.";
494 throw new IDLTypeException(msg);
495 } else {
496 allMethodNames.add(methodName);
497 }
498 }
499 }
500
501 return;
502 }
503
504 /**
505 * Implements 1.2.3 #6
506 */
507 private void validateConstants(final Class c)
508 throws IDLTypeException {
509
510 Field[] fields = null;
511
512 try {
513 fields = (Field[])
514 java.security.AccessController.doPrivileged
515 (new java.security.PrivilegedExceptionAction() {
516 public java.lang.Object run() throws Exception {
517 return c.getFields();
518 }
519 });
520 } catch(java.security.PrivilegedActionException pae) {
521 IDLTypeException ite = new IDLTypeException();
522 ite.initCause(pae);
523 throw ite;
524 }
525
526 for(int i = 0; i < fields.length; i++) {
527 Field next = fields[i];
528 Class fieldType = next.getType();
529 if( (fieldType != java.lang.String.class) &&
530 !isPrimitive(fieldType) ) {
531 String msg = "Constant field '" + next.getName() +
532 "' in class '" + next.getDeclaringClass().getName() +
533 "' has invalid type' " + next.getType() + "'. Constants" +
534 " in RMI/IIOP interfaces can only have primitive" +
535 " types and java.lang.String types.";
536 throw new IDLTypeException(msg);
537 }
538 }
539
540
541 return;
542 }
543
544 }

mercurial