View | Details | Raw Unified | Return to bug 61478
Collapse All | Expand All

(-)src/ooxml/java/org/apache/poi/POIXMLTypeLoader.java (-14 / +21 lines)
Lines 33-38 Link Here
33
33
34
import org.apache.poi.openxml4j.opc.PackageNamespaces;
34
import org.apache.poi.openxml4j.opc.PackageNamespaces;
35
import org.apache.poi.util.DocumentHelper;
35
import org.apache.poi.util.DocumentHelper;
36
import org.apache.poi.util.Removal;
36
import org.apache.xmlbeans.SchemaType;
37
import org.apache.xmlbeans.SchemaType;
37
import org.apache.xmlbeans.SchemaTypeLoader;
38
import org.apache.xmlbeans.SchemaTypeLoader;
38
import org.apache.xmlbeans.XmlBeans;
39
import org.apache.xmlbeans.XmlBeans;
Lines 49-55 Link Here
49
@SuppressWarnings("deprecation")
50
@SuppressWarnings("deprecation")
50
public class POIXMLTypeLoader {
51
public class POIXMLTypeLoader {
51
52
52
    private static ThreadLocal<ClassLoader> classLoader = new ThreadLocal<ClassLoader>();
53
    private static ThreadLocal<SchemaTypeLoader> typeLoader = new ThreadLocal<SchemaTypeLoader>();
53
54
54
    // TODO: Do these have a good home like o.a.p.openxml4j.opc.PackageNamespaces and PackageRelationshipTypes?
55
    // TODO: Do these have a good home like o.a.p.openxml4j.opc.PackageNamespaces and PackageRelationshipTypes?
55
    // These constants should be common to all of POI and easy to use by other applications such as Tika
56
    // These constants should be common to all of POI and easy to use by other applications such as Tika
Lines 109-128 Link Here
109
     * when the user code is finalized.
110
     * when the user code is finalized.
110
     * 
111
     * 
111
     * @param cl the classloader to be used when XmlBeans classes and definitions are looked up
112
     * @param cl the classloader to be used when XmlBeans classes and definitions are looked up
113
     * @deprecated in POI 3.17 - setting a classloader from the outside is now obsolete,
114
     *  the classloader of the SchemaType will be used
112
     */
115
     */
116
    @Deprecated
117
    @Removal(version="4.0")
113
    public static void setClassLoader(ClassLoader cl) {
118
    public static void setClassLoader(ClassLoader cl) {
114
        classLoader.set(cl);
115
    }
119
    }
116
    
120
    
117
    private static SchemaTypeLoader getTypeLoader() {
121
    private static SchemaTypeLoader getTypeLoader(SchemaType type) {
118
        ClassLoader cl = classLoader.get();
122
        SchemaTypeLoader tl = typeLoader.get();
119
        return (cl == null)
123
        if (tl == null) {
120
            ? XmlBeans.getContextTypeLoader()
124
            ClassLoader cl = type.getClass().getClassLoader();
121
            : XmlBeans.typeLoaderForClassLoader(cl);
125
            tl = XmlBeans.typeLoaderForClassLoader(cl);
126
            typeLoader.set(tl);
127
        }
128
        return tl;
122
    }
129
    }
123
    
130
    
124
    public static XmlObject newInstance(SchemaType type, XmlOptions options) {
131
    public static XmlObject newInstance(SchemaType type, XmlOptions options) {
125
        return getTypeLoader().newInstance(type, getXmlOptions(options));
132
        return getTypeLoader(type).newInstance(type, getXmlOptions(options));
126
    }
133
    }
127
134
128
    public static XmlObject parse(String xmlText, SchemaType type, XmlOptions options) throws XmlException {
135
    public static XmlObject parse(String xmlText, SchemaType type, XmlOptions options) throws XmlException {
Lines 154-160 Link Here
154
    public static XmlObject parse(InputStream jiois, SchemaType type, XmlOptions options) throws XmlException, IOException {
161
    public static XmlObject parse(InputStream jiois, SchemaType type, XmlOptions options) throws XmlException, IOException {
155
        try {
162
        try {
156
            Document doc = DocumentHelper.readDocument(jiois);
163
            Document doc = DocumentHelper.readDocument(jiois);
157
            return getTypeLoader().parse(doc.getDocumentElement(), type, getXmlOptions(options));
164
            return getTypeLoader(type).parse(doc.getDocumentElement(), type, getXmlOptions(options));
158
        } catch (SAXException e) {
165
        } catch (SAXException e) {
159
            throw new IOException("Unable to parse xml bean", e);
166
            throw new IOException("Unable to parse xml bean", e);
160
        }
167
        }
Lines 161-173 Link Here
161
    }
168
    }
162
169
163
    public static XmlObject parse(XMLStreamReader xsr, SchemaType type, XmlOptions options) throws XmlException {
170
    public static XmlObject parse(XMLStreamReader xsr, SchemaType type, XmlOptions options) throws XmlException {
164
        return getTypeLoader().parse(xsr, type, getXmlOptions(options));
171
        return getTypeLoader(type).parse(xsr, type, getXmlOptions(options));
165
    }
172
    }
166
173
167
    public static XmlObject parse(Reader jior, SchemaType type, XmlOptions options) throws XmlException, IOException {
174
    public static XmlObject parse(Reader jior, SchemaType type, XmlOptions options) throws XmlException, IOException {
168
        try {
175
        try {
169
            Document doc = DocumentHelper.readDocument(new InputSource(jior));
176
            Document doc = DocumentHelper.readDocument(new InputSource(jior));
170
            return getTypeLoader().parse(doc.getDocumentElement(), type, getXmlOptions(options));
177
            return getTypeLoader(type).parse(doc.getDocumentElement(), type, getXmlOptions(options));
171
        } catch (SAXException e) {
178
        } catch (SAXException e) {
172
            throw new XmlException("Unable to parse xml bean", e);
179
            throw new XmlException("Unable to parse xml bean", e);
173
        }
180
        }
Lines 174-187 Link Here
174
    }
181
    }
175
182
176
    public static XmlObject parse(Node node, SchemaType type, XmlOptions options) throws XmlException {
183
    public static XmlObject parse(Node node, SchemaType type, XmlOptions options) throws XmlException {
177
        return getTypeLoader().parse(node, type, getXmlOptions(options));
184
        return getTypeLoader(type).parse(node, type, getXmlOptions(options));
178
    }
185
    }
179
186
180
    public static XmlObject parse(XMLInputStream xis, SchemaType type, XmlOptions options) throws XmlException, XMLStreamException {
187
    public static XmlObject parse(XMLInputStream xis, SchemaType type, XmlOptions options) throws XmlException, XMLStreamException {
181
        return getTypeLoader().parse(xis, type, getXmlOptions(options));
188
        return getTypeLoader(type).parse(xis, type, getXmlOptions(options));
182
    }
189
    }
183
    
190
    
184
    public static XMLInputStream newValidatingXMLInputStream ( XMLInputStream xis, SchemaType type, XmlOptions options ) throws XmlException, XMLStreamException {
191
    public static XMLInputStream newValidatingXMLInputStream ( XMLInputStream xis, SchemaType type, XmlOptions options ) throws XmlException, XMLStreamException {
185
        return getTypeLoader().newValidatingXMLInputStream(xis, type, getXmlOptions(options));
192
        return getTypeLoader(type).newValidatingXMLInputStream(xis, type, getXmlOptions(options));
186
    }
193
    }
187
}
194
}
(-)src/ooxml/testcases/org/apache/poi/TestPOIXMLDocument.java (-27 / +52 lines)
Lines 28-33 Link Here
28
import java.io.FileOutputStream;
28
import java.io.FileOutputStream;
29
import java.io.IOException;
29
import java.io.IOException;
30
import java.io.InputStream;
30
import java.io.InputStream;
31
import java.lang.Thread.UncaughtExceptionHandler;
31
import java.lang.reflect.InvocationTargetException;
32
import java.lang.reflect.InvocationTargetException;
32
import java.util.ArrayList;
33
import java.util.ArrayList;
33
import java.util.HashMap;
34
import java.util.HashMap;
Lines 40-45 Link Here
40
import org.apache.poi.openxml4j.opc.OPCPackage;
41
import org.apache.poi.openxml4j.opc.OPCPackage;
41
import org.apache.poi.openxml4j.opc.PackagePart;
42
import org.apache.poi.openxml4j.opc.PackagePart;
42
import org.apache.poi.openxml4j.opc.PackageRelationshipTypes;
43
import org.apache.poi.openxml4j.opc.PackageRelationshipTypes;
44
import org.apache.poi.util.IOUtils;
43
import org.apache.poi.util.NullOutputStream;
45
import org.apache.poi.util.NullOutputStream;
44
import org.apache.poi.util.PackageHelper;
46
import org.apache.poi.util.PackageHelper;
45
import org.apache.poi.util.TempFile;
47
import org.apache.poi.util.TempFile;
Lines 321-359 Link Here
321
        }
323
        }
