|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- /*
- * ====================================================================
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ====================================================================
- */
-
- package org.apache.poi.xslf.usermodel;
-
- import java.io.ByteArrayInputStream;
- import java.io.ByteArrayOutputStream;
- import java.io.IOException;
- import java.io.OutputStream;
-
- import javax.xml.namespace.QName;
- import javax.xml.stream.XMLStreamReader;
-
- import org.apache.poi.hpsf.ClassID;
- import org.apache.poi.ooxml.POIXMLDocumentPart.RelationPart;
- import org.apache.poi.ooxml.POIXMLException;
- import org.apache.poi.ooxml.util.XPathHelper;
- import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
- import org.apache.poi.openxml4j.opc.OPCPackage;
- import org.apache.poi.openxml4j.opc.PackagePart;
- import org.apache.poi.openxml4j.opc.PackageRelationship;
- import org.apache.poi.poifs.filesystem.FileMagic;
- import org.apache.poi.poifs.filesystem.Ole10Native;
- import org.apache.poi.poifs.filesystem.POIFSFileSystem;
- import org.apache.poi.sl.usermodel.ObjectMetaData;
- import org.apache.poi.sl.usermodel.ObjectMetaData.Application;
- import org.apache.poi.sl.usermodel.ObjectShape;
- import org.apache.poi.util.Internal;
- import org.apache.xmlbeans.XmlCursor;
- import org.apache.xmlbeans.XmlException;
- import org.openxmlformats.schemas.drawingml.x2006.main.CTBlip;
- import org.openxmlformats.schemas.drawingml.x2006.main.CTBlipFillProperties;
- import org.openxmlformats.schemas.drawingml.x2006.main.CTGraphicalObjectData;
- import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
- import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D;
- import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
- import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties;
- import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;
- import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType;
- import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame;
- import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrameNonVisual;
- import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape;
- import org.openxmlformats.schemas.presentationml.x2006.main.CTOleObject;
- import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture;
- import org.openxmlformats.schemas.presentationml.x2006.main.CTPictureNonVisual;
-
- public class XSLFObjectShape extends XSLFGraphicFrame implements ObjectShape<XSLFShape,XSLFTextParagraph> {
-
- /* package */ static final String OLE_URI = "http://schemas.openxmlformats.org/presentationml/2006/ole";
- private static final QName[] GRAPHIC = { new QName(DML_NS, "graphic") };
- private static final QName[] GRAPHIC_DATA = { new QName(DML_NS, "graphicData") };
- private static final QName[] OLE_OBJ = { new QName(PML_NS, "oleObj") };
- private static final QName[] CT_PICTURE = { new QName(PML_NS, "pic") };
-
- private CTOleObject _oleObject;
- private XSLFPictureData _data;
-
- /*package*/ XSLFObjectShape(CTGraphicalObjectFrame shape, XSLFSheet sheet){
- super(shape, sheet);
-
- // select oleObj potentially under AlternateContent
- // usually the mc:Choice element will be selected first
- try {
- _oleObject = XPathHelper.selectProperty(getXmlObject(), CTOleObject.class, null, GRAPHIC, GRAPHIC_DATA, OLE_OBJ);
- } catch (XmlException e) {
- // ole objects should be also inside AlternateContent tags, even with ECMA 376 edition 1
- throw new IllegalStateException(e);
- }
- }
-
- @Internal
- public CTOleObject getCTOleObject(){
- return _oleObject;
- }
-
- @Override
- public XSLFObjectData getObjectData() {
- String oleRel = getCTOleObject().getId();
- return getSheet().getRelationPartById(oleRel).getDocumentPart();
- }
-
- @Override
- public String getProgId() {
- return (_oleObject == null) ? null : _oleObject.getProgId();
- }
-
- @Override
- public String getFullName() {
- return (_oleObject == null) ? null : _oleObject.getName();
- }
-
-
- /**
- * Return the data on the (internal) picture.
- * For an external linked picture, will return null
- */
- @Override
- public XSLFPictureData getPictureData() {
- if(_data == null){
- String blipId = getBlipId();
- if (blipId == null) {
- return null;
- }
-
- PackagePart p = getSheet().getPackagePart();
- PackageRelationship rel = p.getRelationship(blipId);
- if (rel != null) {
- try {
- PackagePart imgPart = p.getRelatedPart(rel);
- _data = new XSLFPictureData(imgPart);
- }
- catch (Exception e) {
- throw new POIXMLException(e);
- }
- }
- }
- return _data;
- }
-
- protected CTBlip getBlip(){
- return getBlipFill().getBlip();
- }
-
- protected String getBlipId(){
- String id = getBlip().getEmbed();
- if (id.isEmpty()) {
- return null;
- }
- return id;
- }
-
- protected CTBlipFillProperties getBlipFill() {
- try {
- CTPicture pic = XPathHelper.selectProperty
- (getXmlObject(), CTPicture.class, XSLFObjectShape::parse, GRAPHIC, GRAPHIC_DATA, OLE_OBJ, CT_PICTURE);
- return (pic != null) ? pic.getBlipFill() : null;
- } catch (XmlException e) {
- return null;
- }
- }
-
- private static CTPicture parse(XMLStreamReader reader) throws XmlException {
- CTGroupShape gs = CTGroupShape.Factory.parse(reader);
- return (gs.sizeOfPicArray() > 0) ? gs.getPicArray(0) : null;
- }
-
- @Override
- public OutputStream updateObjectData(final Application application, final ObjectMetaData metaData) throws IOException {
- final ObjectMetaData md = (application != null) ? application.getMetaData() : metaData;
- if (md == null || md.getClassID() == null) {
- throw new IllegalArgumentException("either application and/or metaData needs to be set.");
- }
-
-
- final XSLFSheet sheet = getSheet();
-
- final RelationPart rp;
- if (_oleObject.isSetId()) {
- // object data was already set
- rp = sheet.getRelationPartById(_oleObject.getId());
- } else {
- // object data needs to be initialized
- try {
- final XSLFRelation descriptor = XSLFRelation.OLE_OBJECT;
- final OPCPackage pack = sheet.getPackagePart().getPackage();
- int nextIdx = pack.getUnusedPartIndex(descriptor.getDefaultFileName());
- rp = sheet.createRelationship(descriptor, XSLFFactory.getInstance(), nextIdx, false);
- _oleObject.setId(rp.getRelationship().getId());
- } catch (InvalidFormatException e) {
- throw new IOException("Unable to add new ole embedding", e);
- }
-
- // setting spid only works with a vml drawing object
- // oleObj.setSpid("_x0000_s"+(1025+objectIdx));
- }
-
- _oleObject.setProgId(md.getProgId());
- _oleObject.setName(md.getObjectName());
-
- return new XSLFObjectOutputStream(rp.getDocumentPart().getPackagePart(),md);
- }
-
- private static class XSLFObjectOutputStream extends ByteArrayOutputStream {
- final PackagePart objectPart;
- final ObjectMetaData metaData;
- private XSLFObjectOutputStream(final PackagePart objectPart, final ObjectMetaData metaData) {
- super(100000);
- this.objectPart = objectPart;
- this.metaData = metaData;
- }
-
- public void close() throws IOException {
- objectPart.clear();
- try (final OutputStream os = objectPart.getOutputStream()) {
- final ByteArrayInputStream bis = new ByteArrayInputStream(this.buf, 0, size());
- final FileMagic fm = FileMagic.valueOf(this.buf);
-
- if (fm == FileMagic.OLE2) {
- try (final POIFSFileSystem poifs = new POIFSFileSystem(bis)) {
- poifs.getRoot().setStorageClsid(metaData.getClassID());
- poifs.writeFilesystem(os);
- }
- } else if (metaData.getOleEntry() == null) {
- // OLE Name hasn't been specified, pass the input through
- os.write(this.buf, 0, size());
- } else {
- try (final POIFSFileSystem poifs = new POIFSFileSystem()) {
- final ClassID clsId = metaData.getClassID();
- if (clsId != null) {
- poifs.getRoot().setStorageClsid(clsId);
- }
- poifs.createDocument(bis, metaData.getOleEntry());
-
- Ole10Native.createOleMarkerEntry(poifs);
-
- poifs.writeFilesystem(os);
- }
- }
- }
- }
- }
-
-
- /**
- *
- *
- * @param shapeId 1-based shapeId
- * @param picRel relationship to the picture data in the ooxml package
- * @return
- */
- static CTGraphicalObjectFrame prototype(int shapeId, String picRel){
- CTGraphicalObjectFrame frame = CTGraphicalObjectFrame.Factory.newInstance();
- CTGraphicalObjectFrameNonVisual nvGr = frame.addNewNvGraphicFramePr();
-
- CTNonVisualDrawingProps cnv = nvGr.addNewCNvPr();
- // usually the shape name has its index based on the n-th embeding, but having
- // the prototype separate from the actual updating of the object, we use the shape id
- cnv.setName("Object " + shapeId);
- cnv.setId(shapeId);
-
- // add empty property elements otherwise Powerpoint doesn't load the file ...
- nvGr.addNewCNvGraphicFramePr();
- nvGr.addNewNvPr();
-
- frame.addNewXfrm();
- CTGraphicalObjectData gr = frame.addNewGraphic().addNewGraphicData();
- gr.setUri(OLE_URI);
- XmlCursor grCur = gr.newCursor();
- grCur.toEndToken();
- grCur.beginElement(new QName(PML_NS, "oleObj"));
- grCur.insertElement(new QName(PML_NS, "embed"));
-
-
- CTGroupShape grpShp = CTGroupShape.Factory.newInstance();
- CTPicture pic = grpShp.addNewPic();
- CTPictureNonVisual nvPicPr = pic.addNewNvPicPr();
- CTNonVisualDrawingProps cNvPr = nvPicPr.addNewCNvPr();
- cNvPr.setName("");
- cNvPr.setId(0);
- nvPicPr.addNewCNvPicPr();
- nvPicPr.addNewNvPr();
-
-
- CTBlipFillProperties blip = pic.addNewBlipFill();
- blip.addNewBlip().setEmbed(picRel);
- blip.addNewStretch().addNewFillRect();
-
- CTShapeProperties spPr = pic.addNewSpPr();
- CTTransform2D xfrm = spPr.addNewXfrm();
- CTPoint2D off = xfrm.addNewOff();
- off.setX(1270000);
- off.setY(1270000);
- CTPositiveSize2D xext = xfrm.addNewExt();
- xext.setCx(1270000);
- xext.setCy(1270000);
-
- spPr.addNewPrstGeom().setPrst(STShapeType.RECT);
-
-
- XmlCursor picCur = grpShp.newCursor();
- picCur.toStartDoc();
- picCur.moveXmlContents(grCur);
- picCur.dispose();
-
- grCur.dispose();
-
-
- return frame;
- }
- }
|