1 19 package org.netbeans.lib.jmi.xmi; 20 21 import java.io.*; 22 import java.util.*; 23 import java.net.*; 24 25 import org.xml.sax.*; 26 import org.xml.sax.helpers.DefaultHandler ; 27 import javax.xml.parsers.SAXParserFactory ; 28 import javax.xml.parsers.ParserConfigurationException ; 29 import javax.xml.parsers.SAXParser ; 30 31 import org.netbeans.api.xmi.*; 32 33 import javax.jmi.reflect.*; 34 import javax.jmi.model.*; 35 import org.netbeans.lib.jmi.util.Logger; 36 import org.netbeans.lib.jmi.util.DebugException; 37 38 public class XmiSAXReader extends DefaultHandler { 39 40 private URL docURL = null; 41 42 private XmiElement currentElement; 44 private XmiContext context; 46 47 private HashMap diffs = null; 49 private boolean contentIsRead = false; 51 private boolean elementIsDeleted = false; 53 private int lastTimeStamp = 0; 55 private Stack stack = new Stack (); 57 private Locator locator = null; 59 private String rootElementName = null; 61 62 private final Object DELETED = new Integer (0); 64 private final Object EMPTY = new Integer (1); 66 67 private XMIInputConfig config; 68 69 71 public XmiSAXReader () { 72 this (null, null); 73 } 74 75 public XmiSAXReader (XMIInputConfig config) { 76 this (null, config); 77 } 78 79 public XmiSAXReader (XmiContext context, XMIInputConfig config) { 80 this.context = context; 81 if (config == null) 82 this.config = new InputConfig (); 83 else 84 this.config = config; 85 } 86 87 89 public Collection read (InputStream input, String uri, RefPackage[] extents, String encoding) 90 throws IOException, SAXException, ParserConfigurationException { 91 InputSource is = new InputSource (input); 92 if (encoding != null) { 93 is.setEncoding(encoding); 94 } 95 if (uri != null) { 96 is.setSystemId(uri); 97 try { 98 docURL = new URI (uri).toURL (); 99 } catch (URISyntaxException e) { 100 } catch (MalformedURLException e) { 101 } catch (IllegalArgumentException e) { 102 } 103 } 104 return read (is, extents); 105 } 106 107 public Collection read (URL url, RefPackage[] extents, String encoding) 108 throws IOException, SAXException, ParserConfigurationException { 109 docURL = url; 110 InputSource is = new InputSource (url.toString ()); 111 if (encoding != null) 112 is.setEncoding(encoding); 113 return read (is, extents); 114 } 115 116 public Collection read (URL url, RefPackage[] extents, String encoding, HashMap diffs) 117 throws IOException, SAXException, ParserConfigurationException { 118 this.diffs = diffs; 119 return read (url, extents, encoding); 120 } 121 122 public Collection read (InputSource input, RefPackage[] extents) 123 throws IOException, SAXException, ParserConfigurationException { 124 if (diffs == null) 125 Logger.getDefault().log ("XMI reader started"); 126 long time = System.currentTimeMillis (); 127 if (docURL == null) { 128 String systemId = input.getSystemId(); 129 if (systemId != null) { 130 try { 131 docURL = new URL (systemId); 132 } catch (MalformedURLException e) { 133 } catch (IllegalArgumentException e) { 134 } 135 } 136 } 137 if (context == null) 138 context = new XmiContext (extents, docURL, config); 139 SAXParserFactory factory = SAXParserFactory.newInstance (); 140 factory.setValidating (false); 141 SAXParser saxParser = factory.newSAXParser (); 142 saxParser.parse (input, this); 143 time = System.currentTimeMillis () - time; 144 if (diffs == null) 145 Logger.getDefault().log ("finished, TIME: " + time/1000.0 + "[s]"); 146 return context.getOutermostObjects (); 147 } 148 149 void initConsumer (RefPackage pkg) throws SAXException { 150 context = new XmiContext (new RefPackage [] {pkg}, null, config); 151 } 152 153 154 public void startDocument () throws SAXException { 155 rootElementName = null; 156 } 157 158 162 163 public void startElement (String namespaceURI, String sName, String qName, Attributes attrs) 164 throws SAXException { 165 166 try { 167 168 170 if (elementIsDeleted) { 171 stack.push (EMPTY); 172 return; 173 } else if (rootElementName == null) { 174 rootElementName = qName; 175 currentElement = new XmiElement.Document (null, context, qName, attrs); 176 return; 177 } else if (currentElement == null) { 178 throw new DebugException("Not an XMI document. Root element must be <"+XmiConstants.XMI_ROOT+">"); 179 } else if (qName.equals (XmiConstants.XMI_CONTENT)) { 180 stack.push (EMPTY); 181 contentIsRead = true; 182 } else if ((contentIsRead && qName.equals(XmiConstants.XMI_EXTENSION)) || 183 (!contentIsRead && qName.equals(XmiConstants.XMI_EXTENSIONS))) { 184 stack.push (DELETED); 185 elementIsDeleted = true; 186 return; 187 } else if ((contentIsRead) && (diffs != null)) { 188 String xmiId = attrs.getValue (XmiConstants.XMI_ID); 190 List list = null; 191 if (xmiId != null) 192 list = (List) diffs.get (xmiId); 193 if (list != null) { 194 String elementName = null; 195 Iterator iter = list.iterator (); 196 List modifs = new LinkedList (); 197 while (iter.hasNext ()) { 198 XmiElement.Difference.Diff diff = (XmiElement.Difference.Diff) iter.next (); 199 if (diff.timeStamp <= lastTimeStamp) 200 continue; 201 switch (diff.kind) { 202 case XmiElement.Difference.Diff.DELETE: 203 stack.push (DELETED); 204 elementIsDeleted = true; 205 return; 206 case XmiElement.Difference.Diff.ADD: 207 modifs.add (diff); 208 break; 209 case XmiElement.Difference.Diff.REPLACE: 210 XmiElement.Difference.Item item = (XmiElement.Difference.Item) diff.items.removeFirst (); 211 qName = item.qName; 212 attrs = item.attrs; 213 elementName = qName; 214 diff.items.removeLast (); 215 modifs.add (diff); 216 break; 217 } } stack.push (new StackElement (modifs, elementName)); 220 } else { 221 stack.push (EMPTY); 222 } } 225 currentElement = currentElement.startSubElement (qName, attrs); 226 if (currentElement == null) 227 throw new DebugException ("XmiElement.startSubElement("+qName+", ..) returned null"); 229 230 if (contentIsRead && (diffs != null)) 231 applayDiffs (); 232 233 } catch (Exception e) { 234 235 e.printStackTrace (); 236 237 Logger.getDefault().annotate(e, "Error parsing XMI" + getLineNumberErrorString()); 238 throw (SAXException) Logger.getDefault().annotate(new SAXException("XMI parsing error" + getLineNumberErrorString() + ": " + (e.getMessage() != null ? e.getMessage() : e.toString()), e), e); 239 } 240 241 } 242 243 public void endElement (String namespaceURI, String sName, String qName) throws SAXException { 244 246 try { 247 248 if (elementIsDeleted) { 249 if (stack.pop () == DELETED) 250 elementIsDeleted = false; 251 return; 252 } 253 254 if (qName.equals (XmiConstants.XMI_CONTENT)) 255 contentIsRead = false; 256 else { 257 if (contentIsRead && (diffs != null)) { 258 Object obj = stack.pop (); 259 if ((obj instanceof StackElement) && ((StackElement) obj).replacedName != null) 260 qName = ((StackElement) obj).replacedName; 261 } 262 } 264 currentElement = currentElement.endElement (qName); 265 if ((currentElement == null) && !qName.equals (rootElementName)) 266 throw new DebugException ("XmiElement.endElement("+qName+") returned null"); 268 269 if (contentIsRead && (diffs != null)) 270 applayDiffs (); 271 272 } catch (Exception e) { 273 274 e.printStackTrace (); 275 String message = "XMI parsing error" + getLineNumberErrorString() + ": " + (e.getMessage() != null ? e.getMessage() : e.toString()); 276 Logger.getDefault().log(Logger.WARNING, message); 277 SAXException ne = new SAXException(message, e); 278 throw (SAXException) Logger.getDefault().annotate(ne, e); 279 } 280 281 } 282 283 public void characters (char buf[], int offset, int len) throws SAXException { 284 285 String s = new String (buf, offset, len); 286 287 try { 288 289 if (!elementIsDeleted) { 290 if (currentElement != null) 291 currentElement.characters (buf, offset, len); 292 } 293 294 } catch (Exception e) { 295 296 e.printStackTrace (); 297 298 SAXException ne = new SAXException("XMI parsing error" + getLineNumberErrorString() + ": " + (e.getMessage() != null ? e.getMessage() : e.toString()), e); 299 Logger.getDefault().annotate(ne, e); 300 throw (SAXException) Logger.getDefault().annotate(ne, "XMI parsing error" + getLineNumberErrorString()); 301 } 302 303 } 304 305 public void setDocumentLocator (Locator locator) { 306 this.locator = locator; 307 } 308 309 313 private String getLineNumberErrorString() { 314 if ( locator != null ) { 315 return " at line: " + locator.getLineNumber(); 316 } else { 317 return ""; 318 } 319 } 320 321 public InputSource resolveEntity (String publicID, String systemID) { 322 Logger.getDefault().log ("resolving reference: " + publicID + ", " + systemID); 323 return new InputSource (new StringReader ("")); 324 } 325 326 private void applayDiffs () throws SAXException { 327 Object elem = stack.peek (); 328 if (elem != EMPTY) { 329 ((StackElement) elem).position++; 330 Iterator iter = ((StackElement) elem).diffs.iterator (); 331 while (iter.hasNext ()) { 332 XmiElement.Difference.Diff diff = (XmiElement.Difference.Diff) iter.next (); 333 if ((diff.position == ((StackElement) elem).position) && (diff.timeStamp > lastTimeStamp)) { 334 int temp = lastTimeStamp; 335 lastTimeStamp = diff.timeStamp; 336 addContent (diff); 337 lastTimeStamp = temp; 338 } 339 } } } 342 343 private void addContent (XmiElement.Difference.Diff diff) throws SAXException { 344 Iterator iter = diff.items.iterator (); 345 while (iter.hasNext ()) { 346 Object obj = iter.next (); 347 if (obj instanceof XmiElement.Difference.Item) { 348 XmiElement.Difference.Item item = (XmiElement.Difference.Item) obj; 349 if (item.isStart) { 350 startElement (null, "", item.qName, item.attrs); 351 } else { 352 endElement (null, "", item.qName); 353 } 354 } else 355 characters (((String ) obj).toCharArray (), 0, ((String ) obj).length ()); 356 } } 358 359 private static class StackElement { 360 public int position = 0; 361 public List diffs; 362 public String replacedName; 363 364 public StackElement (List diffs, String replacedName) { 365 this.diffs = diffs; 366 this.replacedName = replacedName; 367 } 368 } 370 } | Popular Tags |