/**
   * Convenience method, given a Graphic in a document, to get the byte[] representing the
   * associated image
   *
   * @param wmlPkg
   * @param graphic
   * @return
   */
  public static byte[] getImage(WordprocessingMLPackage wmlPkg, org.docx4j.dml.Graphic graphic) {

    if (wmlPkg == null
        || wmlPkg.getMainDocumentPart() == null
        || wmlPkg.getMainDocumentPart().getRelationshipsPart() == null) {
      return null;
    }

    Pic pic = graphic.getGraphicData().getPic();
    String rId = pic.getBlipFill().getBlip().getEmbed();
    if (rId.equals("")) {
      rId = pic.getBlipFill().getBlip().getLink();
    }
    log.debug("Image rel id: " + rId);
    org.docx4j.relationships.Relationship rel =
        wmlPkg.getMainDocumentPart().getRelationshipsPart().getRelationshipByID(rId);
    if (rel != null) {
      org.docx4j.openpackaging.parts.Part part =
          wmlPkg.getMainDocumentPart().getRelationshipsPart().getPart(rel);
      if (part == null) {
        log.error("Couldn't get Part!");
      } else if (part instanceof BinaryPart) {
        log.debug("getting bytes...");
        return ((BinaryPart) part).getBytes();
      } else {
        log.error("Part was a " + part.getClass().getName());
      }
    } else {
      log.error("Couldn't find rel " + rId);
    }

    return null;
  }