322
    }
324
    }
323
    
325
    
324
    @Test(expected=IllegalStateException.class)
326
    @Test
325
    public void testOSGIClassLoadingAsIs() throws IOException {
327
    public void testOSGIClassLoading() {
328
        // the schema type loader is cached per thread in POIXMLTypeLoader.
329
        // So create a new Thread and change the context class loader (which would normally be used)
330
        // to not contain the OOXML classes
331
        Runnable run = new Runnable() {
332
            public void run() {
333
                InputStream is = POIDataSamples.getSlideShowInstance().openResourceAsStream("table_test.pptx");
334
                XMLSlideShow ppt = null;
335
                try {
336
                    ppt = new XMLSlideShow(is);
337
                    ppt.getSlides().get(0).getShapes();
338
                } catch (IOException e) {
339
                    fail("failed to load XMLSlideShow");
340
                } finally {
341
                    IOUtils.closeQuietly(ppt);
342
                    IOUtils.closeQuietly(is);
343
                }
344
            }
345
        };
346
326
        Thread thread = Thread.currentThread();
347
        Thread thread = Thread.currentThread();
327
        ClassLoader cl = thread.getContextClassLoader();
348
        ClassLoader cl = thread.getContextClassLoader();
328
        InputStream is = POIDataSamples.getSlideShowInstance().openResourceAsStream("table_test.pptx");
349
        UncaughtHandler uh = new UncaughtHandler();
329
        try {
350
        
330
            thread.setContextClassLoader(cl.getParent());
351
        // check schema type loading and check if we could run in an OOM
331
            XMLSlideShow ppt = new XMLSlideShow(is);
352
        Thread ta[] = new Thread[30];
332
            ppt.getSlides().get(0).getShapes();
353
        for (int j=0; j<10; j++) {
333
            ppt.close();
354
            for (int i=0; i<ta.length; i++) {
334
        } finally {
355
                ta[i] = new Thread(run);
335
            thread.setContextClassLoader(cl);
356
                ta[i].setContextClassLoader(cl.getParent());
336
            is.close();
357
                ta[i].setUncaughtExceptionHandler(uh);
358
                ta[i].start();
359
            }
360
            for (int i=0; i<ta.length; i++) {
361
                try {
362
                    ta[i].join();
363
                } catch (InterruptedException e) {
364
                    fail("failed to join thread");
365
                }
366
            }
337
        }
367
        }
368
        assertFalse(uh.hasException());
338
    }
369
    }
339
370
340
371
    private static class UncaughtHandler implements UncaughtExceptionHandler {
341
    @Test
372
        Throwable e;
342
    public void testOSGIClassLoadingFixed() throws IOException {
373
        
343
        Thread thread = Thread.currentThread();
374
        public synchronized void uncaughtException(Thread t, Throwable e) {
344
        ClassLoader cl = thread.getContextClassLoader();
375
            this.e = e;
345
        InputStream is = POIDataSamples.getSlideShowInstance().openResourceAsStream("table_test.pptx");
376
            
346
        try {
347
            thread.setContextClassLoader(cl.getParent());
348
            POIXMLTypeLoader.setClassLoader(cl);
349
            XMLSlideShow ppt = new XMLSlideShow(is);
350
            ppt.getSlides().get(0).getShapes();
351
            ppt.close();
352
        } finally {
353
            thread.setContextClassLoader(cl);
354
            POIXMLTypeLoader.setClassLoader(null);
355
            is.close();
356
        }
377
        }
378
        
379
        public synchronized boolean hasException() {
380
            return e != null;
381
        }
357
    }
382
    }
358
383
359
}
384
}

Return to bug 61478