/* recursively (i) create new Parts for each thing listed in the relationships (ii) add the new Part to the package (iii) cross the PartName off unusedZipEntries */ private void addPartsFromRelationships(Base source, RelationshipsPart rp, ContentTypeManager ctm) throws Docx4JException { OpcPackage pkg = source.getPackage(); for (Relationship r : rp.getRelationships().getRelationship()) { log.debug( "\n For Relationship Id=" + r.getId() + " Source is " + rp.getSourceP().getPartName() + ", Target is " + r.getTarget() + ", type: " + r.getType()); // This is usually the first logged comment for // a part, so start with a line break. try { getPart(pkg, rp, r, ctm); } catch (Exception e) { throw new Docx4JException("Failed to add parts from relationships", e); } } }
protected static void removeDefinedCustomXmlParts( WordprocessingMLPackage wmlPackage, String xpathStorageItemId) { List<PartName> partsToRemove = new ArrayList<PartName>(); RelationshipsPart relationshipsPart = wmlPackage.getMainDocumentPart().getRelationshipsPart(); List<Relationship> relationshipsList = ((relationshipsPart != null) && (relationshipsPart.getRelationships() != null) ? relationshipsPart.getRelationships().getRelationship() : null); Part part = null; CustomXmlDataStoragePart dataPart = null; if (relationshipsList != null) { for (Relationship relationship : relationshipsList) { if (Namespaces.CUSTOM_XML_DATA_STORAGE.equals(relationship.getType())) { part = relationshipsPart.getPart(relationship); if (IsPartToRemove(part, xpathStorageItemId)) { partsToRemove.add(part.getPartName()); } } } } if (!partsToRemove.isEmpty()) { for (int i = 0; i < partsToRemove.size(); i++) { relationshipsPart.removePart(partsToRemove.get(i)); } } }
private OpcPackage process(HashMap<String, ByteArray> partByteArrays) throws Docx4JException { long startTime = System.currentTimeMillis(); // 2. Create a new Package // Eventually, you'll also be able to create an Excel package etc // but only the WordML package exists at present ContentTypeManager ctm = new ContentTypeManager(); try { InputStream is = getInputStreamFromZippedPart(partByteArrays, "[Content_Types].xml"); ctm.parseContentTypesFile(is); } catch (IOException e) { throw new Docx4JException("Couldn't get [Content_Types].xml from ZipFile", e); } catch (NullPointerException e) { throw new Docx4JException("Couldn't get [Content_Types].xml from ZipFile", e); } // .. now find the name of the main part String partName = "_rels/.rels"; RelationshipsPart rp = getRelationshipsPartFromZip(null, partByteArrays, partName); if (rp == null) { throw new Docx4JException("_rels/.rels appears to be missing from this package!"); } String mainPartName = PackageRelsUtil.getNameOfMainPart(rp); String pkgContentType = ctm.getContentType(new PartName("/" + mainPartName)); // 2. Create a new Package; this'll return the appropriate subclass OpcPackage p = ctm.createPackage(pkgContentType); log.info("Instantiated package of type " + p.getClass().getName()); p.setRelationships(rp); rp.setSourceP(p); // // 5. Now recursively // (i) create new Parts for each thing listed // in the relationships // (ii) add the new Part to the package // (iii) cross the PartName off unusedZipEntries addPartsFromRelationships(partByteArrays, p, rp, ctm); // 6. Check unusedZipEntries is empty // if (log.isDebugEnabled()) { // Iterator myVeryOwnIterator = unusedZipEntries.keySet().iterator(); // while(myVeryOwnIterator.hasNext()) { // String key = (String)myVeryOwnIterator.next(); // log.info( key + " " + unusedZipEntries.get(key)); // } // } registerCustomXmlDataStorageParts(p); long endTime = System.currentTimeMillis(); log.info("package read; elapsed time: " + Math.round((endTime - startTime)) + " ms"); return p; }
/** * Traverse the document, and return a map of all styles which are used directly in the document. * (IE this does not include styles on which others are just BasedOn). * * @return */ public Set<String> getStylesInUse() { org.docx4j.wml.Document wmlDocumentEl = (org.docx4j.wml.Document) this.getJaxbElement(); Body body = wmlDocumentEl.getBody(); List<Object> bodyChildren = body.getContent(); Set<String> stylesInUse = new HashSet<String>(); FontAndStyleFinder finder = new FontAndStyleFinder(null, null, stylesInUse); finder.defaultCharacterStyle = this.getStyleDefinitionsPart().getDefaultCharacterStyle(); finder.defaultParagraphStyle = this.getStyleDefinitionsPart().getDefaultParagraphStyle(); new TraversalUtil(bodyChildren, finder); finder.finish(); // Styles in headers, footers? RelationshipsPart rp = this.getRelationshipsPart(); if (rp != null) { for (Relationship r : rp.getRelationships().getRelationship()) { Part part = rp.getPart(r); if (part instanceof FooterPart) { Ftr ftr = ((FooterPart) part).getJaxbElement(); finder.walkJAXBElements(ftr); } else if (part instanceof HeaderPart) { Hdr hdr = ((HeaderPart) part).getJaxbElement(); finder.walkJAXBElements(hdr); } } } // Styles in endnotes, footnotes? if (this.getEndNotesPart() != null) { log.debug("Looking at endnotes"); CTEndnotes endnotes = this.getEndNotesPart().getJaxbElement(); finder.walkJAXBElements(endnotes); } if (this.getFootnotesPart() != null) { log.debug("Looking at footnotes"); CTFootnotes footnotes = this.getFootnotesPart().getJaxbElement(); finder.walkJAXBElements(footnotes); } // Comments if (this.getCommentsPart() != null) { log.debug("Looking at comments"); Comments comments = this.getCommentsPart().getJaxbElement(); finder.walkJAXBElements(comments); } return stylesInUse; }
/** * Create an image part from the provided byte array, attach it to the source part (eg the main * document part, a header part etc), and return it. * * <p>Works for both docx and pptx. * * <p>Knowing the MIME type allows you to avoid ImageInfo, but you'll probably also need to know * the image dimensions * * @param opcPackage * @param sourcePart * @param bytes * @param mime MIME type eg image/png * @return * @throws Exception @Since 3.0.1 */ public static BinaryPartAbstractImage createImagePart( OpcPackage opcPackage, Part sourcePart, byte[] bytes, String mime) throws Exception { String ext = mimeToExt(mime); if (mime == null || ext == null) { log.warn("Null or unknown mime type; image introspection required!"); return createImagePart(opcPackage, sourcePart, bytes); } ContentTypeManager ctm = opcPackage.getContentTypeManager(); // Ensure the relationships part exists if (sourcePart.getRelationshipsPart() == null) { RelationshipsPart.createRelationshipsPartForPart(sourcePart); } String proposedRelId = sourcePart.getRelationshipsPart().getNextId(); BinaryPartAbstractImage imagePart = (BinaryPartAbstractImage) ctm.newPartForContentType( mime, createImageName(opcPackage, sourcePart, proposedRelId, ext), null); log.debug( "created part " + imagePart.getClass().getName() + " with name " + imagePart.getPartName().toString()); imagePart.setBinaryData(bytes); imagePart.rels.add(sourcePart.addTargetPart(imagePart, proposedRelId)); return imagePart; }
// private void addPartsFromRelationships(ZipFile zf, Base source, RelationshipsPart rp) private void addPartsFromRelationships( HashMap<String, ByteArray> partByteArrays, Base source, RelationshipsPart rp, ContentTypeManager ctm) throws Docx4JException { OpcPackage pkg = source.getPackage(); // for (Iterator it = rp.iterator(); it.hasNext(); ) { // Relationship r = (Relationship)it.next(); // log.info("For Relationship Id=" + r.getId() + " Source is " // + r.getSource().getPartName() // + ", Target is " + r.getTargetURI() ); // try { // // getPart(zf, pkg, rp, r); // // } catch (Exception e) { // throw new Docx4JException("Failed to add parts from relationships", e); // } // } for (Relationship r : rp.getRelationships().getRelationship()) { log.debug( "\n For Relationship Id=" + r.getId() + " Source is " + rp.getSourceP().getPartName() + ", Target is " + r.getTarget() + ", type: " + r.getType()); // This is usually the first logged comment for // a part, so start with a line break. try { getPart(partByteArrays, pkg, rp, r, ctm); } catch (Exception e) { throw new Docx4JException("Failed to add parts from relationships", e); } } }
protected static Set<ContentAccessor> getParts(WordprocessingMLPackage srcPackage) { Set<ContentAccessor> partList = new HashSet<ContentAccessor>(); partList.add(srcPackage.getMainDocumentPart()); // Add headers/footers RelationshipsPart rp = srcPackage.getMainDocumentPart().getRelationshipsPart(); for (Relationship r : rp.getRelationships().getRelationship()) { if (r.getType().equals(Namespaces.HEADER)) { partList.add((HeaderPart) rp.getPart(r)); } else if (r.getType().equals(Namespaces.FOOTER)) { partList.add((FooterPart) rp.getPart(r)); } } return partList; }
private RelationshipsPart getRelationshipsPartFromZip(Base p, ZipFile zf, String partName) throws Docx4JException { // Document contents = null; // try { // contents = getDocumentFromZippedPart( zf, partName); // } catch (Exception e) { // e.printStackTrace(); // throw new Docx4JException("Error getting document from Zipped Part", e); // // } // // debugPrint(contents); // // TODO - why don't any of the part names in this document start with "/"? // return new RelationshipsPart( p, new PartName("/" + partName), contents ); RelationshipsPart rp = null; InputStream is = null; try { is = getInputStreamFromZippedPart(zf, partName); // thePart = new RelationshipsPart( p, new PartName("/" + partName), is ); rp = new RelationshipsPart(new PartName("/" + partName)); rp.setSourceP(p); rp.unmarshal(is); } catch (Exception e) { e.printStackTrace(); throw new Docx4JException("Error getting document from Zipped Part:" + partName, e); } finally { if (is != null) { try { is.close(); } catch (IOException exc) { exc.printStackTrace(); } } } return rp; // debugPrint(contents); // TODO - why don't any of the part names in this document start with "/"? }
/** * @param out * @param resolvedPartUri * @param part * @throws Docx4JException * @throws IOException */ public void savePart(ZipOutputStream out, Part part) throws Docx4JException, IOException { // Drop the leading '/' String resolvedPartUri = part.getPartName().getName().substring(1); if (handled.get(resolvedPartUri) != null) { log.debug(".. duplicate save avoided .."); return; } if (part instanceof BinaryPart) { log.debug(".. saving binary stuff"); saveRawBinaryPart(out, part); } else { log.debug(".. saving "); saveRawXmlPart(out, part); } handled.put(resolvedPartUri, resolvedPartUri); // recurse via this parts relationships, if it has any RelationshipsPart rrp = part.getRelationshipsPart(false); // don't create if (rrp != null) { // log.debug("Found relationships " + rrp.getPartName() ); // Only save it if it actually has rels in it if (rrp.getRelationships().getRelationship().size() > 0) { String relPart = PartName.getRelationshipsPartName(resolvedPartUri); // log.debug("Cf constructed name " + relPart ); saveRawXmlPart(out, rrp, relPart); addPartsFromRelationships(out, rrp); } } // else { // log.debug("No relationships for " + resolvedPartUri ); // } }
protected static boolean IsPartToRemove(Part part, String xpathStorageItemId) { boolean ret = false; RelationshipsPart relationshipsPart = part.getRelationshipsPart(); List<Relationship> relationshipsList = ((relationshipsPart != null) && (relationshipsPart.getRelationships() != null) ? relationshipsPart.getRelationships().getRelationship() : null); CustomXmlDataStoragePropertiesPart propertiesPart = null; DatastoreItem datastoreItem = null; if ((relationshipsList != null) && (!relationshipsList.isEmpty())) { for (Relationship relationship : relationshipsList) { if (Namespaces.CUSTOM_XML_DATA_STORAGE_PROPERTIES.equals(relationship.getType())) { propertiesPart = (CustomXmlDataStoragePropertiesPart) relationshipsPart.getPart(relationship); break; } } } if (propertiesPart != null) { datastoreItem = propertiesPart.getJaxbElement(); } if (datastoreItem != null) { if ((datastoreItem.getItemID() != null) && (datastoreItem.getItemID().length() > 0)) { ret = datastoreItem.getItemID().equals(xpathStorageItemId); } if ((!ret) && (datastoreItem.getSchemaRefs() != null) && (datastoreItem.getSchemaRefs().getSchemaRef() != null) && (!datastoreItem.getSchemaRefs().getSchemaRef().isEmpty())) { for (SchemaRef ref : datastoreItem.getSchemaRefs().getSchemaRef()) { if (PART_TO_REMOVE_SCHEMA_TYPES.contains(ref.getUri())) { ret = true; break; } } } } return ret; }
private RelationshipsPart getRelationshipsPartFromZip(Base p, String partName) throws Docx4JException { RelationshipsPart rp = null; InputStream is = null; try { is = partStore.loadPart(partName); if (is == null) { return null; // that's ok } rp = new RelationshipsPart(new PartName("/" + partName)); rp.setSourceP(p); rp.unmarshal(is); } catch (Exception e) { e.printStackTrace(); throw new Docx4JException("Error getting document from Zipped Part:" + partName, e); } finally { IOUtils.closeQuietly(is); } return rp; }
private PartName getNewPartName(String prefix, String suffix, RelationshipsPart rp) throws InvalidFormatException { PartName proposed = null; int i = 1; do { if (i > 1) { proposed = new PartName(prefix + i + suffix); } else { proposed = new PartName(prefix + suffix); } i++; } while (rp.getRel(proposed) != null); return proposed; }
public static void visit( WordprocessingMLPackage wmlPackage, boolean bodyOnly, Callback callback) { MainDocumentPart mainDocument = null; RelationshipsPart relPart = null; List<Relationship> relList = null; List<Object> elementList = null; if ((wmlPackage != null) && (callback != null)) { mainDocument = wmlPackage.getMainDocumentPart(); callback.walkJAXBElements(mainDocument.getJaxbElement().getBody()); if (!bodyOnly) { relPart = mainDocument.getRelationshipsPart(); relList = relPart.getRelationships().getRelationship(); for (Relationship rs : relList) { elementList = null; if (Namespaces.HEADER.equals(rs.getType())) { elementList = ((HeaderPart) relPart.getPart(rs)).getJaxbElement().getContent(); } else if (Namespaces.FOOTER.equals(rs.getType())) { elementList = ((FooterPart) relPart.getPart(rs)).getJaxbElement().getContent(); } else if (Namespaces.ENDNOTES.equals(rs.getType())) { // elementList = ((EndnotesPart) relPart.getPart(rs)).getContent(); elementList = new ArrayList(); elementList.addAll(((EndnotesPart) relPart.getPart(rs)).getJaxbElement().getEndnote()); } else if (Namespaces.FOOTNOTES.equals(rs.getType())) { // elementList = ((FootnotesPart) relPart.getPart(rs)).getContent(); elementList = new ArrayList(); elementList.addAll( ((FootnotesPart) relPart.getPart(rs)).getJaxbElement().getFootnote()); } else if (Namespaces.COMMENTS.equals(rs.getType())) { elementList = new ArrayList(); for (Comment comment : ((CommentsPart) relPart.getPart(rs)).getJaxbElement().getComment()) { elementList.addAll(comment.getEGBlockLevelElts()); } } if ((elementList != null) && (!elementList.isEmpty())) { log.debug("Processing target: " + rs.getTarget() + ", type: " + rs.getType()); callback.walkJAXBElements(elementList); } } } } }
/** * Create an image part from the provided filePath image, attach it to the source part (eg the * main document part, a header part etc), and return it. * * <p>Works for both docx and pptx. * * @param opcPackage * @param sourcePart * @param filePath * @return * @throws Exception */ public static BinaryPartAbstractImage createImagePart( OpcPackage opcPackage, Part sourcePart, File imageFile) throws Exception { final byte[] locByte = new byte[1]; // We are in the case that image is not load (no byte Array) so isLoad is false ImageInfo info = ensureFormatIsSupported(imageFile, locByte, false); ContentTypeManager ctm = opcPackage.getContentTypeManager(); // Ensure the relationships part exists if (sourcePart.getRelationshipsPart() == null) { RelationshipsPart.createRelationshipsPartForPart(sourcePart); } String proposedRelId = sourcePart.getRelationshipsPart().getNextId(); String ext = info.getMimeType().substring(info.getMimeType().indexOf("/") + 1); BinaryPartAbstractImage imagePart = (BinaryPartAbstractImage) ctm.newPartForContentType( info.getMimeType(), createImageName(opcPackage, sourcePart, proposedRelId, ext), null); log.debug( "created part " + imagePart.getClass().getName() + " with name " + imagePart.getPartName().toString()); FileInputStream fis = new FileInputStream(imageFile); imagePart.setBinaryData(fis); imagePart.rels.add(sourcePart.addTargetPart(imagePart, proposedRelId)); imagePart.setImageInfo(info); return imagePart; }
/** * Create an image part from the provided byte array, attach it to the source part (eg the main * document part, a header part etc), and return it. * * <p>Works for both docx and pptx. * * <p>Note: this method creates a temp file (and attempts to delete it). That's because it uses * org.apache.xmlgraphics * * @param opcPackage * @param sourcePart * @param bytes * @return * @throws Exception */ public static BinaryPartAbstractImage createImagePart( OpcPackage opcPackage, Part sourcePart, byte[] bytes) throws Exception { // Whatever image type this is, we're going to need // to know its dimensions. // For that we use ImageInfo, which can only // load an image from a URI. // So first, write the bytes to a temp file File tmpImageFile = File.createTempFile("img", ".img"); FileOutputStream fos = new FileOutputStream(tmpImageFile); fos.write(bytes); fos.close(); log.debug("created tmp file: " + tmpImageFile.getAbsolutePath()); ImageInfo info = ensureFormatIsSupported(tmpImageFile, bytes, true); // In the absence of an exception, tmpImageFile now contains an image // Word will accept ContentTypeManager ctm = opcPackage.getContentTypeManager(); // Ensure the relationships part exists if (sourcePart.getRelationshipsPart() == null) { RelationshipsPart.createRelationshipsPartForPart(sourcePart); } String proposedRelId = sourcePart.getRelationshipsPart().getNextId(); String ext = info.getMimeType().substring(info.getMimeType().indexOf("/") + 1); // System.out.println(ext); BinaryPartAbstractImage imagePart = (BinaryPartAbstractImage) ctm.newPartForContentType( info.getMimeType(), createImageName(opcPackage, sourcePart, proposedRelId, ext), null); log.debug( "created part " + imagePart.getClass().getName() + " with name " + imagePart.getPartName().toString()); FileInputStream fis = new FileInputStream(tmpImageFile); imagePart.setBinaryData(fis); imagePart.rels.add(sourcePart.addTargetPart(imagePart, proposedRelId)); imagePart.setImageInfo(info); // Delete the tmp file // As per http://stackoverflow.com/questions/991489/i-cant-delete-a-file-in-java // the following 3 lines are necessary, at least on Win 7 x64 // Also reported on Win XP, but in my testing, the files were deleting OK anyway. fos = null; fis = null; if (Docx4jProperties.getProperty( "docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage.TempFiles.ForceGC", true)) { System.gc(); } if (tmpImageFile.delete()) { log.debug(".. deleted " + tmpImageFile.getAbsolutePath()); } else { log.warn("Couldn't delete tmp file " + tmpImageFile.getAbsolutePath()); tmpImageFile.deleteOnExit(); // If that doesn't work, see "Clean Up Your Mess: Managing Temp Files in Java Apps" // at devx.com } return imagePart; }
/** * Get a Part (except a relationships part), and all its related parts. This can be called * directly from outside the library, in which case the Part will not be owned by a Package until * the calling code makes it so. * * @param zf * @param source * @param unusedZipEntries * @param pkg * @param r * @param resolvedPartUri * @throws Docx4JException * @throws InvalidFormatException */ private void getPart(OpcPackage pkg, RelationshipsPart rp, Relationship r, ContentTypeManager ctm) throws Docx4JException, InvalidFormatException, URISyntaxException { Base source = null; String resolvedPartUri = null; if (r.getType().equals(Namespaces.HYPERLINK)) { // Could be Internal or External // Example of Internal is w:drawing/wp:inline/wp:docPr/a:hlinkClick log.info("Encountered (but not loading) hyperlink " + r.getTarget()); return; } else if (r.getTargetMode() == null || !r.getTargetMode().equals("External")) { // Usual case source = rp.getSourceP(); resolvedPartUri = URIHelper.resolvePartUri(rp.getSourceURI(), new URI(r.getTarget())).toString(); // Now drop leading "/' resolvedPartUri = resolvedPartUri.substring(1); // Now normalise it .. ie abc/def/../ghi // becomes abc/ghi // Maybe this isn't necessary with a zip file, // - ZipFile class may be smart enough to do it. // But it is certainly necessary in the JCR case. // resolvedPartUri = (new java.net.URI(resolvedPartUri)).normalize().toString(); // log.info("Normalised, it is " + resolvedPartUri ); } else { // EXTERNAL if (loadExternalTargets && r.getType().equals(Namespaces.IMAGE)) { // It could instead be, for example, of type hyperlink, // and we don't want to try to fetch that log.info("Loading external resource " + r.getTarget() + " of type " + r.getType()); BinaryPart bp = ExternalResourceUtils.getExternalResource(r.getTarget()); pkg.getExternalResources().put(bp.getExternalTarget(), bp); } else { log.info( "Encountered (but not loading) external resource " + r.getTarget() + " of type " + r.getType()); } return; } String relationshipType = r.getType(); Part part; if (pkg.handled.get(resolvedPartUri) != null) { // The source Part (or Package) might have a convenience // method for this part = pkg.getParts().getParts().get(new PartName("/" + resolvedPartUri)); if (source.setPartShortcut(part, relationshipType)) { log.debug( "Convenience method established from " + source.getPartName() + " to " + part.getPartName()); } return; } part = getRawPart(ctm, resolvedPartUri, r); // will throw exception if null // The source Part (or Package) might have a convenience // method for this if (source.setPartShortcut(part, relationshipType)) { log.debug( "Convenience method established from " + source.getPartName() + " to " + part.getPartName()); } if (part instanceof BinaryPart || part instanceof DefaultXmlPart) { // The constructors of other parts should take care of this... part.setRelationshipType(relationshipType); } rp.loadPart(part, r); pkg.handled.put(resolvedPartUri, resolvedPartUri); // unusedZipEntries.put(resolvedPartUri, new Boolean(false)); RelationshipsPart rrp = getRelationshipsPart(part); if (rrp != null) { // recurse via this parts relationships, if it has any addPartsFromRelationships(part, rrp, ctm); String relPart = PartName.getRelationshipsPartName(part.getPartName().getName().substring(1)); // unusedZipEntries.put(relPart, new Boolean(false)); } }
/* recursively (i) get each Part listed in the relationships (ii) add the Part to the zip file (iii) traverse its relationship */ public void addPartsFromRelationships(ZipOutputStream out, RelationshipsPart rp) throws Docx4JException { // for (Iterator it = rp.iterator(); it.hasNext(); ) { // Relationship r = (Relationship)it.next(); // log.info("For Relationship Id=" + r.getId() + " Source is " + r.getSource().getPartName() + // ", Target is " + r.getTargetURI() ); for (Relationship r : rp.getRelationships().getRelationship()) { log.debug( "For Relationship Id=" + r.getId() + " Source is " + rp.getSourceP().getPartName() + ", Target is " + r.getTarget()); if (r.getType().equals(Namespaces.HYPERLINK)) { continue; // whether internal or external } if (r.getTargetMode() != null && r.getTargetMode().equals("External")) { // ie its EXTERNAL // As at 1 May 2008, we don't have a Part for these; // there is just the relationship. log.warn("Encountered external resource " + r.getTarget() + " of type " + r.getType()); // So continue; } try { // String resolvedPartUri = URIHelper.resolvePartUri(r.getSourceURI(), r.getTargetURI() // ).toString(); String resolvedPartUri = URIHelper.resolvePartUri(rp.getSourceURI(), new URI(r.getTarget())).toString(); // Now drop leading "/' resolvedPartUri = resolvedPartUri.substring(1); // Now normalise it .. ie abc/def/../ghi // becomes abc/ghi // Maybe this isn't necessary with a zip file, // - ZipFile class may be smart enough to do it. // But it is certainly necessary in the JCR case. // target = (new java.net.URI(target)).normalize().toString(); // log.info("Normalised, it is " + target ); // Document contents = getDocumentFromZippedPart( zf, target); if (!false) { log.debug("Getting part /" + resolvedPartUri); // Part part = p.getParts().get(new PartName("/" + resolvedPartUri)); Part part = rp.getPart(r); // 2012 09 26: If the part is actually attached to // a different package, using this you can still get it. // Use this 'feature' at your own risk! if (part == null) { log.error("Part " + resolvedPartUri + " not found!"); } else { log.debug(part.getClass().getName()); } if (!part.getPackage().equals(p)) { log.warn("Part " + resolvedPartUri + " is attached to some other package"); } savePart(out, part); } } catch (Exception e) { throw new Docx4JException( "Failed to add parts from relationships of " + rp.getSourceP().getPartName(), e); } } }
public OpcPackage get() throws Docx4JException { long startTime = System.currentTimeMillis(); // 1. Get [Content_Types].xml ContentTypeManager ctm = new ContentTypeManager(); InputStream is = null; try { is = partStore.loadPart("[Content_Types].xml"); ctm.parseContentTypesFile(is); } catch (Docx4JException e) { throw new Docx4JException("Couldn't get [Content_Types].xml from ZipFile", e); } catch (NullPointerException e) { throw new Docx4JException("Couldn't get [Content_Types].xml from ZipFile", e); } finally { IOUtils.closeQuietly(is); } // .. now find the name of the main part String partName = "_rels/.rels"; RelationshipsPart rp = getRelationshipsPartFromZip(null, partName); if (rp == null) { throw new Docx4JException("_rels/.rels appears to be missing from this package!"); } String mainPartName = PackageRelsUtil.getNameOfMainPart(rp); PartName mainPartNameObj; if (mainPartName.startsWith("/")) { // OpenXML SDK 2.0 writes Target="/word/document.xml" (note leading "/") mainPartNameObj = new PartName(mainPartName); } else { // Microsoft Word, docx4j etc write Target="word/document.xml" mainPartNameObj = new PartName("/" + mainPartName); } String pkgContentType = ctm.getContentType(mainPartNameObj); // 2. Create a new Package; this'll return the appropriate subclass OpcPackage p = ctm.createPackage(pkgContentType); log.info("Instantiated package of type " + p.getClass().getName()); p.setPartStore(partStore); p.setRelationships(rp); rp.setSourceP(p); // // 5. Now recursively // (i) create new Parts for each thing listed // in the relationships // (ii) add the new Part to the package // (iii) cross the PartName off unusedZipEntries addPartsFromRelationships(p, rp, ctm); // 6. registerCustomXmlDataStorageParts(p); // partStore.finishLoad(); long endTime = System.currentTimeMillis(); log.info("package read; elapsed time: " + Math.round((endTime - startTime)) + " ms"); return p; }
/** * Traverse the document, looking for fonts which have been applied, either directly, or via a * style. * * @return */ public Set<String> fontsInUse() { log.info("fontsInUse.."); getPropertyResolver(); // this inits our virtual DocDefaults style // Setup Set<String> fontsDiscovered = new java.util.HashSet<String>(); // // Keep track of styles we encounter, so we can // // inspect these for fonts // Set<String> stylesInUse = new java.util.HashSet<String>(); // // org.docx4j.wml.Styles styles = null; // if (this.getStyleDefinitionsPart()!=null) { // styles = (org.docx4j.wml.Styles)this.getStyleDefinitionsPart().getJaxbElement(); // } // // It is convenient to have a HashMap of styles // Map<String, Style> stylesDefined = new java.util.HashMap<String, Style>(); // if (styles!=null) { // for (Iterator<Style> iter = styles.getStyle().iterator(); iter.hasNext();) { // Style s = iter.next(); // stylesDefined.put(s.getStyleId(), s); // } // } // // We need to know what fonts and styles are used in the document org.docx4j.wml.Document wmlDocumentEl = (org.docx4j.wml.Document) this.getJaxbElement(); Body body = wmlDocumentEl.getBody(); List<Object> bodyChildren = body.getContent(); FontDiscoveryCharacterVisitor visitor = new FontDiscoveryCharacterVisitor(fontsDiscovered); RunFontSelector runFontSelector = new RunFontSelector( (WordprocessingMLPackage) this.pack, visitor, RunFontActionType.DISCOVERY); FontAndStyleFinder finder = new FontAndStyleFinder(runFontSelector, fontsDiscovered, null); finder.defaultCharacterStyle = this.getStyleDefinitionsPart().getDefaultCharacterStyle(); finder.defaultParagraphStyle = this.getStyleDefinitionsPart().getDefaultParagraphStyle(); new TraversalUtil(bodyChildren, finder); // finder.finish(); fontsDiscovered.add(runFontSelector.getDefaultFont()); // fonts in headers, footers? RelationshipsPart rp = this.getRelationshipsPart(); if (rp != null) { for (Relationship r : rp.getRelationships().getRelationship()) { Part part = rp.getPart(r); if (part instanceof FooterPart) { Ftr ftr = ((FooterPart) part).getJaxbElement(); finder.walkJAXBElements(ftr); } else if (part instanceof HeaderPart) { Hdr hdr = ((HeaderPart) part).getJaxbElement(); finder.walkJAXBElements(hdr); } } } // Styles in endnotes, footnotes? if (this.getEndNotesPart() != null) { log.debug("Looking at endnotes"); CTEndnotes endnotes = this.getEndNotesPart().getJaxbElement(); finder.walkJAXBElements(endnotes); } if (this.getFootnotesPart() != null) { log.debug("Looking at footnotes"); CTFootnotes footnotes = this.getFootnotesPart().getJaxbElement(); finder.walkJAXBElements(footnotes); } // Comments if (this.getCommentsPart() != null) { log.debug("Looking at comments"); Comments comments = this.getCommentsPart().getJaxbElement(); finder.walkJAXBElements(comments); } // Add fonts used in the styles we discovered // .. 2013 03 10: no longer necessary // Fonts can also be used in the numbering part // For now, treat any font mentioned in that part as in use. // Ideally, we'd only register fonts used in numbering levels // that were actually used in the document if (getNumberingDefinitionsPart() != null) { Numbering numbering = getNumberingDefinitionsPart().getJaxbElement(); for (Numbering.AbstractNum abstractNumNode : numbering.getAbstractNum()) { for (Lvl lvl : abstractNumNode.getLvl()) { if (lvl.getRPr() != null && lvl.getRPr().getRFonts() != null) { String fontName = lvl.getRPr().getRFonts().getAscii(); if (fontName != null) { fontsDiscovered.add(fontName); log.debug( "Registered " + fontName + " for abstract list " + abstractNumNode.getAbstractNumId() + " lvl " + lvl.getIlvl()); } } } } } return fontsDiscovered; }