1 16 package com.google.gwt.user.rebind.rpc; 17 18 import com.google.gwt.core.ext.BadPropertyValueException; 19 import com.google.gwt.core.ext.PropertyOracle; 20 import com.google.gwt.core.ext.TreeLogger; 21 import com.google.gwt.core.ext.UnableToCompleteException; 22 import com.google.gwt.core.ext.typeinfo.JArrayType; 23 import com.google.gwt.core.ext.typeinfo.JClassType; 24 import com.google.gwt.core.ext.typeinfo.JField; 25 import com.google.gwt.core.ext.typeinfo.JMethod; 26 import com.google.gwt.core.ext.typeinfo.JParameter; 27 import com.google.gwt.core.ext.typeinfo.JParameterizedType; 28 import com.google.gwt.core.ext.typeinfo.JType; 29 import com.google.gwt.core.ext.typeinfo.NotFoundException; 30 import com.google.gwt.core.ext.typeinfo.TypeOracle; 31 import com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException; 32 import com.google.gwt.user.client.rpc.IsSerializable; 33 import com.google.gwt.user.client.rpc.SerializationStreamReader; 34 import com.google.gwt.user.client.rpc.SerializationStreamWriter; 35 36 import java.io.Serializable ; 37 import java.text.MessageFormat ; 38 import java.util.ArrayList ; 39 import java.util.Arrays ; 40 import java.util.Collection ; 41 import java.util.Comparator ; 42 import java.util.HashMap ; 43 import java.util.Iterator ; 44 import java.util.List ; 45 import java.util.Map ; 46 import java.util.Set ; 47 import java.util.Stack ; 48 import java.util.TreeSet ; 49 50 108 public class SerializableTypeOracleBuilder { 109 113 static final class TypeState { 114 private final String state; 115 116 protected TypeState(String state) { 117 this.state = state; 118 } 119 120 public String toString() { 121 return state; 122 } 123 } 124 125 129 private class MetaTypeInfo { 130 134 private boolean autoSerializable; 135 136 140 private boolean checkedInManualContext; 141 142 145 private boolean checkedSubtypes; 146 147 150 private Set failures; 151 152 155 private JClassType manualSerializer; 156 157 161 private boolean serializable; 162 163 166 private TypeState state = SerializableTypeOracleBuilder.NOT_CHECKED; 167 168 171 private final JType type; 172 173 public MetaTypeInfo(JType type) { 174 this.type = type; 175 176 JClassType classOrInterface = type.isClassOrInterface(); 177 if (classOrInterface != null) { 178 autoSerializable = classOrInterface.isAssignableTo(isSerializableClass) 179 || classOrInterface.isAssignableTo(serializableClass); 180 manualSerializer = findCustomFieldSerializer(typeOracle, 181 classOrInterface); 182 } 183 } 184 185 public void addFailure(String message) { 186 if (failures == null) { 187 failures = new TreeSet (); 188 } 189 190 failures.add(message); 191 } 192 193 public boolean getCheckedInManualContext() { 194 return checkedInManualContext; 195 } 196 197 public boolean getCheckedSubtypes() { 198 return checkedSubtypes; 199 } 200 201 public Set getFailures() { 202 return failures; 203 } 204 205 public JClassType getManualSerializer() { 206 return manualSerializer; 207 } 208 209 public TypeState getState() { 210 return state; 211 } 212 213 public JType getType() { 214 return type; 215 } 216 217 public boolean isSerializable() { 218 if (state == SerializableTypeOracleBuilder.CHECK_IN_PROGRESS) { 219 return true; 222 } 223 224 return serializable && failures == null; 225 } 226 227 238 public boolean needToRecheck(boolean checkSubtypes, boolean inManualContext) { 239 assert (state == SerializableTypeOracleBuilder.CHECK_SUCCEEDED); 240 241 if (!qualifiesForSerialization() && !inManualContext 242 && getCheckedInManualContext()) { 243 return true; 244 } 245 246 if (checkSubtypes && !getCheckedSubtypes()) { 247 return true; 248 } 249 250 return false; 251 } 252 253 261 public boolean qualifiesForAutoSerialization() { 262 return autoSerializable && manualSerializer == null; 263 } 264 265 270 public boolean qualifiesForManualSerialization() { 271 return manualSerializer != null; 272 } 273 274 public boolean qualifiesForSerialization() { 275 return qualifiesForAutoSerialization() 276 || qualifiesForManualSerialization(); 277 } 278 279 public void setCheckedInManualContext(boolean checkedInManualContext) { 280 this.checkedInManualContext = checkedInManualContext; 281 } 282 283 public void setCheckedSubtypes(boolean checkedSubtypes) { 284 this.checkedSubtypes = checkedSubtypes; 285 } 286 287 public void setSerializable(boolean serializable) { 288 this.serializable = serializable; 289 } 290 291 public void setState(TypeState newState) { 292 state = newState; 293 } 294 } 295 296 299 private static final TypeState CHECK_FAILED = new TypeState("Check failed"); 300 301 304 private static final TypeState CHECK_IN_PROGRESS = new TypeState( 305 "Check in progress"); 306 307 310 private static final TypeState CHECK_SUCCEEDED = new TypeState( 311 "Check succeeded"); 312 313 316 private static final TypeState NOT_CHECKED = new TypeState("Not checked"); 317 318 326 static JClassType findCustomFieldSerializer(TypeOracle typeOracle, JType type) { 327 JClassType classOrInterface = type.isClassOrInterface(); 328 if (classOrInterface == null) { 329 return null; 330 } 331 332 String customFieldSerializerName = type.getQualifiedSourceName() 333 + "_CustomFieldSerializer"; 334 JClassType customSerializer = typeOracle.findType(customFieldSerializerName); 335 if (customSerializer == null) { 336 customSerializer = typeOracle.findType("com.google.gwt.user.client.rpc.core." 339 + customFieldSerializerName); 340 } 341 342 return customSerializer; 343 } 344 345 private static JArrayType getArrayType(TypeOracle typeOracle, int rank, 346 JType component) { 347 assert (rank > 0); 348 349 JArrayType array = null; 350 for (int i = 0; i < rank; ++i) { 351 array = typeOracle.getArrayType(component); 352 component = array; 353 } 354 355 return array; 356 } 357 358 private static void logSerializableTypes(TreeLogger logger, JType[] types) { 359 logger = logger.branch(TreeLogger.DEBUG, "Identified " + types.length 360 + " serializable type" + ((types.length == 1) ? "" : "s"), null); 361 362 for (int i = 0; i < types.length; ++i) { 363 logger.branch(TreeLogger.DEBUG, 364 types[i].getParameterizedQualifiedSourceName(), null); 365 } 366 } 367 368 372 private boolean allowUnserializableSubtypesOfAutoSerializableTypes; 373 374 377 private final JClassType collectionClass; 378 379 382 private final Stack contexts = new Stack (); 383 384 387 private final JClassType isSerializableClass; 388 389 392 private final JClassType mapClass; 393 394 private final RemoteServiceAsyncValidator remoteServiceAsyncValidator; 395 396 private final TreeLogger rootLogger; 397 398 402 private final JClassType serializableClass; 403 404 407 private final JClassType streamReaderClass; 408 409 412 private final JClassType streamWriterClass; 413 414 417 private final JClassType stringClass; 418 419 423 private boolean suppressNonStaticFinalFieldWarnings; 424 425 private final TypeOracle typeOracle; 426 427 430 private final Map typeToMetaTypeInfo = new HashMap (); 431 432 436 private boolean validationFailed; 437 438 446 public SerializableTypeOracleBuilder(TreeLogger rootLogger, 447 TypeOracle typeOracle) throws UnableToCompleteException { 448 this.rootLogger = rootLogger; 449 this.typeOracle = typeOracle; 450 451 try { 452 collectionClass = typeOracle.getType(Collection .class.getName()); 453 isSerializableClass = typeOracle.getType(IsSerializable.class.getName()); 454 mapClass = typeOracle.getType(Map .class.getName()); 455 serializableClass = typeOracle.getType(Serializable.class.getName()); 456 stringClass = typeOracle.getType(String .class.getName()); 457 streamReaderClass = typeOracle.getType(SerializationStreamReader.class.getName()); 458 streamWriterClass = typeOracle.getType(SerializationStreamWriter.class.getName()); 459 460 MetaTypeInfo stringMti = getMetaTypeInfo(stringClass); 462 stringMti.setSerializable(true); 463 464 MetaTypeInfo incompatibleRemoteServiceExceptionMti = getMetaTypeInfo(typeOracle.getType(IncompatibleRemoteServiceException.class.getName())); 466 incompatibleRemoteServiceExceptionMti.setSerializable(true); 467 468 remoteServiceAsyncValidator = new RemoteServiceAsyncValidator(typeOracle); 469 } catch (NotFoundException e) { 470 rootLogger.log(TreeLogger.ERROR, null, e); 471 throw new UnableToCompleteException(); 472 } 473 } 474 475 483 public SerializableTypeOracle build(PropertyOracle propertyOracle, 484 JClassType remoteService) throws UnableToCompleteException { 485 486 initializeProperties(rootLogger, propertyOracle); 487 488 remoteServiceAsyncValidator.validateRemoteServiceAsync(rootLogger, 489 remoteService); 490 491 TreeLogger logger = rootLogger.branch(TreeLogger.DEBUG, "Analyzing '" 492 + remoteService.getParameterizedQualifiedSourceName() 493 + "' for serializable types", null); 494 495 validateRemoteService(logger, remoteService); 496 497 if (validationFailed) { 498 throw new UnableToCompleteException(); 500 } 501 502 List serializableTypesList = new ArrayList (); 503 Iterator iterTypes = typeToMetaTypeInfo.values().iterator(); 504 while (iterTypes.hasNext()) { 505 MetaTypeInfo mti = (MetaTypeInfo) iterTypes.next(); 506 JType type = mti.getType(); 507 if (mti.isSerializable() && type.isInterface() == null) { 508 serializableTypesList.add(type); 509 } 510 } 511 512 JType[] serializableTypes = new JType[serializableTypesList.size()]; 513 serializableTypesList.toArray(serializableTypes); 514 515 Arrays.sort(serializableTypes, new Comparator () { 516 public int compare(Object o1, Object o2) { 517 String n1 = ((JType) o1).getQualifiedSourceName(); 518 String n2 = ((JType) o2).getQualifiedSourceName(); 519 return n1.compareTo(n2); 520 } 521 }); 522 523 logSerializableTypes(logger, serializableTypes); 524 525 return new SerializableTypeOracleImpl(typeOracle, serializableTypes); 526 } 527 528 531 private void checkArray(TreeLogger logger, JArrayType array) { 532 checkType( 533 logger.branch(TreeLogger.DEBUG, "Analyzing component type:", null), 534 array.getComponentType(), true); 535 536 JType leafType = array.getLeafType(); 537 JClassType classOrInterface = leafType.isClassOrInterface(); 538 if (leafType.isPrimitive() != null) { 539 getMetaTypeInfo(array).setSerializable(true); 540 } else if (classOrInterface != null) { 541 MetaTypeInfo mti = getMetaTypeInfo(classOrInterface); 542 if (mti.isSerializable()) { 543 getMetaTypeInfo(array).setSerializable(true); 544 } 545 546 JClassType[] subtypes = classOrInterface.getSubtypes(); 547 for (int i = 0; i < subtypes.length; ++i) { 548 JClassType component = subtypes[i]; 549 JArrayType covariantArray = getArrayType(typeOracle, array.getRank(), 550 component); 551 552 MetaTypeInfo cmti = getMetaTypeInfo(component); 553 if (cmti.isSerializable()) { 554 logger.branch(TreeLogger.DEBUG, 555 covariantArray.getParameterizedQualifiedSourceName(), null); 556 getMetaTypeInfo(covariantArray).setSerializable(true); 557 } 558 } 559 } 560 } 561 562 579 private void checkClassOrInterface(TreeLogger logger, JClassType type, 580 boolean validateSubtypes) { 581 if (type == stringClass) { 582 return; 584 } 585 586 if (type == typeOracle.getJavaLangObject()) { 587 setUnserializableAndLog( 589 logger, 590 inManualSerializationContext() ? TreeLogger.WARN : TreeLogger.ERROR, 591 "In order to produce smaller client-side code, 'Object' is not allowed; consider using a more specific type", 592 type); 593 return; 594 } 595 596 JClassType superclass = type.getSuperclass(); 597 if (superclass != null) { 598 MetaTypeInfo smti = getMetaTypeInfo(superclass); 599 if (smti.qualifiesForSerialization()) { 600 checkType( 601 logger.branch(TreeLogger.DEBUG, "Analyzing superclass:", null), 602 superclass, false); 603 } else { 604 logger.branch(TreeLogger.DEBUG, "Not analyzing superclass '" 605 + superclass.getParameterizedQualifiedSourceName() 606 + "' because it is not assignable to '" 607 + IsSerializable.class.getName() + "' or '" 608 + Serializable.class.getName() 609 + "' nor does it have a custom field serializer", null); 610 } 611 } 612 613 MetaTypeInfo mti = getMetaTypeInfo(type); 614 if (mti.qualifiesForManualSerialization()) { 615 List failures = CustomFieldSerializerValidator.validate( 616 streamReaderClass, streamWriterClass, mti.getManualSerializer(), type); 617 if (!failures.isEmpty()) { 618 setUnserializableAndLog(logger, TreeLogger.ERROR, failures, type); 619 return; 620 } 621 622 mti.setSerializable(true); 623 624 checkFields(logger, type); 625 626 } else if (mti.qualifiesForAutoSerialization()) { 627 if (type.isLocalType()) { 628 setUnserializableAndLog( 629 logger, 630 TreeLogger.WARN, 631 "Is a local type, it will be excluded from the set of serializable types", 632 type); 633 return; 634 } 635 636 if (type.isMemberType() && !type.isStatic()) { 637 setUnserializableAndLog( 638 logger, 639 TreeLogger.WARN, 640 "Is nested but not static, it will be excluded from the set of serializable types", 641 type); 642 return; 643 } 644 645 if (type.isClass() != null && !type.isDefaultInstantiable()) { 646 setUnserializableAndLog( 647 logger, 648 TreeLogger.ERROR, 649 "Was not default instantiable (it must have a zero-argument public constructor or no constructors at all)", 650 type); 651 return; 652 } 653 654 if (type.isAbstract() && type.getSubtypes().length == 0) { 655 return; 657 } 658 659 getMetaTypeInfo(type).setSerializable(true); 660 661 checkMethods(logger, type); 662 663 checkFields(logger, type); 664 } 665 666 if (validateSubtypes) { 667 int nSubtypes = 0; 668 int nSerializableSubtypes = 0; 669 670 JClassType[] subtypes = type.getSubtypes(); 671 if (subtypes.length > 0) { 672 TreeLogger localLogger = logger.branch(TreeLogger.DEBUG, 673 "Analyzing subclasses:", null); 674 675 for (int i = 0; i < subtypes.length; ++i) { 676 JClassType subtype = subtypes[i]; 677 MetaTypeInfo smti = getMetaTypeInfo(subtype); 678 if (smti.qualifiesForSerialization()) { 679 checkType(localLogger, subtype, false); 680 681 ++nSubtypes; 682 683 if (smti.isSerializable()) { 684 ++nSerializableSubtypes; 685 } else { 686 localLogger.branch(TreeLogger.DEBUG, 687 subtype.getParameterizedQualifiedSourceName() 688 + " is not serializable", null); 689 690 if (subtype.isLocalType() || subtype.isMemberType() 691 && !subtype.isStatic()) { 692 --nSubtypes; 693 } 694 } 695 } else { 696 localLogger.branch(TreeLogger.DEBUG, "Not analyzing subclass '" 697 + subtype.getParameterizedQualifiedSourceName() 698 + "' because it is not assignable to '" 699 + IsSerializable.class.getName() + "' or '" 700 + Serializable.class.getName() 701 + "' nor does it have a custom field serializer", null); 702 } 703 } 704 } 705 706 if (mti.qualifiesForAutoSerialization()) { 707 if (nSerializableSubtypes < nSubtypes) { 708 setUnserializableAndLog(logger, 709 allowUnserializableSubtypesOfAutoSerializableTypes 710 ? TreeLogger.WARN : TreeLogger.ERROR, 711 "Not all subtypes of the automatically serializable type '" 712 + type.getQualifiedSourceName() 713 + "' are themselves automatically serializable", type); 714 } 715 } else if (!mti.qualifiesForManualSerialization() 716 && nSerializableSubtypes == 0) { 717 722 String message = MessageFormat.format( 723 "Type ''{0}'' is not assignable to IsSerializable or java.io.Serializable, it does not have a custom field serializer and it does not have any serializable subtypes", 724 new String [] {type.getParameterizedQualifiedSourceName()}); 725 setUnserializableAndLog(logger, inManualSerializationContext() 726 ? TreeLogger.WARN : TreeLogger.ERROR, message, type); 727 } 728 } 729 } 730 731 private void checkFields(TreeLogger logger, JClassType classOrInterface) { 732 TreeLogger localLogger = logger; 733 JField[] fields = classOrInterface.getFields(); 734 if (fields.length > 0) { 735 localLogger = localLogger.branch(TreeLogger.DEBUG, "Analyzing Fields:", 736 null); 737 738 contexts.push(classOrInterface); 739 740 for (int i = 0; i < fields.length; ++i) { 741 JField field = fields[i]; 742 743 if (field.isStatic() || field.isTransient()) { 744 continue; 745 } 746 747 if (field.isFinal()) { 748 if (!suppressNonStaticFinalFieldWarnings) { 749 localLogger.branch(TreeLogger.WARN, "Field '" + field.toString() 750 + "' will not be serialized because it is final", null); 751 } 752 continue; 753 } 754 755 TreeLogger fieldLogger = localLogger.branch(TreeLogger.DEBUG, 756 field.toString(), null); 757 JType fieldType = field.getType(); 758 checkForUnparameterizedType(fieldLogger, fieldType); 759 checkType(fieldLogger, fieldType, true); 760 } 761 762 contexts.pop(); 763 764 } else { 765 localLogger.branch(TreeLogger.DEBUG, "No fields to analyze", null); 766 } 767 } 768 769 private void checkForUnparameterizedType(TreeLogger logger, JType type) { 770 if (type.isParameterized() != null) { 771 return; 772 } 773 774 JClassType classOrInterface = type.isClassOrInterface(); 775 if (classOrInterface != null) { 776 if (classOrInterface.isAssignableTo(collectionClass) 777 || classOrInterface.isAssignableTo(mapClass)) { 778 TreeLogger localLogger = logger.branch( 779 TreeLogger.WARN, 780 "Type '" 781 + type.getQualifiedSourceName() 782 + "' should be parameterized to help the compiler produce the smallest code size possible for your module. Since the gwt.typeArgs javadoc annotation is missing, all subtypes of Object will be analyzed for serializability even if they are not directly or indirectly used", 783 null); 784 785 791 JClassType[] allTypes = typeOracle.getJavaLangObject().getSubtypes(); 792 for (int i = 0; i < allTypes.length; ++i) { 793 JClassType cls = allTypes[i]; 794 MetaTypeInfo mti = getMetaTypeInfo(cls); 795 if (mti.qualifiesForSerialization()) { 796 checkType(localLogger, cls, true); 797 } 798 } 799 } 800 } 801 } 802 803 private void checkMethods(TreeLogger logger, JClassType classOrInterface) { 804 JMethod[] methods = classOrInterface.getMethods(); 805 for (int i = 0; i < methods.length; ++i) { 806 if (methods[i].isNative()) { 807 logger.branch( 808 TreeLogger.WARN, 809 MessageFormat.format( 810 "Method ''{0}'' is native, calling this method in server side code will result in an UnsatisfiedLinkError", 811 new String [] {methods[i].toString()}), null); 812 } 813 } 814 } 815 816 820 private void checkType(TreeLogger logger, JType type, boolean checkSubtypes) { 821 if (type == null || type.isPrimitive() != null) { 822 return; 823 } 824 825 logger = logger.branch(TreeLogger.DEBUG, 826 type.getParameterizedQualifiedSourceName(), null); 827 828 MetaTypeInfo mti = getMetaTypeInfo(type); 829 TypeState state = mti.getState(); 830 831 if (state == SerializableTypeOracleBuilder.CHECK_FAILED) { 832 logReasonsForUnserializability(logger, type); 833 return; 834 } else if (state == SerializableTypeOracleBuilder.CHECK_IN_PROGRESS) { 835 logger.branch(TreeLogger.DEBUG, "'" 836 + type.getParameterizedQualifiedSourceName() 837 + "' is being analyzed; skipping", null); 838 return; 839 } else if (state == SerializableTypeOracleBuilder.CHECK_SUCCEEDED) { 840 if (!mti.needToRecheck(checkSubtypes, inManualSerializationContext())) { 841 logger.branch(TreeLogger.DEBUG, "Type has already been analyzed", null); 842 return; 843 } 844 } 845 846 mti.setState(SerializableTypeOracleBuilder.CHECK_IN_PROGRESS); 847 848 if (type.isParameterized() != null) { 849 JParameterizedType parameterized = type.isParameterized(); 850 checkType(logger.branch(TreeLogger.DEBUG, "Analyzing raw type", null), 851 parameterized.getRawType(), true); 852 853 checkTypes(logger.branch(TreeLogger.DEBUG, "Analyzing type args", null), 854 parameterized.getTypeArgs()); 855 } else if (type.isArray() != null) { 856 checkArray(logger, type.isArray()); 857 } else if (type.isClassOrInterface() != null) { 858 checkClassOrInterface(logger, type.isClassOrInterface(), checkSubtypes); 859 } 860 861 if (mti.getState() != SerializableTypeOracleBuilder.CHECK_FAILED) { 862 mti.setState(SerializableTypeOracleBuilder.CHECK_SUCCEEDED); 863 } 864 865 mti.setCheckedSubtypes(checkSubtypes); 866 mti.setCheckedInManualContext(inManualSerializationContext()); 867 } 868 869 private void checkTypes(TreeLogger logger, JType[] types) { 870 for (int i = 0; i < types.length; ++i) { 871 checkType(logger, types[i], true); 872 } 873 } 874 875 private MetaTypeInfo getMetaTypeInfo(JType type) { 876 MetaTypeInfo mti = (MetaTypeInfo) typeToMetaTypeInfo.get(type); 877 if (mti == null) { 878 mti = new MetaTypeInfo(type); 879 typeToMetaTypeInfo.put(type, mti); 880 } 881 882 return mti; 883 } 884 885 private void initializeProperties(TreeLogger logger, 886 PropertyOracle propertyOracle) { 887 allowUnserializableSubtypesOfAutoSerializableTypes = false; 889 890 try { 891 String propVal = propertyOracle.getPropertyValue(logger, 892 "gwt.allowUnserializableSubtypesOfAutoSerializableTypes"); 893 if (propVal.equals("true")) { 894 allowUnserializableSubtypesOfAutoSerializableTypes = true; 895 } 896 } catch (BadPropertyValueException e) { 897 } 900 901 suppressNonStaticFinalFieldWarnings = false; 902 try { 903 String propVal = propertyOracle.getPropertyValue(logger, 904 "gwt.suppressNonStaticFinalFieldWarnings"); 905 if (propVal.equals("true")) { 906 suppressNonStaticFinalFieldWarnings = true; 907 } 908 } catch (BadPropertyValueException e) { 909 } 912 } 913 914 921 private boolean inManualSerializationContext() { 922 if (contexts.isEmpty()) { 923 return false; 924 } 925 926 JType parent = (JType) contexts.peek(); 927 JClassType parentClass = parent.isClassOrInterface(); 928 929 if (parentClass != null) { 930 return getMetaTypeInfo(parentClass).qualifiesForManualSerialization(); 931 } 932 933 return false; 934 } 935 936 private void logReasonsForUnserializability(TreeLogger logger, JType type) { 937 TreeLogger.Type logType; 938 MetaTypeInfo mti = getMetaTypeInfo(type); 939 940 boolean autoSerializable = mti.qualifiesForAutoSerialization(); 941 if (inManualSerializationContext() && !autoSerializable) { 942 logType = TreeLogger.WARN; 943 } else { 944 logType = TreeLogger.ERROR; 945 946 if (autoSerializable) { 947 JClassType classOrInterface = type.isClassOrInterface(); 948 949 if (classOrInterface.isLocalType() 950 || (classOrInterface.isMemberType() && !classOrInterface.isStatic())) { 951 logType = TreeLogger.WARN; 952 } 953 } 954 } 955 956 if (logType == TreeLogger.ERROR) { 957 validationFailed = true; 958 } 959 960 Set reasons = mti.getFailures(); 961 Iterator iter = reasons.iterator(); 962 while (iter.hasNext()) { 963 logger.branch(logType, (String ) iter.next(), null); 964 } 965 } 966 967 private void setUnserializableAndLog(TreeLogger logger, 968 TreeLogger.Type logType, List failures, JClassType type) { 969 Iterator iter = failures.iterator(); 970 while (iter.hasNext()) { 971 setUnserializableAndLog(logger, logType, (String ) iter.next(), type); 972 } 973 } 974 975 private void setUnserializableAndLog(TreeLogger logger, 976 TreeLogger.Type logType, String message, JType type) { 977 MetaTypeInfo mti = getMetaTypeInfo(type); 978 mti.setState(SerializableTypeOracleBuilder.CHECK_FAILED); 979 mti.setSerializable(false); 980 mti.addFailure(message); 981 982 if (logType == TreeLogger.ERROR) { 983 validationFailed = true; 984 } 985 986 logger.branch(logType, message, null); 987 } 988 989 private void validateRemoteService(TreeLogger logger, JClassType remoteService) { 990 JMethod[] methods = remoteService.getOverridableMethods(); 991 992 logger = logger.branch(TreeLogger.DEBUG, "Analyzing methods:", null); 993 994 for (int i = 0; i < methods.length; ++i) { 995 JMethod method = methods[i]; 996 TreeLogger methodLogger = logger.branch(TreeLogger.DEBUG, 997 method.toString(), null); 998 JType returnType = method.getReturnType(); 999 TreeLogger returnTypeLogger = methodLogger.branch(TreeLogger.DEBUG, 1000 "Return type: " + returnType.getParameterizedQualifiedSourceName(), 1001 null); 1002 checkForUnparameterizedType(returnTypeLogger, returnType); 1003 checkType(returnTypeLogger, returnType, true); 1004 1005 JParameter[] params = method.getParameters(); 1006 for (int j = 0; j < params.length; ++j) { 1007 JParameter param = params[j]; 1008 TreeLogger paramLogger = methodLogger.branch(TreeLogger.DEBUG, 1009 "Parameter: " + param.toString(), null); 1010 JType paramType = param.getType(); 1011 checkForUnparameterizedType(paramLogger, paramType); 1012 checkType(paramLogger, paramType, true); 1013 } 1014 1015 JType[] exs = method.getThrows(); 1016 if (exs.length > 0) { 1017 checkTypes(methodLogger.branch(TreeLogger.DEBUG, "Throws:", null), 1018 method.getThrows()); 1019 } 1020 } 1021 } 1022} 1023 | Popular Tags |