1 19 20 package org.netbeans.core.registry.oldformats; 21 22 import org.openide.ErrorManager; 23 import org.openide.filesystems.FileLock; 24 import org.openide.filesystems.FileObject; 25 import org.openide.modules.ModuleInfo; 26 import org.openide.modules.SpecificationVersion; 27 import org.openide.util.Lookup; 28 import org.w3c.dom.*; 29 import org.xml.sax.Attributes ; 30 import org.xml.sax.SAXException ; 31 import org.xml.sax.XMLReader ; 32 import org.xml.sax.helpers.DefaultHandler ; 33 import org.netbeans.core.registry.oldformats.InstanceUtils; 34 import org.netbeans.core.registry.DocumentUtils; 35 36 import java.io.*; 37 import java.util.HashSet ; 38 import java.util.Iterator ; 39 import java.util.Set ; 40 import java.util.Stack ; 41 42 46 47 public class SerialDataConvertor { 48 49 private static final String INSTANCE_DTD_ID = "-//NetBeans//DTD Session settings 1.0//EN"; private static final String INSTANCE_DTD_WWW = "http://www.netbeans.org/dtds/sessionsettings-1_0.dtd"; 52 private final static char[] HEXDIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', 54 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 55 '0', '1', '2', '3', '4', '5', '6', '7'}; 56 57 private static final int INDENT = 8; 58 private static final int BLOCK = 64; 59 private static final int BUFFSIZE = INDENT + BLOCK; 60 61 private String moduleCodeName = null; 62 63 public SerialDataConvertor() { 64 } 65 66 public static Object read(org.w3c.dom.Element element, FileObject fo) throws IOException, ClassNotFoundException { 67 String moduleCodeName = null; 68 String instanceClass = null; 69 String instanceMethod = null; 70 String serialData = null; 71 72 NodeList nodes = element.getChildNodes(); 73 for (int i = 0; i < nodes.getLength(); i++) { 74 Node node = nodes.item(i); 75 if (node.getNodeType() == Node.ELEMENT_NODE) { 76 Element e = (Element)node; 77 if (e.getNodeName().equals("module")) { 78 moduleCodeName = e.getAttribute("name"); 79 } 80 if (e.getNodeName().equals("instance")) { 81 instanceClass = e.getAttribute("class"); 82 instanceMethod = e.getAttribute("method"); 83 if (instanceMethod.length() == 0) { 84 instanceMethod = null; 85 } 86 instanceClass = org.openide.util.Utilities.translate(instanceClass); 87 } 88 if (e.getNodeName().equals("serialdata")) { 89 instanceClass = e.getAttribute("class"); 90 serialData = DocumentUtils.getTextValue(e); 91 instanceClass = org.openide.util.Utilities.translate(instanceClass); 92 } 93 } 94 } 95 return createInstance(serialData, instanceClass, instanceMethod, fo); 96 } 97 98 public static boolean isSettingsFormat(org.w3c.dom.Element element) { 99 if (element.getNodeName().equals("settings") && 100 element.getNamespaceURI() == null && 101 element.getAttribute("version").equals("1.0")) { 102 return true; 103 } else { 104 return false; 105 } 106 } 107 108 public static String getModuleCodeName(org.w3c.dom.Element element) { 109 NodeList nodes = element.getChildNodes(); 110 for (int i = 0; i < nodes.getLength(); i++) { 111 Node node = nodes.item(i); 112 if (node.getNodeType() == Node.ELEMENT_NODE) { 113 Element e = (Element)node; 114 if (e.getNodeName().equals("module")) { 115 return e.getAttribute("name"); 116 } 117 } 118 } 119 return null; 120 } 121 122 123 public void write(FileObject fo, Object inst) throws IOException, UnsupportedOperationException { 124 FileLock lock = fo.lock(); 125 OutputStream os = fo.getOutputStream(lock); 126 boolean ok = false; 127 try { 128 PrintWriter pw = new PrintWriter (os); 129 pw.println("<?xml version=\"1.0\"?>"); pw.print("<!DOCTYPE settings PUBLIC \""); 131 pw.print(INSTANCE_DTD_ID); pw.print("\" \""); 133 pw.print(INSTANCE_DTD_WWW); 134 pw.println("\">"); pw.println("<settings version=\"1.0\">"); 137 storeModule(inst, pw); 138 139 storeInstanceOf(inst, pw); 140 141 storeSerialData(inst, pw); 143 144 pw.println("</settings>"); pw.flush(); 146 ok = true; 147 } finally { 148 os.close(); 149 lock.releaseLock(); 150 if (!ok) { 151 fo.delete(); 152 } 153 } 154 } 155 156 private static Object createInstance(String serialData, String instanceClass, String instanceMethod, FileObject fo) throws IOException, ClassNotFoundException { 157 if (serialData != null) { 158 return InstanceUtils.serialValue(serialData); 159 } 160 if (instanceMethod != null) { 161 return InstanceUtils.methodValue(instanceClass, instanceMethod, fo); 162 } 163 if (instanceClass != null) { 164 return InstanceUtils.newValue(instanceClass); 165 } 166 throw new IOException("Do not know how to create instance from file XXXX"); 167 168 } 169 170 private void storeInstanceOf (Object inst, PrintWriter pw) throws IOException { 171 Iterator it = getSuperClasses(inst.getClass(), null).iterator(); 172 Class clazz; 173 while (it.hasNext()) { 174 clazz = (Class ) it.next(); 175 pw.print(" <instanceof class=\""); pw.print(clazz.getName()); 177 pw.println("\"/>"); } 179 } 180 181 private void storeModule(Object inst, PrintWriter pw) throws IOException { 182 Iterator it = Lookup.getDefault().lookup( 183 new Lookup.Template(ModuleInfo.class)).allInstances().iterator(); 184 while (it.hasNext()) { 185 ModuleInfo mi = (ModuleInfo)it.next(); 186 if (mi.owns(inst.getClass())) { 187 String modulName = mi.getCodeName(); 188 SpecificationVersion spec = mi.getSpecificationVersion(); 189 pw.print(" <module"); if (modulName != null && modulName.length() != 0) { 191 pw.print(" name=\""); 192 pw.print(modulName); 193 pw.print('"'); } 195 if (spec != null) { 196 pw.print(" spec=\""); 197 pw.print(spec.toString()); 198 pw.print('"'); } 200 pw.println("/>"); 202 moduleCodeName = modulName; 203 204 return; 205 } 206 } 207 ErrorManager.getDefault().log(ErrorManager.WARNING, "ModuleInfo was not found for class "+inst.getClass()); 208 } 209 210 211 public String getModuleCodeName() { 213 return moduleCodeName; 214 } 215 216 private void storeSerialData (Object inst, PrintWriter pw) throws IOException { 217 pw.print (" <serialdata class=\""); 218 pw.print(inst.getClass().getName()); 219 pw.println("\">"); 221 ByteArrayOutputStream baos = new ByteArrayOutputStream (1024); 222 ObjectOutput oo = new SpecialObjectOutputStream (baos); 223 oo.writeObject (inst); 224 byte[] bdata = baos.toByteArray (); 225 226 char[] cdata = new char[BUFFSIZE]; 227 for (int i=0; i < INDENT; i++ ) cdata[i] = ' '; 228 229 int i = 0; int j; int blen = bdata.length; 232 233 while (i < blen) { 234 int mark = INDENT + Math.min( 2*(blen-i), BLOCK ); 235 for (j=INDENT; j < mark; j += 2) { 236 int b = ((int)bdata[i++]) + 256; 237 cdata[j] = HEXDIGITS[b >> 4]; 238 cdata[j+1] = HEXDIGITS[b & 15]; 239 } 240 pw.write(cdata, 0, j); 241 pw.println(); 242 } 243 pw.println (" </serialdata>"); pw.flush(); 245 } 246 247 248 private Set getSuperClasses(Class clazz, Set classes) { 249 if (classes == null) { 250 classes = new HashSet (); 251 } 252 253 if (clazz == null || !classes.add(clazz)) { 254 return classes; 255 } 256 257 Class [] cs = clazz.getInterfaces(); 258 259 if (cs != null) { 263 for (int i = 0; i < cs.length; i++) { 264 getSuperClasses(cs[i], classes); 265 } 266 } else { 267 ErrorManager.getDefault().log(ErrorManager.ERROR, 268 "Error: if you encounter this message, please attach " + "the class name to the issue http://www.netbeans.org/issues/show_bug.cgi?id=16257. " + "Class.getInterfaces() == null for the class: " + clazz); } 272 273 return getSuperClasses(clazz.getSuperclass(), classes); 274 } 275 276 277 282 private static class SpecialObjectOutputStream extends org.openide.util.io.NbObjectOutputStream { 283 284 private boolean first; 285 286 public SpecialObjectOutputStream(OutputStream os) throws IOException { 287 super (os); 288 first = true; 289 } 290 291 public Object replaceObject (Object obj) throws IOException { 292 if (first) { 293 if (obj == null) { 294 throw new NotSerializableException(); 296 } 297 first = false; 298 } 299 return super.replaceObject(obj); 300 } 301 302 } 303 304 private static class SettingsSAXHandler extends DefaultHandler { 305 306 private static final String ELM_SETTING = "settings"; private static final String ATR_SETTING_VERSION = "version"; 309 private static final String ELM_MODULE = "module"; private static final String ATR_MODULE_NAME = "name"; private static final String ATR_MODULE_SPEC = "spec"; private static final String ATR_MODULE_IMPL = "impl"; 314 private static final String ELM_INSTANCE = "instance"; private static final String ATR_INSTANCE_CLASS = "class"; private static final String ATR_INSTANCE_METHOD = "method"; 318 private static final String ELM_INSTANCEOF = "instanceof"; private static final String ATR_INSTANCEOF_CLASS = "class"; 321 private static final String ELM_SERIALDATA = "serialdata"; private static final String ATR_SERIALDATA_CLASS = "class"; 324 325 326 private String codeName; 328 private String instanceClass; 330 331 private Set instanceOf = new HashSet (); 333 334 private String instanceMethod; 336 337 338 private SpecificationVersion moduleSpec; 340 private String moduleImpl; 342 343 private String version; 345 346 347 private String serialdata; 349 350 351 private String codeNameBase; 353 354 private int codeNameRelease; 356 357 358 private Stack stack; 359 private CharArrayWriter chaos = null; 360 361 private boolean readModuleOnly; 362 363 public SettingsSAXHandler(boolean readModuleOnly) { 364 stack = new Stack (); 365 this.readModuleOnly = readModuleOnly; 366 } 367 368 public org.xml.sax.InputSource resolveEntity(String publicId, String systemId) throws SAXException { 369 if (INSTANCE_DTD_ID.equals(publicId)) { 370 return new org.xml.sax.InputSource (new ByteArrayInputStream(new byte[0])); 371 } else { 372 return null; } 374 } 375 376 public void characters(char[] values, int start, int length) throws SAXException { 377 String element = (String ) stack.peek(); 378 if (ELM_SERIALDATA.equals(element)) { 379 if (chaos == null) { 381 chaos = new CharArrayWriter(length); 382 } 383 chaos.write(values, start, length); 384 } 385 } 386 387 public void startElement(String uri, String localName, String qName, Attributes attribs) throws SAXException { 388 stack.push(qName); 389 if (ELM_SETTING.equals(qName)) { 390 version = attribs.getValue(ATR_SETTING_VERSION); 391 } else if (ELM_MODULE.equals(qName)) { 392 codeName = attribs.getValue(ATR_MODULE_NAME); 393 resolveModuleElm(codeName); 394 moduleImpl = attribs.getValue(ATR_MODULE_IMPL); 395 if (readModuleOnly) { 396 throw new StopSAXException(); 397 } 398 try { 399 String spec = attribs.getValue(ATR_MODULE_SPEC); 400 moduleSpec = spec == null ? null : new SpecificationVersion(spec); 401 } catch (NumberFormatException nfe) { 402 throw new SAXException (nfe); 403 } 404 } else if (ELM_INSTANCEOF.equals(qName)) { 405 instanceOf.add(org.openide.util.Utilities.translate(attribs.getValue(ATR_INSTANCEOF_CLASS))); 406 } else if (ELM_INSTANCE.equals(qName)) { 407 instanceClass = attribs.getValue(ATR_INSTANCE_CLASS); 408 instanceClass = org.openide.util.Utilities.translate(instanceClass); 409 instanceMethod = attribs.getValue(ATR_INSTANCE_METHOD); 410 } else if (ELM_SERIALDATA.equals(qName)) { 411 instanceClass = attribs.getValue(ATR_SERIALDATA_CLASS); 412 instanceClass = org.openide.util.Utilities.translate(instanceClass); 413 } 414 } 415 416 417 private void resolveModuleElm(String codeName) { 418 if (codeName != null) { 419 int slash = codeName.indexOf("/"); if (slash == -1) { 421 codeNameBase = codeName; 422 codeNameRelease = -1; 423 } else { 424 codeNameBase = codeName.substring(0, slash); 425 try { 426 codeNameRelease = Integer.parseInt(codeName.substring(slash + 1)); 427 } catch (NumberFormatException ex) { 428 ErrorManager emgr = ErrorManager.getDefault(); 429 emgr.annotate(ex, "Source: XXXXX"); emgr.notify(ErrorManager.INFORMATIONAL, ex); 431 codeNameRelease = -1; 432 } 433 } 434 } else { 435 codeNameBase = null; 436 codeNameRelease = -1; 437 } 438 } 439 440 public void endElement(String uri, String localName, String qName) throws SAXException { 441 String element = (String ) stack.pop(); 442 if (ELM_SERIALDATA.equals(element)) { 443 if (chaos != null) { 444 serialdata = chaos.toString(); 445 } 446 } 447 } 448 449 } 450 451 final static class StopSAXException extends SAXException { 452 public StopSAXException() { 453 super("Parser stopped"); } 455 } 456 457 } 458 | Popular Tags |