Categories:
Audio (13)
Biotech (29)
Bytecode (36)
Database (77)
Framework (7)
Game (7)
General (507)
Graphics (53)
I/O (35)
IDE (2)
JAR Tools (101)
JavaBeans (21)
JDBC (121)
JDK (426)
JSP (20)
Logging (108)
Mail (58)
Messaging (8)
Network (84)
PDF (97)
Report (7)
Scripting (84)
Security (32)
Server (121)
Servlet (26)
SOAP (24)
Testing (54)
Web (15)
XML (309)
Collections:
Other Resources:
iText kernel.jar Source Code
kernel.jar is a component in iText Java library to provide low-level functionalities. iText Java library allows you to generate and manage PDF documents.
The Source Code files are provided together with the JAR file in the binary packge like iText7-Core-7.1.4.zip. You can download it at iText 7 Core Download site.
You can compile it to generate your JAR file, using kernel.pom as the build configuration file.
The source code of kernel-7.1.4.jar is provided below:
✍: FYIcenter.com
⏎ com/itextpdf/kernel/xmp/impl/XMPNodeUtils.java
//Copyright (c) 2006, Adobe Systems Incorporated //All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // 3. All advertising materials mentioning features or use of this software // must display the following acknowledgement: // This product includes software developed by the Adobe Systems Incorporated. // 4. Neither the name of the Adobe Systems Incorporated nor the // names of its contributors may be used to endorse or promote products // derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY ADOBE SYSTEMS INCORPORATED ''AS IS'' AND ANY // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL ADOBE SYSTEMS INCORPORATED BE LIABLE FOR ANY // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // http://www.adobe.com/devnet/xmp/library/eula-xmp-library-java.html package com.itextpdf.kernel.xmp.impl; import com.itextpdf.kernel.xmp.XMPConst; import com.itextpdf.kernel.xmp.XMPDateTime; import com.itextpdf.kernel.xmp.XMPDateTimeFactory; import com.itextpdf.kernel.xmp.XMPError; import com.itextpdf.kernel.xmp.XMPException; import com.itextpdf.kernel.xmp.XMPMetaFactory; import com.itextpdf.kernel.xmp.XMPUtils; import com.itextpdf.kernel.xmp.impl.xpath.XMPPath; import com.itextpdf.kernel.xmp.impl.xpath.XMPPathSegment; import com.itextpdf.kernel.xmp.options.AliasOptions; import com.itextpdf.kernel.xmp.options.PropertyOptions; import java.util.GregorianCalendar; import java.util.Iterator; /** * Utilities for <code>XMPNode</code>. * * @since Aug 28, 2006 */ public final class XMPNodeUtils implements XMPConst { /** */ static final int CLT_NO_VALUES = 0; /** */ static final int CLT_SPECIFIC_MATCH = 1; /** */ static final int CLT_SINGLE_GENERIC = 2; /** */ static final int CLT_MULTIPLE_GENERIC = 3; /** */ static final int CLT_XDEFAULT = 4; /** */ static final int CLT_FIRST_ITEM = 5; /** * Private Constructor */ private XMPNodeUtils() { // EMPTY } /** * Find or create a schema node if <code>createNodes</code> is false and * * @param tree the root of the xmp tree. * @param namespaceURI a namespace * @param createNodes a flag indicating if the node shall be created if not found. * <em>Note:</em> The namespace must be registered prior to this call. * * @return Returns the schema node if found, <code>null</code> otherwise. * Note: If <code>createNodes</code> is <code>true</code>, it is <b>always</b> * returned a valid node. * @throws XMPException An exception is only thrown if an error occurred, not if a * node was not found. */ static XMPNode findSchemaNode(XMPNode tree, String namespaceURI, boolean createNodes) throws XMPException { return findSchemaNode(tree, namespaceURI, null, createNodes); } /** * Find or create a schema node if <code>createNodes</code> is true. * * @param tree the root of the xmp tree. * @param namespaceURI a namespace * @param suggestedPrefix If a prefix is suggested, the namespace is allowed to be registered. * @param createNodes a flag indicating if the node shall be created if not found. * <em>Note:</em> The namespace must be registered prior to this call. * * @return Returns the schema node if found, <code>null</code> otherwise. * Note: If <code>createNodes</code> is <code>true</code>, it is <b>always</b> * returned a valid node. * @throws XMPException An exception is only thrown if an error occurred, not if a * node was not found. */ static XMPNode findSchemaNode(XMPNode tree, String namespaceURI, String suggestedPrefix, boolean createNodes) throws XMPException { assert tree.getParent() == null; // make sure that its the root XMPNode schemaNode = tree.findChildByName(namespaceURI); if (schemaNode == null && createNodes) { schemaNode = new XMPNode(namespaceURI, new PropertyOptions() .setSchemaNode(true)); schemaNode.setImplicit(true); // only previously registered schema namespaces are allowed in the XMP tree. String prefix = XMPMetaFactory.getSchemaRegistry().getNamespacePrefix(namespaceURI); if (prefix == null) { if (suggestedPrefix != null && suggestedPrefix.length() != 0) { prefix = XMPMetaFactory.getSchemaRegistry().registerNamespace(namespaceURI, suggestedPrefix); } else { throw new XMPException("Unregistered schema namespace URI", XMPError.BADSCHEMA); } } schemaNode.setValue(prefix); tree.addChild(schemaNode); } return schemaNode; } /** * Find or create a child node under a given parent node. If the parent node is no * Returns the found or created child node. * * @param parent * the parent node * @param childName * the node name to find * @param createNodes * flag, if new nodes shall be created. * @return Returns the found or created node or <code>null</code>. * @throws XMPException Thrown if */ static XMPNode findChildNode(XMPNode parent, String childName, boolean createNodes) throws XMPException { if (!parent.getOptions().isSchemaNode() && !parent.getOptions().isStruct()) { if (!parent.isImplicit()) { throw new XMPException("Named children only allowed for schemas and structs", XMPError.BADXPATH); } else if (parent.getOptions().isArray()) { throw new XMPException("Named children not allowed for arrays", XMPError.BADXPATH); } else if (createNodes) { parent.getOptions().setStruct(true); } } XMPNode childNode = parent.findChildByName(childName); if (childNode == null && createNodes) { PropertyOptions options = new PropertyOptions(); childNode = new XMPNode(childName, options); childNode.setImplicit(true); parent.addChild(childNode); } assert childNode != null || !createNodes; return childNode; } /** * Follow an expanded path expression to find or create a node. * * @param xmpTree the node to begin the search. * @param xpath the complete xpath * @param createNodes flag if nodes shall be created * (when called by <code>setProperty()</code>) * @param leafOptions the options for the created leaf nodes (only when * <code>createNodes == true</code>). * @return Returns the node if found or created or <code>null</code>. * @throws XMPException An exception is only thrown if an error occurred, * not if a node was not found. */ static XMPNode findNode(XMPNode xmpTree, XMPPath xpath, boolean createNodes, PropertyOptions leafOptions) throws XMPException { // check if xpath is set. if (xpath == null || xpath.size() == 0) { throw new XMPException("Empty XMPPath", XMPError.BADXPATH); } // Root of implicitly created subtree to possible delete it later. // Valid only if leaf is new. XMPNode rootImplicitNode = null; XMPNode currNode = null; // resolve schema step currNode = findSchemaNode(xmpTree, xpath.getSegment(XMPPath.STEP_SCHEMA).getName(), createNodes); if (currNode == null) { return null; } else if (currNode.isImplicit()) { currNode.setImplicit(false); // Clear the implicit node bit. rootImplicitNode = currNode; // Save the top most implicit node. } // Now follow the remaining steps of the original XMPPath. try { for (int i = 1; i < xpath.size(); i++) { currNode = followXPathStep(currNode, xpath.getSegment(i), createNodes); if (currNode == null) { if (createNodes) { // delete implicitly created nodes deleteNode(rootImplicitNode); } return null; } else if (currNode.isImplicit()) { // clear the implicit node flag currNode.setImplicit(false); // if node is an ALIAS (can be only in root step, auto-create array // when the path has been resolved from a not simple alias type if (i == 1 && xpath.getSegment(i).isAlias() && xpath.getSegment(i).getAliasForm() != 0) { currNode.getOptions().setOption(xpath.getSegment(i).getAliasForm(), true); } // "CheckImplicitStruct" in C++ else if (i < xpath.size() - 1 && xpath.getSegment(i).getKind() == XMPPath.STRUCT_FIELD_STEP && !currNode.getOptions().isCompositeProperty()) { currNode.getOptions().setStruct(true); } if (rootImplicitNode == null) { rootImplicitNode = currNode; // Save the top most implicit node. } } } } catch (XMPException e) { // if new notes have been created prior to the error, delete them if (rootImplicitNode != null) { deleteNode(rootImplicitNode); } throw e; } if (rootImplicitNode != null) { // set options only if a node has been successful created currNode.getOptions().mergeWith(leafOptions); currNode.setOptions(currNode.getOptions()); } return currNode; } /** * Deletes the the given node and its children from its parent. * Takes care about adjusting the flags. * @param node the top-most node to delete. */ static void deleteNode(XMPNode node) { XMPNode parent = node.getParent(); if (node.getOptions().isQualifier()) { // root is qualifier parent.removeQualifier(node); } else { // root is NO qualifier parent.removeChild(node); } // delete empty Schema nodes if (!parent.hasChildren() && parent.getOptions().isSchemaNode()) { parent.getParent().removeChild(parent); } } /** * This is setting the value of a leaf node. * * @param node an XMPNode * @param value a value */ static void setNodeValue(XMPNode node, Object value) { String strValue = serializeNodeValue(value); if (!(node.getOptions().isQualifier() && XML_LANG.equals(node.getName()))) { node.setValue(strValue); } else { node.setValue(Utils.normalizeLangValue(strValue)); } } /** * Verifies the PropertyOptions for consistancy and updates them as needed. * If options are <code>null</code> they are created with default values. * * @param options the <code>PropertyOptions</code> * @param itemValue the node value to set * @return Returns the updated options. * @throws XMPException If the options are not consistant. */ static PropertyOptions verifySetOptions(PropertyOptions options, Object itemValue) throws XMPException { // create empty and fix existing options if (options == null) { // set default options options = new PropertyOptions(); } if (options.isArrayAltText()) { options.setArrayAlternate(true); } if (options.isArrayAlternate()) { options.setArrayOrdered(true); } if (options.isArrayOrdered()) { options.setArray(true); } if (options.isCompositeProperty() && itemValue != null && itemValue.toString().length() > 0) { throw new XMPException("Structs and arrays can't have values", XMPError.BADOPTIONS); } options.assertConsistency(options.getOptions()); return options; } /** * Converts the node value to String, apply special conversions for defined * types in XMP. * * @param value * the node value to set * @return Returns the String representation of the node value. */ static String serializeNodeValue(Object value) { String strValue; if (value == null) { strValue = null; } else if (value instanceof Boolean) { strValue = XMPUtils.convertFromBoolean((boolean) value); } else if (value instanceof Integer) { strValue = XMPUtils.convertFromInteger((int) value); } else if (value instanceof Long) { strValue = XMPUtils.convertFromLong((long) value); } else if (value instanceof Double) { strValue = XMPUtils.convertFromDouble((double) value); } else if (value instanceof XMPDateTime) { strValue = XMPUtils.convertFromDate((XMPDateTime) value); } else if (value instanceof GregorianCalendar) { XMPDateTime dt = XMPDateTimeFactory.createFromCalendar((GregorianCalendar) value); strValue = XMPUtils.convertFromDate(dt); } else if (value instanceof byte[]) { strValue = XMPUtils.encodeBase64((byte[]) value); } else { strValue = value.toString(); } return strValue != null ? Utils.removeControlChars(strValue) : null; } /** * After processing by ExpandXPath, a step can be of these forms: * <ul> * <li>qualName - A top level property or struct field. * <li>[index] - An element of an array. * <li>[last()] - The last element of an array. * <li>[qualName="value"] - An element in an array of structs, chosen by a field value. * <li>[?qualName="value"] - An element in an array, chosen by a qualifier value. * <li>?qualName - A general qualifier. * </ul> * Find the appropriate child node, resolving aliases, and optionally creating nodes. * * @param parentNode the node to start to start from * @param nextStep the xpath segment * @param createNodes * @return returns the found or created XMPPath node * @throws XMPException */ private static XMPNode followXPathStep( XMPNode parentNode, XMPPathSegment nextStep, boolean createNodes) throws XMPException { XMPNode nextNode = null; int index = 0; int stepKind = nextStep.getKind(); if (stepKind == XMPPath.STRUCT_FIELD_STEP) { nextNode = findChildNode(parentNode, nextStep.getName(), createNodes); } else if (stepKind == XMPPath.QUALIFIER_STEP) { nextNode = findQualifierNode( parentNode, nextStep.getName().substring(1), createNodes); } else { // This is an array indexing step. First get the index, then get the node. if (!parentNode.getOptions().isArray()) { throw new XMPException("Indexing applied to non-array", XMPError.BADXPATH); } if (stepKind == XMPPath.ARRAY_INDEX_STEP) { index = findIndexedItem(parentNode, nextStep.getName(), createNodes); } else if (stepKind == XMPPath.ARRAY_LAST_STEP) { index = parentNode.getChildrenLength(); } else if (stepKind == XMPPath.FIELD_SELECTOR_STEP) { String[] result = Utils.splitNameAndValue(nextStep.getName()); String fieldName = result[0]; String fieldValue = result[1]; index = lookupFieldSelector(parentNode, fieldName, fieldValue); } else if (stepKind == XMPPath.QUAL_SELECTOR_STEP) { String[] result = Utils.splitNameAndValue(nextStep.getName()); String qualName = result[0]; String qualValue = result[1]; index = lookupQualSelector( parentNode, qualName, qualValue, nextStep.getAliasForm()); } else { throw new XMPException("Unknown array indexing step in FollowXPathStep", XMPError.INTERNALFAILURE); } if (1 <= index && index <= parentNode.getChildrenLength()) { nextNode = parentNode.getChild(index); } } return nextNode; } /** * Find or create a qualifier node under a given parent node. Returns a pointer to the * qualifier node, and optionally an iterator for the node's position in * the parent's vector of qualifiers. The iterator is unchanged if no qualifier node (null) * is returned. * <em>Note:</em> On entry, the qualName parameter must not have the leading '?' from the * XMPPath step. * * @param parent the parent XMPNode * @param qualName the qualifier name * @param createNodes flag if nodes shall be created * @return Returns the qualifier node if found or created, <code>null</code> otherwise. * @throws XMPException */ private static XMPNode findQualifierNode(XMPNode parent, String qualName, boolean createNodes) throws XMPException { assert !qualName.startsWith("?"); XMPNode qualNode = parent.findQualifierByName(qualName); if (qualNode == null && createNodes) { qualNode = new XMPNode(qualName, null); qualNode.setImplicit(true); parent.addQualifier(qualNode); } return qualNode; } /** * @param arrayNode an array node * @param segment the segment containing the array index * @param createNodes flag if new nodes are allowed to be created. * @return Returns the index or index = -1 if not found * @throws XMPException Throws Exceptions */ private static int findIndexedItem(XMPNode arrayNode, String segment, boolean createNodes) throws XMPException { int index = 0; try { segment = segment.substring(1, segment.length() - 1); index = Integer.parseInt(segment); if (index < 1) { throw new XMPException("Array index must be larger than zero", XMPError.BADXPATH); } } catch (NumberFormatException e) { throw new XMPException("Array index not digits.", XMPError.BADXPATH); } if (createNodes && index == arrayNode.getChildrenLength() + 1) { // Append a new last + 1 node. XMPNode newItem = new XMPNode(ARRAY_ITEM_NAME, null); newItem.setImplicit(true); arrayNode.addChild(newItem); } return index; } /** * Searches for a field selector in a node: * [fieldName="value] - an element in an array of structs, chosen by a field value. * No implicit nodes are created by field selectors. * * @param arrayNode * @param fieldName * @param fieldValue * @return Returns the index of the field if found, otherwise -1. * @throws XMPException */ private static int lookupFieldSelector(XMPNode arrayNode, String fieldName, String fieldValue) throws XMPException { int result = -1; for (int index = 1; index <= arrayNode.getChildrenLength() && result < 0; index++) { XMPNode currItem = arrayNode.getChild(index); if (!currItem.getOptions().isStruct()) { throw new XMPException("Field selector must be used on array of struct", XMPError.BADXPATH); } for (int f = 1; f <= currItem.getChildrenLength(); f++) { XMPNode currField = currItem.getChild(f); if (!fieldName.equals(currField.getName())) { continue; } if (fieldValue.equals(currField.getValue())) { result = index; break; } } } return result; } /** * Searches for a qualifier selector in a node: * [?qualName="value"] - an element in an array, chosen by a qualifier value. * No implicit nodes are created for qualifier selectors, * except for an alias to an x-default item. * * @param arrayNode an array node * @param qualName the qualifier name * @param qualValue the qualifier value * @param aliasForm in case the qual selector results from an alias, * an x-default node is created if there has not been one. * @return Returns the index of th * @throws XMPException */ private static int lookupQualSelector(XMPNode arrayNode, String qualName, String qualValue, int aliasForm) throws XMPException { if (XML_LANG.equals(qualName)) { qualValue = Utils.normalizeLangValue(qualValue); int index = XMPNodeUtils.lookupLanguageItem(arrayNode, qualValue); if (index < 0 && (aliasForm & AliasOptions.PROP_ARRAY_ALT_TEXT) > 0) { XMPNode langNode = new XMPNode(ARRAY_ITEM_NAME, null); XMPNode xdefault = new XMPNode(XML_LANG, X_DEFAULT, null); langNode.addQualifier(xdefault); arrayNode.addChild(1, langNode); return 1; } else { return index; } } else { for (int index = 1; index < arrayNode.getChildrenLength(); index++) { XMPNode currItem = arrayNode.getChild(index); for (Iterator it = currItem.iterateQualifier(); it.hasNext();) { XMPNode qualifier = (XMPNode) it.next(); if (qualName.equals(qualifier.getName()) && qualValue.equals(qualifier.getValue())) { return index; } } } return -1; } } /** * Make sure the x-default item is first. Touch up "single value" * arrays that have a default plus one real language. This case should have * the same value for both items. Older Adobe apps were hardwired to only * use the "x-default" item, so we copy that value to the other * item. * * @param arrayNode * an alt text array node */ static void normalizeLangArray(XMPNode arrayNode) { if (!arrayNode.getOptions().isArrayAltText()) { return; } // check if node with x-default qual is first place for (int i = 2; i <= arrayNode.getChildrenLength(); i++) { XMPNode child = arrayNode.getChild(i); if (child.hasQualifier() && X_DEFAULT.equals(child.getQualifier(1).getValue())) { // move node to first place try { arrayNode.removeChild(i); arrayNode.addChild(1, child); } catch (XMPException e) { // cannot occur, because same child is removed before assert false; } if (i == 2) { arrayNode.getChild(2).setValue(child.getValue()); } break; } } } /** * See if an array is an alt-text array. If so, make sure the x-default item * is first. * * @param arrayNode * the array node to check if its an alt-text array */ static void detectAltText(XMPNode arrayNode) { if (arrayNode.getOptions().isArrayAlternate() && arrayNode.hasChildren()) { boolean isAltText = false; for (Iterator it = arrayNode.iterateChildren(); it.hasNext();) { XMPNode child = (XMPNode) it.next(); if (child.getOptions().getHasLanguage()) { isAltText = true; break; } } if (isAltText) { arrayNode.getOptions().setArrayAltText(true); normalizeLangArray(arrayNode); } } } /** * Appends a language item to an alt text array. * * @param arrayNode the language array * @param itemLang the language of the item * @param itemValue the content of the item * @throws XMPException Thrown if a duplicate property is added */ static void appendLangItem(XMPNode arrayNode, String itemLang, String itemValue) throws XMPException { XMPNode newItem = new XMPNode(ARRAY_ITEM_NAME, itemValue, null); XMPNode langQual = new XMPNode(XML_LANG, itemLang, null); newItem.addQualifier(langQual); if (!X_DEFAULT.equals(langQual.getValue())) { arrayNode.addChild(newItem); } else { arrayNode.addChild(1, newItem); } } /** * <ol> * <li>Look for an exact match with the specific language. * <li>If a generic language is given, look for partial matches. * <li>Look for an "x-default"-item. * <li>Choose the first item. * </ol> * * @param arrayNode * the alt text array node * @param genericLang * the generic language * @param specificLang * the specific language * @return Returns the kind of match as an Integer and the found node in an * array. * * @throws XMPException */ static Object[] chooseLocalizedText(XMPNode arrayNode, String genericLang, String specificLang) throws XMPException { // See if the array has the right form. Allow empty alt arrays, // that is what parsing returns. if (!arrayNode.getOptions().isArrayAltText()) { throw new XMPException("Localized text array is not alt-text", XMPError.BADXPATH); } else if (!arrayNode.hasChildren()) { return new Object[] { new Integer(XMPNodeUtils.CLT_NO_VALUES), null }; } int foundGenericMatches = 0; XMPNode resultNode = null; XMPNode xDefault = null; // Look for the first partial match with the generic language. for (Iterator it = arrayNode.iterateChildren(); it.hasNext();) { XMPNode currItem = (XMPNode) it.next(); // perform some checks on the current item if (currItem.getOptions().isCompositeProperty()) { throw new XMPException("Alt-text array item is not simple", XMPError.BADXPATH); } else if (!currItem.hasQualifier() || !XML_LANG.equals(currItem.getQualifier(1).getName())) { throw new XMPException("Alt-text array item has no language qualifier", XMPError.BADXPATH); } String currLang = currItem.getQualifier(1).getValue(); // Look for an exact match with the specific language. if (specificLang.equals(currLang)) { return new Object[] { new Integer(XMPNodeUtils.CLT_SPECIFIC_MATCH), currItem }; } else if (genericLang != null && currLang.startsWith(genericLang)) { if (resultNode == null) { resultNode = currItem; } // ! Don't return/break, need to look for other matches. foundGenericMatches++; } else if (X_DEFAULT.equals(currLang)) { xDefault = currItem; } } // evaluate loop if (foundGenericMatches == 1) { return new Object[] { new Integer(XMPNodeUtils.CLT_SINGLE_GENERIC), resultNode }; } else if (foundGenericMatches > 1) { return new Object[] { new Integer(XMPNodeUtils.CLT_MULTIPLE_GENERIC), resultNode }; } else if (xDefault != null) { return new Object[] { new Integer(XMPNodeUtils.CLT_XDEFAULT), xDefault }; } else { // Everything failed, choose the first item. return new Object[] { new Integer(XMPNodeUtils.CLT_FIRST_ITEM), arrayNode.getChild(1) }; } } /** * Looks for the appropriate language item in a text alternative array.item * * @param arrayNode * an array node * @param language * the requested language * @return Returns the index if the language has been found, -1 otherwise. * @throws XMPException */ static int lookupLanguageItem(XMPNode arrayNode, String language) throws XMPException { if (!arrayNode.getOptions().isArray()) { throw new XMPException("Language item must be used on array", XMPError.BADXPATH); } for (int index = 1; index <= arrayNode.getChildrenLength(); index++) { XMPNode child = arrayNode.getChild(index); if (!child.hasQualifier() || !XML_LANG.equals(child.getQualifier(1).getName())) { continue; } else if (language.equals(child.getQualifier(1).getValue())) { return index; } } return -1; } }
⏎ com/itextpdf/kernel/xmp/impl/XMPNodeUtils.java
Or download all of them as a single archive file:
File name: kernel-7.1.4-sources.jar File size: 1201221 bytes Release date: 2018-10-09 Download
⇐ Download and Install iText7-Core-7.1.4.zip
2010-02-18, 86325👍, 0💬
Popular Posts:
JDK 11 java.security.jgss.jmod is the JMOD file for JDK 11 Security JGSS (Java Generic Security Serv...
Java Servlet 3.0 Specification API. JAR File Size and Download Location: File name: servlet-api.jar,...
What Is jaxb-impl-2.1.12.jar? Java Architecture for XML Binding (JAXB) is a Java API that allows Jav...
Jackson is "the Java JSON library" or "the best JSON parser for Java". Or simply as "JSON for Java"....
Java Architecture for XML Binding (JAXB) is a Java API that allows Java developers to map Java class...