1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 package org.apache.openoffice.ooxml.parser; 23 24 import java.io.InputStream; 25 import java.util.Vector; 26 27 import javax.xml.stream.Location; 28 import javax.xml.stream.XMLInputFactory; 29 import javax.xml.stream.XMLStreamException; 30 import javax.xml.stream.XMLStreamReader; 31 32 import org.apache.openoffice.ooxml.parser.action.ActionManager; 33 import org.apache.openoffice.ooxml.parser.attribute.AttributeProvider; 34 35 /** This is the actual parser (where OOXMLParser is the front end that handles 36 * parameters given to the main method). 37 */ 38 public class Parser 39 { Parser( final StateMachine aMachine, final InputStream aIn)40 public Parser ( 41 final StateMachine aMachine, 42 final InputStream aIn) 43 { 44 maMachine = aMachine; 45 maReader = GetStreamReader(aIn, "input"); 46 mnElementCount = 0; 47 } 48 49 50 51 Parse()52 public void Parse () 53 { 54 Location aLocation = null; 55 try 56 { 57 final AttributeProvider aAttributeProvider = new AttributeProvider(maReader); 58 while (maReader.hasNext()) 59 { 60 aLocation = maReader.getLocation(); 61 final int nCode = maReader.next(); 62 switch(nCode) 63 { 64 case XMLStreamReader.START_ELEMENT: 65 ++mnElementCount; 66 if (maMachine.IsInSkipState()) 67 { 68 if (Log.Dbg != null) 69 Log.Dbg.printf("is skip state -> starting to skip\n"); 70 Skip(); 71 } 72 else if ( ! maMachine.ProcessStartElement( 73 maReader.getNamespaceURI(), 74 maReader.getLocalName(), 75 aLocation, 76 maReader.getLocation(), 77 aAttributeProvider)) 78 { 79 if (Log.Dbg != null) 80 Log.Dbg.printf("starting to skip to recover from error\n"); 81 Skip(); 82 } 83 break; 84 85 case XMLStreamReader.END_ELEMENT: 86 maMachine.ProcessEndElement( 87 maReader.getNamespaceURI(), 88 maReader.getLocalName(), 89 aLocation, 90 maReader.getLocation()); 91 break; 92 93 case XMLStreamReader.CHARACTERS: 94 maMachine.ProcessCharacters( 95 maReader.getText(), 96 aLocation, 97 maReader.getLocation()); 98 break; 99 100 case XMLStreamReader.END_DOCUMENT: 101 break; 102 103 default: 104 Log.Err.printf("can't handle XML event of type %d\n", nCode); 105 } 106 } 107 108 maReader.close(); 109 } 110 catch (final XMLStreamException aException) 111 { 112 aException.printStackTrace(); 113 } 114 catch (final Exception aException) 115 { 116 throw new ParseException( 117 aException, 118 aLocation); 119 } 120 } 121 122 123 124 125 126 GetElementCount()127 public int GetElementCount () 128 { 129 return mnElementCount; 130 } 131 132 133 134 Skip()135 private void Skip () 136 { 137 if (Log.Dbg != null) 138 { 139 Log.Dbg.printf("starting to skip on %s at L%dC%d\n", 140 maReader.getLocalName(), 141 maReader.getLocation().getLineNumber(), 142 maReader.getLocation().getColumnNumber()); 143 Log.Dbg.IncreaseIndentation(); 144 } 145 146 // We are called when processing a start element. This means that we are 147 // already at relative depth 1. 148 int nRelativeDepth = 1; 149 try 150 { 151 while (maReader.hasNext()) 152 { 153 final int nCode = maReader.next(); 154 switch (nCode) 155 { 156 case XMLStreamReader.START_ELEMENT: 157 ++nRelativeDepth; 158 ++mnElementCount; 159 if (Log.Dbg != null) 160 { 161 Log.Dbg.printf("skipping start element %s\n", maReader.getLocalName()); 162 Log.Dbg.IncreaseIndentation(); 163 } 164 break; 165 166 case XMLStreamReader.END_ELEMENT: 167 --nRelativeDepth; 168 if (Log.Dbg != null) 169 Log.Dbg.DecreaseIndentation(); 170 if (nRelativeDepth <= 0) 171 { 172 if (Log.Dbg != null) 173 Log.Dbg.printf("leaving skip mode on %s\n", maReader.getLocalName()); 174 return; 175 } 176 break; 177 178 case XMLStreamReader.END_DOCUMENT: 179 throw new RuntimeException("saw end of document while skipping elements\n"); 180 181 case XMLStreamReader.CHARACTERS: 182 SkipText(maReader.getText()); 183 break; 184 185 default: 186 if (Log.Dbg != null) 187 Log.Dbg.printf("%s\n", nCode); 188 break; 189 } 190 } 191 } 192 catch (final XMLStreamException aException) 193 { 194 aException.printStackTrace(); 195 } 196 } 197 198 199 200 SkipText(final String sText)201 private void SkipText (final String sText) 202 { 203 if (Log.Dbg != null) 204 Log.Dbg.printf("skipping text [%s]\n", sText.replace("\n", "\\n")); 205 } 206 207 208 209 GetStreamReader( final InputStream aIn, final String sDescription)210 private XMLStreamReader GetStreamReader ( 211 final InputStream aIn, 212 final String sDescription) 213 { 214 if (aIn == null) 215 return null; 216 217 try 218 { 219 final XMLInputFactory aFactory = (XMLInputFactory)XMLInputFactory.newInstance(); 220 aFactory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, false); 221 aFactory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false); 222 aFactory.setProperty(XMLInputFactory.IS_COALESCING, false); 223 224 return (XMLStreamReader)aFactory.createXMLStreamReader( 225 sDescription, 226 aIn); 227 } 228 catch (final Exception aException) 229 { 230 aException.printStackTrace(); 231 return null; 232 } 233 } 234 235 236 237 GetActionManager()238 public ActionManager GetActionManager() 239 { 240 return maMachine.GetActionManager(); 241 } 242 243 244 245 246 private final XMLStreamReader maReader; 247 private final StateMachine maMachine; 248 private int mnElementCount; 249 } 250