1 4 package com.tc.util; 5 6 import com.tc.text.NonPortableReasonFormatter; 7 8 import java.io.IOException ; 9 import java.io.ObjectOutputStream ; 10 import java.io.Serializable ; 11 import java.util.ArrayList ; 12 import java.util.Collection ; 13 import java.util.Iterator ; 14 import java.util.LinkedList ; 15 import java.util.List ; 16 17 public class NonPortableReason implements Serializable { 18 19 private static final long serialVersionUID = 8149536931286184441L; 20 21 public static final byte UNDEFINED = 0x00; 22 23 public static final byte CLASS_NOT_ADAPTABLE = 0x01; 24 public static final byte SUPER_CLASS_NOT_ADAPTABLE = 0x02; 25 public static final byte SUBCLASS_OF_LOGICALLY_MANAGED_CLASS = 0x03; 26 public static final byte CLASS_NOT_IN_BOOT_JAR = 0x04; 27 public static final byte CLASS_NOT_INCLUDED_IN_CONFIG = 0x05; 28 public static final byte SUPER_CLASS_NOT_INSTRUMENTED = 0x06; 29 public static final byte TEST_REASON = 0x07; 30 31 private static final byte LAST_DEFINED = 0x07; 32 33 private final String className; 34 private final List nonBootJarClasses = new ArrayList (); 35 private final List bootJarClasses = new ArrayList (); 36 private final Collection details; 37 private final byte reason; 38 private transient String detailedReason; 39 private String message; 40 private String ultimateNonPortableFieldName; 41 42 public NonPortableReason(Class clazz, byte reasonCode) { 43 this.reason = reasonCode; 44 this.className = clazz.getName(); 45 this.details = new LinkedList (); 46 } 47 48 public NonPortableReason(String className, byte reasonCode) { 49 this.className = className; 50 this.reason = reasonCode; 51 this.details = new LinkedList (); 52 } 53 54 public String getClassName() { 55 return className; 56 } 57 58 public synchronized String getDetailedReason() { 59 if (detailedReason == null) { 60 detailedReason = constructDetailedReason(); 61 } 62 return detailedReason; 63 } 64 65 private void writeObject(ObjectOutputStream out) throws IOException { 66 checkSanity(); 67 out.defaultWriteObject(); 68 } 69 70 public void addDetail(String label, String value) { 71 this.details.add(new NonPortableDetail(label, value)); 72 } 73 74 private String constructDetailedReason() { 75 boolean hasPreamble = message != null; 78 StringBuffer sb = (message == null ? new StringBuffer () : new StringBuffer (message)); 79 80 switch (reason) { 81 case CLASS_NOT_ADAPTABLE: 82 if (hasPreamble) { 83 sb.append(" This unshareable class is a"); 84 } else { 85 sb.append("Attempted to share a"); 86 } 87 sb.append(" JVM- or host machine-specific resource. Please ensure that instances of this class" 88 + " don't enter the shared object graph."); 89 addDetail("Unshareable class", className); 90 break; 91 case SUPER_CLASS_NOT_ADAPTABLE: 92 if (hasPreamble) { 93 sb.append(" This unshareable class is a"); 94 } else { 95 sb.append("Attempted to share an instance of a class that is a"); 96 } 97 sb.append(" subclass of a JVM- or host machine-specific resource."); 98 sb.append(" Please either modify the class hierarchy or ensure that instances of this class don't" 99 + " enter the shared object graph."); 100 addDetail("Unshareable superclass names", getErroneousSuperClassNames()); 101 break; 102 case SUBCLASS_OF_LOGICALLY_MANAGED_CLASS: 103 if (hasPreamble) { 104 sb.append(" This unshareable class"); 105 } else { 106 sb.append("Attempted to share an instance of a class which"); 107 } 108 sb.append(" has a logically-managed superclass."); 109 sb.append(" Subclasses of logically-managed classes cannot be shared. Please either"); 110 sb.append(" modify the class hierarchy or ensure that instances of this class" 111 + " don't enter the shared object graph."); 112 addDetail("Unshareable class", className); 113 addDetail("Logically-managed superclass names", getErroneousSuperClassNames()); 114 break; 115 case CLASS_NOT_IN_BOOT_JAR: 116 if (hasPreamble) { 117 sb.append(" This unshareable class"); 118 } else { 119 sb.append("Attempted to share an instance of a class which"); 120 } 121 if (!this.bootJarClasses.isEmpty()) { 122 sb.append(" must be in the DSO boot jar. It also has superclasses which must be in the DSO" 123 + " boot jar. Please add all of these classes to the boot jar configuration and re-create" 124 + " the DSO boot jar."); 125 List classes = new ArrayList (); 126 classes.addAll(bootJarClasses); 127 classes.add(this.className); 128 addDetail("Classses to add to boot jar", csvList(classes)); 129 } else { 130 sb.append(" must be in the DSO boot jar. Please add this class to the boot jar configuration" 131 + " and re-create the DSO boot jar."); 132 addDetail("Class to add to boot jar", this.className); 133 } 134 135 break; 136 case SUPER_CLASS_NOT_INSTRUMENTED: 137 if (hasPreamble) { 138 sb.append(" This unshareable class"); 139 } else { 140 sb.append("Attempted to share an instance of a class which has"); 141 } 142 boolean plural = (this.bootJarClasses.size() + this.nonBootJarClasses.size()) > 1; 143 sb.append(plural ? " super-classes" : " a super-class"); 144 sb.append(" that" + (plural ? " are" : " is") + " uninstrumented." + 145 " Subclasses of uninstrumented classes cannot be shared."); 146 if (! this.bootJarClasses.isEmpty()) { 147 sb.append(" Please"); 148 if (this.bootJarClasses.size() > 1) { 149 sb.append(" add the relevant super-classes to the boot jar configuration and re-create" + 150 " the DSO boot jar."); 151 }else { 152 sb.append(" add the relevant super-class to the boot jar configuration and re-create" + 153 " the DSO boot jar."); 154 } 155 } 156 if (! this.nonBootJarClasses.isEmpty()) { 157 sb.append(" Please"); 158 if (this.nonBootJarClasses.size() > 1) { 159 sb.append(" add the relevant super-classes to the <includes> section of the configuration file."); 160 } else { 161 sb.append(" add the relevant super-class to the <includes> section of the configuration file."); 162 } 163 } 164 165 addDetail("Unshareable class", className); 166 if (! this.bootJarClasses.isEmpty()) { 167 addDetail("Classes to add to boot jar", csvList(bootJarClasses)); 168 } 169 if (! this.nonBootJarClasses.isEmpty()) { 170 addDetail("Classes to add to the <includes> configuration", csvList(nonBootJarClasses)); 171 } 172 break; 173 case CLASS_NOT_INCLUDED_IN_CONFIG: 174 if (hasPreamble) { 175 sb.append(" This unshareable class"); 176 } else { 177 sb.append("Attempted to share an instance of a class which"); 178 } 179 sb.append(" has not been included for sharing in the configuration. Please add this class to the <includes>"); 180 sb.append(" section of the configuration file."); 181 if (!this.nonBootJarClasses.isEmpty()) { 182 if (this.nonBootJarClasses.size() == 1) { 183 sb.append(" This class also has a super-class that has not been included for sharing in" 184 + " the configuration. Please add this class to the <includes> section in the" 185 + " configuration file also."); 186 } else { 187 sb.append(" This class also has super-classes that have not been included for sharing in" 188 + " the configuration. Please add these classes to the <includes> section of" 189 + " the configuration file also."); 190 } 191 List classes = new LinkedList (); 192 classes.add(className); 193 classes.addAll(this.nonBootJarClasses); 194 addDetail("Non-included classes", csvList(classes)); 195 } else { 196 addDetail("Non-included class", className); 197 } 198 199 if (!this.bootJarClasses.isEmpty()) { 200 if (this.bootJarClasses.size() == 1) { 201 sb.append(" This class also has a super-class that must be in the DSO boot jar." 202 + " Please add this class to the boot jar configuration"); 203 addDetail("Class to add to boot jar", csvList(bootJarClasses)); 204 } else { 205 sb.append(" This class also has super-classes that must be in the DSO boot jar." 206 + " Please add these classes to the boot jar configuration"); 207 addDetail("Classes to add to boot jar", csvList(bootJarClasses)); 208 } 209 sb.append(" and re-create the DSO boot jar."); 210 } 211 212 break; 213 case TEST_REASON: 214 break; 215 default: 216 throw new AssertionError ("Unknown reason: " + reason); 217 } 218 return sb.toString(); 219 } 220 221 public boolean hasUltimateNonPortableFieldName() { 222 return this.ultimateNonPortableFieldName != null; 223 } 224 225 public void setUltimateNonPortableFieldName(String name) { 226 addDetail("Referring field", name); 227 this.ultimateNonPortableFieldName = name; 228 } 229 230 public String getUltimateNonPortableFieldName() { 231 return this.ultimateNonPortableFieldName; 232 } 233 234 private String getErroneousSuperClassNames() { 235 Collection supers = new ArrayList (nonBootJarClasses); 236 supers.addAll(bootJarClasses); 237 return csvList(supers); 238 } 239 240 private String csvList(Collection list) { 241 StringBuffer sb = new StringBuffer (); 242 for (Iterator i = list.iterator(); i.hasNext();) { 243 sb.append(i.next()); 244 if (i.hasNext()) { 245 sb.append(", "); 246 } 247 } 248 249 return sb.toString(); 250 } 251 252 private void checkSanity() { 253 if (reason <= UNDEFINED || reason > LAST_DEFINED) { 254 throw new AssertionError ( 256 "Please specify the reason for Non-portability by calling setReason() with one of the defined reasons."); 257 } 258 if ((reason == SUBCLASS_OF_LOGICALLY_MANAGED_CLASS || reason == SUPER_CLASS_NOT_ADAPTABLE || reason == SUPER_CLASS_NOT_INSTRUMENTED) 259 && ((nonBootJarClasses.size() == 0) && (bootJarClasses.size() == 0))) { 260 throw new AssertionError ("Please add erroneous super classes by calling addErroneousSuperClass()"); 262 } 263 } 264 265 public byte getReason() { 266 return reason; 267 } 268 269 public void addErroneousSuperClass(Class superClass) { 270 if (superClass.getClassLoader() == null) { 271 bootJarClasses.add(superClass.getName()); 272 } else { 273 nonBootJarClasses.add(superClass.getName()); 274 } 275 } 276 277 public List getErroneousSuperClasses() { 278 return nonBootJarClasses; 279 } 280 281 public List getErroneousBootJarSuperClasses() { 282 return bootJarClasses; 283 } 284 285 public String toString() { 286 return getDetailedReason(); 287 } 288 289 public void setMessage(String msg) { 290 this.message = msg; 291 } 292 293 public String getMessage() { 294 return message; 295 } 296 297 public void accept(NonPortableReasonFormatter formatter) { 298 formatter.formatReasonText(getDetailedReason()); 299 for (Iterator i = details.iterator(); i.hasNext();) { 300 formatter.formatDetail((NonPortableDetail) i.next()); 301 } 302 } 303 304 } 305 | Popular Tags |