Example #2
0
  /**
   * Get a Part (except a relationships part), but not its relationships part or related parts.
   * Useful if you need quick access to just this part. 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.
   *
   * @see To get a Part and all its related parts, and add all to a package, use getPart.
   * @param partByteArrays
   * @param ctm
   * @param resolvedPartUri
   * @param rel
   * @return
   * @throws Docx4JException including if result is null
   */
  public Part getRawPart(ContentTypeManager ctm, String resolvedPartUri, Relationship rel)
      throws Docx4JException {

    Part part = null;

    InputStream is = null;
    try {
      try {
        log.debug("resolved uri: " + resolvedPartUri);

        // Get a subclass of Part appropriate for this content type
        // This will throw UnrecognisedPartException in the absence of
        // specific knowledge. Hence it is important to get the is
        // first, as we do above.
        part = ctm.getPart("/" + resolvedPartUri, rel);

        log.info("ctm returned " + part.getClass().getName());

        if (part instanceof org.docx4j.openpackaging.parts.ThemePart
            || part instanceof org.docx4j.openpackaging.parts.DocPropsCorePart
            || part instanceof org.docx4j.openpackaging.parts.DocPropsCustomPart
            || part instanceof org.docx4j.openpackaging.parts.DocPropsExtendedPart
            || part instanceof org.docx4j.openpackaging.parts.CustomXmlDataStoragePropertiesPart
            || part instanceof org.docx4j.openpackaging.parts.digitalsignature.XmlSignaturePart
            || part instanceof org.docx4j.openpackaging.parts.JaxbXmlPart) {

          // Nothing to do here

        } else if (part instanceof org.docx4j.openpackaging.parts.WordprocessingML.BinaryPart) {

          log.debug("Detected BinaryPart " + part.getClass().getName());
          //					is = partStore.loadPart( resolvedPartUri);
          //					((BinaryPart)part).setBinaryData(is);

        } else if (part instanceof org.docx4j.openpackaging.parts.CustomXmlDataStoragePart) {
          // ContentTypeManager initially detects them as CustomXmlDataStoragePart;
          // the below changes as necessary

          // Is it a part we know?
          is = partStore.loadPart(resolvedPartUri);
          try {
            Unmarshaller u = Context.jc.createUnmarshaller();
            Object o = u.unmarshal(is);
            log.debug(o.getClass().getName());

            PartName name = part.getPartName();
            if (o instanceof CoverPageProperties) {

              part = new DocPropsCoverPagePart(name);
              ((DocPropsCoverPagePart) part).setJaxbElement((CoverPageProperties) o);

            } else if (o instanceof org.opendope.conditions.Conditions) {

              part = new ConditionsPart(name);
              ((ConditionsPart) part).setJaxbElement((org.opendope.conditions.Conditions) o);

            } else if (o instanceof org.opendope.xpaths.Xpaths) {

              part = new XPathsPart(name);
              ((XPathsPart) part).setJaxbElement((org.opendope.xpaths.Xpaths) o);

            } else if (o instanceof org.opendope.questions.Questionnaire) {

              part = new QuestionsPart(name);
              ((QuestionsPart) part).setJaxbElement((org.opendope.questions.Questionnaire) o);

            } else if (o instanceof org.opendope.answers.Answers) {

              part = new StandardisedAnswersPart(name);
              ((StandardisedAnswersPart) part).setJaxbElement((org.opendope.answers.Answers) o);

            } else if (o instanceof org.opendope.components.Components) {

              part = new ComponentsPart(name);
              ((ComponentsPart) part).setJaxbElement((org.opendope.components.Components) o);

            } else if (o instanceof JAXBElement<?>
                && XmlUtils.unwrap(o) instanceof org.docx4j.bibliography.CTSources) {
              part = new BibliographyPart(name);
              ((BibliographyPart) part)
                  .setJaxbElement((JAXBElement<org.docx4j.bibliography.CTSources>) o);

            } else {

              log.error("TODO: handle known CustomXmlPart part  " + o.getClass().getName());

              CustomXmlDataStorage data = getCustomXmlDataStorageClass().factory();
              is.reset();
              data.setDocument(is); // Not necessarily JAXB, that's just our method name
              ((org.docx4j.openpackaging.parts.CustomXmlDataStoragePart) part).setData(data);
            }

          } catch (javax.xml.bind.UnmarshalException ue) {

            log.warn("No JAXB model for this CustomXmlDataStorage part; " + ue.getMessage());

            CustomXmlDataStorage data = getCustomXmlDataStorageClass().factory();
            is.reset();
            data.setDocument(is); // Not necessarily JAXB, that's just our method name
            ((org.docx4j.openpackaging.parts.CustomXmlDataStoragePart) part).setData(data);
          }

        } else if (part instanceof org.docx4j.openpackaging.parts.XmlPart) {

          is = partStore.loadPart(resolvedPartUri);

          //					try {
          ((XmlPart) part).setDocument(is);

          // Experimental 22/6/2011; don't fall back to binary (which we used to)

          //					} catch (Docx4JException d) {
          //						// This isn't an XML part after all,
          //						// even though ContentTypeManager detected it as such
          //						// So get it as a binary part
          //						part = getBinaryPart(partByteArrays, ctm, resolvedPartUri);
          //						log.warn("Could not parse as XML, so using BinaryPart for "
          //								+ resolvedPartUri);
          //						((BinaryPart)part).setBinaryData(is);
          //					}

        } else {
          // Shouldn't happen, since ContentTypeManagerImpl should
          // return an instance of one of the above, or throw an
          // Exception.

          log.error("No suitable part found for: " + resolvedPartUri);
          part = null;
        }

      } catch (PartUnrecognisedException e) {
        log.error("PartUnrecognisedException shouldn't happen anymore!", e);
        // Try to get it as a binary part
        part = getBinaryPart(ctm, resolvedPartUri);
        log.warn("Using BinaryPart for " + resolvedPartUri);

        //				is = partStore.loadPart( resolvedPartUri);
        //				((BinaryPart)part).setBinaryData(is);
      }
    } catch (Exception ex) {
      // IOException, URISyntaxException
      ex.printStackTrace();
      throw new Docx4JException("Failed to getPart", ex);

    } finally {
      IOUtils.closeQuietly(is);
    }

    if (part == null) {
      throw new Docx4JException(
          "cannot find part "
              + resolvedPartUri
              + " from rel "
              + rel.getId()
              + "="
              + rel.getTarget());
    }

    return part;
  }
