From ad93d569daec924390fa9346a1bf74eed52f5fa8 Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Fri, 6 Jul 2018 19:07:22 +0000 Subject: [PATCH] [bug-62522] include partName in exception message git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1835276 13f79535-47bb-0310-9956-ffa450edef68 --- .../opc/internal/ContentTypeManager.java | 817 +++++++++--------- 1 file changed, 409 insertions(+), 408 deletions(-) diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ContentTypeManager.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ContentTypeManager.java index ac23a7cada..26ea1b0c7a 100644 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ContentTypeManager.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ContentTypeManager.java @@ -43,433 +43,434 @@ import org.xml.sax.SAXException; */ public abstract class ContentTypeManager { - /** - * Content type part name. - */ - public static final String CONTENT_TYPES_PART_NAME = "[Content_Types].xml"; - - /** - * Content type namespace - */ - public static final String TYPES_NAMESPACE_URI = PackageNamespaces.CONTENT_TYPES; - - /* Xml elements in content type part */ - - private static final String TYPES_TAG_NAME = "Types"; - - private static final String DEFAULT_TAG_NAME = "Default"; - - private static final String EXTENSION_ATTRIBUTE_NAME = "Extension"; - - private static final String CONTENT_TYPE_ATTRIBUTE_NAME = "ContentType"; - - private static final String OVERRIDE_TAG_NAME = "Override"; - - private static final String PART_NAME_ATTRIBUTE_NAME = "PartName"; - - /** - * Reference to the package using this content type manager. - */ - protected OPCPackage container; - - /** - * Default content type tree. - */ - private TreeMap defaultContentType; - - /** - * Override content type tree. - */ - private TreeMap overrideContentType; - - /** - * Constructor. Parses the content of the specified input stream. - * - * @param in - * If different of null then the content types part is - * retrieve and parse. - * @throws InvalidFormatException - * If the content types part content is not valid. - */ - public ContentTypeManager(InputStream in, OPCPackage pkg) - throws InvalidFormatException { - this.container = pkg; - this.defaultContentType = new TreeMap<>(); - if (in != null) { - try { - parseContentTypesFile(in); - } catch (InvalidFormatException e) { - InvalidFormatException ex = new InvalidFormatException("Can't read content types part !"); + /** + * Content type part name. + */ + public static final String CONTENT_TYPES_PART_NAME = "[Content_Types].xml"; + + /** + * Content type namespace + */ + public static final String TYPES_NAMESPACE_URI = PackageNamespaces.CONTENT_TYPES; + + /* Xml elements in content type part */ + + private static final String TYPES_TAG_NAME = "Types"; + + private static final String DEFAULT_TAG_NAME = "Default"; + + private static final String EXTENSION_ATTRIBUTE_NAME = "Extension"; + + private static final String CONTENT_TYPE_ATTRIBUTE_NAME = "ContentType"; + + private static final String OVERRIDE_TAG_NAME = "Override"; + + private static final String PART_NAME_ATTRIBUTE_NAME = "PartName"; + + /** + * Reference to the package using this content type manager. + */ + protected OPCPackage container; + + /** + * Default content type tree. + */ + private TreeMap defaultContentType; + + /** + * Override content type tree. + */ + private TreeMap overrideContentType; + + /** + * Constructor. Parses the content of the specified input stream. + * + * @param in + * If different of null then the content types part is + * retrieve and parse. + * @throws InvalidFormatException + * If the content types part content is not valid. + */ + public ContentTypeManager(InputStream in, OPCPackage pkg) + throws InvalidFormatException { + this.container = pkg; + this.defaultContentType = new TreeMap<>(); + if (in != null) { + try { + parseContentTypesFile(in); + } catch (InvalidFormatException e) { + InvalidFormatException ex = new InvalidFormatException("Can't read content types part !"); // here it is useful to add the cause to not loose the original stack-trace ex.initCause(e); - + throw ex; - } - } - } - - /** - * Build association extention-> content type (will be stored in - * [Content_Types].xml) for example ContentType="image/png" Extension="png" - *

- * [M2.8]: When adding a new part to a package, the package implementer - * shall ensure that a content type for that part is specified in the - * Content Types stream; the package implementer shall perform the steps - * described in §9.1.2.3: - *

- * 1. Get the extension from the part name by taking the substring to the - * right of the rightmost occurrence of the dot character (.) from the - * rightmost segment. - *

- * 2. If a part name has no extension, a corresponding Override element - * shall be added to the Content Types stream. - *

- * 3. Compare the resulting extension with the values specified for the - * Extension attributes of the Default elements in the Content Types stream. - * The comparison shall be case-insensitive ASCII. - *

- * 4. If there is a Default element with a matching Extension attribute, - * then the content type of the new part shall be compared with the value of - * the ContentType attribute. The comparison might be case-sensitive and - * include every character regardless of the role it plays in the - * content-type grammar of RFC 2616, or it might follow the grammar of RFC - * 2616. - *

- * a. If the content types match, no further action is required. - *

- * b. If the content types do not match, a new Override element shall be - * added to the Content Types stream. . - *

- * 5. If there is no Default element with a matching Extension attribute, a - * new Default element or Override element shall be added to the Content - * Types stream. - *

- */ - public void addContentType(PackagePartName partName, String contentType) { - boolean defaultCTExists = this.defaultContentType.containsValue(contentType); - String extension = partName.getExtension().toLowerCase(Locale.ROOT); - if ((extension.length() == 0) - || (this.defaultContentType.containsKey(extension) && !defaultCTExists)) - this.addOverrideContentType(partName, contentType); - else if (!defaultCTExists) - this.addDefaultContentType(extension, contentType); - } - - /** - * Add an override content type for a specific part. - * - * @param partName - * Name of the part. - * @param contentType - * Content type of the part. - */ - private void addOverrideContentType(PackagePartName partName, - String contentType) { - if (overrideContentType == null) - overrideContentType = new TreeMap<>(); - overrideContentType.put(partName, contentType); - } - - /** - * Add a content type associated with the specified extension. - * - * @param extension - * The part name extension to bind to a content type. - * @param contentType - * The content type associated with the specified extension. - */ - private void addDefaultContentType(String extension, String contentType) { - // Remark : Originally the latest parameter was : - // contentType.toLowerCase(). Change due to a request ID 1996748. - defaultContentType.put(extension.toLowerCase(Locale.ROOT), contentType); - } - - /** + } + } + } + + /** + * Build association extention-> content type (will be stored in + * [Content_Types].xml) for example ContentType="image/png" Extension="png" + *

+ * [M2.8]: When adding a new part to a package, the package implementer + * shall ensure that a content type for that part is specified in the + * Content Types stream; the package implementer shall perform the steps + * described in §9.1.2.3: + *

+ * 1. Get the extension from the part name by taking the substring to the + * right of the rightmost occurrence of the dot character (.) from the + * rightmost segment. + *

+ * 2. If a part name has no extension, a corresponding Override element + * shall be added to the Content Types stream. + *

+ * 3. Compare the resulting extension with the values specified for the + * Extension attributes of the Default elements in the Content Types stream. + * The comparison shall be case-insensitive ASCII. + *

+ * 4. If there is a Default element with a matching Extension attribute, + * then the content type of the new part shall be compared with the value of + * the ContentType attribute. The comparison might be case-sensitive and + * include every character regardless of the role it plays in the + * content-type grammar of RFC 2616, or it might follow the grammar of RFC + * 2616. + *

+ * a. If the content types match, no further action is required. + *

+ * b. If the content types do not match, a new Override element shall be + * added to the Content Types stream. . + *

+ * 5. If there is no Default element with a matching Extension attribute, a + * new Default element or Override element shall be added to the Content + * Types stream. + *

+ */ + public void addContentType(PackagePartName partName, String contentType) { + boolean defaultCTExists = this.defaultContentType.containsValue(contentType); + String extension = partName.getExtension().toLowerCase(Locale.ROOT); + if ((extension.length() == 0) + || (this.defaultContentType.containsKey(extension) && !defaultCTExists)) + this.addOverrideContentType(partName, contentType); + else if (!defaultCTExists) + this.addDefaultContentType(extension, contentType); + } + + /** + * Add an override content type for a specific part. + * + * @param partName + * Name of the part. + * @param contentType + * Content type of the part. + */ + private void addOverrideContentType(PackagePartName partName, + String contentType) { + if (overrideContentType == null) + overrideContentType = new TreeMap<>(); + overrideContentType.put(partName, contentType); + } + + /** + * Add a content type associated with the specified extension. + * + * @param extension + * The part name extension to bind to a content type. + * @param contentType + * The content type associated with the specified extension. + */ + private void addDefaultContentType(String extension, String contentType) { + // Remark : Originally the latest parameter was : + // contentType.toLowerCase(). Change due to a request ID 1996748. + defaultContentType.put(extension.toLowerCase(Locale.ROOT), contentType); + } + + /** + *

+ * Delete a content type based on the specified part name. If the specified + * part name is register with an override content type, then this content + * type is remove, else the content type is remove in the default content + * type list if it exists and if no part is associated with it yet. + *

+ * Check rule M2.4: The package implementer shall require that the Content + * Types stream contain one of the following for every part in the package: + * One matching Default element One matching Override element Both a + * matching Default element and a matching Override element, in which case + * the Override element takes precedence. + *

+ * @param partName + * The part URI associated with the override content type to + * delete. + * @exception InvalidOperationException + * Throws if + */ + public void removeContentType(PackagePartName partName) + throws InvalidOperationException { + if (partName == null) + throw new IllegalArgumentException("partName"); + + /* Override content type */ + if (this.overrideContentType != null + && (this.overrideContentType.get(partName) != null)) { + // Remove the override definition for the specified part. + this.overrideContentType.remove(partName); + return; + } + + /* Default content type */ + String extensionToDelete = partName.getExtension(); + boolean deleteDefaultContentTypeFlag = true; + if (this.container != null) { + try { + for (PackagePart part : this.container.getParts()) { + if (!part.getPartName().equals(partName) + && part.getPartName().getExtension() + .equalsIgnoreCase(extensionToDelete)) { + deleteDefaultContentTypeFlag = false; + break; + } + } + } catch (InvalidFormatException e) { + throw new InvalidOperationException(e.getMessage()); + } + } + + // Remove the default content type, no other part use this content type. + if (deleteDefaultContentTypeFlag) { + this.defaultContentType.remove(extensionToDelete); + } + + /* + * Check rule 2.4: The package implementer shall require that the + * Content Types stream contain one of the following for every part in + * the package: One matching Default element One matching Override + * element Both a matching Default element and a matching Override + * element, in which case the Override element takes precedence. + */ + if (this.container != null) { + try { + for (PackagePart part : this.container.getParts()) { + if (!part.getPartName().equals(partName) + && this.getContentType(part.getPartName()) == null) + throw new InvalidOperationException( + "Rule M2.4 is not respected: Nor a default element or override element is associated with the part: " + + part.getPartName().getName()); + } + } catch (InvalidFormatException e) { + throw new InvalidOperationException(e.getMessage()); + } + } + } + + /** + * Check if the specified content type is already register. + * + * @param contentType + * The content type to check. + * @return true if the specified content type is already + * register, then false. + */ + public boolean isContentTypeRegister(String contentType) { + if (contentType == null) + throw new IllegalArgumentException("contentType"); + + return (this.defaultContentType.values().contains(contentType) || (this.overrideContentType != null && this.overrideContentType + .values().contains(contentType))); + } + + /** + * Get the content type for the specified part, if any. *

- * Delete a content type based on the specified part name. If the specified - * part name is register with an override content type, then this content - * type is remove, else the content type is remove in the default content - * type list if it exists and if no part is associated with it yet. - *

- * Check rule M2.4: The package implementer shall require that the Content - * Types stream contain one of the following for every part in the package: - * One matching Default element One matching Override element Both a - * matching Default element and a matching Override element, in which case - * the Override element takes precedence. - *

- * @param partName - * The part URI associated with the override content type to - * delete. - * @exception InvalidOperationException - * Throws if - */ - public void removeContentType(PackagePartName partName) - throws InvalidOperationException { - if (partName == null) - throw new IllegalArgumentException("partName"); - - /* Override content type */ - if (this.overrideContentType != null - && (this.overrideContentType.get(partName) != null)) { - // Remove the override definition for the specified part. - this.overrideContentType.remove(partName); - return; - } - - /* Default content type */ - String extensionToDelete = partName.getExtension(); - boolean deleteDefaultContentTypeFlag = true; - if (this.container != null) { - try { - for (PackagePart part : this.container.getParts()) { - if (!part.getPartName().equals(partName) - && part.getPartName().getExtension() - .equalsIgnoreCase(extensionToDelete)) { - deleteDefaultContentTypeFlag = false; - break; - } - } - } catch (InvalidFormatException e) { - throw new InvalidOperationException(e.getMessage()); - } - } - - // Remove the default content type, no other part use this content type. - if (deleteDefaultContentTypeFlag) { - this.defaultContentType.remove(extensionToDelete); - } - - /* - * Check rule 2.4: The package implementer shall require that the - * Content Types stream contain one of the following for every part in - * the package: One matching Default element One matching Override - * element Both a matching Default element and a matching Override - * element, in which case the Override element takes precedence. - */ - if (this.container != null) { - try { - for (PackagePart part : this.container.getParts()) { - if (!part.getPartName().equals(partName) - && this.getContentType(part.getPartName()) == null) - throw new InvalidOperationException( - "Rule M2.4 is not respected: Nor a default element or override element is associated with the part: " - + part.getPartName().getName()); - } - } catch (InvalidFormatException e) { - throw new InvalidOperationException(e.getMessage()); - } - } - } - - /** - * Check if the specified content type is already register. - * - * @param contentType - * The content type to check. - * @return true if the specified content type is already - * register, then false. - */ - public boolean isContentTypeRegister(String contentType) { - if (contentType == null) - throw new IllegalArgumentException("contentType"); - - return (this.defaultContentType.values().contains(contentType) || (this.overrideContentType != null && this.overrideContentType - .values().contains(contentType))); - } - - /** - * Get the content type for the specified part, if any. - *

- * Rule [M2.9]: To get the content type of a part, the package implementer - * shall perform the steps described in §9.1.2.4: - *

- * 1. Compare the part name with the values specified for the PartName - * attribute of the Override elements. The comparison shall be - * case-insensitive ASCII. - *

- * 2. If there is an Override element with a matching PartName attribute, - * return the value of its ContentType attribute. No further action is - * required. - *

- * 3. If there is no Override element with a matching PartName attribute, - * then a. Get the extension from the part name by taking the substring to - * the right of the rightmost occurrence of the dot character (.) from the - * rightmost segment. b. Check the Default elements of the Content Types - * stream, comparing the extension with the value of the Extension - * attribute. The comparison shall be case-insensitive ASCII. - *

- * 4. If there is a Default element with a matching Extension attribute, - * return the value of its ContentType attribute. No further action is - * required. - *

- * 5. If neither Override nor Default elements with matching attributes are - * found for the specified part name, the implementation shall not map this - * part name to a part. - *

- * @param partName - * The URI part to check. - * @return The content type associated with the URI (in case of an override - * content type) or the extension (in case of default content type), - * else null. - * - * @exception OpenXML4JRuntimeException - * Throws if the content type manager is not able to find the - * content from an existing part. - */ - public String getContentType(PackagePartName partName) { - if (partName == null) - throw new IllegalArgumentException("partName"); - - if ((this.overrideContentType != null) - && this.overrideContentType.containsKey(partName)) - return this.overrideContentType.get(partName); - - String extension = partName.getExtension().toLowerCase(Locale.ROOT); - if (this.defaultContentType.containsKey(extension)) - return this.defaultContentType.get(extension); - - /* - * [M2.4] : The package implementer shall require that the Content Types - * stream contain one of the following for every part in the package: - * One matching Default element, One matching Override element, Both a - * matching Default element and a matching Override element, in which - * case the Override element takes precedence. - */ - if (this.container != null && this.container.getPart(partName) != null) { - throw new OpenXML4JRuntimeException( - "Rule M2.4 exception : this error should NEVER happen! If you can provide the triggering file, then please raise a bug at https://bz.apache.org/bugzilla/enter_bug.cgi?product=POI and attach the file that triggers it, thanks!"); - } - return null; - } - - /** - * Clear all content types. - */ - public void clearAll() { - this.defaultContentType.clear(); - if (this.overrideContentType != null) - this.overrideContentType.clear(); - } - - /** - * Clear all override content types. - * - */ - public void clearOverrideContentTypes() { - if (this.overrideContentType != null) - this.overrideContentType.clear(); - } - - /** - * Parse the content types part. - * - * @throws InvalidFormatException - * Throws if the content type doesn't exist or the XML format is - * invalid. - */ - private void parseContentTypesFile(InputStream in) - throws InvalidFormatException { - try { - Document xmlContentTypetDoc = DocumentHelper.readDocument(in); - - // Default content types - NodeList defaultTypes = xmlContentTypetDoc.getDocumentElement().getElementsByTagNameNS(TYPES_NAMESPACE_URI, DEFAULT_TAG_NAME); - int defaultTypeCount = defaultTypes.getLength(); - for (int i = 0; i < defaultTypeCount; i++) { + * Rule [M2.9]: To get the content type of a part, the package implementer + * shall perform the steps described in §9.1.2.4: + *

+ * 1. Compare the part name with the values specified for the PartName + * attribute of the Override elements. The comparison shall be + * case-insensitive ASCII. + *

+ * 2. If there is an Override element with a matching PartName attribute, + * return the value of its ContentType attribute. No further action is + * required. + *

+ * 3. If there is no Override element with a matching PartName attribute, + * then a. Get the extension from the part name by taking the substring to + * the right of the rightmost occurrence of the dot character (.) from the + * rightmost segment. b. Check the Default elements of the Content Types + * stream, comparing the extension with the value of the Extension + * attribute. The comparison shall be case-insensitive ASCII. + *

+ * 4. If there is a Default element with a matching Extension attribute, + * return the value of its ContentType attribute. No further action is + * required. + *

+ * 5. If neither Override nor Default elements with matching attributes are + * found for the specified part name, the implementation shall not map this + * part name to a part. + *

+ * @param partName + * The URI part to check. + * @return The content type associated with the URI (in case of an override + * content type) or the extension (in case of default content type), + * else null. + * + * @exception OpenXML4JRuntimeException + * Throws if the content type manager is not able to find the + * content from an existing part. + */ + public String getContentType(PackagePartName partName) { + if (partName == null) + throw new IllegalArgumentException("partName"); + + if ((this.overrideContentType != null) + && this.overrideContentType.containsKey(partName)) + return this.overrideContentType.get(partName); + + String extension = partName.getExtension().toLowerCase(Locale.ROOT); + if (this.defaultContentType.containsKey(extension)) + return this.defaultContentType.get(extension); + + /* + * [M2.4] : The package implementer shall require that the Content Types + * stream contain one of the following for every part in the package: + * One matching Default element, One matching Override element, Both a + * matching Default element and a matching Override element, in which + * case the Override element takes precedence. + */ + if (this.container != null && this.container.getPart(partName) != null) { + throw new OpenXML4JRuntimeException( + "Rule M2.4 exception : Part \'" + partName + + "\' not found - this error should NEVER happen! If you can provide the triggering file, then please raise a bug at https://bz.apache.org/bugzilla/enter_bug.cgi?product=POI and attach the file that triggers it, thanks!"); + } + return null; + } + + /** + * Clear all content types. + */ + public void clearAll() { + this.defaultContentType.clear(); + if (this.overrideContentType != null) + this.overrideContentType.clear(); + } + + /** + * Clear all override content types. + * + */ + public void clearOverrideContentTypes() { + if (this.overrideContentType != null) + this.overrideContentType.clear(); + } + + /** + * Parse the content types part. + * + * @throws InvalidFormatException + * Throws if the content type doesn't exist or the XML format is + * invalid. + */ + private void parseContentTypesFile(InputStream in) + throws InvalidFormatException { + try { + Document xmlContentTypetDoc = DocumentHelper.readDocument(in); + + // Default content types + NodeList defaultTypes = xmlContentTypetDoc.getDocumentElement().getElementsByTagNameNS(TYPES_NAMESPACE_URI, DEFAULT_TAG_NAME); + int defaultTypeCount = defaultTypes.getLength(); + for (int i = 0; i < defaultTypeCount; i++) { Element element = (Element) defaultTypes.item(i); - String extension = element.getAttribute(EXTENSION_ATTRIBUTE_NAME); - String contentType = element.getAttribute(CONTENT_TYPE_ATTRIBUTE_NAME); - addDefaultContentType(extension, contentType); - } + String extension = element.getAttribute(EXTENSION_ATTRIBUTE_NAME); + String contentType = element.getAttribute(CONTENT_TYPE_ATTRIBUTE_NAME); + addDefaultContentType(extension, contentType); + } - // Overriden content types + // Overriden content types NodeList overrideTypes = xmlContentTypetDoc.getDocumentElement().getElementsByTagNameNS(TYPES_NAMESPACE_URI, OVERRIDE_TAG_NAME); int overrideTypeCount = overrideTypes.getLength(); for (int i = 0; i < overrideTypeCount; i++) { - Element element = (Element) overrideTypes.item(i); - URI uri = new URI(element.getAttribute(PART_NAME_ATTRIBUTE_NAME)); - PackagePartName partName = PackagingURIHelper.createPartName(uri); - String contentType = element.getAttribute(CONTENT_TYPE_ATTRIBUTE_NAME); - addOverrideContentType(partName, contentType); - } - } catch (URISyntaxException | IOException | SAXException e) { - throw new InvalidFormatException(e.getMessage()); + Element element = (Element) overrideTypes.item(i); + URI uri = new URI(element.getAttribute(PART_NAME_ATTRIBUTE_NAME)); + PackagePartName partName = PackagingURIHelper.createPartName(uri); + String contentType = element.getAttribute(CONTENT_TYPE_ATTRIBUTE_NAME); + addOverrideContentType(partName, contentType); + } + } catch (URISyntaxException | IOException | SAXException e) { + throw new InvalidFormatException(e.getMessage()); } - } - - /** - * Save the contents type part. - * - * @param outStream - * The output stream use to save the XML content of the content - * types part. - * @return true if the operation success, else false. - */ - public boolean save(OutputStream outStream) { - Document xmlOutDoc = DocumentHelper.createDocument(); - - // Building namespace - Element typesElem = xmlOutDoc.createElementNS(TYPES_NAMESPACE_URI, TYPES_TAG_NAME); + } + + /** + * Save the contents type part. + * + * @param outStream + * The output stream use to save the XML content of the content + * types part. + * @return true if the operation success, else false. + */ + public boolean save(OutputStream outStream) { + Document xmlOutDoc = DocumentHelper.createDocument(); + + // Building namespace + Element typesElem = xmlOutDoc.createElementNS(TYPES_NAMESPACE_URI, TYPES_TAG_NAME); xmlOutDoc.appendChild(typesElem); - // Adding default types - for (Entry entry : defaultContentType.entrySet()) { - appendDefaultType(typesElem, entry); - } - - // Adding specific types if any exist - if (overrideContentType != null) { - for (Entry entry : overrideContentType - .entrySet()) { - appendSpecificTypes(typesElem, entry); - } - } - xmlOutDoc.normalize(); - - // Save content in the specified output stream - return this.saveImpl(xmlOutDoc, outStream); - } - - /** - * Use to append specific type XML elements, use by the save() method. - * - * @param root - * XML parent element use to append this override type element. - * @param entry - * The values to append. - * @see #save(java.io.OutputStream) - */ - private void appendSpecificTypes(Element root, - Entry entry) { + // Adding default types + for (Entry entry : defaultContentType.entrySet()) { + appendDefaultType(typesElem, entry); + } + + // Adding specific types if any exist + if (overrideContentType != null) { + for (Entry entry : overrideContentType + .entrySet()) { + appendSpecificTypes(typesElem, entry); + } + } + xmlOutDoc.normalize(); + + // Save content in the specified output stream + return this.saveImpl(xmlOutDoc, outStream); + } + + /** + * Use to append specific type XML elements, use by the save() method. + * + * @param root + * XML parent element use to append this override type element. + * @param entry + * The values to append. + * @see #save(java.io.OutputStream) + */ + private void appendSpecificTypes(Element root, + Entry entry) { Element specificType = root.getOwnerDocument().createElementNS(TYPES_NAMESPACE_URI, OVERRIDE_TAG_NAME); specificType.setAttribute(PART_NAME_ATTRIBUTE_NAME, entry.getKey().getName()); specificType.setAttribute(CONTENT_TYPE_ATTRIBUTE_NAME, entry.getValue()); root.appendChild(specificType); - } - - /** - * Use to append default types XML elements, use by the save() method. - * - * @param root - * XML parent element use to append this default type element. - * @param entry - * The values to append. - * @see #save(java.io.OutputStream) - */ - private void appendDefaultType(Element root, Entry entry) { + } + + /** + * Use to append default types XML elements, use by the save() method. + * + * @param root + * XML parent element use to append this default type element. + * @param entry + * The values to append. + * @see #save(java.io.OutputStream) + */ + private void appendDefaultType(Element root, Entry entry) { Element defaultType = root.getOwnerDocument().createElementNS(TYPES_NAMESPACE_URI, DEFAULT_TAG_NAME); defaultType.setAttribute(EXTENSION_ATTRIBUTE_NAME, entry.getKey()); defaultType.setAttribute(CONTENT_TYPE_ATTRIBUTE_NAME, entry.getValue()); root.appendChild(defaultType); - } - - /** - * Specific implementation of the save method. Call by the save() method, - * call before exiting. - * - * @param out - * The output stream use to write the content type XML. - */ - public abstract boolean saveImpl(Document content, OutputStream out); + } + + /** + * Specific implementation of the save method. Call by the save() method, + * call before exiting. + * + * @param out + * The output stream use to write the content type XML. + */ + public abstract boolean saveImpl(Document content, OutputStream out); } -- 2.39.5