1 19 20 package org.netbeans.spi.settings; 21 22 import java.io.IOException ; 23 import java.util.Map ; 24 import org.openide.filesystems.FileObject; 25 import org.openide.util.Lookup; 26 import org.openide.xml.XMLUtil; 27 import org.w3c.dom.Document ; 28 import org.xml.sax.InputSource ; 29 import org.xml.sax.SAXException ; 30 31 38 public abstract class DOMConvertor extends Convertor { 39 40 private final static String ATTR_PUBLIC_ID = "dtd_public_id"; 42 private final static String ATTR_ID = "id"; private final static String ATTR_IDREF = "idref"; 49 57 private final static String ELM_DELEGATE = "domconvertor"; 59 private final static java.util.Map <Document , Map <Object ,CacheRec>> refsCache = 60 new java.util.HashMap <Document , Map <Object ,CacheRec>>(); 61 62 private final static java.util.Map <Document , Lookup> ctxCache = new java.util.HashMap <Document , Lookup>(); 63 64 private String publicID; 65 private String systemID; 66 private String rootElement; 67 68 73 protected DOMConvertor(String publicID, String systemID, String rootElement) { 74 this.publicID = publicID; 75 this.systemID = systemID; 76 this.rootElement = rootElement; 77 if (publicID == null) throw new NullPointerException ("publicID"); if (systemID == null) throw new NullPointerException ("systemID"); if (rootElement == null) throw new NullPointerException ("rootElement"); } 81 82 90 public final Object read(java.io.Reader r) throws java.io.IOException , ClassNotFoundException { 91 Document doc = null; 92 try { 93 InputSource is = new InputSource (r); 94 doc = XMLUtil.parse(is, false, false, null, org.openide.xml.EntityCatalog.getDefault()); 95 setDocumentContext(doc, findContext(r)); 96 return readElement(doc.getDocumentElement()); 97 } catch (SAXException ex) { 98 IOException ioe = new IOException (ex.getLocalizedMessage()); 99 ioe.initCause(ex); 100 throw ioe; 101 } finally { 102 if (doc != null) { 103 clearCashesForDocument(doc); 104 } 105 } 106 } 107 108 114 public final void write(java.io.Writer w, Object inst) throws java.io.IOException { 115 Document doc = null; 116 try { 117 doc = XMLUtil.createDocument(rootElement, null, publicID, systemID); 118 setDocumentContext(doc, findContext(w)); 119 writeElement(doc, doc.getDocumentElement(), inst); 120 java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream (1024); 121 XMLUtil.write(doc, baos, "UTF-8"); w.write(baos.toString("UTF-8")); } catch (org.w3c.dom.DOMException ex) { 124 IOException e = new IOException (ex.getLocalizedMessage()); 125 e.initCause(ex); 126 throw e; 127 } finally { 128 if (doc != null) { 129 clearCashesForDocument(doc); 130 } 131 } 132 } 133 134 141 protected abstract Object readElement(org.w3c.dom.Element element) throws java.io.IOException , ClassNotFoundException ; 142 143 151 protected abstract void writeElement( 152 org.w3c.dom.Document doc, 153 org.w3c.dom.Element element, 154 Object obj) throws java.io.IOException , org.w3c.dom.DOMException ; 155 156 164 protected final static Object delegateRead(org.w3c.dom.Element element) throws java.io.IOException , ClassNotFoundException { 165 Object obj; 166 167 String idref = element.getAttribute(ATTR_IDREF); 170 if (idref.length() != 0) { 171 obj = getCache(element.getOwnerDocument(), idref.intern()); 172 if (obj != null) { 173 return obj; 174 } else { 175 throw new IOException ("broken reference: " + element + ", idref=" + idref); } 177 } 178 179 String publicId = element.getAttribute(ATTR_PUBLIC_ID); 181 Convertor c = ConvertorResolver.getDefault().getConvertor(publicId); 182 if (c == null) throw new IOException ("Convertor not found. publicId: " + publicId); 184 if (element.getTagName().equals(ELM_DELEGATE)) { 186 org.w3c.dom.NodeList children = element.getChildNodes(); 188 String content = null; 189 for (int i = 0, size = children.getLength(); i < size; i++) { 190 org.w3c.dom.Node n = children.item(i); 191 if (n.getNodeType() == org.w3c.dom.Node.CDATA_SECTION_NODE) { 192 content = n.getNodeValue(); 193 break; 194 } else if (n.getNodeType() == org.w3c.dom.Node.TEXT_NODE) { 195 String text = n.getNodeValue().trim(); 197 if (text.length() > 0) { 198 content = text; 199 break; 200 } 201 } 202 } 203 204 if (content == null) { 205 throw new IOException ("Expected CDATA block under: " + element.getTagName()); 207 } 208 obj = readFromString(c, content, findContext(element.getOwnerDocument())); 209 } else if (c instanceof DOMConvertor) { 210 DOMConvertor dc = (DOMConvertor) c; 211 obj = dc.readElement(element); 212 } else { 213 throw new IOException ( 214 "Missing DOMConvertor for publicId: " + publicId); } 216 217 String id = element.getAttribute(ATTR_ID); 219 if (id.length() != 0) { 220 setCache(element.getOwnerDocument(), id, obj); 221 } 222 223 return obj; 224 } 225 226 235 protected final static org.w3c.dom.Element delegateWrite(org.w3c.dom.Document doc, Object obj) throws java.io.IOException , org.w3c.dom.DOMException { 236 CacheRec cache = setCache(doc, obj); 239 if (cache.used) { 240 return writeReference(doc, cache); 241 } 242 243 ConvertorResolver res = ConvertorResolver.getDefault(); 244 Class clazz = obj.getClass(); 245 Convertor c = res.getConvertor(clazz); 246 if (c == null) { 247 throw new IOException ("Convertor not found for object: " + obj); } 249 250 org.w3c.dom.Element el; 251 if (c instanceof DOMConvertor) { 252 DOMConvertor dc = (DOMConvertor) c; 253 el = doc.createElement(dc.rootElement); 254 dc.writeElement(doc, el, obj); 255 if (el.getAttribute(ATTR_PUBLIC_ID).length() == 0) { 256 el.setAttribute(ATTR_PUBLIC_ID, res.getPublicID(clazz)); 257 } 258 } else { 259 el = doc.createElement(ELM_DELEGATE); 261 el.setAttribute(ATTR_PUBLIC_ID, res.getPublicID(clazz)); 262 el.appendChild(doc.createCDATASection(writeToString(c, obj, findContext(doc)))); 263 } 264 265 cache.elm = el; 267 return el; 268 } 269 270 276 protected static org.openide.util.Lookup findContext(org.w3c.dom.Document doc) { 277 synchronized (ctxCache) { 278 Lookup ctx = ctxCache.get(doc); 279 return ctx == null? Lookup.EMPTY: ctx; 280 } 281 } 282 283 284 286 287 private static void setDocumentContext(Document doc, Lookup ctx) { 288 synchronized (ctxCache) { 289 ctxCache.put(doc, ctx); 290 } 291 } 292 293 294 private static String writeToString(Convertor c, Object obj, Lookup ctx) throws IOException { 295 java.io.Writer caw = new java.io.CharArrayWriter (1024); 296 java.io.Writer w = caw; 297 298 FileObject fo = (FileObject) ctx.lookup(FileObject.class); 299 if (fo != null) { 300 w = org.netbeans.modules.settings.ContextProvider.createWriterContextProvider(caw, fo); 301 } 302 303 c.write(w, obj); 304 w.close(); 305 return caw.toString(); 306 } 307 308 309 private static Object readFromString(Convertor c, String s, Lookup ctx) throws IOException , ClassNotFoundException { 310 java.io.Reader r = new java.io.StringReader (s); 311 312 FileObject fo = (FileObject) ctx.lookup(FileObject.class); 313 if (fo != null) { 314 r = org.netbeans.modules.settings.ContextProvider.createReaderContextProvider(r, fo); 315 } 316 317 return c.read(r); 318 } 319 320 321 private static org.w3c.dom.Element writeReference(org.w3c.dom.Document doc, CacheRec cache) throws org.w3c.dom.DOMException { 322 org.w3c.dom.Element el = doc.createElement(cache.elm.getTagName()); 323 el.setAttribute(ATTR_IDREF, (String ) cache.value); 324 cache.elm.setAttribute(ATTR_ID, (String ) cache.value); 325 return el; 326 } 327 328 331 private static CacheRec setCache(org.w3c.dom.Document key, Object obj) { 332 synchronized (refsCache) { 333 Map <Object , CacheRec> refs = refsCache.get(key); 334 if (refs == null) { 335 refs = new java.util.HashMap <Object , CacheRec>(); 336 refsCache.put(key, refs); 337 } 338 339 CacheRec cr = refs.get(obj); 340 if (cr == null) { 341 cr = new CacheRec(); 342 cr.key = obj; 343 cr.value = "ID_" + String.valueOf(refs.size()); refs.put(obj, cr); 345 } 346 cr.used = cr.elm != null; 347 return cr; 348 } 349 } 350 351 356 private static CacheRec setCache(org.w3c.dom.Document key, Object id, Object obj) { 357 synchronized (refsCache) { 358 Map <Object , CacheRec> refs = refsCache.get(key); 359 if (refs == null) { 360 refs = new java.util.HashMap <Object , CacheRec>(); 361 refsCache.put(key, refs); 362 } 363 364 CacheRec cr = refs.get(id); 365 if (cr == null) { 366 cr = new CacheRec(); 367 cr.key = id; 368 cr.value = obj; 369 refs.put(id, cr); 370 } 371 return cr; 372 } 373 } 374 375 378 private static Object getCache(org.w3c.dom.Document key, Object idref) { 379 synchronized (refsCache) { 380 java.util.Map refs = (java.util.Map ) refsCache.get(key); 381 if (refs == null) { 382 return null; 383 } 384 385 CacheRec cr = (CacheRec) refs.get(idref); 386 return cr.value; 387 } 388 } 389 390 391 private static void clearCashesForDocument(Document doc) { 392 synchronized(refsCache) { 393 refsCache.remove(doc); 394 } 395 synchronized(ctxCache) { 396 ctxCache.remove(doc); 397 } 398 } 399 400 private static class CacheRec { 401 CacheRec() {} 402 Object key; 405 org.w3c.dom.Element elm; 406 Object value; 407 boolean used; 408 } 409 } 410 | Popular Tags |