/**
   * 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 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;
  }
Пример #3
0
  /* Save a Package as a Zip file in the outputstream provided */
  public boolean save(OutputStream realOS) throws Docx4JException {
    handled = new HashMap<String, String>();
    try {

      ZipOutputStream out = new ZipOutputStream(realOS);

      // 3. Save [Content_Types].xml
      ContentTypeManager ctm = p.getContentTypeManager();
      out.putNextEntry(new ZipEntry("[Content_Types].xml"));
      ctm.marshal(out);
      out.closeEntry();

      // 4. Start with _rels/.rels

      //			<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
      //			  <Relationship Id="rId3"
      // Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml"/>
      //			  <Relationship Id="rId2"
      // Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml"/>
      //			  <Relationship Id="rId1"
      // Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"
      // Target="word/document.xml"/>
      //			</Relationships>

      String partName = "_rels/.rels";
      RelationshipsPart rp = p.getRelationshipsPart();
      // deprecatedSaveRawXmlPart(out, partName, rp.getDocument() );
      // 2008 06 12 - try this neater method
      saveRawXmlPart(out, rp, partName);

      // 5. Now recursively
      //			addPartsFromRelationships(out, "", rp );
      addPartsFromRelationships(out, rp);

      // Complete the ZIP file
      // Don't forget to do this or everything will appear
      // to work, but when you open the zip file you'll get an error
      // "End-of-central-directory signature not found."
      out.close();
      realOS.close();
    } catch (Exception e) {
      e.printStackTrace();
      if (e instanceof Docx4JException) {
        throw (Docx4JException) e;
      } else {
        throw new Docx4JException("Failed to save package", e);
      }
    }

    log.info("...Done!");

    return true;
  }
  // public static Part getBinaryPart(ZipFile zf, ContentTypeManager ctm, String resolvedPartUri)
  public static Part getBinaryPart(
      HashMap<String, ByteArray> partByteArrays, ContentTypeManager ctm, String resolvedPartUri)
      throws Docx4JException {

    Part part = null;
    InputStream in = null;
    try {
      // in = zf.getInputStream( zf.getEntry(resolvedPartUri ) );
      in = partByteArrays.get(resolvedPartUri).getInputStream();
      part = new BinaryPart(new PartName("/" + resolvedPartUri));

      // Set content type
      part.setContentType(new ContentType(ctm.getContentType(new PartName("/" + resolvedPartUri))));

      ((BinaryPart) part).setBinaryData(in);
      log.info("Stored as BinaryData");

    } catch (Exception ioe) {
      ioe.printStackTrace();
    } finally {
      if (in != null) {
        try {
          in.close();
        } catch (IOException exc) {
          exc.printStackTrace();
        }
      }
    }
    return part;
  }
  /**
   * Create a linked image part, and attach it as a rel of the specified source part (eg a header
   * part).
   *
   * <p>The current behaviour is that the part is added to the package, but since the target mode of
   * the rel is external, the part is redundant.
   *
   * @param wordMLPackage
   * @param sourcePart
   * @param url
   * @return
   * @throws Exception
   */
  public static BinaryPartAbstractImage createLinkedImagePart(
      OpcPackage opcPackage, Part sourcePart, URL url) throws Exception {

    log.debug("Incoming url for linked image: " + url.toString());

    ImageInfo info =
        ensureFormatIsSupported(url, null, null, false); // final param doesn't matter in this case

    ContentTypeManager ctm = opcPackage.getContentTypeManager();
    String proposedRelId = sourcePart.getRelationshipsPart().getNextId();
    // In order to ensure unique part name,
    // idea is to use the relId, which ought to be unique
    String ext = info.getMimeType().substring(info.getMimeType().indexOf("/") + 1);

    BinaryPartAbstractImage imagePart =
        (BinaryPartAbstractImage)
            ctm.newPartForContentType(
                info.getMimeType(),
                createImageName(opcPackage, sourcePart, proposedRelId, ext),
                null);

    // NB: contents never populated

    log.debug(
        "created part "
            + imagePart.getClass().getName()
            + " with name "
            + imagePart.getPartName().toString());

    imagePart.rels.add(
        sourcePart.addTargetPart(
            imagePart)); // want to create rel with suitable name; side effect is to add part
    imagePart.getRelLast().setTargetMode("External");

    opcPackage.getExternalResources().put(imagePart.getExternalTarget(), imagePart);

    //		if (!url.getProtocol().equals("file") && new File(url.toString() ).isFile()) {
    //			imagePart.rel.setTarget("file:///" + url);
    //		} else {
    //			imagePart.rel.setTarget(url.toString());
    //		}
    imagePart.getRelLast().setTarget(url.toString());

    imagePart.setImageInfo(info);

    return imagePart;
  }
  /**
   * 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;
  }
Пример #7
0
  public Part getBinaryPart(ContentTypeManager ctm, String resolvedPartUri) throws Docx4JException {

    Part part = null;
    InputStream is = null;
    try {
      is = partStore.loadPart(resolvedPartUri);
      // in = partByteArrays.get(resolvedPartUri).getInputStream();
      part = new BinaryPart(new PartName("/" + resolvedPartUri));

      // Set content type
      part.setContentType(new ContentType(ctm.getContentType(new PartName("/" + resolvedPartUri))));

      ((BinaryPart) part).setBinaryData(is);
      log.info("Stored as BinaryData");

    } catch (Exception ioe) {
      ioe.printStackTrace();
    } finally {
      IOUtils.closeQuietly(is);
    }
    return part;
  }
Пример #8
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;
  }
Пример #9
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;
  }
Пример #10
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;
  }
Пример #11
0
  public OpcPackage get(File f) throws Docx4JException {
    log.info("Filepath = " + f.getPath());

    ZipFile zf = null;
    try {
      if (!f.exists()) {
        log.info("Couldn't find " + f.getPath());
      }
      zf = new ZipFile(f);
    } catch (IOException ioe) {
      ioe.printStackTrace();
      throw new Docx4JException("Couldn't get ZipFile", ioe);
    }

    // dumpZipFileContents(zf);

    // 1. The idea is to walk the tree of relationships, getting
    //		everything we need from the zip file.  But I'd like to know
    //		whether there are any orphans, so first we make
    //		a HashMap containing the names of all the zip file
    //		entries, so we can tick them off.

    //		unusedZipEntries = new HashMap();
    Enumeration entries = zf.entries();
    while (entries.hasMoreElements()) {
      ZipEntry entry = (ZipEntry) entries.nextElement();
      //			unusedZipEntries.put(entry.getName(), new Boolean(true) );
    }

    // 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(zf, "[Content_Types].xml");
      ctm.parseContentTypesFile(is);
    } catch (IOException e) {
      throw new Docx4JException("Couldn't get [Content_Types].xml from ZipFile", e);
    }

    OpcPackage p = ctm.createPackage();

    // 3. Get [Content_Types].xml
    //		Once we've got this, then we can look up the content type for
    //		each PartName, and use it in the Part constructor.
    //		p.setContentTypeManager(ctm); - 20080111 - done by ctm.createPackage();
    //		unusedZipEntries.put("[Content_Types].xml", new Boolean(false));

    // 4. Start with _rels/.rels

    //		<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
    //		  <Relationship Id="rId3"
    // Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml"/>
    //		  <Relationship Id="rId2"
    // Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties"
    // Target="docProps/core.xml"/>
    //		  <Relationship Id="rId1"
    // Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"
    // Target="word/document.xml"/>
    //		</Relationships>

    String partName = "_rels/.rels";
    RelationshipsPart rp = getRelationshipsPartFromZip(p, zf, partName);
    p.setRelationships(rp);
    // rp.setPackageRelationshipPart(true);
    //		unusedZipEntries.put(partName, new Boolean(false));

    log.info("Object created for: " + partName);
    // log.info( rp.toString());

    // 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(zf, 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));
    //			 }
    //		}
    try {
      zf.close();
    } catch (IOException exc) {
      exc.printStackTrace();
    }

    registerCustomXmlDataStorageParts(p);

    return p;
  }
Пример #12
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
      }
    }
  }
  /**
   * 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;
  }