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 26 import javax.xml.stream.Location; 27 import javax.xml.stream.XMLInputFactory; 28 import javax.xml.stream.XMLStreamException; 29 import javax.xml.stream.XMLStreamReader; 30 31 import org.apache.openoffice.ooxml.parser.action.ActionManager; 32 import org.apache.openoffice.ooxml.parser.attribute.AttributeProvider; 33 34 /** This is the actual parser (where OOXMLParser is the front end that handles 35 * parameters given to the main method). 36 */ 37 public class Parser 38 { Parser( final StateMachine aMachine, final InputStream aIn)39 public Parser ( 40 final StateMachine aMachine, 41 final InputStream aIn) 42 { 43 maMachine = aMachine; 44 maReader = GetStreamReader(aIn, "input"); 45 mnElementCount = 0; 46 } 47 48 49 50 Parse()51 public void Parse () 52 { 53 Location aLocation = null; 54 try 55 { 56 final AttributeProvider aAttributeProvider = new AttributeProvider(maReader); 57 while (maReader.hasNext()) 58 { 59 aLocation = maReader.getLocation(); 60 final int nCode = maReader.next(); 61 switch(nCode) 62 { 63 case XMLStreamReader.START_ELEMENT: 64 ++mnElementCount; 65 if (maMachine.IsInSkipState()) 66 { 67 if (Log.Dbg != null) 68 Log.Dbg.printf("is skip state -> starting to skip\n"); 69 Skip(); 70 } 71 else if ( ! maMachine.ProcessStartElement( 72 maReader.getNamespaceURI(), 73 maReader.getLocalName(), 74 aLocation, 75 maReader.getLocation(), 76 aAttributeProvider)) 77 { 78 if (Log.Dbg != null) 79 Log.Dbg.printf("starting to skip to recover from error\n"); 80 Skip(); 81 } 82 break; 83 84 case XMLStreamReader.END_ELEMENT: 85 maMachine.ProcessEndElement( 86 maReader.getNamespaceURI(), 87 maReader.getLocalName(), 88 aLocation, 89 maReader.getLocation()); 90 break; 91 92 case XMLStreamReader.CHARACTERS: 93 maMachine.ProcessCharacters( 94 maReader.getText(), 95 aLocation, 96 maReader.getLocation()); 97 break; 98 99 case XMLStreamReader.END_DOCUMENT: 100 break; 101 102 default: 103 Log.Err.printf("can't handle XML event of type %d\n", nCode); 104 } 105 } 106 107 maReader.close(); 108 } 109 catch (final XMLStreamException aException) 110 { 111 aException.printStackTrace(); 112 } 113 catch (final Exception aException) 114 { 115 throw new ParseException( 116 aException, 117 aLocation); 118 } 119 } 120 121 122 123 124 125 GetElementCount()126 public int GetElementCount () 127 { 128 return mnElementCount; 129 } 130 131 132 133 Skip()134 private void Skip () 135 { 136 if (Log.Dbg != null) 137 { 138 Log.Dbg.printf("starting to skip on %s at L%dC%d\n", 139 maReader.getLocalName(), 140 maReader.getLocation().getLineNumber(), 141 maReader.getLocation().getColumnNumber()); 142 Log.Dbg.IncreaseIndentation(); 143 } 144 145 // We are called when processing a start element. This means that we are 146 // already at relative depth 1. 147 int nRelativeDepth = 1; 148 try 149 { 150 while (maReader.hasNext()) 151 { 152 final int nCode = maReader.next(); 153 switch (nCode) 154 { 155 case XMLStreamReader.START_ELEMENT: 156 ++nRelativeDepth; 157 ++mnElementCount; 158 if (Log.Dbg != null) 159 { 160 Log.Dbg.printf("skipping start element %s\n", maReader.getLocalName()); 161 Log.Dbg.IncreaseIndentation(); 162 } 163 break; 164 165 case XMLStreamReader.END_ELEMENT: 166 --nRelativeDepth; 167 if (Log.Dbg != null) 168 Log.Dbg.DecreaseIndentation(); 169 if (nRelativeDepth <= 0) 170 { 171 if (Log.Dbg != null) 172 Log.Dbg.printf("leaving skip mode on %s\n", maReader.getLocalName()); 173 return; 174 } 175 break; 176 177 case XMLStreamReader.END_DOCUMENT: 178 throw new RuntimeException("saw end of document while skipping elements\n"); 179 180 case XMLStreamReader.CHARACTERS: 181 SkipText(maReader.getText()); 182 break; 183 184 default: 185 if (Log.Dbg != null) 186 Log.Dbg.printf("%s\n", nCode); 187 break; 188 } 189 } 190 } 191 catch (final XMLStreamException aException) 192 { 193 aException.printStackTrace(); 194 } 195 } 196 197 198 199 SkipText(final String sText)200 private void SkipText (final String sText) 201 { 202 if (Log.Dbg != null) 203 Log.Dbg.printf("skipping text [%s]\n", sText.replace("\n", "\\n")); 204 } 205 206 207 208 GetStreamReader( final InputStream aIn, final String sDescription)209 private XMLStreamReader GetStreamReader ( 210 final InputStream aIn, 211 final String sDescription) 212 { 213 if (aIn == null) 214 return null; 215 216 try 217 { 218 final XMLInputFactory aFactory = (XMLInputFactory)XMLInputFactory.newInstance(); 219 aFactory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, false); 220 aFactory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false); 221 aFactory.setProperty(XMLInputFactory.IS_COALESCING, false); 222 223 return (XMLStreamReader)aFactory.createXMLStreamReader( 224 sDescription, 225 aIn); 226 } 227 catch (final Exception aException) 228 { 229 aException.printStackTrace(); 230 return null; 231 } 232 } 233 234 235 236 GetActionManager()237 public ActionManager GetActionManager() 238 { 239 return maMachine.GetActionManager(); 240 } 241 242 243 244 245 private final XMLStreamReader maReader; 246 private final StateMachine maMachine; 247 private int mnElementCount; 248 } 249