You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ki...@apache.org on 2018/04/20 13:45:18 UTC

svn commit: r1829656 - in /poi: site/src/documentation/content/xdocs/ trunk/src/java/org/apache/poi/sl/usermodel/ trunk/src/java/org/apache/poi/util/ trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/ trunk/src/scratchpad/src/org/apache/poi/hslf/recor...

Author: kiwiwings
Date: Fri Apr 20 13:45:18 2018
New Revision: 1829656

URL: http://svn.apache.org/viewvc?rev=1829656&view=rev
Log:
#61459 - HSLFShape.getShapeName() returns name of shapeType and not the shape name

Modified:
    poi/site/src/documentation/content/xdocs/status.xml
    poi/trunk/src/java/org/apache/poi/sl/usermodel/Shape.java
    poi/trunk/src/java/org/apache/poi/sl/usermodel/SlideShowFactory.java
    poi/trunk/src/java/org/apache/poi/util/StringUtil.java
    poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java
    poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideShowFactory.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/FontEntityAtom.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShape.java
    poi/trunk/src/testcases/org/apache/poi/sl/usermodel/BaseTestSlideShow.java
    poi/trunk/test-data/slideshow/SampleShow.ppt
    poi/trunk/test-data/slideshow/SampleShow.pptx

Modified: poi/site/src/documentation/content/xdocs/status.xml
URL: http://svn.apache.org/viewvc/poi/site/src/documentation/content/xdocs/status.xml?rev=1829656&r1=1829655&r2=1829656&view=diff
==============================================================================
--- poi/site/src/documentation/content/xdocs/status.xml (original)
+++ poi/site/src/documentation/content/xdocs/status.xml Fri Apr 20 13:45:18 2018
@@ -68,6 +68,7 @@
         <summary-item>Provide new ooxml-schemas-1.4.jar</summary-item>
       </summary>
       <actions>
+        <action dev="PD" type="fix" fixes-bug="61459" module="HSLF">HSLFShape.getShapeName() returns name of shapeType and not the shape name</action>
         <action dev="PD" type="add" fixes-bug="62319" breaks-compatibility="true" module="SL Common">Decommission XSLF-/PowerPointExtractor</action>
         <action dev="PD" type="add" fixes-bug="62092" module="SL Common">Text not extracted from grouped text shapes in HSLF</action>
 		<action dev="PD" type="add" fixes-bug="62159" module="OPC">Support XML signature over windows certificate store</action>

Modified: poi/trunk/src/java/org/apache/poi/sl/usermodel/Shape.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/usermodel/Shape.java?rev=1829656&r1=1829655&r2=1829656&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/usermodel/Shape.java (original)
+++ poi/trunk/src/java/org/apache/poi/sl/usermodel/Shape.java Fri Apr 20 13:45:18 2018
@@ -38,7 +38,14 @@ public interface Shape<
     * @return the anchor of this shape
     */
    Rectangle2D getAnchor();
-   
+
+   /**
+    * @return human-readable name of this shape, e.g. "Rectange 3"
+    *
+    * @since POI 4.0.0
+    */
+   String getShapeName();
+
    /**
     * Convenience method to draw a single shape
     *

Modified: poi/trunk/src/java/org/apache/poi/sl/usermodel/SlideShowFactory.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/sl/usermodel/SlideShowFactory.java?rev=1829656&r1=1829655&r2=1829656&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/sl/usermodel/SlideShowFactory.java (original)
+++ poi/trunk/src/java/org/apache/poi/sl/usermodel/SlideShowFactory.java Fri Apr 20 13:45:18 2018
@@ -44,7 +44,10 @@ public class SlideShowFactory {
      *
      * @throws IOException if an error occurs while reading the data
      */
