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 23 24 package org.openoffice.xmerge.converter.xml; 25 26 import java.io.IOException; 27 28 import javax.xml.parsers.DocumentBuilder; 29 import javax.xml.parsers.DocumentBuilderFactory; 30 import javax.xml.parsers.ParserConfigurationException; 31 32 import org.w3c.dom.Document; 33 import org.w3c.dom.DOMException; 34 import org.w3c.dom.Element; 35 import org.w3c.dom.Node; 36 37 import org.xml.sax.SAXException; 38 39 /** 40 * This class represents those embedded objects in an OpenOffice.org document 41 * that have an XML representation. Currently, according to the OpenOffice.org 42 * File Format 1.0 document, there are 6 such objects: 43 * 44 * Formulae created with Math (application/vnd.sun.xml.math) 45 * Charts created with Chart (application/vnd.sun.xml.chart) 46 * Spreadsheets created with Calc (application/vnd.sun.xml.calc) 47 * Text created with Writer (application/vnd.sun.xml.writer) 48 * Drawings created with Draw (application/vnd.sun.xml.draw) 49 * Presentations created with Impress (application/vnd.sun.xml.impress) 50 * 51 * These object types are stored using a combination of content, settings and styles 52 * XML files. 53 */ 54 public class EmbeddedXMLObject extends EmbeddedObject { 55 56 // Entries for the subdocuments that constitute this object; 57 protected Document contentDOM = null; 58 protected Document settingsDOM = null; 59 protected Document stylesDOM = null; 60 61 private DocumentBuilder builder = null; 62 63 /** 64 * Constructor for an embedded object stored using an XML representation. 65 * 66 * @param name The name of the object. 67 * @param type The mime-type of the object. See the class summary. 68 */ EmbeddedXMLObject(String name, String type)69 public EmbeddedXMLObject(String name, String type) { 70 super(name, type); 71 } 72 73 /** 74 * Package private constructor for use when reading an object from a 75 * compressed SX? file. 76 * 77 * @param name The name of the object. 78 * @param type The mime-type of the object. See the class summary. 79 * @param source The OfficeZip representation of the SX? file that stores 80 * the object. 81 */ EmbeddedXMLObject(String name, String type, OfficeZip source)82 EmbeddedXMLObject(String name, String type, OfficeZip source) { 83 super(name, type, source); 84 } 85 86 87 /** 88 * Returns the content data for this embedded object. 89 * 90 * @return DOM represenation of "content.xml" 91 * 92 * @throws SAXException If any parser error occurs 93 * @throws IOException If any IO error occurs 94 */ getContentDOM()95 public Document getContentDOM() throws SAXException, IOException { 96 97 if (contentDOM == null) { 98 contentDOM = getNamedDOM("content.xml"); 99 } 100 101 return contentDOM; 102 } 103 104 105 /** 106 * Sets the content data for the embedded object. 107 * 108 * @param content DOM representation of the object's content. 109 */ setContentDOM(Document content)110 public void setContentDOM(Document content) { 111 contentDOM = content; 112 hasChanged = true; 113 } 114 115 116 /** 117 * Returns the settings data for this embedded object. 118 * 119 * @return DOM represenation of "settings.xml" 120 * 121 * @throws SAXException If any parser error occurs 122 * @throws IOException If any IO error occurs 123 */ getSettingsDOM()124 public Document getSettingsDOM() throws SAXException, IOException { 125 126 if (settingsDOM == null) { 127 settingsDOM = getNamedDOM("settings.xml"); 128 } 129 130 return settingsDOM; 131 } 132 133 134 /** 135 * Sets the settings data for the embedded object. 136 * 137 * @param settings DOM representation of the object's styles. 138 */ setSettingsDOM(Document settings)139 public void setSettingsDOM(Document settings) { 140 settingsDOM = settings; 141 hasChanged = true; 142 } 143 144 145 /** 146 * Returns the style data for this embedded object. 147 * 148 * @return DOM represenation of "styles.xml" 149 * 150 * @throws SAXException If any parser error occurs 151 * @throws IOException If any IO error occurs 152 */ getStylesDOM()153 public Document getStylesDOM() throws SAXException, IOException { 154 155 if (stylesDOM == null) { 156 stylesDOM = getNamedDOM("styles.xml"); 157 } 158 159 return stylesDOM; 160 } 161 162 163 /** 164 * Sets the styles data for the embedded object. 165 * 166 * @param styles DOM representation of the object's styles. 167 */ setStylesDOM(Document styles)168 public void setStylesDOM(Document styles) { 169 stylesDOM = styles; 170 hasChanged = true; 171 } 172 173 174 /** 175 * This method extracts the data for the given XML file from the SX? file 176 * and creates a DOM representation of it. 177 * 178 * @param name The name of the XML file to retrieve. It is paired with 179 * the object name to access the SX? file. 180 * 181 * @return DOM representation of the named XML file. 182 * 183 * @throws SAXException If any parser error occurs 184 * @throws IOException If any IO error occurs 185 */ getNamedDOM(String name)186 private Document getNamedDOM(String name) throws SAXException, IOException { 187 if (zipFile == null) { 188 return null; 189 } 190 191 try { 192 if (builder == null) { 193 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 194 195 factory.setValidating(false); 196 builder = factory.newDocumentBuilder(); 197 } 198 199 byte[] data = zipFile.getNamedBytes(new String(objName + "/" + name)); 200 if (data != null) { 201 return OfficeDocument.parse(builder, data); 202 } 203 else { 204 return null; 205 } 206 207 } 208 catch (SAXException se) { 209 throw se; 210 } 211 catch (IOException ioe) { 212 throw ioe; 213 } 214 catch (ParserConfigurationException pce) { 215 throw new SAXException(pce); 216 } 217 } 218 219 220 /** 221 * Package private method for writing the data of the EmbeddedObject to a 222 * SX? file. 223 * 224 * @param zip An <code>OfficeZip</code> instance representing the file 225 * the data is to be written to. 226 */ write(OfficeZip zip)227 void write(OfficeZip zip) throws IOException { 228 if (hasChanged == true) { 229 if (contentDOM != null) { 230 zip.setNamedBytes(new String(objName + "/content.xml"), 231 OfficeDocument.docToBytes(contentDOM)); 232 } 233 if (settingsDOM != null) { 234 zip.setNamedBytes(new String(objName + "/settings.xml"), 235 OfficeDocument.docToBytes(settingsDOM)); 236 } 237 if (stylesDOM != null) { 238 zip.setNamedBytes(new String(objName + "/styles.xml"), 239 OfficeDocument.docToBytes(stylesDOM)); 240 } 241 } 242 } 243 244 /** 245 * Package private method that constructs the manifest.xml entries for this 246 * embedded object. 247 * 248 * @param manifestDoc <code>Document</code> containing the manifest entries. 249 */ writeManifestData(Document manifestDoc)250 void writeManifestData(Document manifestDoc) throws DOMException { 251 Node root = manifestDoc.getDocumentElement(); 252 253 if (contentDOM != null) { 254 Element contentNode = manifestDoc.createElement(OfficeConstants.TAG_MANIFEST_FILE); 255 256 contentNode.setAttribute(OfficeConstants.ATTRIBUTE_MANIFEST_FILE_TYPE, "text/xml"); 257 contentNode.setAttribute(OfficeConstants.ATTRIBUTE_MANIFEST_FILE_PATH, 258 new String(objName + "/content.xml")); 259 260 root.appendChild(contentNode); 261 } 262 263 if (settingsDOM != null) { 264 Element settingsNode = manifestDoc.createElement(OfficeConstants.TAG_MANIFEST_FILE); 265 266 settingsNode.setAttribute(OfficeConstants.ATTRIBUTE_MANIFEST_FILE_TYPE, "text/xml"); 267 settingsNode.setAttribute(OfficeConstants.ATTRIBUTE_MANIFEST_FILE_PATH, 268 new String(objName + "/settings.xml")); 269 270 root.appendChild(settingsNode); 271 } 272 273 if (stylesDOM != null) { 274 Element stylesNode = manifestDoc.createElement(OfficeConstants.TAG_MANIFEST_FILE); 275 276 stylesNode.setAttribute(OfficeConstants.ATTRIBUTE_MANIFEST_FILE_TYPE, "text/xml"); 277 stylesNode.setAttribute(OfficeConstants.ATTRIBUTE_MANIFEST_FILE_PATH, 278 new String(objName + "/styles.xml")); 279 } 280 281 282 Element objectNode = manifestDoc.createElement(OfficeConstants.TAG_MANIFEST_FILE); 283 284 objectNode.setAttribute(OfficeConstants.ATTRIBUTE_MANIFEST_FILE_TYPE, objType); 285 objectNode.setAttribute(OfficeConstants.ATTRIBUTE_MANIFEST_FILE_PATH, 286 new String(objName + "/")); 287 288 root.appendChild(objectNode); 289 } 290 291 } 292