Example #3
0
  /**
   * Get a Part (except a relationships part), but not its relationships part or related parts.
   * Useful if you need quick access to just this part. 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.
   *
   * @see To get a Part and all its related parts, and add all to a package, use getPart.
   * @param zf
   * @param resolvedPartUri
   * @return
   * @throws URISyntaxException
   * @throws InvalidFormatException
   */
  public static Part getRawPart(
      ZipFile zf, ContentTypeManager ctm, String resolvedPartUri, Relationship rel)
      throws Docx4JException {
    Part part = null;

    InputStream is = null;
    try {
      try {
        log.debug("resolved uri: " + resolvedPartUri);
        is = getInputStreamFromZippedPart(zf, resolvedPartUri);

        // Get a subclass of Part appropriate for this content type
        // This will throw UnrecognisedPartException in the absence of
        // specific knowledge. Hence it is important to get the is
        // first, as we do above.
        part = ctm.getPart("/" + resolvedPartUri, rel);

        if (part instanceof org.docx4j.openpackaging.parts.ThemePart) {

          ((org.docx4j.openpackaging.parts.JaxbXmlPart) part).setJAXBContext(Context.jcThemePart);
          ((org.docx4j.openpackaging.parts.JaxbXmlPart) part).unmarshal(is);

        } else if (part instanceof org.docx4j.openpackaging.parts.DocPropsCorePart) {

          ((org.docx4j.openpackaging.parts.JaxbXmlPart) part)
              .setJAXBContext(Context.jcDocPropsCore);
          ((org.docx4j.openpackaging.parts.JaxbXmlPart) part).unmarshal(is);

        } else if (part instanceof org.docx4j.openpackaging.parts.DocPropsCustomPart) {

          ((org.docx4j.openpackaging.parts.JaxbXmlPart) part)
              .setJAXBContext(Context.jcDocPropsCustom);
          ((org.docx4j.openpackaging.parts.JaxbXmlPart) part).unmarshal(is);

        } else if (part instanceof org.docx4j.openpackaging.parts.DocPropsExtendedPart) {

          ((org.docx4j.openpackaging.parts.JaxbXmlPart) part)
              .setJAXBContext(Context.jcDocPropsExtended);
          ((org.docx4j.openpackaging.parts.JaxbXmlPart) part).unmarshal(is);

        } else if (part
            instanceof org.docx4j.openpackaging.parts.CustomXmlDataStoragePropertiesPart) {

          ((org.docx4j.openpackaging.parts.JaxbXmlPart) part)
              .setJAXBContext(Context.jcCustomXmlProperties);
          ((org.docx4j.openpackaging.parts.JaxbXmlPart) part).unmarshal(is);

        } else if (part
            instanceof org.docx4j.openpackaging.parts.digitalsignature.XmlSignaturePart) {

          ((org.docx4j.openpackaging.parts.JaxbXmlPart) part).setJAXBContext(Context.jcXmlDSig);
          ((org.docx4j.openpackaging.parts.JaxbXmlPart) part).unmarshal(is);

        } else if (part instanceof org.docx4j.openpackaging.parts.JaxbXmlPart) {

          // MainDocument part, Styles part, Font part etc

          ((org.docx4j.openpackaging.parts.JaxbXmlPart) part).setJAXBContext(Context.jc);
          ((org.docx4j.openpackaging.parts.JaxbXmlPart) part).unmarshal(is);

        } else if (part instanceof org.docx4j.openpackaging.parts.WordprocessingML.BinaryPart) {

          log.debug("Detected BinaryPart " + part.getClass().getName());
          if (conserveMemory) {
            ((BinaryPart) part).setBinaryDataRef(zf.getName(), resolvedPartUri);
          } else {
            ((BinaryPart) part).setBinaryData(is);
          }

        } else if (part instanceof org.docx4j.openpackaging.parts.CustomXmlDataStoragePart) {

          // Is it a part we know?
          try {
            Unmarshaller u = Context.jc.createUnmarshaller();
            Object o = u.unmarshal(is);
            log.debug(o.getClass().getName());

            PartName name = part.getPartName();

            if (o instanceof org.opendope.conditions.Conditions) {

              part = new ConditionsPart(name);
              ((ConditionsPart) part).setJaxbElement((org.opendope.conditions.Conditions) o);

            } else if (o instanceof org.opendope.xpaths.Xpaths) {

              part = new XPathsPart(name);
              ((XPathsPart) part).setJaxbElement((org.opendope.xpaths.Xpaths) o);

            } else if (o instanceof org.opendope.questions.Questionnaire) {

              part = new QuestionsPart(name);
              ((QuestionsPart) part).setJaxbElement((org.opendope.questions.Questionnaire) o);

            } else if (o instanceof org.opendope.answers.Answers) {

              part = new StandardisedAnswersPart(name);
              ((StandardisedAnswersPart) part).setJaxbElement((org.opendope.answers.Answers) o);

            } else if (o instanceof org.opendope.components.Components) {

              part = new ComponentsPart(name);
              ((ComponentsPart) part).setJaxbElement((org.opendope.components.Components) o);

            } else if (o instanceof JAXBElement<?>
                && XmlUtils.unwrap(o) instanceof org.docx4j.bibliography.CTSources) {
              part = new BibliographyPart(name);
              ((BibliographyPart) part)
                  .setJaxbElement((JAXBElement<org.docx4j.bibliography.CTSources>) o);

            } else {

              log.warn("No known part after all for CustomXmlPart " + o.getClass().getName());

              CustomXmlDataStorage data = getCustomXmlDataStorageClass().factory();
              is.reset();
              data.setDocument(is); // Not necessarily JAXB, that's just our method name
              ((org.docx4j.openpackaging.parts.CustomXmlDataStoragePart) part).setData(data);
            }

          } catch (javax.xml.bind.UnmarshalException ue) {

            // No ...
            CustomXmlDataStorage data = getCustomXmlDataStorageClass().factory();
            is.reset();
            data.setDocument(is); // Not necessarily JAXB, that's just our method name
            ((org.docx4j.openpackaging.parts.CustomXmlDataStoragePart) part).setData(data);
          }

        } else if (part instanceof org.docx4j.openpackaging.parts.XmlPart) {

          try {
            ((XmlPart) part).setDocument(is);
          } catch (Docx4JException d) {
            // This isn't an XML part after all,
            // even though ContentTypeManager detected it as such
            // So get it as a binary part
            part = getBinaryPart(zf, ctm, resolvedPartUri);
            if (conserveMemory) {
              ((BinaryPart) part).setBinaryDataRef(zf.getName(), resolvedPartUri);
            } else {
              ((BinaryPart) part).setBinaryData(is);
            }
          }

        } else {
          // Shouldn't happen, since ContentTypeManagerImpl should
          // return an instance of one of the above, or throw an
          // Exception.

          log.error("No suitable part found for: " + resolvedPartUri);
          part = null;
        }

      } catch (PartUnrecognisedException e) {
        log.warn("PartUnrecognisedException shouldn't happen anymore!");
        // Try to get it as a binary part
        part = getBinaryPart(zf, ctm, resolvedPartUri);
        if (conserveMemory) {
          ((BinaryPart) part).setBinaryDataRef(zf.getName(), resolvedPartUri);
        } else {
          ((BinaryPart) part).setBinaryData(is);
        }
      }
    } catch (Exception ex) {
      // IOException, URISyntaxException
      ex.printStackTrace();
      throw new Docx4JException("Failed to getPart", ex);

    } finally {
      if (is != null) {
        try {
          is.close();
        } catch (IOException exc) {
          exc.printStackTrace();
        }
      }
    }
    return part;
  }