-    public static SlideShow<?,?> create(NPOIFSFileSystem fs) throws IOException {
+    public static <
+        S extends Shape<S,P>,
+        P extends TextParagraph<S,P,? extends TextRun>
+    > SlideShow<S,P> create(NPOIFSFileSystem fs) throws IOException {
         return create(fs, null);
     }
 
@@ -59,7 +62,10 @@ public class SlideShowFactory {
      *
      * @throws IOException if an error occurs while reading the data
      */
-    public static SlideShow<?,?> create(final NPOIFSFileSystem fs, String password) throws IOException {
+    public static <
+        S extends Shape<S,P>,
+        P extends TextParagraph<S,P,? extends TextRun>
+    > SlideShow<S,P> create(final NPOIFSFileSystem fs, String password) throws IOException {
         return create(fs.getRoot(), password);
     }
 
@@ -72,7 +78,10 @@ public class SlideShowFactory {
      *
      * @throws IOException if an error occurs while reading the data
      */
-    public static SlideShow<?,?> create(final DirectoryNode root) throws IOException {
+    public static <
+        S extends Shape<S,P>,
+        P extends TextParagraph<S,P,? extends TextRun>
+    > SlideShow<S,P> create(final DirectoryNode root) throws IOException {
         return create(root, null);
     }
 
@@ -88,7 +97,10 @@ public class SlideShowFactory {
      *
      * @throws IOException if an error occurs while reading the data
      */
-    public static SlideShow<?,?> create(final DirectoryNode root, String password) throws IOException {
+    public static <
+        S extends Shape<S,P>,
+        P extends TextParagraph<S,P,? extends TextRun>
+    > SlideShow<S,P> create(final DirectoryNode root, String password) throws IOException {
         // Encrypted OOXML files go inside OLE2 containers, is this one?
         if (root.hasEntry(Decryptor.DEFAULT_POIFS_ENTRY)) {
             InputStream stream = null;
@@ -136,7 +148,10 @@ public class SlideShowFactory {
      *  @throws IOException if an error occurs while reading the data
      *  @throws EncryptedDocumentException If the SlideShow given is password protected
      */
-    public static SlideShow<?,?> create(InputStream inp) throws IOException, EncryptedDocumentException {
+    public static <
+        S extends Shape<S,P>,
+        P extends TextParagraph<S,P,? extends TextRun>
+    > SlideShow<S,P> create(InputStream inp) throws IOException, EncryptedDocumentException {
         return create(inp, null);
     }
 
@@ -160,7 +175,10 @@ public class SlideShowFactory {
      *  @throws IOException if an error occurs while reading the data
      *  @throws EncryptedDocumentException If the wrong password is given for a protected file
      */
-    public static SlideShow<?,?> create(InputStream inp, String password) throws IOException, EncryptedDocumentException {
+    public static <
+        S extends Shape<S,P>,
+        P extends TextParagraph<S,P,? extends TextRun>
+    > SlideShow<S,P> create(InputStream inp, String password) throws IOException, EncryptedDocumentException {
         InputStream is = FileMagic.prepareToCheckMagic(inp);
         FileMagic fm = FileMagic.valueOf(is);
         
@@ -188,7 +206,10 @@ public class SlideShowFactory {
      *  @throws IOException if an error occurs while reading the data
      *  @throws EncryptedDocumentException If the SlideShow given is password protected
      */
-    public static SlideShow<?,?> create(File file) throws IOException, EncryptedDocumentException {
+    public static <
+        S extends Shape<S,P>,
+        P extends TextParagraph<S,P,? extends TextRun>
+    > SlideShow<S,P> create(File file) throws IOException, EncryptedDocumentException {
         return create(file, null);
     }
 
@@ -207,7 +228,10 @@ public class SlideShowFactory {
      *  @throws IOException if an error occurs while reading the data
      *  @throws EncryptedDocumentException If the wrong password is given for a protected file
      */
-    public static SlideShow<?,?> create(File file, String password) throws IOException, EncryptedDocumentException {
+    public static <
+        S extends Shape<S,P>,
+        P extends TextParagraph<S,P,? extends TextRun>
+    > SlideShow<S,P> create(File file, String password) throws IOException, EncryptedDocumentException {
         return create(file, password, false);
     }
 
@@ -228,7 +252,10 @@ public class SlideShowFactory {
      *  @throws IOException if an error occurs while reading the data
      *  @throws EncryptedDocumentException If the wrong password is given for a protected file
      */
-    public static SlideShow<?,?> create(File file, String password, boolean readOnly) throws IOException, EncryptedDocumentException {
+    public static <
+        S extends Shape<S,P>,
+        P extends TextParagraph<S,P,? extends TextRun>
+    > SlideShow<S,P> create(File file, String password, boolean readOnly) throws IOException, EncryptedDocumentException {
         if (!file.exists()) {
             throw new FileNotFoundException(file.toString());
         }
@@ -246,15 +273,24 @@ public class SlideShowFactory {
         }
     }
     
-    protected static SlideShow<?,?> createHSLFSlideShow(Object... args) throws IOException, EncryptedDocumentException {
+    private static <
+        S extends Shape<S,P>,
+        P extends TextParagraph<S,P,? extends TextRun>
+    > SlideShow<S,P> createHSLFSlideShow(Object... args) throws IOException, EncryptedDocumentException {
         return createSlideShow("org.apache.poi.hslf.usermodel.HSLFSlideShowFactory", args);
     }
     
-    protected static SlideShow<?,?> createXSLFSlideShow(Object... args) throws IOException, EncryptedDocumentException {
+    private static <
+        S extends Shape<S,P>,
+        P extends TextParagraph<S,P,? extends TextRun>
+    > SlideShow<S,P> createXSLFSlideShow(Object... args) throws IOException, EncryptedDocumentException {
         return createSlideShow("org.apache.poi.xslf.usermodel.XSLFSlideShowFactory", args);
     }
-    
-    protected static SlideShow<?,?> createSlideShow(String factoryClass, Object args[]) throws IOException, EncryptedDocumentException {
+
+    private static <
+        S extends Shape<S,P>,
+        P extends TextParagraph<S,P,? extends TextRun>
+    > SlideShow<S,P> createSlideShow(String factoryClass, Object args[]) throws IOException, EncryptedDocumentException {
         try {
             Class<?> clazz = Thread.currentThread().getContextClassLoader().loadClass(factoryClass);
             Class<?> argsClz[] = new Class<?>[args.length];
@@ -269,7 +305,7 @@ public class SlideShowFactory {
                 argsClz[i++] = c;
             }
             Method m = clazz.getMethod("createSlideShow", argsClz);
-            return (SlideShow<?,?>)m.invoke(null, args);
+            return (SlideShow<S,P>)m.invoke(null, args);
         } catch (InvocationTargetException e) {
             Throwable t = e.getCause();
             if (t instanceof IOException) {

Modified: poi/trunk/src/java/org/apache/poi/util/StringUtil.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/util/StringUtil.java?rev=1829656&r1=1829655&r2=1829656&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/util/StringUtil.java (original)
+++ poi/trunk/src/java/org/apache/poi/util/StringUtil.java Fri Apr 20 13:45:18 2018
@@ -652,4 +652,76 @@ public class StringUtil {
         }
         return count;
     }
+
+
+    /**
+     * Given a byte array of 16-bit unicode characters in Little Endian
+     * format (most important byte last), return a Java String representation
+     * of it.
+     *
+     * Scans the byte array for two continous 0 bytes and returns the string before.
+     * <p>
+     *
+     * #61881: there seem to be programs out there, which write the 0-termination also
+     * at the beginning of the string. Check if the next two bytes contain a valid ascii char
+     * and correct the _recdata with a '?' char
+     *
+     *
+     * @param string the byte array to be converted
+     * @param offset the initial offset into the
+     *               byte array. it is assumed that string[ offset ] and string[ offset +
+     *               1 ] contain the first 16-bit unicode character
+     * @param len    the max. length of the final string
+     * @return the converted string, never <code>null</code>.
+     * @throws ArrayIndexOutOfBoundsException if offset is out of bounds for
+     *                                        the byte array (i.e., is negative or is greater than or equal to
+     *                                        string.length)
+     * @throws IllegalArgumentException       if len is too large (i.e.,
+     *                                        there is not enough data in string to create a String of that
+     *                                        length)
+     */
+    public static String getFromUnicodeLE0Terminated(
+            final byte[] string,
+            final int offset,
+            final int len)
+            throws ArrayIndexOutOfBoundsException, IllegalArgumentException {
+        if ((offset < 0) || (offset >= string.length)) {
+            throw new ArrayIndexOutOfBoundsException("Illegal offset " + offset + " (String data is of length " + string.length + ")");
+        }
+
+        if ((len < 0) || (((string.length - offset) / 2) < len)) {
+            throw new IllegalArgumentException("Illegal length " + len);
+        }
+
+        final int newOffset;
+        final int newMaxLen;
+        final String prefix;
+
+        // #61881 - for now we only check the first char
+        if (len > 0 && string[offset] == 0 && string[offset+1] == 0) {
+            newOffset = offset+2;
+            prefix = "?";
+
+            // check if the next char is garbage and limit the len if necessary
+            final int cp = (len > 1) ? LittleEndian.getShort(string, offset+2) : 0;
+            newMaxLen = Character.isJavaIdentifierPart(cp) ? len-1 : 0;
+        } else {
+            newOffset = offset;
+            prefix = "";
+            newMaxLen = len;
+        }
+
+        int newLen = 0;
+
+        // loop until we find a null-terminated end
+        for(; newLen < newMaxLen; newLen++) {
+            if (string[newOffset + newLen * 2] == 0 && string[newOffset + newLen * 2 + 1] == 0) {
+                break;
+            }
+        }
+        newLen = Math.min(newLen, newMaxLen);
+
+        return prefix + ((newLen == 0) ? "" : new String(string, newOffset, newLen * 2, UTF16LE));
+    }
+
 }

Modified: poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java?rev=1829656&r1=1829655&r2=1829656&view=diff
==============================================================================
--- poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java (original)
+++ poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java Fri Apr 20 13:45:18 2018
@@ -97,9 +97,7 @@ public abstract class XSLFShape implemen
         return _sheet;
     }
     
-    /**
-     * @return human-readable name of this shape, e.g. "Rectange 3"
-     */
+    @Override
     public String getShapeName(){
         return getCNvPr().getName();
     }

Modified: poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideShowFactory.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideShowFactory.java?rev=1829656&r1=1829655&r2=1829656&view=diff
==============================================================================
--- poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideShowFactory.java (original)
+++ poi/trunk/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideShowFactory.java Fri Apr 20 13:45:18 2018
@@ -25,7 +25,6 @@ import org.apache.poi.EncryptedDocumentE
 import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
 import org.apache.poi.openxml4j.opc.OPCPackage;
 import org.apache.poi.openxml4j.opc.PackageAccess;
-import org.apache.poi.sl.usermodel.SlideShow;
 import org.apache.poi.sl.usermodel.SlideShowFactory;
 import org.apache.poi.util.Internal;
 
@@ -45,7 +44,7 @@ public class XSLFSlideShowFactory extend
      *  @throws IOException if an error occurs while reading the data
      * @throws InvalidFormatException 
      */
-    public static SlideShow<?,?> createSlideShow(OPCPackage pkg) throws IOException {
+    public static XMLSlideShow createSlideShow(OPCPackage pkg) throws IOException {
         try {
             return new XMLSlideShow(pkg);
         } catch (IllegalArgumentException ioe) {
@@ -72,7 +71,7 @@ public class XSLFSlideShowFactory extend
      *  @throws EncryptedDocumentException If the wrong password is given for a protected file
      */
     @SuppressWarnings("resource")
-    public static SlideShow<?,?> createSlideShow(File file, boolean readOnly)
+    public static XMLSlideShow createSlideShow(File file, boolean readOnly)
     throws IOException, InvalidFormatException {
         OPCPackage pkg = OPCPackage.open(file, readOnly ? PackageAccess.READ : PackageAccess.READ_WRITE);
         return createSlideShow(pkg);
@@ -92,7 +91,7 @@ public class XSLFSlideShowFactory extend
      * @throws InvalidFormatException 
      */
     @SuppressWarnings("resource")
-    public static SlideShow<?,?> createSlideShow(InputStream stream) throws IOException, InvalidFormatException {
+    public static XMLSlideShow createSlideShow(InputStream stream) throws IOException, InvalidFormatException {
         OPCPackage pkg = OPCPackage.open(stream);
         return createSlideShow(pkg);
     }

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/FontEntityAtom.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/FontEntityAtom.java?rev=1829656&r1=1829655&r2=1829656&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/FontEntityAtom.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/FontEntityAtom.java Fri Apr 20 13:45:18 2018
@@ -86,38 +86,8 @@ public final class FontEntityAtom extend
      * @return font name
      */
     public String getFontName(){
-    	final int maxLen = Math.min(_recdata.length,64);
-        for(int i = 0; i+1 < maxLen; i+=2){
-            //loop until find null-terminated end of the font name
-            if(_recdata[i] == 0 && _recdata[i + 1] == 0 && !isFontNamePremature0terminated(i)) {
-                return StringUtil.getFromUnicodeLE(_recdata, 0, i/2);
-            }
-        }
-        return null;
-    }
-    
-    /**
-     * #61881: there seem to be programs out there, which write the 0-termination also
-     * at the beginning of the string. Check if the next two bytes contain a valid ascii char
-     * and correct the _recdata with a '?' char
-     */
-    private boolean isFontNamePremature0terminated(final int index) {
-        if (index > 0) {
-            // for now we only check the first char
-            return false;
-        }
-        
-        if (_recdata.length < index+4) {
-            return false;
-        }
-        
-        final int cp = LittleEndian.getShort(_recdata, index+2);
-        if (!Character.isJavaIdentifierPart(cp)) {
-            return false;
-        }
-        
-        _recdata[index] = '?';
-        return true;
+    	final int maxLen = Math.min(_recdata.length,64)/2;
+    	return StringUtil.getFromUnicodeLE0Terminated(_recdata, 0, maxLen);
     }
 
     /**

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShape.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShape.java?rev=1829656&r1=1829655&r2=1829656&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShape.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShape.java Fri Apr 20 13:45:18 2018
@@ -30,6 +30,7 @@ import org.apache.poi.ddf.EscherClientDa
 import org.apache.poi.ddf.EscherColorRef;
 import org.apache.poi.ddf.EscherColorRef.SysIndexProcedure;
 import org.apache.poi.ddf.EscherColorRef.SysIndexSource;
+import org.apache.poi.ddf.EscherComplexProperty;
 import org.apache.poi.ddf.EscherContainerRecord;
 import org.apache.poi.ddf.EscherProperties;
 import org.apache.poi.ddf.EscherProperty;
@@ -49,6 +50,7 @@ import org.apache.poi.sl.usermodel.Shape
 import org.apache.poi.sl.usermodel.ShapeType;
 import org.apache.poi.util.POILogFactory;
 import org.apache.poi.util.POILogger;
+import org.apache.poi.util.StringUtil;
 import org.apache.poi.util.Units;
 
 /**
@@ -123,8 +125,15 @@ public abstract class HSLFShape implemen
     /**
      * @return name of the shape.
      */
+    @Override
     public String getShapeName(){
-        return getShapeType().nativeName;
+        final EscherComplexProperty ep = getEscherProperty(getEscherOptRecord(), EscherProperties.GROUPSHAPE__SHAPENAME);
+        if (ep != null) {
+            final byte[] cd = ep.getComplexData();
+            return StringUtil.getFromUnicodeLE0Terminated(cd, 0, cd.length/2);
+        } else {
+            return getShapeType().nativeName+" "+getShapeId();
+        }
     }
 
     public ShapeType getShapeType(){

Modified: poi/trunk/src/testcases/org/apache/poi/sl/usermodel/BaseTestSlideShow.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/sl/usermodel/BaseTestSlideShow.java?rev=1829656&r1=1829655&r2=1829656&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/sl/usermodel/BaseTestSlideShow.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/sl/usermodel/BaseTestSlideShow.java Fri Apr 20 13:45:18 2018
@@ -157,4 +157,19 @@ public abstract class BaseTestSlideShow
             }
         }        
     }
+
+    @Test
+    public void shapeName() throws IOException {
+        final String file = "SampleShow.ppt"+(getClass().getSimpleName().contains("XML")?"x":"");
+        try (final InputStream is = slTests.openResourceAsStream(file)) {
+            try (final SlideShow<? extends Shape, ?> ppt = SlideShowFactory.create(is)) {
+                final List<? extends Shape> shapes1 = ppt.getSlides().get(0).getShapes();
+                assertEquals("The Title", shapes1.get(0).getShapeName());
+                assertEquals("Another Subtitle", shapes1.get(1).getShapeName());
+                final List<? extends Shape> shapes2 = ppt.getSlides().get(1).getShapes();
+                assertEquals("Title 1", shapes2.get(0).getShapeName());
+                assertEquals("Content Placeholder 2", shapes2.get(1).getShapeName());
+            }
+        }
+    }
 }

Modified: poi/trunk/test-data/slideshow/SampleShow.ppt
URL: http://svn.apache.org/viewvc/poi/trunk/test-data/slideshow/SampleShow.ppt?rev=1829656&r1=1829655&r2=1829656&view=diff
==============================================================================
Binary files - no diff available.

Modified: poi/trunk/test-data/slideshow/SampleShow.pptx
URL: http://svn.apache.org/viewvc/poi/trunk/test-data/slideshow/SampleShow.pptx?rev=1829656&r1=1829655&r2=1829656&view=diff
==============================================================================
Binary files - no diff available.



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org