Beispiel #1
0
  /* 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;
  }
Beispiel #8
0
  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 "/"?
  }
Beispiel #9
0
  /**
   * @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;
  }
Beispiel #11
0
  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;
  }
Beispiel #13
0
  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;
  }
Beispiel #16
0
  /**
   * 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));
    }
  }
Beispiel #17
0
  /* 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);
      }
    }
  }
Beispiel #18
0
  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;
  }
Beispiel #19
0
  /**
   * 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;
  }