Example #4
0
  public static void apply(WordprocessingMLPackage otherPackage, Alterations alterations)
      throws Docx4JException, JAXBException {

    if (alterations.getContentTypes() != null) {
      log.info("replacing [Content_Types].xml");
      ContentTypeManager newCTM = new ContentTypeManager();
      newCTM.parseContentTypesFile(new ByteArrayInputStream(alterations.getContentTypes()));
      otherPackage.setContentTypeManager(newCTM);
    }

    if (alterations.isEmpty()) return;

    // -- Deletions
    List<PartName> removedParts = new ArrayList<PartName>();

    for (Alteration a : alterations.getPartsDeleted()) {

      org.docx4j.xmlPackage.Part xmlpart = a.getPart();

      // These deleted parts are likely to be attached to
      // to otherPackage, but there is no requirement for
      // that to be so.  In other words, you could try
      // to apply the alterations to some third docx.

      // It might have already been deleted as a consequence
      // of recursive deletion...
      if (removedParts.contains(xmlpart.getName())) continue;

      // Design decision: how to find owning rels part?
      // Since part might not be from this package, can't do:
      // part.getOwningRelationshipPart().removePart(p.getPartName())
      // We could store the info when AlteredParts is run,
      // but lets try to get away without that...
      // If a part has been deleted, we know its owning rels will
      // have been modified or deleted.  So look for that.
      // BUT IT WON'T BE THERE IF ITS BEEN DELETED! DOH!
      // So we have to store the info when AlteredParts is run
      // after all.

      Part parentPart = otherPackage.getParts().get(a.getSourcePartName());
      if (a.getPart().getContentType().equals(ContentTypes.RELATIONSHIPS_PART)) {
        parentPart.setRelationships(null);
      } else {
        removedParts.addAll(
            parentPart.getRelationshipsPart().removePart(new PartName(xmlpart.getName())));
      }
    }

    // -- Modifications
    for (Alteration a : alterations.getPartsModified()) {

      log.info("Applying modifications to part: " + a.getPart().getName());

      if (a.getPart().getContentType().equals(ContentTypes.RELATIONSHIPS_PART)) {

        RelationshipsPart newRP = null; // FlatOpcXmlImporter.createRelationshipsPart(a.getPart());

        if (a.getSourcePartName().equals("/")) {
          newRP = otherPackage.getRelationshipsPart(true);
          //					otherPackage.setRelationships(newRP);
          //					newRP.setSourceP(otherPackage);
        } else {
          Part parentPart = otherPackage.getParts().get(a.getSourcePartName());
          newRP = parentPart.getRelationshipsPart(true);
          //					parentPart.setRelationships(newRP);
          //					newRP.setSourceP(parentPart);
        }
        FlatOpcXmlImporter.populateRelationshipsPart(newRP, a.getPart().getXmlData().getAny());

      } else {

        Part targetPart = otherPackage.getParts().get(new PartName(a.getPart().getName()));

        if (targetPart == null) {
          log.error(
              "Couldn't find " + a.getPart().getName() + " @ " + a.getSourcePartName().getName());
          continue;
        }

        Part tmpPart =
            FlatOpcXmlImporter.getRawPart(otherPackage.getContentTypeManager(), a.getPart(), null);

        if (targetPart instanceof JaxbXmlPart) {
          ((JaxbXmlPart) targetPart).setJaxbElement(((JaxbXmlPart) tmpPart).getJaxbElement());

        } else if (targetPart instanceof XmlPart) {

          ((XmlPart) targetPart).setDocument(((XmlPart) tmpPart).getDocument());

        } else if (targetPart instanceof CustomXmlDataStoragePart) {

          ((CustomXmlDataStoragePart) targetPart)
              .setData(((CustomXmlDataStoragePart) tmpPart).getData());
          // TODO: check that

        } else if (targetPart instanceof BinaryPart) {

          ((BinaryPart) targetPart).setBinaryData(((BinaryPart) tmpPart).getBuffer());

        } else {
          log.error("TODO: handle " + targetPart.getClass().getName());
        }
      }
    }

    // -- Additions
    for (Alteration a : alterations.getPartsAdded()) {

      log.info("Adding part: " + a.getPart().getName());

      if (a.getPart().getContentType().equals(ContentTypes.RELATIONSHIPS_PART)) {

        RelationshipsPart newRP = null; // FlatOpcXmlImporter.createRelationshipsPart(a.getPart());

        if (a.getSourcePartName().equals("/")) {
          newRP = otherPackage.getRelationshipsPart(true);
          //					otherPackage.setRelationships(newRP);
          //					newRP.setSourceP(otherPackage);
        } else {
          Part parentPart = otherPackage.getParts().get(a.getSourcePartName());
          newRP = parentPart.getRelationshipsPart(true);
          //					parentPart.setRelationships(newRP);
          //					newRP.setSourceP(parentPart);
        }
        FlatOpcXmlImporter.populateRelationshipsPart(newRP, a.getPart().getXmlData().getAny());

      } else {

        Part parentPart = otherPackage.getParts().get(a.getSourcePartName());
        Part newPart =
            FlatOpcXmlImporter.getRawPart(otherPackage.getContentTypeManager(), a.getPart(), null);

        // There will already be a rel for the new part,
        // since we will already have modified or added the rels part
        // so don't do AddTargetPart (which will probably create a new rel id,
        // which will cause problems)

        newPart.setOwningRelationshipPart(parentPart.getRelationshipsPart());
        newPart
            .getSourceRelationships()
            .add(parentPart.getRelationshipsPart().getRel(new PartName(a.getPart().getName())));
        otherPackage.getParts().put(newPart);
        newPart.setPackage(otherPackage);

        // TODO: add content type if necessary
      }
    }
  }
Example #5
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);
      }
    }
  }