@Override
    public void parse(InputStream stream, ContentHandler recursiveParserWrapperHandler,
                      Metadata metadata, ParseContext context)
            throws IOException, SAXException, TikaException {
        //this tracks the state of the parent parser, per call to #parse
        ParserState parserState;
        if (recursiveParserWrapperHandler instanceof AbstractRecursiveParserWrapperHandler) {
            parserState = new ParserState(
                    (AbstractRecursiveParserWrapperHandler) recursiveParserWrapperHandler);
        } else {
            throw new IllegalStateException(
                    "ContentHandler must implement RecursiveParserWrapperHandler");
        }
        EmbeddedParserDecorator decorator =
                new EmbeddedParserDecorator(getWrappedParser(), "/", "/", parserState);
        context.set(Parser.class, decorator);
        ContentHandler localHandler =
                parserState.recursiveParserWrapperHandler.getNewContentHandler();
        long started = System.currentTimeMillis();
        parserState.recursiveParserWrapperHandler.startDocument();
        TemporaryResources tmp = new TemporaryResources();
        int writeLimit = -1;
        boolean throwOnWriteLimitReached = true;

        if (recursiveParserWrapperHandler instanceof AbstractRecursiveParserWrapperHandler) {
            ContentHandlerFactory factory =
                    ((AbstractRecursiveParserWrapperHandler)recursiveParserWrapperHandler).getContentHandlerFactory();
            if (factory instanceof WriteLimiter) {
                writeLimit = ((WriteLimiter)factory).getWriteLimit();
                throwOnWriteLimitReached = ((WriteLimiter)factory).isThrowOnWriteLimitReached();
            }
        }
        try {
            TikaInputStream tis = TikaInputStream.get(stream, tmp, metadata);
            RecursivelySecureContentHandler secureContentHandler =
                    new RecursivelySecureContentHandler(localHandler, tis, new SecureHandlerCounter(writeLimit),
                            throwOnWriteLimitReached, context);
            context.set(RecursivelySecureContentHandler.class, secureContentHandler);
            getWrappedParser().parse(tis, secureContentHandler, metadata, context);
        } catch (Throwable e) {
            if (e instanceof EncryptedDocumentException) {
                metadata.set(TikaCoreProperties.IS_ENCRYPTED, "true");
            }
            if (WriteLimitReachedException.isWriteLimitReached(e)) {
                metadata.set(TikaCoreProperties.WRITE_LIMIT_REACHED, "true");
            } else {
                String stackTrace = ExceptionUtils.getFilteredStackTrace(e);
                metadata.add(TikaCoreProperties.CONTAINER_EXCEPTION, stackTrace);
                throw e;
            }
        } finally {
            tmp.dispose();
            long elapsedMillis = System.currentTimeMillis() - started;
            metadata.set(TikaCoreProperties.PARSE_TIME_MILLIS, Long.toString(elapsedMillis));
            parserState.recursiveParserWrapperHandler.endDocument(localHandler, metadata);
            parserState.recursiveParserWrapperHandler.endDocument();
            context.set(RecursivelySecureContentHandler.class, null);
        }
    }
@param stream
@param recursiveParserWrapperHandler -- handler must implement
{@link RecursiveParserWrapperHandler}
@param metadata
@param context
@throws IOException
@throws SAXException
@throws TikaException
@throws IllegalStateException if the handler is not a {@link RecursiveParserWrapperHandler}
tika-core/src/main/java/org/apache/tika/parser/RecursiveParserWrapper.java