You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tika.apache.org by ta...@apache.org on 2025/12/15 11:29:36 UTC

(tika) 02/02: TIKA-4541 - TikaInputStream everywhere

This is an automated email from the ASF dual-hosted git repository.

tallison pushed a commit to branch TIKA-4541-tis-everywhere
in repository https://gitbox.apache.org/repos/asf/tika.git

commit 9b0db80292e4537b879586bec78600b4a93d0620
Author: tallison <ta...@apache.org>
AuthorDate: Mon Dec 15 06:29:09 2025 -0500

    TIKA-4541 - TikaInputStream everywhere
---
 .../src/main/java/org/apache/tika/cli/TikaCLI.java |  20 +-
 .../src/main/java/org/apache/tika/gui/TikaGUI.java |  36 +-
 .../test/java/org/apache/tika/bundle/BundleIT.java |  45 +-
 tika-core/src/main/java/org/apache/tika/Tika.java  |  14 +-
 .../org/apache/tika/detect/AutoDetectReader.java   |  18 +-
 .../org/apache/tika/detect/CompositeDetector.java  |   6 +-
 .../tika/detect/CompositeEncodingDetector.java     |   8 +-
 .../main/java/org/apache/tika/detect/Detector.java |  15 +-
 .../java/org/apache/tika/detect/EmptyDetector.java |   4 +-
 .../org/apache/tika/detect/EncodingDetector.java   |  12 +-
 .../apache/tika/detect/FileCommandDetector.java    |  28 +-
 .../java/org/apache/tika/detect/MagicDetector.java |  20 +-
 .../java/org/apache/tika/detect/NameDetector.java  |   6 +-
 .../org/apache/tika/detect/OverrideDetector.java   |   4 +-
 .../tika/detect/OverrideEncodingDetector.java      |   4 +-
 .../java/org/apache/tika/detect/TextDetector.java  |  16 +-
 .../apache/tika/detect/TrainedModelDetector.java   |  11 +-
 .../java/org/apache/tika/detect/TypeDetector.java  |   7 +-
 .../apache/tika/detect/ZeroSizeFileDetector.java   |  12 +-
 .../org/apache/tika/digest/CompositeDigester.java  |  19 +-
 .../java/org/apache/tika/digest/DigestHelper.java  |  18 +-
 .../main/java/org/apache/tika/digest/Digester.java |  14 +-
 .../apache/tika/digest/InputStreamDigester.java    |  35 +-
 .../tika/extractor/ParserContainerExtractor.java   |  45 +-
 .../apache/tika/extractor/RUnpackExtractor.java    |   4 +-
 .../apache/tika/fork}/AutoDetectParserFactory.java |  11 +-
 .../main/java/org/apache/tika/fork/ForkParser.java |  14 +-
 .../main/java/org/apache/tika/fork/ForkServer.java |   6 +-
 .../tika/{parser => fork}/ParserFactory.java       |   3 +-
 .../org/apache/tika/fork/ParserFactoryFactory.java |   1 -
 .../main/java/org/apache/tika/fork/ParserShim.java |  21 +-
 .../java/org/apache/tika/fork/ParserWrapper.java   |  28 +-
 .../main/java/org/apache/tika/fork/RPWShim.java    |  31 +-
 .../main/java/org/apache/tika/mime/MagicMatch.java |   6 +-
 .../main/java/org/apache/tika/mime/MimeTypes.java  |  20 +-
 .../mime/ProbabilisticMimeDetectionSelector.java   |  12 +-
 .../org/apache/tika/parser/AbstractParser.java     |  10 +-
 .../org/apache/tika/parser/AutoDetectParser.java   |  88 ++-
 .../org/apache/tika/parser/CompositeParser.java    |  11 +-
 .../java/org/apache/tika/parser/CryptoParser.java  |   9 +-
 .../org/apache/tika/parser/DelegatingParser.java   |   6 +-
 .../org/apache/tika/parser/DigestingParser.java    |   6 +-
 .../java/org/apache/tika/parser/EmptyParser.java   |   4 +-
 .../java/org/apache/tika/parser/ErrorParser.java   |   4 +-
 .../java/org/apache/tika/parser/NetworkParser.java |  18 +-
 .../main/java/org/apache/tika/parser/Parser.java   |   4 +-
 .../org/apache/tika/parser/ParserDecorator.java    |   6 +-
 .../apache/tika/parser/ParserPostProcessor.java    |   6 +-
 .../java/org/apache/tika/parser/ParsingReader.java |  13 +-
 .../apache/tika/parser/RecursiveParserWrapper.java |  19 +-
 .../org/apache/tika/parser/RegexCaptureParser.java |   6 +-
 .../tika/parser/external/ExternalParser.java       |  10 +-
 .../tika/parser/external2/ExternalParser.java      |  12 +-
 .../parser/multiple/AbstractMultipleParser.java    |  14 +-
 .../apache/tika/renderer/CompositeRenderer.java    |   6 +-
 .../java/org/apache/tika/renderer/Renderer.java    |   6 +-
 .../java/org/apache/tika/utils/ParserUtils.java    |  49 +-
 .../org/apache/custom/detect/MyCustomDetector.java |   4 +-
 .../org/apache/tika/MultiThreadedTikaTest.java     |  13 +-
 .../src/test/java/org/apache/tika/TikaTest.java    |  84 ++-
 .../tika/detect/FileCommandDetectorTest.java       |  10 +-
 .../org/apache/tika/detect/MagicDetectorTest.java  |  24 +-
 .../tika/detect/MimeDetectionWithNNTest.java       |  18 +-
 .../org/apache/tika/detect/TextDetectorTest.java   |  13 +-
 .../tika/detect/ZeroSizeFileDetectorTest.java      |   7 +-
 .../java/org/apache/tika/fork/ForkParserTest.java  |  66 +-
 .../apache/tika/fork/ForkParserTikaBinTest.java    |  11 +-
 .../java/org/apache/tika/fork/ForkTestParser.java  |  22 +-
 .../org/apache/tika/io/TikaInputStreamTest.java    |  46 +-
 .../org/apache/tika/mime/MimeDetectionTest.java    |  44 +-
 .../org/apache/tika/mime/MimeTypesReaderTest.java  |   5 +-
 .../tika/mime/ProbabilisticMimeDetectionTest.java  |  37 +-
 .../org/apache/tika/mime/RFC822DetectionTest.java  |   5 +-
 .../apache/tika/parser/CompositeParserTest.java    |  12 +-
 .../java/org/apache/tika/parser/DummyParser.java   |   4 +-
 .../apache/tika/parser/ParserDecoratorTest.java    |   6 +-
 .../apache/tika/parser/RegexCaptureParserTest.java |   5 +-
 .../tika/parser/mock/AutoDetectParserFactory.java  |   2 +-
 .../org/apache/tika/parser/mock/MockParser.java    |   7 +-
 .../apache/tika/parser/mock/MockParserFactory.java |   2 +-
 .../tika/parser/multiple/MultipleParserTest.java   |  16 +-
 .../tika/sax/BasicContentHandlerFactoryTest.java   |   4 +-
 .../apache/tika/sax/BodyContentHandlerTest.java    |   6 +-
 .../apache/tika/sax/CustomErrorHandlerTest.java    |   5 +-
 .../apache/tika/detect/magika/MagikaDetector.java  |  27 +-
 .../tika/detect/siegfried/SiegfriedDetector.java   |  27 +-
 .../apache/tika/example/AdvancedTypeDetector.java  |   5 +-
 .../apache/tika/example/ContentHandlerExample.java |  11 +-
 .../org/apache/tika/example/DirListParser.java     |  13 +-
 .../apache/tika/example/DisplayMetInstance.java    |   3 +-
 .../example/EncryptedPrescriptionDetector.java     |   5 +-
 .../tika/example/EncryptedPrescriptionParser.java  |   7 +-
 .../apache/tika/example/ExtractEmbeddedFiles.java  |   5 +-
 .../tika/example/GrabPhoneNumbersExample.java      |   3 +-
 .../org/apache/tika/example/ImportContextImpl.java |   3 +-
 .../tika/example/InterruptableParsingExample.java  |   8 +-
 .../java/org/apache/tika/example/Language.java     |   3 +-
 .../tika/example/LanguageDetectingParser.java      |   6 +-
 .../tika/example/MetadataAwareLuceneIndexer.java   |  11 +-
 .../java/org/apache/tika/example/MyFirstTika.java  |  17 +-
 .../org/apache/tika/example/ParsingExample.java    |  12 +-
 .../tika/example/PickBestTextEncodingParser.java   |  10 +-
 .../org/apache/tika/example/RollbackSoftware.java  |  12 +-
 .../org/apache/tika/example/SpringExample.java     |   4 +-
 .../tika/example/StandardsExtractionExample.java   |   3 +-
 .../org/apache/tika/example/TIAParsingExample.java | 151 ++---
 .../tika/pipes/grpc/ExpiringFetcherStoreTest.java  |   4 +-
 .../org/apache/custom/parser/MyCustomParser.java   |   4 +-
 .../apache/tika/parser/envi/EnviHeaderParser.java  |   8 +-
 .../org/apache/tika/parser/gdal/GDALParser.java    |   9 +-
 .../geoinfo/GeographicInformationParser.java       |  10 +-
 .../org/apache/tika/parser/grib/GribParser.java    |   6 +-
 .../java/org/apache/tika/parser/hdf/HDFParser.java |   6 +-
 .../apache/tika/parser/isatab/ISArchiveParser.java |  12 +-
 .../apache/tika/parser/netcdf/NetCDFParser.java    |   7 +-
 .../tika/parser/envi/EnviHeaderParserTest.java     |  18 +-
 .../apache/tika/parser/gdal/TestGDALParser.java    |  19 +-
 .../apache/tika/parser/grib/GribParserTest.java    |   9 +-
 .../org/apache/tika/parser/hdf/HDFParserTest.java  |  11 +-
 .../tika/parser/isatab/ISArchiveParserTest.java    |   7 +-
 .../tika/parser/netcdf/NetCDFParserTest.java       |   9 +-
 .../src/test/resources/2.4.0-no-tesseract.txt      |  38 +-
 .../src/test/resources/2.4.0-tesseract.txt         |  38 +-
 .../src/test/resources/2.4.1-no-tesseract.txt      |  38 +-
 .../src/test/resources/2.4.1-tesseract.txt         |  38 +-
 .../apache/tika/parser/geopkg/GeoPkgParser.java    |   6 +-
 .../tika/parser/sqlite3/SQLite3DBParser.java       |  20 +-
 .../apache/tika/parser/sqlite3/SQLite3Parser.java  |   6 +-
 .../tika/parser/sqlite3/SQLite3ParserTest.java     |   7 +-
 .../apache/tika/mime/TestMimeTypesExtended.java    |  11 +-
 .../tika/parser/sqlite3/SQLite3ParserTest.java     |  29 +-
 .../apache/tika/parser/ctakes/CTAKESParser.java    |   6 +-
 .../apache/tika/parser/geo/topic/GeoParser.java    |   6 +-
 .../apache/tika/parser/journal/JournalParser.java  |   8 +-
 .../apache/tika/parser/ner/NamedEntityParser.java  |   8 +-
 .../parser/sentiment/SentimentAnalysisParser.java  |   6 +-
 .../tika/parser/geo/topic/GeoParserTest.java       |  13 +-
 .../tika/parser/journal/JournalParserTest.java     |   7 +-
 .../org/apache/tika/parser/journal/TEITest.java    |   6 +-
 .../tika/parser/ner/NamedEntityParserTest.java     |   7 +-
 .../tika/parser/ner/nltk/NLTKNERecogniserTest.java |   4 +-
 .../parser/ner/regex/RegexNERecogniserTest.java    |   4 +-
 .../sentiment/SentimentAnalysisParserTest.java     |  12 +-
 .../parser/transcribe/aws/AmazonTranscribe.java    |   7 +-
 .../apache/tika/detect/apple/BPListDetector.java   |  23 +-
 .../tika/parser/apple/AppleSingleFileParser.java   |  51 +-
 .../org/apache/tika/parser/apple/PListParser.java  |  13 +-
 .../tika/parser/iwork/IWorkPackageParser.java      |   9 +-
 .../parser/iwork/iwana/IWork13PackageParser.java   |  21 +-
 .../parser/iwork/iwana/IWork18PackageParser.java   |  20 +-
 .../apache/tika/parser/iwork/IWorkParserTest.java  |   5 +-
 .../tika/parser/iwork/iwana/IWork13ParserTest.java |   7 +-
 .../tika-parser-audiovideo-module/pom.xml          |  11 -
 .../org/apache/tika/detect/MatroskaDetector.java   |  14 +-
 .../org/apache/tika/detect/ogg/OggDetector.java    | 235 +++++++
 .../org/apache/tika/parser/audio/AudioParser.java  |  13 +-
 .../org/apache/tika/parser/audio/MidiParser.java   |  12 +-
 .../java/org/apache/tika/parser/mp3/Mp3Parser.java |   9 +-
 .../java/org/apache/tika/parser/mp4/MP4Parser.java |  10 +-
 .../org/apache/tika/parser/ogg/FlacParser.java     | 104 +++
 .../org/apache/tika/parser/ogg/OggAudioParser.java | 158 +++++
 .../java/org/apache/tika/parser/ogg/OggParser.java | 156 +++++
 .../org/apache/tika/parser/ogg/OpusParser.java     |  95 +++
 .../org/apache/tika/parser/ogg/SpeexParser.java    |  95 +++
 .../org/apache/tika/parser/ogg/TheoraParser.java   |  95 +++
 .../org/apache/tika/parser/ogg/VorbisParser.java   |  93 +++
 .../org/apache/tika/parser/video/FLVParser.java    |   8 +-
 .../apache/tika/detect/MatroskaDetectorTest.java   |  11 +-
 .../org/apache/tika/parser/mp3/Mp3ParserTest.java  |   5 +-
 .../org/apache/tika/parser/mp3/MpegStreamTest.java |  15 +-
 .../org/apache/tika/parser/dgn/DGN8Parser.java     |   7 +-
 .../java/org/apache/tika/parser/dwg/DWGParser.java |  79 +--
 .../org/apache/tika/parser/dwg/DWGReadParser.java  |   6 +-
 .../java/org/apache/tika/parser/prt/PRTParser.java |  43 +-
 .../org/apache/tika/parser/dwg/DWGParserTest.java  |  40 +-
 .../org/apache/tika/parser/prt/PRTParserTest.java  |   7 +-
 .../org/apache/tika/parser/asm/ClassParser.java    |   6 +-
 .../apache/tika/parser/code/SourceCodeParser.java  |   6 +-
 .../tika/parser/executable/ExecutableParser.java   |  59 +-
 .../executable/UniversalExecutableParser.java      |  30 +-
 .../java/org/apache/tika/parser/mat/MatParser.java | 138 ++--
 .../org/apache/tika/parser/sas/SAS7BDATParser.java |   6 +-
 .../tika/parser/code/SourceCodeParserTest.java     |   3 +-
 .../org/apache/tika/parser/mat/MatParserTest.java  |   7 +-
 .../apache/tika/parser/sas/SAS7BDATParserTest.java |  10 +-
 .../org/apache/tika/parser/crypto/Pkcs7Parser.java |   8 +-
 .../org/apache/tika/parser/crypto/TSDParser.java   |  12 +-
 .../apache/tika/parser/crypto/Pkcs7ParserTest.java |   5 +-
 .../apache/tika/parser/crypto/TSDParserTest.java   |  14 +-
 .../tika/parser/font/AdobeFontMetricParser.java    |   6 +-
 .../apache/tika/parser/font/TrueTypeParser.java    |   4 +-
 .../tika/parser/html/HtmlEncodingDetector.java     |  14 +-
 .../org/apache/tika/parser/html/JSoupParser.java   |   8 +-
 .../StandardHtmlEncodingDetector.java              |   9 +-
 .../tika/parser/html/HtmlEncodingDetectorTest.java |   5 +-
 .../apache/tika/parser/html/HtmlParserTest.java    |  97 ++-
 .../html/StandardHtmlEncodingDetectorTest.java     |  14 +-
 .../tika/parser/image/AbstractImageParser.java     |   7 +-
 .../org/apache/tika/parser/image/ICNSParser.java   |  10 +-
 .../org/apache/tika/parser/image/JXLParser.java    |   6 +-
 .../org/apache/tika/parser/image/PSDParser.java    |  43 +-
 .../org/apache/tika/parser/image/WebPParser.java   |   7 +-
 .../apache/tika/parser/image/HeifParserTest.java   |  33 +-
 .../apache/tika/parser/image/ICNSParserTest.java   |  14 +-
 .../apache/tika/parser/image/ImageParserTest.java  |  31 +-
 .../apache/tika/parser/image/JpegParserTest.java   |  50 +-
 .../apache/tika/parser/image/PSDParserTest.java    |  11 +-
 .../apache/tika/parser/jdbc/AbstractDBParser.java  |  12 +-
 .../apache/tika/parser/jdbc/JDBCTableReader.java   |  10 +-
 .../org/apache/tika/parser/mail/RFC822Parser.java  |  10 +-
 .../org/apache/tika/parser/mbox/MboxParser.java    |   5 +-
 .../apache/tika/parser/mail/RFC822ParserTest.java  |  41 +-
 .../apache/tika/parser/mbox/MboxParserTest.java    |  22 +-
 .../detect/microsoft/POIFSContainerDetector.java   |  50 +-
 .../apache/tika/parser/microsoft/EMFParser.java    |   5 +-
 .../tika/parser/microsoft/JackcessParser.java      |   4 +-
 .../tika/parser/microsoft/MSOwnerFileParser.java   |  12 +-
 .../apache/tika/parser/microsoft/OfficeParser.java |  38 +-
 .../tika/parser/microsoft/OldExcelParser.java      |   6 +-
 .../tika/parser/microsoft/OutlookExtractor.java    |   3 +-
 .../apache/tika/parser/microsoft/TNEFParser.java   |   5 +-
 .../apache/tika/parser/microsoft/WMFParser.java    |   6 +-
 .../microsoft/activemime/ActiveMimeParser.java     |  29 +-
 .../tika/parser/microsoft/chm/ChmParser.java       |   5 +-
 .../tika/parser/microsoft/libpst/LibPstParser.java |  17 +-
 .../parser/microsoft/onenote/OneNoteParser.java    |   5 +-
 .../microsoft/ooxml/OOXMLExtractorFactory.java     |  14 +-
 .../tika/parser/microsoft/ooxml/OOXMLParser.java   |   6 +-
 .../ooxml/XWPFWordExtractorDecorator.java          |   6 +-
 .../ooxml/xwpf/ml2006/Word2006MLParser.java        |   6 +-
 .../parser/microsoft/pst/OutlookPSTParser.java     |   7 +-
 .../parser/microsoft/pst/PSTMailItemParser.java    |   4 +-
 .../tika/parser/microsoft/rtf/RTFParser.java       |   7 +-
 .../microsoft/xml/AbstractXML2003Parser.java       |   6 +-
 .../microsoft/POIFSContainerDetectorTest.java      |  32 +-
 .../AbstractPOIContainerExtractionTest.java        |   8 +-
 .../tika/parser/microsoft/ExcelParserTest.java     |  58 +-
 .../tika/parser/microsoft/JackcessParserTest.java  |  32 +-
 .../tika/parser/microsoft/OfficeParserTest.java    |   4 +-
 .../tika/parser/microsoft/OldExcelParserTest.java  |  12 +-
 .../tika/parser/microsoft/OutlookParserTest.java   |  26 +-
 .../parser/microsoft/PowerPointParserTest.java     |  22 +-
 .../tika/parser/microsoft/ProjectParserTest.java   |  18 +-
 .../tika/parser/microsoft/PublisherParserTest.java |   9 +-
 .../parser/microsoft/SolidworksParserTest.java     |  27 +-
 .../tika/parser/microsoft/TNEFParserTest.java      |   8 +-
 .../tika/parser/microsoft/VisioParserTest.java     |   9 +-
 .../tika/parser/microsoft/WordParserTest.java      |  26 +-
 .../parser/microsoft/WriteProtectedParserTest.java |   9 +-
 .../parser/microsoft/chm/TestChmExtraction.java    |  31 +-
 .../parser/microsoft/chm/TestChmExtractor.java     |   4 +-
 .../parser/microsoft/ooxml/OOXMLParserTest.java    |  29 +-
 .../parser/microsoft/ooxml/SXSLFExtractorTest.java |  22 +-
 .../parser/microsoft/ooxml/xps/XPSParserTest.java  |   6 +-
 .../apache/tika/detect/ole/MiscOLEDetector.java    |  35 +-
 .../java/org/apache/tika/parser/dbf/DBFParser.java |   8 +-
 .../java/org/apache/tika/parser/dif/DIFParser.java |   6 +-
 .../apache/tika/parser/epub/EpubContentParser.java |   6 +-
 .../org/apache/tika/parser/epub/EpubParser.java    |  26 +-
 .../org/apache/tika/parser/hwp/HwpV5Parser.java    |   6 +-
 .../apache/tika/parser/indesign/IDMLParser.java    |  19 +-
 .../java/org/apache/tika/parser/mif/MIFParser.java |   6 +-
 .../tika/parser/odf/FlatOpenDocumentParser.java    |   6 +-
 .../tika/parser/odf/OpenDocumentContentParser.java |   9 +-
 .../tika/parser/odf/OpenDocumentMetaParser.java    |   6 +-
 .../apache/tika/parser/odf/OpenDocumentParser.java |  48 +-
 .../tika/parser/wordperfect/QuattroProParser.java  |   6 +-
 .../tika/parser/wordperfect/WordPerfectParser.java |   6 +-
 .../org/apache/tika/parser/dbf/DBFParserTest.java  |   5 +-
 .../org/apache/tika/parser/dif/DIFParserTest.java  |   7 +-
 .../apache/tika/parser/epub/EpubParserTest.java    |   6 +-
 .../org/apache/tika/parser/odf/ODFParserTest.java  |  60 +-
 .../parser/odf/OpenDocumentContentParserTest.java  |  11 +-
 .../tika/parser/wordperfect/WPInputStreamTest.java |   5 +-
 .../org/apache/tika/parser/feed/FeedParser.java    |   6 +-
 .../apache/tika/parser/iptc/IptcAnpaParser.java    |   9 +-
 .../apache/tika/parser/feed/FeedParserTest.java    |   9 +-
 .../apache/tika/parser/ocr/TesseractOCRParser.java |  14 +-
 .../apache/tika/parser/pdf/AbstractPDF2XHTML.java  |   8 +-
 .../java/org/apache/tika/parser/pdf/PDFParser.java |  27 +-
 .../tika/renderer/pdf/mutool/MuPDFRenderer.java    |   5 +-
 .../tika/renderer/pdf/pdfbox/PDFBoxRenderer.java   |   6 +-
 .../apache/tika/parser/pdf/CustomTikaXMPTest.java  |   6 +-
 .../org/apache/tika/parser/pdf/PDFParserTest.java  |  58 +-
 .../detect/gzip/GZipSpecializationDetector.java    |  15 +-
 .../apache/tika/parser/pkg/CompressorParser.java   |  19 +-
 .../org/apache/tika/parser/pkg/PackageParser.java  |  27 +-
 .../java/org/apache/tika/parser/pkg/RarParser.java |   4 +-
 .../org/apache/tika/parser/pkg/UnrarParser.java    |   5 +-
 .../apache/tika/parser/pkg/AbstractPkgTest.java    |   6 +-
 .../org/apache/tika/parser/pkg/ArParserTest.java   |  11 +-
 .../apache/tika/parser/pkg/Bzip2ParserTest.java    |   7 +-
 .../apache/tika/parser/pkg/CompressParserTest.java |   7 +-
 .../org/apache/tika/parser/pkg/GzipParserTest.java |   7 +-
 .../org/apache/tika/parser/pkg/RarParserTest.java  |  11 +-
 .../apache/tika/parser/pkg/Seven7ParserTest.java   |   7 +-
 .../org/apache/tika/parser/pkg/TarParserTest.java  |   7 +-
 .../apache/tika/parser/pkg/UnrarParserTest.java    |   7 +-
 .../org/apache/tika/parser/pkg/ZipParserTest.java  |  14 +-
 .../org/apache/tika/parser/pkg/ZlibParserTest.java |   7 +-
 .../apache/tika/parser/csv/TextAndCSVParser.java   |  16 +-
 .../tika/parser/strings/Latin1StringsParser.java   |  17 +-
 .../apache/tika/parser/strings/StringsParser.java  |  13 +-
 .../org/apache/tika/parser/txt/BOMDetector.java    |  10 +-
 .../tika/parser/txt/Icu4jEncodingDetector.java     |   8 +-
 .../java/org/apache/tika/parser/txt/TXTParser.java |   6 +-
 .../tika/parser/txt/UniversalEncodingDetector.java |  14 +-
 .../tika/parser/csv/TextAndCSVParserTest.java      |  24 +-
 .../parser/strings/Latin1StringsParserTest.java    |   7 +-
 .../tika/parser/strings/StringsParserTest.java     |   6 +-
 .../apache/tika/parser/txt/BOMDetectorTest.java    |  15 +-
 .../tika/parser/txt/CharsetDetectorTest.java       |  19 +-
 .../org/apache/tika/parser/txt/TXTParserTest.java  |  32 +-
 .../org/apache/tika/parser/http/HttpParser.java    |   9 +-
 .../org/apache/tika/parser/wacz/WACZParser.java    |  30 +-
 .../org/apache/tika/parser/warc/WARCParser.java    |   7 +-
 .../java/org/apache/tika/parser/tmx/TMXParser.java |   6 +-
 .../apache/tika/parser/xliff/XLIFF12Parser.java    |   6 +-
 .../org/apache/tika/parser/xliff/XLZParser.java    |  24 +-
 .../java/org/apache/tika/parser/xml/XMLParser.java |   6 +-
 .../org/apache/tika/parser/xml/XMLProfiler.java    |   6 +-
 .../org/apache/tika/parser/tmx/TMXParserTest.java  |   7 +-
 .../tika/parser/xliff/XLIFF12ParserTest.java       |   7 +-
 .../apache/tika/parser/xliff/XLZParserTest.java    |  12 +-
 .../apache/tika/parser/xml/DcXMLParserTest.java    |  11 +-
 .../EmptyAndDuplicateElementsXMLParserTest.java    |  11 +-
 .../tika/parser/xml/FictionBookParserTest.java     |  13 +-
 .../parser/xml/TextAndAttributeXMLParserTest.java  |   6 +-
 .../tika/parser/xmp/JempboxExtractorTest.java      |  30 +-
 .../detect/zip/DefaultZipContainerDetector.java    |  24 +-
 .../DeprecatedStreamingZipContainerDetector.java   |  15 +-
 .../detect/zip/StreamingZipContainerDetector.java  |  18 +-
 .../apache/tika/detect/zip/ZipDetectionTest.java   |  17 +-
 .../tika/detect/TestContainerAwareDetector.java    |   8 +-
 .../apache/tika/detect/TestDetectorLoading.java    |  15 +-
 .../org/apache/tika/detect/TestZipDetector.java    |   4 +-
 .../java/org/apache/tika/mime/OneOffMimeTest.java  |   8 +-
 .../java/org/apache/tika/mime/TestMimeTypes.java   |  26 +-
 .../java/org/apache/tika/ossfuzz/ParserFuzzer.java |   3 +-
 .../apache/tika/parser/AutoDetectParserTest.java   |  38 +-
 .../tika/parser/AutoDetectReaderParserTest.java    |   4 +-
 .../tika/parser/RecursiveParserWrapperTest.java    |  28 +-
 .../java/org/apache/tika/parser/TestParsers.java   |  10 +-
 .../apache/tika/parser/TestXMLEntityExpansion.java |   8 +-
 .../java/org/apache/tika/parser/XMLTestBase.java   |   8 +-
 .../parser/fork/ForkParserIntegrationTest.java     |  19 +-
 .../apache/tika/parser/image/JpegParserTest.java   |   3 +-
 .../apache/tika/parser/mail/MboxParserTest.java    |   3 +-
 .../apache/tika/parser/mail/RFC822ParserTest.java  |   7 +-
 .../parser/microsoft/ooxml/TruncatedOOXMLTest.java |   2 +-
 .../apache/tika/parser/mock/MockParserTest.java    |   3 +-
 .../org/apache/tika/parser/pkg/ArParserTest.java   |  11 +-
 .../apache/tika/parser/pkg/Bzip2ParserTest.java    |   7 +-
 .../pkg/CompositeZipContainerDetectorTest.java     |  37 +-
 .../apache/tika/parser/pkg/CompressParserTest.java |   7 +-
 .../org/apache/tika/parser/pkg/GzipParserTest.java |  11 +-
 .../org/apache/tika/parser/pkg/RarParserTest.java  |   7 +-
 .../apache/tika/parser/pkg/Seven7ParserTest.java   |  22 +-
 .../org/apache/tika/parser/pkg/TarParserTest.java  |   7 +-
 .../org/apache/tika/parser/pkg/ZipParserTest.java  |   9 +-
 .../org/apache/tika/parser/pkg/ZlibParserTest.java |   7 +-
 .../sax/PhoneExtractingContentHandlerTest.java     |   3 +-
 .../sax/StandardsExtractingContentHandlerTest.java |   9 +-
 .../apache/tika/utils/ServiceLoaderUtilsTest.java  |   2 +-
 .../org/apache/tika/pipes/api/fetcher/Fetcher.java |   6 +-
 .../tika/pipes/api/fetcher/RangeFetcher.java       |   6 +-
 .../tika/pipes/core/fetcher/EmptyFetcher.java      |   4 +-
 .../tika/pipes/core/server/FetchHandler.java       |  11 +-
 .../tika/pipes/core/server/ParseHandler.java       |  21 +-
 tika-pipes/tika-pipes-integration-tests/pom.xml    |  29 +-
 .../apache/tika/pipes/core/CrashingDetector.java   |   4 +-
 .../tika/pipes/core/async/MockDigesterFactory.java |   2 +-
 .../tika/pipes/fetcher/azblob/AZBlobFetcher.java   |   3 +-
 .../tika/pipes/fetcher/fs/FileSystemFetcher.java   |   3 +-
 .../apache/tika/pipes/fetcher/gcs/GCSFetcher.java  |   3 +-
 .../tika/pipes/fetcher/http/HttpFetcher.java       |   8 +-
 .../microsoftgraph/MicrosoftGraphFetcher.java      |   5 +-
 .../apache/tika/pipes/emitter/s3/S3Emitter.java    |   4 +-
 .../apache/tika/pipes/fetcher/s3/S3Fetcher.java    |   8 +-
 .../tika/config/loader/ComponentRegistry.java      |   3 -
 .../src/test/java/org/apache/tika/TikaTest.java    | 694 ---------------------
 .../tika/config/loader/ConfigurableTestParser.java |   4 +-
 .../tika/config/loader/FallbackTestParser.java     |   4 +-
 .../tika/config/loader/MinimalTestParser.java      |   4 +-
 .../apache/tika/config/loader/OptInTestParser.java |   4 +-
 .../apache/tika/config/loader/TikaLoaderTest.java  |  19 +-
 .../writefilter/StandardWriteFilterTest.java       |   8 +-
 .../tika/parser/external2/ExternalParserTest.java  |   4 +-
 .../server/core/DefaultInputStreamFactory.java     |   7 +-
 .../tika/server/core/FetcherStreamFactory.java     |   5 +-
 .../tika/server/core/InputStreamFactory.java       |   5 +-
 .../server/core/resource/MetadataResource.java     |   9 +-
 .../core/resource/RecursiveMetadataResource.java   |  10 +-
 .../tika/server/core/resource/TikaResource.java    |  34 +-
 .../server/core/resource/UnpackerResource.java     |  10 +-
 .../standard/resource/XMPMetadataResource.java     |   3 +-
 .../tika/server/standard/TikaDetectorsTest.java    |   2 +-
 .../tika/server/standard/TikaMimeTypesTest.java    |   2 +-
 .../tika/server/standard/TikaParsersTest.java      |   2 +-
 .../tika/server/standard/UnpackerResourceTest.java |   3 +-
 .../standard/UnpackerResourceWithConfigTest.java   |   5 +-
 401 files changed, 3610 insertions(+), 3777 deletions(-)

diff --git a/tika-app/src/main/java/org/apache/tika/cli/TikaCLI.java b/tika-app/src/main/java/org/apache/tika/cli/TikaCLI.java
index 7c673b31c9..0e6dbf0359 100644
--- a/tika-app/src/main/java/org/apache/tika/cli/TikaCLI.java
+++ b/tika-app/src/main/java/org/apache/tika/cli/TikaCLI.java
@@ -190,10 +190,10 @@ public class TikaCLI {
     };
     private final OutputType DETECT = new OutputType() {
         @Override
-        public void process(InputStream stream, OutputStream output, Metadata metadata) throws Exception {
+        public void process(TikaInputStream tis, OutputStream output, Metadata metadata) throws Exception {
             PrintWriter writer = new PrintWriter(getOutputWriter(output, encoding));
             writer.println(detector
-                    .detect(stream, metadata)
+                    .detect(tis, metadata)
                     .toString());
             writer.flush();
         }
@@ -492,8 +492,8 @@ public class TikaCLI {
             configure();
 
             if (arg.equals("-")) {
-                try (InputStream stream = TikaInputStream.get(CloseShieldInputStream.wrap(System.in))) {
-                    type.process(stream, System.out, new Metadata());
+                try (TikaInputStream tis = TikaInputStream.get(CloseShieldInputStream.wrap(System.in))) {
+                    type.process(tis, System.out, new Metadata());
                 }
             } else {
                 URL url;
@@ -509,8 +509,8 @@ public class TikaCLI {
                     handleRecursiveJson(url, System.out);
                 } else {
                     Metadata metadata = new Metadata();
-                    try (InputStream input = TikaInputStream.get(url, metadata)) {
-                        type.process(input, System.out, metadata);
+                    try (TikaInputStream tis = TikaInputStream.get(url, metadata)) {
+                        type.process(tis, System.out, metadata);
                     } finally {
                         System.out.flush();
                     }
@@ -559,8 +559,8 @@ public class TikaCLI {
         RecursiveParserWrapper wrapper = new RecursiveParserWrapper(parser);
         RecursiveParserWrapperHandler handler = new RecursiveParserWrapperHandler(getContentHandlerFactory(type), -1,
                 tikaLoader.loadMetadataFilters());
-        try (InputStream input = TikaInputStream.get(url, metadata)) {
-            wrapper.parse(input, handler, metadata, context);
+        try (TikaInputStream tis = TikaInputStream.get(url, metadata)) {
+            wrapper.parse(tis, handler, metadata, context);
         }
         JsonMetadataList.setPrettyPrinting(prettyPrint);
         try (Writer writer = getOutputWriter(output, encoding)) {
@@ -1104,14 +1104,14 @@ public class TikaCLI {
     }
 
     private class OutputType {
-        public void process(InputStream input, OutputStream output, Metadata metadata) throws Exception {
+        public void process(TikaInputStream tis, OutputStream output, Metadata metadata) throws Exception {
             Parser p = parser;
             if (fork) {
                 p = new ForkParser(TikaCLI.class.getClassLoader(), p);
             }
             ContentHandler handler = getContentHandler(output, metadata);
             try {
-                p.parse(input, handler, metadata, context);
+                p.parse(tis, handler, metadata, context);
                 // fix for TIKA-596: if a parser doesn't generate
                 // XHTML output, the lack of an output document prevents
                 // metadata from being output: this fixes that
diff --git a/tika-app/src/main/java/org/apache/tika/gui/TikaGUI.java b/tika-app/src/main/java/org/apache/tika/gui/TikaGUI.java
index 5e6adb2423..b1438294af 100644
--- a/tika-app/src/main/java/org/apache/tika/gui/TikaGUI.java
+++ b/tika-app/src/main/java/org/apache/tika/gui/TikaGUI.java
@@ -305,8 +305,8 @@ public class TikaGUI extends JFrame implements ActionListener, HyperlinkListener
     public void openFile(File file) {
         try {
             Metadata metadata = new Metadata();
-            try (TikaInputStream stream = TikaInputStream.get(file.toPath(), metadata)) {
-                handleStream(stream, metadata);
+            try (TikaInputStream tis = TikaInputStream.get(file.toPath(), metadata)) {
+                handleStream(tis, metadata);
             }
         } catch (Throwable t) {
             handleError(file.getPath(), t);
@@ -316,15 +316,15 @@ public class TikaGUI extends JFrame implements ActionListener, HyperlinkListener
     public void openURL(URL url) {
         try {
             Metadata metadata = new Metadata();
-            try (TikaInputStream stream = TikaInputStream.get(url, metadata)) {
-                handleStream(stream, metadata);
+            try (TikaInputStream tis = TikaInputStream.get(url, metadata)) {
+                handleStream(tis, metadata);
             }
         } catch (Throwable t) {
             handleError(url.toString(), t);
         }
     }
 
-    private void handleStream(InputStream input, Metadata md) throws Exception {
+    private void handleStream(TikaInputStream tis, Metadata md) throws Exception {
         StringWriter htmlBuffer = new StringWriter();
         StringWriter textBuffer = new StringWriter();
         StringWriter textMainBuffer = new StringWriter();
@@ -336,21 +336,17 @@ public class TikaGUI extends JFrame implements ActionListener, HyperlinkListener
 
         context.set(DocumentSelector.class, new ImageDocumentSelector());
 
-        input = TikaInputStream.get(input);
-
-        if (input.markSupported()) {
+        if (tis.markSupported()) {
             int mark = -1;
-            if (input instanceof TikaInputStream) {
-                if (((TikaInputStream) input).hasFile()) {
-                    mark = (int) ((TikaInputStream) input).getLength();
-                }
+            if (tis.hasFile()) {
+                mark = (int) tis.getLength();
             }
             if (mark == -1) {
                 mark = MAX_MARK;
             }
-            input.mark(mark);
+            tis.mark(mark);
         }
-        parser.parse(input, handler, md, context);
+        parser.parse(tis, handler, md, context);
 
         String[] names = md.names();
         Arrays.sort(names);
@@ -375,14 +371,14 @@ public class TikaGUI extends JFrame implements ActionListener, HyperlinkListener
         setText(text, textBuffer.toString());
         setText(textMain, textMainBuffer.toString());
         setText(html, htmlBuffer.toString());
-        if (!input.markSupported()) {
+        if (!tis.markSupported()) {
             setText(json, "InputStream does not support mark/reset for Recursive Parsing");
             layout.show(cards, "metadata");
             return;
         }
         boolean isReset = false;
         try {
-            input.reset();
+            tis.reset();
             isReset = true;
         } catch (IOException e) {
             setText(json, "Error during stream reset.\n" + "There's a limit of " + MAX_MARK + " bytes for this type of processing in the GUI.\n" +
@@ -392,7 +388,7 @@ public class TikaGUI extends JFrame implements ActionListener, HyperlinkListener
             RecursiveParserWrapperHandler recursiveParserWrapperHandler =
                     new RecursiveParserWrapperHandler(new BasicContentHandlerFactory(BasicContentHandlerFactory.HANDLER_TYPE.BODY, -1), -1);
             RecursiveParserWrapper wrapper = new RecursiveParserWrapper(parser);
-            wrapper.parse(input, recursiveParserWrapperHandler, new Metadata(), new ParseContext());
+            wrapper.parse(tis, recursiveParserWrapperHandler, new Metadata(), new ParseContext());
             StringWriter jsonBuffer = new StringWriter();
             JsonMetadataList.setPrettyPrinting(true);
             List<Metadata> metadataList = recursiveParserWrapperHandler.getMetadataList();
@@ -653,15 +649,15 @@ public class TikaGUI extends JFrame implements ActionListener, HyperlinkListener
         }
 
         @Override
-        public void parse(InputStream stream, ContentHandler handler, Metadata metadata, ParseContext context) throws IOException, SAXException, TikaException {
+        public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata, ParseContext context) throws IOException, SAXException, TikaException {
             String name = metadata.get(TikaCoreProperties.RESOURCE_NAME_KEY);
             if (name != null && wanted.containsKey(name)) {
                 try (FileOutputStream out = new FileOutputStream(wanted.get(name))) {
-                    IOUtils.copy(stream, out);
+                    IOUtils.copy(tis, out);
                 }
             } else {
                 if (downstreamParser != null) {
-                    downstreamParser.parse(stream, handler, metadata, context);
+                    downstreamParser.parse(tis, handler, metadata, context);
                 }
             }
         }
diff --git a/tika-bundles/tika-bundle-standard/src/test/java/org/apache/tika/bundle/BundleIT.java b/tika-bundles/tika-bundle-standard/src/test/java/org/apache/tika/bundle/BundleIT.java
index 82b1ff91ba..8704ed6f5b 100644
--- a/tika-bundles/tika-bundle-standard/src/test/java/org/apache/tika/bundle/BundleIT.java
+++ b/tika-bundles/tika-bundle-standard/src/test/java/org/apache/tika/bundle/BundleIT.java
@@ -26,11 +26,9 @@ import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
 import static org.ops4j.pax.exam.CoreOptions.options;
 import static org.ops4j.pax.exam.CoreOptions.systemPackages;
 
-import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.StringWriter;
 import java.io.Writer;
 import java.net.URISyntaxException;
@@ -160,19 +158,20 @@ public class BundleIT {
         try (ForkParser parser = new ForkParser(Activator.class.getClassLoader(), defaultParser)) {
             String data =
                     "<!DOCTYPE html>\n<html><body><p>test <span>content</span></p></body></html>";
-            InputStream stream = new ByteArrayInputStream(data.getBytes(UTF_8));
-            Writer writer = new StringWriter();
-            ContentHandler contentHandler = new BodyContentHandler(writer);
-            Metadata metadata = new Metadata();
-            MediaType type = contentTypeDetector.detect(stream, metadata);
-            assertEquals(type.toString(), "text/html");
-            metadata.add(Metadata.CONTENT_TYPE, type.toString());
-            ParseContext parseCtx = new ParseContext();
-            parser.parse(stream, contentHandler, metadata, parseCtx);
-            writer.flush();
-            String content = writer.toString();
-            assertTrue(content.length() > 0);
-            assertEquals("test content", content.trim());
+            try (TikaInputStream tis = TikaInputStream.get(data.getBytes(UTF_8))) {
+                Writer writer = new StringWriter();
+                ContentHandler contentHandler = new BodyContentHandler(writer);
+                Metadata metadata = new Metadata();
+                MediaType type = contentTypeDetector.detect(tis, metadata);
+                assertEquals(type.toString(), "text/html");
+                metadata.add(Metadata.CONTENT_TYPE, type.toString());
+                ParseContext parseCtx = new ParseContext();
+                parser.parse(tis, contentHandler, metadata, parseCtx);
+                writer.flush();
+                String content = writer.toString();
+                assertTrue(content.length() > 0);
+                assertEquals("test content", content.trim());
+            }
         }
     }
 
@@ -259,8 +258,8 @@ public class BundleIT {
         ContentHandler handler = new BodyContentHandler();
         ParseContext context = new ParseContext();
         Parser tesseractParser = new TesseractOCRParser();
-        try (InputStream stream = new FileInputStream("src/test/resources/testOCR.jpg")) {
-            tesseractParser.parse(stream, handler, new Metadata(), context);
+        try (TikaInputStream tis = TikaInputStream.get(Paths.get("src/test/resources/testOCR.jpg"))) {
+            tesseractParser.parse(tis, handler, new Metadata(), context);
         }
     }
 
@@ -274,9 +273,9 @@ public class BundleIT {
         ParseContext context = new ParseContext();
         context.set(Parser.class, parser);
 
-        try (InputStream stream = TikaInputStream.get(
+        try (TikaInputStream tis = TikaInputStream.get(
                 Paths.get("src/test/resources/test-documents.zip"))) {
-            parser.parse(stream, handler, new Metadata(), context);
+            parser.parse(tis, handler, new Metadata(), context);
         }
 
         String content = handler.toString();
@@ -310,9 +309,9 @@ public class BundleIT {
         ParseContext context = new ParseContext();
         context.set(Parser.class, parser);
 
-        try (InputStream stream = TikaInputStream.get(
+        try (TikaInputStream tis = TikaInputStream.get(
                 Paths.get("src/test/resources/testPPT.pptx"))) {
-            parser.parse(stream, handler, new Metadata(), context);
+            parser.parse(tis, handler, new Metadata(), context);
         }
 
         String content = handler.toString();
@@ -340,8 +339,8 @@ public class BundleIT {
             }
             System.out.println("about to parse " + f);
             Metadata metadata = new Metadata();
-            try (InputStream is = TikaInputStream.get(f.toPath())) {
-                parser.parse(is, handler, metadata, context);
+            try (TikaInputStream tis = TikaInputStream.get(f.toPath())) {
+                parser.parse(tis, handler, metadata, context);
             } catch (EncryptedDocumentException e) {
                 //swallow
             } catch (SAXException e) {
diff --git a/tika-core/src/main/java/org/apache/tika/Tika.java b/tika-core/src/main/java/org/apache/tika/Tika.java
index 5eb69463e4..d023437458 100644
--- a/tika-core/src/main/java/org/apache/tika/Tika.java
+++ b/tika-core/src/main/java/org/apache/tika/Tika.java
@@ -16,7 +16,6 @@
  */
 package org.apache.tika;
 
-import java.io.BufferedInputStream;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
@@ -146,10 +145,11 @@ public class Tika {
      * @throws IOException if the stream can not be read
      */
     public String detect(InputStream stream, Metadata metadata) throws IOException {
-        if (stream == null || stream.markSupported()) {
-            return detector.detect(stream, metadata).toString();
-        } else {
-            return detector.detect(new BufferedInputStream(stream), metadata).toString();
+        if (stream == null) {
+            return detector.detect(null, metadata).toString();
+        }
+        try (TikaInputStream tis = TikaInputStream.get(stream)) {
+            return detector.detect(tis, metadata).toString();
         }
     }
 
@@ -513,8 +513,8 @@ public class Tika {
         WriteOutContentHandler handler = new WriteOutContentHandler(maxLength);
         ParseContext context = new ParseContext();
         context.set(Parser.class, parser);
-        try (stream) {
-            parser.parse(stream, new BodyContentHandler(handler), metadata, context);
+        try (TikaInputStream tis = TikaInputStream.get(stream)) {
+            parser.parse(tis, new BodyContentHandler(handler), metadata, context);
         } catch (SAXException e) {
             if (!WriteLimitReachedException.isWriteLimitReached(e)) {
                 // This should never happen with BodyContentHandler...
diff --git a/tika-core/src/main/java/org/apache/tika/detect/AutoDetectReader.java b/tika-core/src/main/java/org/apache/tika/detect/AutoDetectReader.java
index bce58cd211..cd3a9b1249 100644
--- a/tika-core/src/main/java/org/apache/tika/detect/AutoDetectReader.java
+++ b/tika-core/src/main/java/org/apache/tika/detect/AutoDetectReader.java
@@ -16,7 +16,6 @@
  */
 package org.apache.tika.detect;
 
-import java.io.BufferedInputStream;
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStream;
@@ -27,6 +26,7 @@ import org.xml.sax.InputSource;
 
 import org.apache.tika.config.ServiceLoader;
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
 import org.apache.tika.mime.MediaType;
@@ -65,12 +65,12 @@ public class AutoDetectReader extends BufferedReader {
 
     public AutoDetectReader(InputStream stream, Metadata metadata,
                             EncodingDetector encodingDetector) throws IOException, TikaException {
-        this(getBuffered(stream), detect(getBuffered(stream), metadata, encodingDetector));
+        this(getTikaInputStream(stream), detect(getTikaInputStream(stream), metadata, encodingDetector));
     }
 
     public AutoDetectReader(InputStream stream, Metadata metadata, ServiceLoader loader)
             throws IOException, TikaException {
-        this(getBuffered(stream), metadata,
+        this(getTikaInputStream(stream), metadata,
                 new CompositeEncodingDetector(loader.loadServiceProviders(EncodingDetector.class)));
     }
 
@@ -83,11 +83,11 @@ public class AutoDetectReader extends BufferedReader {
         this(stream, new Metadata());
     }
 
-    private static Charset detect(InputStream input, Metadata metadata,
+    private static Charset detect(TikaInputStream tis, Metadata metadata,
                                   EncodingDetector detector)
             throws IOException, TikaException {
         // Ask all given detectors for the character encoding
-        Charset charset = detector.detect(input, metadata);
+        Charset charset = detector.detect(tis, metadata);
         if (charset != null) {
             return charset;
         }
@@ -112,11 +112,11 @@ public class AutoDetectReader extends BufferedReader {
         throw new TikaException("Failed to detect the character encoding of a document");
     }
 
-    private static InputStream getBuffered(InputStream stream) {
-        if (stream.markSupported()) {
-            return stream;
+    private static TikaInputStream getTikaInputStream(InputStream stream) {
+        if (stream instanceof TikaInputStream) {
+            return (TikaInputStream) stream;
         }
-        return new BufferedInputStream(stream);
+        return TikaInputStream.get(stream);
     }
 
 
diff --git a/tika-core/src/main/java/org/apache/tika/detect/CompositeDetector.java b/tika-core/src/main/java/org/apache/tika/detect/CompositeDetector.java
index ed53918540..99ca74a8b8 100644
--- a/tika-core/src/main/java/org/apache/tika/detect/CompositeDetector.java
+++ b/tika-core/src/main/java/org/apache/tika/detect/CompositeDetector.java
@@ -17,13 +17,13 @@
 package org.apache.tika.detect;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
 import org.apache.tika.mime.MediaType;
@@ -71,7 +71,7 @@ public class CompositeDetector implements Detector {
         this(Arrays.asList(detectors));
     }
 
-    public MediaType detect(InputStream input, Metadata metadata) throws IOException {
+    public MediaType detect(TikaInputStream tis, Metadata metadata) throws IOException {
         MediaType override = detectOverrides(metadata);
         if (override != null) {
             return override;
@@ -81,7 +81,7 @@ public class CompositeDetector implements Detector {
         //we have to iterate through all detectors because the override detector may
         //be within a CompositeDetector
         for (Detector detector : getDetectors()) {
-            MediaType detected = detector.detect(input, metadata);
+            MediaType detected = detector.detect(tis, metadata);
             if (registry.isSpecializationOf(detected, type)) {
                 type = detected;
             }
diff --git a/tika-core/src/main/java/org/apache/tika/detect/CompositeEncodingDetector.java b/tika-core/src/main/java/org/apache/tika/detect/CompositeEncodingDetector.java
index 7db79ccc7b..eaf1abfd05 100644
--- a/tika-core/src/main/java/org/apache/tika/detect/CompositeEncodingDetector.java
+++ b/tika-core/src/main/java/org/apache/tika/detect/CompositeEncodingDetector.java
@@ -17,7 +17,6 @@
 package org.apache.tika.detect;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.Serializable;
 import java.nio.charset.Charset;
 import java.util.Collection;
@@ -25,6 +24,7 @@ import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
 
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
 
@@ -55,15 +55,15 @@ public class CompositeEncodingDetector implements EncodingDetector, Serializable
     }
 
     /**
-     * @param input    text document input stream, or <code>null</code>
+     * @param tis      text document input stream, or <code>null</code>
      * @param metadata input metadata for the document
      * @return the detected Charset or null if no charset could be detected
      * @throws IOException
      */
     @Override
-    public Charset detect(InputStream input, Metadata metadata) throws IOException {
+    public Charset detect(TikaInputStream tis, Metadata metadata) throws IOException {
         for (EncodingDetector detector : getDetectors()) {
-            Charset detected = detector.detect(input, metadata);
+            Charset detected = detector.detect(tis, metadata);
             if (detected != null) {
                 metadata.set(TikaCoreProperties.DETECTED_ENCODING, detected.name());
                 //if this has been set by a leaf detector, do not overwrite
diff --git a/tika-core/src/main/java/org/apache/tika/detect/Detector.java b/tika-core/src/main/java/org/apache/tika/detect/Detector.java
index 3d513f042a..991efe9d84 100644
--- a/tika-core/src/main/java/org/apache/tika/detect/Detector.java
+++ b/tika-core/src/main/java/org/apache/tika/detect/Detector.java
@@ -17,10 +17,10 @@
 package org.apache.tika.detect;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.Serializable;
 
 import org.apache.tika.config.SelfConfiguring;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 
@@ -41,20 +41,17 @@ public interface Detector extends Serializable, SelfConfiguring {
      * If the document input stream is not available, then the first
      * argument may be <code>null</code>. Otherwise the detector may
      * read bytes from the start of the stream to help in type detection.
-     * The given stream is guaranteed to support the
-     * {@link InputStream#markSupported() mark feature} and the detector
-     * is expected to {@link InputStream#mark(int) mark} the stream before
-     * reading any bytes from it, and to {@link InputStream#reset() reset}
-     * the stream before returning. The stream must not be closed by the
-     * detector.
+     * The detector is expected to mark the stream before reading any bytes
+     * from it, and to reset the stream before returning. The stream must
+     * not be closed by the detector.
      * <p>
      * The given input metadata is only read, not modified, by the detector.
      *
-     * @param input    document input stream, or <code>null</code>
+     * @param tis      document input stream, or <code>null</code>
      * @param metadata input metadata for the document
      * @return detected media type, or <code>application/octet-stream</code>
      * @throws IOException if the document input stream could not be read
      */
-    MediaType detect(InputStream input, Metadata metadata) throws IOException;
+    MediaType detect(TikaInputStream tis, Metadata metadata) throws IOException;
 
 }
diff --git a/tika-core/src/main/java/org/apache/tika/detect/EmptyDetector.java b/tika-core/src/main/java/org/apache/tika/detect/EmptyDetector.java
index 74f7d7fa5d..06504900e3 100644
--- a/tika-core/src/main/java/org/apache/tika/detect/EmptyDetector.java
+++ b/tika-core/src/main/java/org/apache/tika/detect/EmptyDetector.java
@@ -17,9 +17,9 @@
 package org.apache.tika.detect;
 
 import java.io.IOException;
-import java.io.InputStream;
 
 import org.apache.tika.config.TikaComponent;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 
@@ -34,7 +34,7 @@ public class EmptyDetector implements Detector {
      */
     public static final EmptyDetector INSTANCE = new EmptyDetector();
 
-    public MediaType detect(InputStream input, Metadata metadata) throws IOException {
+    public MediaType detect(TikaInputStream tis, Metadata metadata) throws IOException {
         return MediaType.OCTET_STREAM;
     }
 
diff --git a/tika-core/src/main/java/org/apache/tika/detect/EncodingDetector.java b/tika-core/src/main/java/org/apache/tika/detect/EncodingDetector.java
index 25f7bfa9d5..7e99648e3f 100644
--- a/tika-core/src/main/java/org/apache/tika/detect/EncodingDetector.java
+++ b/tika-core/src/main/java/org/apache/tika/detect/EncodingDetector.java
@@ -17,11 +17,11 @@
 package org.apache.tika.detect;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.Serializable;
 import java.nio.charset.Charset;
 
 import org.apache.tika.config.SelfConfiguring;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 
 /**
@@ -41,19 +41,19 @@ public interface EncodingDetector extends Serializable, SelfConfiguring {
      * argument may be <code>null</code>. Otherwise the detector may
      * read bytes from the start of the stream to help in encoding detection.
      * The given stream is guaranteed to support the
-     * {@link InputStream#markSupported() mark feature} and the detector
-     * is expected to {@link InputStream#mark(int) mark} the stream before
-     * reading any bytes from it, and to {@link InputStream#reset() reset}
+     * {@link TikaInputStream#markSupported() mark feature} and the detector
+     * is expected to {@link TikaInputStream#mark(int) mark} the stream before
+     * reading any bytes from it, and to {@link TikaInputStream#reset() reset}
      * the stream before returning. The stream must not be closed by the
      * detector.
      * <p>
      * The given input metadata is only read, not modified, by the detector.
      *
-     * @param input    text document input stream, or <code>null</code>
+     * @param tis      text document input stream, or <code>null</code>
      * @param metadata input metadata for the document
      * @return detected character encoding, or <code>null</code>
      * @throws IOException if the document input stream could not be read
      */
-    Charset detect(InputStream input, Metadata metadata) throws IOException;
+    Charset detect(TikaInputStream tis, Metadata metadata) throws IOException;
 
 }
diff --git a/tika-core/src/main/java/org/apache/tika/detect/FileCommandDetector.java b/tika-core/src/main/java/org/apache/tika/detect/FileCommandDetector.java
index 3fbede66fb..e9aedf4c03 100644
--- a/tika-core/src/main/java/org/apache/tika/detect/FileCommandDetector.java
+++ b/tika-core/src/main/java/org/apache/tika/detect/FileCommandDetector.java
@@ -16,19 +16,13 @@
  */
 package org.apache.tika.detect;
 
-import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
-
 import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Files;
 import java.nio.file.Path;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import org.apache.tika.config.TikaComponent;
-import org.apache.tika.io.BoundedInputStream;
-import org.apache.tika.io.TemporaryResources;
 import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.ExternalProcess;
 import org.apache.tika.metadata.Metadata;
@@ -83,13 +77,13 @@ public class FileCommandDetector implements Detector {
     }
 
     /**
-     * @param input    document input stream, or <code>null</code>
+     * @param tis      document input stream, or <code>null</code>
      * @param metadata input metadata for the document
      * @return mime as identified by the file command or application/octet-stream otherwise
      * @throws IOException
      */
     @Override
-    public MediaType detect(InputStream input, Metadata metadata) throws IOException {
+    public MediaType detect(TikaInputStream tis, Metadata metadata) throws IOException {
         if (hasFileCommand == null) {
             hasFileCommand = checkHasFile(this.fileCommandPath);
         }
@@ -100,21 +94,11 @@ public class FileCommandDetector implements Detector {
             }
             return MediaType.OCTET_STREAM;
         }
-        TikaInputStream tis = TikaInputStream.cast(input);
-        if (tis != null) {
-            //spool the full file to disk, if called with a TikaInputStream
-            //and there is no underlying file
-            return detectOnPath(tis.getPath(), metadata);
-        }
-
-        input.mark(maxBytes);
-        try (TemporaryResources tmp = new TemporaryResources()) {
-            Path tmpFile = tmp.createTempFile(metadata);
-            Files.copy(new BoundedInputStream(maxBytes, input), tmpFile, REPLACE_EXISTING);
-            return detectOnPath(tmpFile, metadata);
-        } finally {
-            input.reset();
+        if (tis == null) {
+            return MediaType.OCTET_STREAM;
         }
+        //spool the full file to disk, if there is no underlying file
+        return detectOnPath(tis.getPath(), metadata);
     }
 
     private MediaType detectOnPath(Path path, Metadata metadata) throws IOException {
diff --git a/tika-core/src/main/java/org/apache/tika/detect/MagicDetector.java b/tika-core/src/main/java/org/apache/tika/detect/MagicDetector.java
index ae29d7b461..e75840b033 100644
--- a/tika-core/src/main/java/org/apache/tika/detect/MagicDetector.java
+++ b/tika-core/src/main/java/org/apache/tika/detect/MagicDetector.java
@@ -21,7 +21,6 @@ import static java.nio.charset.StandardCharsets.UTF_8;
 
 import java.io.CharArrayWriter;
 import java.io.IOException;
-import java.io.InputStream;
 import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
 import java.util.Arrays;
@@ -30,6 +29,7 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import org.apache.tika.config.TikaComponent;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 
@@ -336,24 +336,24 @@ public class MagicDetector implements Detector {
     }
 
     /**
-     * @param input    document input stream, or <code>null</code>
+     * @param tis      document input stream, or <code>null</code>
      * @param metadata ignored
      */
-    public MediaType detect(InputStream input, Metadata metadata) throws IOException {
-        if (input == null) {
+    public MediaType detect(TikaInputStream tis, Metadata metadata) throws IOException {
+        if (tis == null) {
             return MediaType.OCTET_STREAM;
         }
 
-        input.mark(offsetRangeEnd + length);
+        tis.mark(offsetRangeEnd + length);
         try {
             int offset = 0;
 
             // Skip bytes at the beginning, using skip() or read()
             while (offset < offsetRangeBegin) {
-                long n = input.skip(offsetRangeBegin - offset);
+                long n = tis.skip(offsetRangeBegin - offset);
                 if (n > 0) {
                     offset += n;
-                } else if (input.read() != -1) {
+                } else if (tis.read() != -1) {
                     offset += 1;
                 } else {
                     return MediaType.OCTET_STREAM;
@@ -362,13 +362,13 @@ public class MagicDetector implements Detector {
 
             // Fill in the comparison window
             byte[] buffer = new byte[length + (offsetRangeEnd - offsetRangeBegin)];
-            int n = input.read(buffer);
+            int n = tis.read(buffer);
             if (n > 0) {
                 offset += n;
             }
             while (n != -1 && offset < offsetRangeEnd + length) {
                 int bufferOffset = offset - offsetRangeBegin;
-                n = input.read(buffer, bufferOffset, buffer.length - bufferOffset);
+                n = tis.read(buffer, bufferOffset, buffer.length - bufferOffset);
                 // increment offset - in case not all read (see testDetectStreamReadProblems)
                 if (n > 0) {
                     offset += n;
@@ -419,7 +419,7 @@ public class MagicDetector implements Detector {
 
             return MediaType.OCTET_STREAM;
         } finally {
-            input.reset();
+            tis.reset();
         }
     }
 
diff --git a/tika-core/src/main/java/org/apache/tika/detect/NameDetector.java b/tika-core/src/main/java/org/apache/tika/detect/NameDetector.java
index 36d01e1711..e394f01ae2 100644
--- a/tika-core/src/main/java/org/apache/tika/detect/NameDetector.java
+++ b/tika-core/src/main/java/org/apache/tika/detect/NameDetector.java
@@ -18,12 +18,12 @@ package org.apache.tika.detect;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 
-import java.io.InputStream;
 import java.io.UnsupportedEncodingException;
 import java.net.URLDecoder;
 import java.util.Map;
 import java.util.regex.Pattern;
 
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
 import org.apache.tika.mime.MediaType;
@@ -90,11 +90,11 @@ public class NameDetector implements Detector {
      * all the configured name patterns. If a match is found, then the (first)
      * matching media type is returned.
      *
-     * @param input    ignored
+     * @param tis      ignored
      * @param metadata input metadata, possibly with a RESOURCE_NAME_KEY value
      * @return detected media type, or <code>application/octet-stream</code>
      */
-    public MediaType detect(InputStream input, Metadata metadata) {
+    public MediaType detect(TikaInputStream tis, Metadata metadata) {
         // Look for a resource name in the input metadata
         String name = metadata.get(TikaCoreProperties.RESOURCE_NAME_KEY);
         if (name != null) {
diff --git a/tika-core/src/main/java/org/apache/tika/detect/OverrideDetector.java b/tika-core/src/main/java/org/apache/tika/detect/OverrideDetector.java
index b6c5a41f8a..7bd6dfc270 100644
--- a/tika-core/src/main/java/org/apache/tika/detect/OverrideDetector.java
+++ b/tika-core/src/main/java/org/apache/tika/detect/OverrideDetector.java
@@ -17,8 +17,8 @@
 package org.apache.tika.detect;
 
 import java.io.IOException;
-import java.io.InputStream;
 
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
 import org.apache.tika.mime.MediaType;
@@ -36,7 +36,7 @@ import org.apache.tika.mime.MediaType;
 public class OverrideDetector implements Detector {
 
     @Override
-    public MediaType detect(InputStream input, Metadata metadata) throws IOException {
+    public MediaType detect(TikaInputStream tis, Metadata metadata) throws IOException {
         String type = metadata.get(TikaCoreProperties.CONTENT_TYPE_PARSER_OVERRIDE);
         if (type != null) {
             return MediaType.parse(type);
diff --git a/tika-core/src/main/java/org/apache/tika/detect/OverrideEncodingDetector.java b/tika-core/src/main/java/org/apache/tika/detect/OverrideEncodingDetector.java
index 964398d062..3565ebe8ac 100644
--- a/tika-core/src/main/java/org/apache/tika/detect/OverrideEncodingDetector.java
+++ b/tika-core/src/main/java/org/apache/tika/detect/OverrideEncodingDetector.java
@@ -17,13 +17,13 @@
 package org.apache.tika.detect;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
 
 import org.apache.tika.config.ConfigDeserializer;
 import org.apache.tika.config.JsonConfig;
 import org.apache.tika.config.TikaComponent;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 
 /**
@@ -81,7 +81,7 @@ public class OverrideEncodingDetector implements EncodingDetector {
     }
 
     @Override
-    public Charset detect(InputStream input, Metadata metadata) throws IOException {
+    public Charset detect(TikaInputStream tis, Metadata metadata) throws IOException {
         return charset;
     }
 
diff --git a/tika-core/src/main/java/org/apache/tika/detect/TextDetector.java b/tika-core/src/main/java/org/apache/tika/detect/TextDetector.java
index 96583be7c2..4392d00597 100644
--- a/tika-core/src/main/java/org/apache/tika/detect/TextDetector.java
+++ b/tika-core/src/main/java/org/apache/tika/detect/TextDetector.java
@@ -17,9 +17,9 @@
 package org.apache.tika.detect;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.util.Arrays;
 
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 
@@ -105,27 +105,27 @@ public class TextDetector implements Detector {
      * Looks at the beginning of the document input stream to determine
      * whether the document is text or not.
      *
-     * @param input    document input stream, or <code>null</code>
+     * @param tis      document input stream, or <code>null</code>
      * @param metadata ignored
      * @return "text/plain" if the input stream suggest a text document,
      * "application/octet-stream" otherwise
      */
-    public MediaType detect(InputStream input, Metadata metadata) throws IOException {
-        if (input == null) {
+    public MediaType detect(TikaInputStream tis, Metadata metadata) throws IOException {
+        if (tis == null) {
             return MediaType.OCTET_STREAM;
         }
 
-        input.mark(bytesToTest);
+        tis.mark(bytesToTest);
         try {
             TextStatistics stats = new TextStatistics();
 
             byte[] buffer = new byte[1024];
             int n = 0;
-            int m = input.read(buffer, 0, Math.min(bytesToTest, buffer.length));
+            int m = tis.read(buffer, 0, Math.min(bytesToTest, buffer.length));
             while (m != -1 && n < bytesToTest) {
                 stats.addData(buffer, 0, m);
                 n += m;
-                m = input.read(buffer, 0, Math.min(bytesToTest - n, buffer.length));
+                m = tis.read(buffer, 0, Math.min(bytesToTest - n, buffer.length));
             }
 
             if (stats.isMostlyAscii() || stats.looksLikeUTF8()) {
@@ -134,7 +134,7 @@ public class TextDetector implements Detector {
                 return MediaType.OCTET_STREAM;
             }
         } finally {
-            input.reset();
+            tis.reset();
         }
     }
 
diff --git a/tika-core/src/main/java/org/apache/tika/detect/TrainedModelDetector.java b/tika-core/src/main/java/org/apache/tika/detect/TrainedModelDetector.java
index 0f0fafeb48..f1d88968de 100644
--- a/tika-core/src/main/java/org/apache/tika/detect/TrainedModelDetector.java
+++ b/tika-core/src/main/java/org/apache/tika/detect/TrainedModelDetector.java
@@ -32,6 +32,7 @@ import java.util.HashMap;
 import java.util.Map;
 
 import org.apache.tika.io.TemporaryResources;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 
@@ -47,11 +48,11 @@ public abstract class TrainedModelDetector implements Detector {
         return Integer.MAX_VALUE;
     }
 
-    public MediaType detect(InputStream input, Metadata metadata) throws IOException {
+    public MediaType detect(TikaInputStream tis, Metadata metadata) throws IOException {
         // convert to byte-histogram
-        if (input != null) {
-            input.mark(getMinLength());
-            float[] histogram = readByteFrequencies(input);
+        if (tis != null) {
+            tis.mark(getMinLength());
+            float[] histogram = readByteFrequencies(tis);
             // writeHisto(histogram); //on testing purpose
 
             // threshold will be considered as
@@ -72,7 +73,7 @@ public abstract class TrainedModelDetector implements Detector {
                     maxType = key;
                 }
             }
-            input.reset();
+            tis.reset();
             return maxType;
         }
         return null;
diff --git a/tika-core/src/main/java/org/apache/tika/detect/TypeDetector.java b/tika-core/src/main/java/org/apache/tika/detect/TypeDetector.java
index 60d75c7b0c..aa8d7e7193 100644
--- a/tika-core/src/main/java/org/apache/tika/detect/TypeDetector.java
+++ b/tika-core/src/main/java/org/apache/tika/detect/TypeDetector.java
@@ -16,8 +16,7 @@
  */
 package org.apache.tika.detect;
 
-import java.io.InputStream;
-
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 
@@ -37,11 +36,11 @@ public class TypeDetector implements Detector {
      * If that attribute exists and contains a valid type name, then that
      * type is returned.
      *
-     * @param input    ignored
+     * @param tis      ignored
      * @param metadata input metadata, possibly with a CONTENT_TYPE value
      * @return detected media type, or <code>application/octet-stream</code>
      */
-    public MediaType detect(InputStream input, Metadata metadata) {
+    public MediaType detect(TikaInputStream tis, Metadata metadata) {
         // Look for a type hint in the input metadata
         String hint = metadata.get(Metadata.CONTENT_TYPE);
         if (hint != null) {
diff --git a/tika-core/src/main/java/org/apache/tika/detect/ZeroSizeFileDetector.java b/tika-core/src/main/java/org/apache/tika/detect/ZeroSizeFileDetector.java
index 5ce52681e2..11d6701a27 100644
--- a/tika-core/src/main/java/org/apache/tika/detect/ZeroSizeFileDetector.java
+++ b/tika-core/src/main/java/org/apache/tika/detect/ZeroSizeFileDetector.java
@@ -17,8 +17,8 @@
 package org.apache.tika.detect;
 
 import java.io.IOException;
-import java.io.InputStream;
 
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 
@@ -26,15 +26,15 @@ import org.apache.tika.mime.MediaType;
  * Detector to identify zero length files as application/x-zerovalue
  */
 public class ZeroSizeFileDetector implements Detector {
-    public MediaType detect(InputStream stream, Metadata metadata) throws IOException {
-        if (stream != null) {
+    public MediaType detect(TikaInputStream tis, Metadata metadata) throws IOException {
+        if (tis != null) {
             try {
-                stream.mark(1);
-                if (stream.read() == -1) {
+                tis.mark(1);
+                if (tis.read() == -1) {
                     return MediaType.EMPTY;
                 }
             } finally {
-                stream.reset();
+                tis.reset();
             }
         }
         return MediaType.OCTET_STREAM;
diff --git a/tika-core/src/main/java/org/apache/tika/digest/CompositeDigester.java b/tika-core/src/main/java/org/apache/tika/digest/CompositeDigester.java
index ac824e1295..445cd51749 100644
--- a/tika-core/src/main/java/org/apache/tika/digest/CompositeDigester.java
+++ b/tika-core/src/main/java/org/apache/tika/digest/CompositeDigester.java
@@ -17,10 +17,7 @@
 package org.apache.tika.digest;
 
 import java.io.IOException;
-import java.io.InputStream;
 
-import org.apache.tika.exception.TikaException;
-import org.apache.tika.io.TemporaryResources;
 import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.parser.ParseContext;
@@ -35,19 +32,9 @@ public class CompositeDigester implements Digester {
     }
 
     @Override
-    public void digest(InputStream is, Metadata m, ParseContext parseContext) throws IOException {
-        TemporaryResources tmp = new TemporaryResources();
-        TikaInputStream tis = TikaInputStream.get(is, tmp, m);
-        try {
-            for (Digester digester : digesters) {
-                digester.digest(tis, m, parseContext);
-            }
-        } finally {
-            try {
-                tmp.dispose();
-            } catch (TikaException e) {
-                throw new IOException(e);
-            }
+    public void digest(TikaInputStream tis, Metadata m, ParseContext parseContext) throws IOException {
+        for (Digester digester : digesters) {
+            digester.digest(tis, m, parseContext);
         }
     }
 }
diff --git a/tika-core/src/main/java/org/apache/tika/digest/DigestHelper.java b/tika-core/src/main/java/org/apache/tika/digest/DigestHelper.java
index 4035e13319..d2bb3aee43 100644
--- a/tika-core/src/main/java/org/apache/tika/digest/DigestHelper.java
+++ b/tika-core/src/main/java/org/apache/tika/digest/DigestHelper.java
@@ -47,15 +47,13 @@ public class DigestHelper {
      * @param skipContainerDocumentDigest  if true, skip digesting for top-level documents (depth 0)
      * @param metadata                     metadata to read embedded depth from and write digests to
      * @param context                      parse context (may contain SkipContainerDocumentDigest marker)
-     * @param tmp                          temporary resources for creating temp files if needed
      * @throws IOException if an I/O error occurs
      */
     public static void maybeDigest(TikaInputStream tis,
                                    Digester digester,
                                    boolean skipContainerDocumentDigest,
                                    Metadata metadata,
-                                   ParseContext context,
-                                   TemporaryResources tmp) throws IOException {
+                                   ParseContext context) throws IOException {
         if (digester == null) {
             return;
         }
@@ -69,12 +67,14 @@ public class DigestHelper {
 
         // Handle embedded stream translation if needed (e.g., for OLE2 objects in TikaInputStream's open container)
         if (EMBEDDED_STREAM_TRANSLATOR.shouldTranslate(tis, metadata)) {
-            Path tmpBytes = tmp.createTempFile();
-            try (OutputStream os = Files.newOutputStream(tmpBytes)) {
-                EMBEDDED_STREAM_TRANSLATOR.translate(tis, metadata, os);
-            }
-            try (TikaInputStream translated = TikaInputStream.get(tmpBytes)) {
-                digester.digest(translated, metadata, context);
+            try (TemporaryResources tmp = new TemporaryResources()) {
+                Path tmpBytes = tmp.createTempFile();
+                try (OutputStream os = Files.newOutputStream(tmpBytes)) {
+                    EMBEDDED_STREAM_TRANSLATOR.translate(tis, metadata, os);
+                }
+                try (TikaInputStream translated = TikaInputStream.get(tmpBytes)) {
+                    digester.digest(translated, metadata, context);
+                }
             }
         } else {
             digester.digest(tis, metadata, context);
diff --git a/tika-core/src/main/java/org/apache/tika/digest/Digester.java b/tika-core/src/main/java/org/apache/tika/digest/Digester.java
index 87a0605e4c..ac6459607c 100644
--- a/tika-core/src/main/java/org/apache/tika/digest/Digester.java
+++ b/tika-core/src/main/java/org/apache/tika/digest/Digester.java
@@ -17,8 +17,8 @@
 package org.apache.tika.digest;
 
 import java.io.IOException;
-import java.io.InputStream;
 
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.parser.ParseContext;
 
@@ -29,20 +29,20 @@ import org.apache.tika.parser.ParseContext;
  */
 public interface Digester {
     /**
-     * Digests an InputStream and sets the appropriate value(s) in the metadata.
+     * Digests a TikaInputStream and sets the appropriate value(s) in the metadata.
      * The Digester is also responsible for marking and resetting the stream.
      * <p>
      * The given stream is guaranteed to support the
-     * {@link InputStream#markSupported() mark feature} and the detector
-     * is expected to {@link InputStream#mark(int) mark} the stream before
-     * reading any bytes from it, and to {@link InputStream#reset() reset}
+     * {@link TikaInputStream#markSupported() mark feature} and the detector
+     * is expected to {@link TikaInputStream#mark(int) mark} the stream before
+     * reading any bytes from it, and to {@link TikaInputStream#reset() reset}
      * the stream before returning. The stream must not be closed by the
      * detector.
      *
-     * @param is           InputStream to digest
+     * @param tis          TikaInputStream to digest
      * @param m            Metadata to set the values for
      * @param parseContext ParseContext
      * @throws IOException on I/O error
      */
-    void digest(InputStream is, Metadata m, ParseContext parseContext) throws IOException;
+    void digest(TikaInputStream tis, Metadata m, ParseContext parseContext) throws IOException;
 }
diff --git a/tika-core/src/main/java/org/apache/tika/digest/InputStreamDigester.java b/tika-core/src/main/java/org/apache/tika/digest/InputStreamDigester.java
index 3df2e7c1eb..5a458fd6a2 100644
--- a/tika-core/src/main/java/org/apache/tika/digest/InputStreamDigester.java
+++ b/tika-core/src/main/java/org/apache/tika/digest/InputStreamDigester.java
@@ -24,9 +24,7 @@ import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.security.Provider;
 
-import org.apache.tika.exception.TikaException;
 import org.apache.tika.io.BoundedInputStream;
-import org.apache.tika.io.TemporaryResources;
 import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.parser.ParseContext;
@@ -109,22 +107,16 @@ public class InputStreamDigester implements Digester {
     }
 
     /**
-     * @param is           InputStream to digest. Best to use a TikaInputStream because
-     *                     of potential need to spool to disk.  InputStream must
-     *                     support mark/reset.
+     * @param tis          TikaInputStream to digest
      * @param metadata     metadata in which to store the digest information
      * @param parseContext ParseContext -- not actually used yet, but there for future expansion
      * @throws IOException on IO problem or IllegalArgumentException if algorithm couldn't be found
      */
     @Override
-    public void digest(InputStream is, Metadata metadata, ParseContext parseContext)
+    public void digest(TikaInputStream tis, Metadata metadata, ParseContext parseContext)
             throws IOException {
-        TikaInputStream tis = TikaInputStream.cast(is);
-        if (tis != null && tis.hasFile()) {
-            long sz = -1;
-            if (tis.hasFile()) {
-                sz = tis.getLength();
-            }
+        if (tis.hasFile()) {
+            long sz = tis.getLength();
             //if the inputstream has a file,
             //and its size is greater than its mark limit,
             //just digest the underlying file.
@@ -134,11 +126,10 @@ public class InputStreamDigester implements Digester {
             }
         }
 
-
         //try the usual mark/reset stuff.
         //however, if you actually hit the bound,
         //then stop and spool to file via TikaInputStream
-        BoundedInputStream bis = new BoundedInputStream(markLimit, is);
+        BoundedInputStream bis = new BoundedInputStream(markLimit, tis);
         boolean finishedStream = false;
         bis.mark(markLimit + 1);
         finishedStream = digestStream(bis, metadata);
@@ -148,21 +139,7 @@ public class InputStreamDigester implements Digester {
         }
         //if the stream wasn't finished -- if the stream was longer than the mark limit --
         //spool to File and digest that.
-        if (tis != null) {
-            digestFile(tis.getFile(), -1, metadata);
-        } else {
-            TemporaryResources tmp = new TemporaryResources();
-            try {
-                TikaInputStream tmpTikaInputStream = TikaInputStream.get(is, tmp, metadata);
-                digestFile(tmpTikaInputStream.getFile(), -1, metadata);
-            } finally {
-                try {
-                    tmp.dispose();
-                } catch (TikaException e) {
-                    throw new IOException(e);
-                }
-            }
-        }
+        digestFile(tis.getFile(), -1, metadata);
     }
 
     private void digestFile(File f, long sz, Metadata m) throws IOException {
diff --git a/tika-core/src/main/java/org/apache/tika/extractor/ParserContainerExtractor.java b/tika-core/src/main/java/org/apache/tika/extractor/ParserContainerExtractor.java
index b9c20d1d58..0d1e7d396f 100644
--- a/tika-core/src/main/java/org/apache/tika/extractor/ParserContainerExtractor.java
+++ b/tika-core/src/main/java/org/apache/tika/extractor/ParserContainerExtractor.java
@@ -18,7 +18,6 @@ package org.apache.tika.extractor;
 
 import java.io.File;
 import java.io.IOException;
-import java.io.InputStream;
 import java.util.Set;
 
 import org.xml.sax.ContentHandler;
@@ -28,7 +27,6 @@ import org.xml.sax.helpers.DefaultHandler;
 import org.apache.tika.detect.DefaultDetector;
 import org.apache.tika.detect.Detector;
 import org.apache.tika.exception.TikaException;
-import org.apache.tika.io.TemporaryResources;
 import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
@@ -104,34 +102,27 @@ public class ParserContainerExtractor implements ContainerExtractor {
 
         @Override
         public void parse(
-                InputStream stream, ContentHandler ignored,
+                TikaInputStream stream, ContentHandler ignored,
                 Metadata metadata, ParseContext context)
                 throws IOException, SAXException, TikaException {
-            TemporaryResources tmp = new TemporaryResources();
-            try {
-                TikaInputStream tis = TikaInputStream.get(stream, tmp, metadata);
-
-                // Figure out what we have to process
-                String filename = metadata.get(TikaCoreProperties.RESOURCE_NAME_KEY);
-                MediaType type = detector.detect(tis, metadata);
-
-                if (extractor == null) {
-                    // Let the handler process the embedded resource 
-                    handler.handle(filename, type, tis);
-                } else {
-                    // Use a temporary file to process the stream twice
-                    File file = tis.getFile();
-
-                    // Let the handler process the embedded resource
-                    try (InputStream input = TikaInputStream.get(file.toPath())) {
-                        handler.handle(filename, type, input);
-                    }
-
-                    // Recurse
-                    extractor.extract(tis, extractor, handler);
+            // Figure out what we have to process
+            String filename = metadata.get(TikaCoreProperties.RESOURCE_NAME_KEY);
+            MediaType type = detector.detect(stream, metadata);
+
+            if (extractor == null) {
+                // Let the handler process the embedded resource
+                handler.handle(filename, type, stream);
+            } else {
+                // Use a temporary file to process the stream twice
+                File file = stream.getFile();
+
+                // Let the handler process the embedded resource
+                try (TikaInputStream input = TikaInputStream.get(file.toPath())) {
+                    handler.handle(filename, type, input);
                 }
-            } finally {
-                tmp.dispose();
+
+                // Recurse
+                extractor.extract(stream, extractor, handler);
             }
         }
 
diff --git a/tika-core/src/main/java/org/apache/tika/extractor/RUnpackExtractor.java b/tika-core/src/main/java/org/apache/tika/extractor/RUnpackExtractor.java
index 234c3155f1..851f24d90c 100644
--- a/tika-core/src/main/java/org/apache/tika/extractor/RUnpackExtractor.java
+++ b/tika-core/src/main/java/org/apache/tika/extractor/RUnpackExtractor.java
@@ -141,9 +141,9 @@ public class RUnpackExtractor extends ParsingEmbeddedDocumentExtractor {
         }
     }
 
-    private void parse(InputStream stream, ContentHandler handler, Metadata metadata)
+    private void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata)
             throws TikaException, IOException, SAXException {
-        getDelegatingParser().parse(stream,
+        getDelegatingParser().parse(tis,
                 new EmbeddedContentHandler(new BodyContentHandler(handler)),
                 metadata, context);
     }
diff --git a/tika-core/src/test/java/org/apache/tika/parser/mock/AutoDetectParserFactory.java b/tika-core/src/main/java/org/apache/tika/fork/AutoDetectParserFactory.java
similarity index 81%
copy from tika-core/src/test/java/org/apache/tika/parser/mock/AutoDetectParserFactory.java
copy to tika-core/src/main/java/org/apache/tika/fork/AutoDetectParserFactory.java
index d5931846fc..ed8bd46273 100644
--- a/tika-core/src/test/java/org/apache/tika/parser/mock/AutoDetectParserFactory.java
+++ b/tika-core/src/main/java/org/apache/tika/fork/AutoDetectParserFactory.java
@@ -14,16 +14,19 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.tika.parser.mock;
+package org.apache.tika.fork;
 
+import java.io.IOException;
 import java.util.Map;
 
+import org.xml.sax.SAXException;
+
+import org.apache.tika.exception.TikaException;
 import org.apache.tika.parser.AutoDetectParser;
 import org.apache.tika.parser.Parser;
-import org.apache.tika.parser.ParserFactory;
 
 /**
- * Simple factory that returns a default AutoDetectParser.
+ * Factory for an AutoDetectParser
  */
 public class AutoDetectParserFactory extends ParserFactory {
 
@@ -32,7 +35,7 @@ public class AutoDetectParserFactory extends ParserFactory {
     }
 
     @Override
-    public Parser build() {
+    public Parser build() throws IOException, SAXException, TikaException {
         return new AutoDetectParser();
     }
 }
diff --git a/tika-core/src/main/java/org/apache/tika/fork/ForkParser.java b/tika-core/src/main/java/org/apache/tika/fork/ForkParser.java
index 961d2775c6..7020875ace 100644
--- a/tika-core/src/main/java/org/apache/tika/fork/ForkParser.java
+++ b/tika-core/src/main/java/org/apache/tika/fork/ForkParser.java
@@ -18,7 +18,6 @@ package org.apache.tika.fork;
 
 import java.io.Closeable;
 import java.io.IOException;
-import java.io.InputStream;
 import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -32,12 +31,14 @@ import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
 
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
 import org.apache.tika.mime.MediaType;
 import org.apache.tika.parser.AutoDetectParser;
 import org.apache.tika.parser.ParseContext;
 import org.apache.tika.parser.Parser;
+import org.apache.tika.parser.RecursiveParserWrapper;
 import org.apache.tika.sax.AbstractRecursiveParserWrapperHandler;
 import org.apache.tika.sax.TeeContentHandler;
 
@@ -121,6 +122,11 @@ public class ForkParser implements Parser, Closeable {
                     "The underlying parser of a ForkParser should not be a ForkParser, " +
                             "but a specific implementation.");
         }
+        if (parser instanceof RecursiveParserWrapper) {
+            parser = new RPWShim(((RecursiveParserWrapper) parser).getWrappedParser());
+        } else {
+            parser = new ParserWrapper(parser);
+        }
         this.tikaBin = null;
         this.parserFactoryFactory = null;
         this.loader = loader;
@@ -227,9 +233,9 @@ public class ForkParser implements Parser, Closeable {
      * @throws SAXException
      * @throws TikaException
      */
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
-        if (stream == null) {
+        if (tis == null) {
             throw new NullPointerException("null stream");
         }
 
@@ -242,7 +248,7 @@ public class ForkParser implements Parser, Closeable {
                     (handler instanceof AbstractRecursiveParserWrapperHandler) ? handler :
                             new TeeContentHandler(handler, new MetadataContentHandler(metadata));
 
-            t = client.call("parse", stream, tee, metadata, context);
+            t = client.call("parseStream", tis, tee, metadata, context);
             alive = true;
         } catch (TikaException te) {
             // Problem occurred on our side
diff --git a/tika-core/src/main/java/org/apache/tika/fork/ForkServer.java b/tika-core/src/main/java/org/apache/tika/fork/ForkServer.java
index c3249c1d1f..1a45e4e1ff 100644
--- a/tika-core/src/main/java/org/apache/tika/fork/ForkServer.java
+++ b/tika-core/src/main/java/org/apache/tika/fork/ForkServer.java
@@ -30,7 +30,6 @@ import java.net.URL;
 import org.xml.sax.SAXException;
 
 import org.apache.tika.exception.TikaException;
-import org.apache.tika.parser.ParserFactory;
 
 class ForkServer implements Runnable {
 
@@ -195,7 +194,7 @@ class ForkServer implements Runnable {
                     //the user has submitted a parser factory, but no class loader
                     classLoader = ForkServer.class.getClassLoader();
                     ParserFactory parserFactory = ((ParserFactoryFactory) firstObject).build();
-                    parser = parserFactory.build();
+                    parser = new ParserWrapper(parserFactory.build());
                 } else {
                     throw new IllegalArgumentException(
                             "Expecting only one object of class ParserFactoryFactory");
@@ -216,7 +215,7 @@ class ForkServer implements Runnable {
                 if (firstObject instanceof ParserFactoryFactory) {
                     //the user has submitted a parser factory and a class loader
                     ParserFactory parserFactory = ((ParserFactoryFactory) firstObject).build();
-                    parser = parserFactory.build();
+                    parser = new ParserWrapper(parserFactory.build());
                     classLoader = (ClassLoader) readObject(ForkServer.class.getClassLoader());
                     Thread.currentThread().setContextClassLoader(classLoader);
                 } else {
@@ -298,7 +297,6 @@ class ForkServer implements Runnable {
         // Tell the parent process that we successfully received this object
         output.writeByte(ForkServer.DONE);
         output.flush();
-
         return object;
     }
 }
diff --git a/tika-core/src/main/java/org/apache/tika/parser/ParserFactory.java b/tika-core/src/main/java/org/apache/tika/fork/ParserFactory.java
similarity index 94%
rename from tika-core/src/main/java/org/apache/tika/parser/ParserFactory.java
rename to tika-core/src/main/java/org/apache/tika/fork/ParserFactory.java
index e764701f68..6e0d957381 100644
--- a/tika-core/src/main/java/org/apache/tika/parser/ParserFactory.java
+++ b/tika-core/src/main/java/org/apache/tika/fork/ParserFactory.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.tika.parser;
+package org.apache.tika.fork;
 
 
 import java.io.IOException;
@@ -23,6 +23,7 @@ import java.util.Map;
 import org.xml.sax.SAXException;
 
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.parser.Parser;
 
 public abstract class ParserFactory {
 
diff --git a/tika-core/src/main/java/org/apache/tika/fork/ParserFactoryFactory.java b/tika-core/src/main/java/org/apache/tika/fork/ParserFactoryFactory.java
index 77192b8647..4f7b8f1756 100644
--- a/tika-core/src/main/java/org/apache/tika/fork/ParserFactoryFactory.java
+++ b/tika-core/src/main/java/org/apache/tika/fork/ParserFactoryFactory.java
@@ -22,7 +22,6 @@ import java.lang.reflect.Constructor;
 import java.util.Map;
 
 import org.apache.tika.exception.TikaException;
-import org.apache.tika.parser.ParserFactory;
 
 /**
  * Lightweight, easily serializable class that contains enough information
diff --git a/tika-pipes/tika-pipes-core/src/main/java/org/apache/tika/pipes/core/fetcher/EmptyFetcher.java b/tika-core/src/main/java/org/apache/tika/fork/ParserShim.java
similarity index 66%
copy from tika-pipes/tika-pipes-core/src/main/java/org/apache/tika/pipes/core/fetcher/EmptyFetcher.java
copy to tika-core/src/main/java/org/apache/tika/fork/ParserShim.java
index 6e9569ab87..04d1348200 100644
--- a/tika-pipes/tika-pipes-core/src/main/java/org/apache/tika/pipes/core/fetcher/EmptyFetcher.java
+++ b/tika-core/src/main/java/org/apache/tika/fork/ParserShim.java
@@ -14,26 +14,21 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.tika.pipes.core.fetcher;
+package org.apache.tika.fork;
 
 import java.io.IOException;
 import java.io.InputStream;
 
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
 import org.apache.tika.exception.TikaException;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.parser.ParseContext;
-import org.apache.tika.pipes.api.fetcher.Fetcher;
-import org.apache.tika.plugins.ExtensionConfig;
-
-public class EmptyFetcher implements Fetcher {
 
-    @Override
-    public InputStream fetch(String fetchKey, Metadata metadata, ParseContext parseContext) throws TikaException, IOException {
-        return null;
-    }
+//temporary workaround to handle requiring parsers take TikaInputStreams
+public interface ParserShim {
 
-    @Override
-    public ExtensionConfig getExtensionConfig() {
-        return new ExtensionConfig("empty", "empty-fetcher", null);
-    }
+    void parseStream(InputStream is, ContentHandler recursiveParserWrapperHandler,
+                     Metadata metadata, ParseContext context) throws IOException, TikaException, SAXException;
 }
diff --git a/tika-integration-tests/tika-resource-loading-tests/src/test/java/org/apache/custom/parser/MyCustomParser.java b/tika-core/src/main/java/org/apache/tika/fork/ParserWrapper.java
similarity index 58%
copy from tika-integration-tests/tika-resource-loading-tests/src/test/java/org/apache/custom/parser/MyCustomParser.java
copy to tika-core/src/main/java/org/apache/tika/fork/ParserWrapper.java
index bddf0afe0a..e9877e849c 100644
--- a/tika-integration-tests/tika-resource-loading-tests/src/test/java/org/apache/custom/parser/MyCustomParser.java
+++ b/tika-core/src/main/java/org/apache/tika/fork/ParserWrapper.java
@@ -14,38 +14,32 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.custom.parser;
+package org.apache.tika.fork;
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.Collections;
-import java.util.Set;
 
 import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
 
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
-import org.apache.tika.mime.MediaType;
 import org.apache.tika.parser.ParseContext;
 import org.apache.tika.parser.Parser;
-import org.apache.tika.sax.XHTMLContentHandler;
+import org.apache.tika.parser.ParserDecorator;
 
-public class MyCustomParser implements Parser {
+public class ParserWrapper extends ParserDecorator implements ParserShim {
 
-    @Override
-    public Set<MediaType> getSupportedTypes(ParseContext context) {
-        return Collections.singleton(MediaType.application("mock+xml"));
+    public ParserWrapper(Parser parser) {
+        super(parser);
     }
 
     @Override
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
-                      ParseContext context) throws IOException, SAXException, TikaException {
-        XHTMLContentHandler xhtml = new XHTMLContentHandler(handler, metadata);
-        xhtml.startDocument();
-        xhtml.startElement("p");
-        xhtml.characters("my custom parser");
-        xhtml.endElement("p");
-        xhtml.endDocument();
+    public void parseStream(InputStream is, ContentHandler recursiveParserWrapperHandler, Metadata metadata, ParseContext context) throws IOException, TikaException, SAXException {
+        Parser p = getWrappedParser();
+        try (TikaInputStream tis = TikaInputStream.get(is)) {
+            p.parse(tis, recursiveParserWrapperHandler, metadata, context);
+        }
     }
 }
diff --git a/tika-example/src/main/java/org/apache/tika/example/DisplayMetInstance.java b/tika-core/src/main/java/org/apache/tika/fork/RPWShim.java
old mode 100755
new mode 100644
similarity index 58%
copy from tika-example/src/main/java/org/apache/tika/example/DisplayMetInstance.java
copy to tika-core/src/main/java/org/apache/tika/fork/RPWShim.java
index e516c60c57..1bcdbd85d2
--- a/tika-example/src/main/java/org/apache/tika/example/DisplayMetInstance.java
+++ b/tika-core/src/main/java/org/apache/tika/fork/RPWShim.java
@@ -14,32 +14,31 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.tika.example;
+package org.apache.tika.fork;
 
 import java.io.IOException;
-import java.net.URL;
+import java.io.InputStream;
 
+import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
 
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.parser.ParseContext;
-import org.apache.tika.parser.pdf.PDFParser;
-import org.apache.tika.sax.BodyContentHandler;
+import org.apache.tika.parser.Parser;
+import org.apache.tika.parser.RecursiveParserWrapper;
 
-/**
- * Grabs a PDF file from a URL and prints its {@link Metadata}
- */
-public class DisplayMetInstance {
-    public static Metadata getMet(URL url) throws IOException, SAXException, TikaException {
-        Metadata met = new Metadata();
-        PDFParser parser = new PDFParser();
-        parser.parse(url.openStream(), new BodyContentHandler(), met, new ParseContext());
-        return met;
+public class RPWShim extends RecursiveParserWrapper implements ParserShim {
+
+    public RPWShim(Parser wrappedParser) {
+        super(wrappedParser);
     }
 
-    public static void main(String[] args) throws Exception {
-        Metadata met = DisplayMetInstance.getMet(new URL(args[0]));
-        System.out.println(met);
+    public void parseStream(InputStream is, ContentHandler recursiveParserWrapperHandler,
+                      Metadata metadata, ParseContext context) throws IOException, TikaException, SAXException {
+        try (TikaInputStream tis = TikaInputStream.get(is)) {
+            super.parse(tis, recursiveParserWrapperHandler, metadata, context);
+        }
     }
 }
diff --git a/tika-core/src/main/java/org/apache/tika/mime/MagicMatch.java b/tika-core/src/main/java/org/apache/tika/mime/MagicMatch.java
index 4917ea5428..687506ab7b 100644
--- a/tika-core/src/main/java/org/apache/tika/mime/MagicMatch.java
+++ b/tika-core/src/main/java/org/apache/tika/mime/MagicMatch.java
@@ -21,6 +21,7 @@ import java.io.IOException;
 import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
 
 import org.apache.tika.detect.MagicDetector;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 
 /**
@@ -56,8 +57,9 @@ class MagicMatch implements Clause {
     }
 
     public boolean eval(byte[] data) {
-        try {
-            return getDetector().detect(UnsynchronizedByteArrayInputStream.builder().setByteArray(data).get(), new Metadata()) !=
+        try (TikaInputStream tis = TikaInputStream.get(
+                UnsynchronizedByteArrayInputStream.builder().setByteArray(data).get())) {
+            return getDetector().detect(tis, new Metadata()) !=
                     MediaType.OCTET_STREAM;
         } catch (IOException e) {
             // Should never happen with a ByteArrayInputStream
diff --git a/tika-core/src/main/java/org/apache/tika/mime/MimeTypes.java b/tika-core/src/main/java/org/apache/tika/mime/MimeTypes.java
index 59137229dd..88e6ebf5c5 100644
--- a/tika-core/src/main/java/org/apache/tika/mime/MimeTypes.java
+++ b/tika-core/src/main/java/org/apache/tika/mime/MimeTypes.java
@@ -39,6 +39,7 @@ import org.apache.tika.config.TikaComponent;
 import org.apache.tika.detect.Detector;
 import org.apache.tika.detect.TextDetector;
 import org.apache.tika.detect.XmlRootExtractor;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
 
@@ -294,10 +295,11 @@ public final class MimeTypes implements Detector, Serializable {
         // Finally, assume plain text if no control bytes are found
         try {
             TextDetector detector = new TextDetector(getMinLength());
-            UnsynchronizedByteArrayInputStream stream =
-                    UnsynchronizedByteArrayInputStream.builder().setByteArray(data).get();
-            MimeType type = forName(detector.detect(stream, new Metadata()).toString());
-            return Collections.singletonList(type);
+            try (TikaInputStream tis = TikaInputStream.get(
+                    UnsynchronizedByteArrayInputStream.builder().setByteArray(data).get())) {
+                MimeType type = forName(detector.detect(tis, new Metadata()).toString());
+                return Collections.singletonList(type);
+            }
         } catch (Exception e) {
             return rootMimeTypeL;
         }
@@ -518,17 +520,17 @@ public final class MimeTypes implements Detector, Serializable {
      * @throws IOException if the document stream could not be read
      */
     @Override
-    public MediaType detect(InputStream input, Metadata metadata) throws IOException {
+    public MediaType detect(TikaInputStream tis, Metadata metadata) throws IOException {
         List<MimeType> possibleTypes = null;
 
         // Get type based on magic prefix
-        if (input != null) {
-            input.mark(getMinLength());
+        if (tis != null) {
+            tis.mark(getMinLength());
             try {
-                byte[] prefix = readMagicHeader(input);
+                byte[] prefix = readMagicHeader(tis);
                 possibleTypes = getMimeType(prefix);
             } finally {
-                input.reset();
+                tis.reset();
             }
         }
 
diff --git a/tika-core/src/main/java/org/apache/tika/mime/ProbabilisticMimeDetectionSelector.java b/tika-core/src/main/java/org/apache/tika/mime/ProbabilisticMimeDetectionSelector.java
index 5e33b85795..b54b61a0fa 100644
--- a/tika-core/src/main/java/org/apache/tika/mime/ProbabilisticMimeDetectionSelector.java
+++ b/tika-core/src/main/java/org/apache/tika/mime/ProbabilisticMimeDetectionSelector.java
@@ -17,13 +17,13 @@
 package org.apache.tika.mime;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.tika.detect.Detector;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
 
@@ -121,19 +121,19 @@ public class ProbabilisticMimeDetectionSelector implements Detector {
         threshold = 0.5001f;
     }
 
-    public MediaType detect(InputStream input, Metadata metadata) throws IOException {
+    public MediaType detect(TikaInputStream tis, Metadata metadata) throws IOException {
 
         List<MimeType> possibleTypes = new ArrayList<>();
 
         // Get type based on magic prefix
-        if (input != null) {
-            input.mark(mimeTypes.getMinLength());
+        if (tis != null) {
+            tis.mark(mimeTypes.getMinLength());
             try {
-                byte[] prefix = mimeTypes.readMagicHeader(input);
+                byte[] prefix = mimeTypes.readMagicHeader(tis);
                 //defensive copy
                 possibleTypes.addAll(mimeTypes.getMimeType(prefix));
             } finally {
-                input.reset();
+                tis.reset();
             }
         }
 
diff --git a/tika-core/src/main/java/org/apache/tika/parser/AbstractParser.java b/tika-core/src/main/java/org/apache/tika/parser/AbstractParser.java
index 4bfbe9317e..a5666dc0a2 100644
--- a/tika-core/src/main/java/org/apache/tika/parser/AbstractParser.java
+++ b/tika-core/src/main/java/org/apache/tika/parser/AbstractParser.java
@@ -17,12 +17,12 @@
 package org.apache.tika.parser;
 
 import java.io.IOException;
-import java.io.InputStream;
 
 import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
 
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 
 /**
@@ -42,19 +42,19 @@ public abstract class AbstractParser implements Parser {
 
     /**
      * Calls the
-     * {@link Parser#parse(InputStream, ContentHandler, Metadata, ParseContext)}
+     * {@link Parser#parse(TikaInputStream, ContentHandler, Metadata, ParseContext)}
      * method with an empty {@link ParseContext}. This method exists as a
      * leftover from Tika 0.x when the three-argument parse() method still
      * existed in the {@link Parser} interface. No new code should call this
      * method anymore, it's only here for backwards compatibility.
      *
-     * @deprecated use the {@link Parser#parse(InputStream, ContentHandler,
+     * @deprecated use the {@link Parser#parse(TikaInputStream, ContentHandler,
      * Metadata, ParseContext)} method instead
      */
     @Deprecated
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata)
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata)
             throws IOException, SAXException, TikaException {
-        parse(stream, handler, metadata, new ParseContext());
+        parse(tis, handler, metadata, new ParseContext());
     }
 
 }
diff --git a/tika-core/src/main/java/org/apache/tika/parser/AutoDetectParser.java b/tika-core/src/main/java/org/apache/tika/parser/AutoDetectParser.java
index c4ac7327ac..3c5cd236f5 100644
--- a/tika-core/src/main/java/org/apache/tika/parser/AutoDetectParser.java
+++ b/tika-core/src/main/java/org/apache/tika/parser/AutoDetectParser.java
@@ -17,7 +17,6 @@
 package org.apache.tika.parser;
 
 import java.io.IOException;
-import java.io.InputStream;
 
 import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
@@ -30,7 +29,6 @@ import org.apache.tika.exception.ZeroByteFileException;
 import org.apache.tika.extractor.EmbeddedDocumentExtractor;
 import org.apache.tika.extractor.EmbeddedDocumentExtractorFactory;
 import org.apache.tika.extractor.ParsingEmbeddedDocumentExtractorFactory;
-import org.apache.tika.io.TemporaryResources;
 import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.HttpHeaders;
 import org.apache.tika.metadata.Metadata;
@@ -147,58 +145,52 @@ public class AutoDetectParser extends CompositeParser {
         return this.autoDetectParserConfig;
     }
 
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
         if (autoDetectParserConfig.getMetadataWriteFilterFactory() != null) {
             metadata.setMetadataWriteFilter(
                     autoDetectParserConfig.getMetadataWriteFilterFactory().newInstance());
         }
-        TemporaryResources tmp = new TemporaryResources();
-        try {
-            TikaInputStream tis = TikaInputStream.get(stream, tmp, metadata);
-            //figure out if we should spool to disk
-            maybeSpool(tis, autoDetectParserConfig, metadata);
-
-            // Compute digests before type detection if configured
-            DigestHelper.maybeDigest(tis,
-                    autoDetectParserConfig.digester(),
-                    autoDetectParserConfig.isSkipContainerDocumentDigest(),
-                    metadata, context, tmp);
-
-            // Automatically detect the MIME type of the document
-            MediaType type = detector.detect(tis, metadata);
-            //update CONTENT_TYPE as long as it wasn't set by parser override
-            if (metadata.get(TikaCoreProperties.CONTENT_TYPE_PARSER_OVERRIDE) == null ||
-                    !metadata.get(TikaCoreProperties.CONTENT_TYPE_PARSER_OVERRIDE)
-                            .equals(type.toString())) {
-                metadata.set(Metadata.CONTENT_TYPE, type.toString());
-            }
-            //check for zero-byte inputstream
-            if (tis.getOpenContainer() == null) {
-                if (autoDetectParserConfig.getThrowOnZeroBytes()) {
-                    tis.mark(1);
-                    if (tis.read() == -1) {
-                        throw new ZeroByteFileException("InputStream must have > 0 bytes");
-                    }
-                    tis.reset();
+        //figure out if we should spool to disk
+        maybeSpool(tis, autoDetectParserConfig, metadata);
+
+        // Compute digests before type detection if configured
+        DigestHelper.maybeDigest(tis,
+                autoDetectParserConfig.digester(),
+                autoDetectParserConfig.isSkipContainerDocumentDigest(),
+                metadata, context);
+
+        // Automatically detect the MIME type of the document
+        MediaType type = detector.detect(tis, metadata);
+        //update CONTENT_TYPE as long as it wasn't set by parser override
+        if (metadata.get(TikaCoreProperties.CONTENT_TYPE_PARSER_OVERRIDE) == null ||
+                !metadata.get(TikaCoreProperties.CONTENT_TYPE_PARSER_OVERRIDE)
+                        .equals(type.toString())) {
+            metadata.set(Metadata.CONTENT_TYPE, type.toString());
+        }
+        //check for zero-byte inputstream
+        if (tis.getOpenContainer() == null) {
+            if (autoDetectParserConfig.getThrowOnZeroBytes()) {
+                tis.mark(1);
+                if (tis.read() == -1) {
+                    throw new ZeroByteFileException("InputStream must have > 0 bytes");
                 }
+                tis.reset();
             }
-            handler = decorateHandler(handler, metadata, context, autoDetectParserConfig);
-            // TIKA-216: Zip bomb prevention
-            SecureContentHandler sch = handler != null ?
-                    createSecureContentHandler(handler, tis, autoDetectParserConfig) : null;
+        }
+        handler = decorateHandler(handler, metadata, context, autoDetectParserConfig);
+        // TIKA-216: Zip bomb prevention
+        SecureContentHandler sch = handler != null ?
+                createSecureContentHandler(handler, tis, autoDetectParserConfig) : null;
 
-            initializeEmbeddedDocumentExtractor(metadata, context);
-            try {
-                // Parse the document
-                super.parse(tis, sch, metadata, context);
-            } catch (SAXException e) {
-                // Convert zip bomb exceptions to TikaExceptions
-                sch.throwIfCauseOf(e);
-                throw e;
-            }
-        } finally {
-            tmp.dispose();
+        initializeEmbeddedDocumentExtractor(metadata, context);
+        try {
+            // Parse the document
+            super.parse(tis, sch, metadata, context);
+        } catch (SAXException e) {
+            // Convert zip bomb exceptions to TikaExceptions
+            sch.throwIfCauseOf(e);
+            throw e;
         }
     }
 
@@ -273,11 +265,11 @@ public class AutoDetectParser extends CompositeParser {
         context.set(EmbeddedDocumentExtractor.class, edx);
     }
 
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata)
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata)
             throws IOException, SAXException, TikaException {
         ParseContext context = new ParseContext();
         context.set(Parser.class, this);
-        parse(stream, handler, metadata, context);
+        parse(tis, handler, metadata, context);
     }
 
     private SecureContentHandler createSecureContentHandler(ContentHandler handler,
diff --git a/tika-core/src/main/java/org/apache/tika/parser/CompositeParser.java b/tika-core/src/main/java/org/apache/tika/parser/CompositeParser.java
index b3aaebf7a8..f48cd74459 100644
--- a/tika-core/src/main/java/org/apache/tika/parser/CompositeParser.java
+++ b/tika-core/src/main/java/org/apache/tika/parser/CompositeParser.java
@@ -17,7 +17,6 @@
 package org.apache.tika.parser;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -32,7 +31,6 @@ import org.xml.sax.SAXException;
 
 import org.apache.tika.exception.TikaException;
 import org.apache.tika.exception.WriteLimitReachedException;
-import org.apache.tika.io.TemporaryResources;
 import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
@@ -281,17 +279,15 @@ public class CompositeParser implements Parser {
      * handler are automatically wrapped into {@link TikaException}s to better
      * honor the {@link Parser} contract.
      */
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
         Parser parser = getParser(metadata, context);
-        TemporaryResources tmp = new TemporaryResources();
         ParseRecord parserRecord = context.get(ParseRecord.class);
         if (parserRecord == null) {
             parserRecord = new ParseRecord();
             context.set(ParseRecord.class, parserRecord);
         }
         try {
-            TikaInputStream taggedStream = TikaInputStream.get(stream, tmp, metadata);
             TaggedContentHandler taggedHandler =
                     handler != null ? new TaggedContentHandler(handler) : null;
             String parserClassname = ParserUtils.getParserClassname(parser);
@@ -299,12 +295,12 @@ public class CompositeParser implements Parser {
             ParserUtils.recordParserDetails(parserClassname, metadata);
             parserRecord.beforeParse();
             try {
-                parser.parse(taggedStream, taggedHandler, metadata, context);
+                parser.parse(tis, taggedHandler, metadata, context);
             } catch (SecurityException e) {
                 //rethrow security exceptions
                 throw e;
             } catch (IOException e) {
-                taggedStream.throwIfCauseOf(e);
+                tis.throwIfCauseOf(e);
                 throw new TikaException("TIKA-198: Illegal IOException from " + parser, e);
             } catch (SAXException e) {
                 WriteLimitReachedException.throwIfWriteLimitReached(e);
@@ -316,7 +312,6 @@ public class CompositeParser implements Parser {
                 throw new TikaException("Unexpected RuntimeException from " + parser, e);
             }
         } finally {
-            tmp.dispose();
             parserRecord.afterParse();
             if (parserRecord.getDepth() == 0) {
                 metadata.set(TikaCoreProperties.TIKA_PARSED_BY_FULL_SET, parserRecord.getParsers());
diff --git a/tika-core/src/main/java/org/apache/tika/parser/CryptoParser.java b/tika-core/src/main/java/org/apache/tika/parser/CryptoParser.java
index 1ffd851db3..cd69d8e753 100644
--- a/tika-core/src/main/java/org/apache/tika/parser/CryptoParser.java
+++ b/tika-core/src/main/java/org/apache/tika/parser/CryptoParser.java
@@ -17,7 +17,6 @@
 package org.apache.tika.parser;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.security.AlgorithmParameters;
 import java.security.GeneralSecurityException;
 import java.security.Key;
@@ -32,6 +31,7 @@ import org.xml.sax.SAXException;
 
 import org.apache.tika.exception.EncryptedDocumentException;
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 
@@ -69,7 +69,7 @@ public abstract class CryptoParser extends DelegatingParser {
         return types;
     }
 
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
         try {
             Cipher cipher;
@@ -96,7 +96,10 @@ public abstract class CryptoParser extends DelegatingParser {
                 cipher.init(Cipher.DECRYPT_MODE, key);
             }
 
-            super.parse(new CipherInputStream(stream, cipher), handler, metadata, context);
+            try (TikaInputStream decrypted = TikaInputStream.get(
+                    new CipherInputStream(tis, cipher))) {
+                super.parse(decrypted, handler, metadata, context);
+            }
         } catch (GeneralSecurityException e) {
             throw new TikaException("Unable to decrypt document stream", e);
         }
diff --git a/tika-core/src/main/java/org/apache/tika/parser/DelegatingParser.java b/tika-core/src/main/java/org/apache/tika/parser/DelegatingParser.java
index f2e007cfe9..094a72c302 100644
--- a/tika-core/src/main/java/org/apache/tika/parser/DelegatingParser.java
+++ b/tika-core/src/main/java/org/apache/tika/parser/DelegatingParser.java
@@ -17,13 +17,13 @@
 package org.apache.tika.parser;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.util.Set;
 
 import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
 
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 
@@ -66,9 +66,9 @@ public class DelegatingParser implements Parser {
      * be passed to this base class method to be parsed by the configured
      * delegate parser.
      */
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws SAXException, IOException, TikaException {
-        getDelegateParser(context).parse(stream, handler, metadata, context);
+        getDelegateParser(context).parse(tis, handler, metadata, context);
     }
 
 }
diff --git a/tika-core/src/main/java/org/apache/tika/parser/DigestingParser.java b/tika-core/src/main/java/org/apache/tika/parser/DigestingParser.java
index 69f9c2ce6b..30369bf752 100644
--- a/tika-core/src/main/java/org/apache/tika/parser/DigestingParser.java
+++ b/tika-core/src/main/java/org/apache/tika/parser/DigestingParser.java
@@ -18,7 +18,6 @@ package org.apache.tika.parser;
 
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.OutputStream;
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -65,16 +64,15 @@ public class DigestingParser extends ParserDecorator {
     }
 
     @Override
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
 
 
         if (! shouldDigest(metadata)) {
-            super.parse(stream, handler, metadata, context);
+            super.parse(tis, handler, metadata, context);
             return;
         }
         TemporaryResources tmp = new TemporaryResources();
-        TikaInputStream tis = TikaInputStream.get(stream, tmp, metadata);
         try {
 
             if (embeddedStreamTranslator.shouldTranslate(tis, metadata)) {
diff --git a/tika-core/src/main/java/org/apache/tika/parser/EmptyParser.java b/tika-core/src/main/java/org/apache/tika/parser/EmptyParser.java
index 83e88a1463..1da391f2bd 100644
--- a/tika-core/src/main/java/org/apache/tika/parser/EmptyParser.java
+++ b/tika-core/src/main/java/org/apache/tika/parser/EmptyParser.java
@@ -16,7 +16,6 @@
  */
 package org.apache.tika.parser;
 
-import java.io.InputStream;
 import java.util.Collections;
 import java.util.Set;
 
@@ -24,6 +23,7 @@ import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
 
 import org.apache.tika.config.TikaComponent;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 import org.apache.tika.sax.XHTMLContentHandler;
@@ -48,7 +48,7 @@ public class EmptyParser implements Parser {
         return Collections.emptySet();
     }
 
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws SAXException {
         XHTMLContentHandler xhtml = new XHTMLContentHandler(handler, metadata);
         xhtml.startDocument();
diff --git a/tika-core/src/main/java/org/apache/tika/parser/ErrorParser.java b/tika-core/src/main/java/org/apache/tika/parser/ErrorParser.java
index f7d4063d6c..fec6ebbb68 100644
--- a/tika-core/src/main/java/org/apache/tika/parser/ErrorParser.java
+++ b/tika-core/src/main/java/org/apache/tika/parser/ErrorParser.java
@@ -16,7 +16,6 @@
  */
 package org.apache.tika.parser;
 
-import java.io.InputStream;
 import java.util.Collections;
 import java.util.Set;
 
@@ -24,6 +23,7 @@ import org.xml.sax.ContentHandler;
 
 import org.apache.tika.config.TikaComponent;
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 
@@ -44,7 +44,7 @@ public class ErrorParser implements Parser {
         return Collections.emptySet();
     }
 
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws TikaException {
         throw new TikaException("Parse error");
     }
diff --git a/tika-core/src/main/java/org/apache/tika/parser/NetworkParser.java b/tika-core/src/main/java/org/apache/tika/parser/NetworkParser.java
index 76bab3b5e7..ff88f17c11 100644
--- a/tika-core/src/main/java/org/apache/tika/parser/NetworkParser.java
+++ b/tika-core/src/main/java/org/apache/tika/parser/NetworkParser.java
@@ -35,7 +35,6 @@ import org.xml.sax.SAXException;
 import org.xml.sax.helpers.DefaultHandler;
 
 import org.apache.tika.exception.TikaException;
-import org.apache.tika.io.TemporaryResources;
 import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
@@ -63,22 +62,11 @@ public class NetworkParser implements Parser {
         return supportedTypes;
     }
 
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
-        TemporaryResources tmp = new TemporaryResources();
-        try {
-            TikaInputStream tis = TikaInputStream.get(stream, tmp, metadata);
-            parse(tis, handler, metadata, context);
-        } finally {
-            tmp.dispose();
-        }
-    }
-
-    private void parse(TikaInputStream stream, ContentHandler handler, Metadata metadata,
-                       ParseContext context) throws IOException, SAXException, TikaException {
         if ("telnet".equals(uri.getScheme())) {
             try (Socket socket = new Socket(uri.getHost(), uri.getPort())) {
-                new ParsingTask(stream, new FilterOutputStream(socket.getOutputStream()) {
+                new ParsingTask(tis, new FilterOutputStream(socket.getOutputStream()) {
                     @Override
                     public void close() throws IOException {
                         socket.shutdownOutput();
@@ -91,7 +79,7 @@ public class NetworkParser implements Parser {
             connection.setDoOutput(true);
             connection.connect();
             try (InputStream input = connection.getInputStream()) {
-                new ParsingTask(stream, connection.getOutputStream())
+                new ParsingTask(tis, connection.getOutputStream())
                         .parse(CloseShieldInputStream.wrap(input), handler, metadata, context);
             }
         }
diff --git a/tika-core/src/main/java/org/apache/tika/parser/Parser.java b/tika-core/src/main/java/org/apache/tika/parser/Parser.java
index ef5299ba56..0dd6d76b9c 100644
--- a/tika-core/src/main/java/org/apache/tika/parser/Parser.java
+++ b/tika-core/src/main/java/org/apache/tika/parser/Parser.java
@@ -17,7 +17,6 @@
 package org.apache.tika.parser;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.Serializable;
 import java.util.Set;
 
@@ -26,6 +25,7 @@ import org.xml.sax.SAXException;
 
 import org.apache.tika.config.SelfConfiguring;
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 
@@ -64,7 +64,7 @@ public interface Parser extends Serializable, SelfConfiguring {
      * @throws TikaException if the document could not be parsed
      * @since Apache Tika 0.5
      */
-    void parse(InputStream stream, ContentHandler handler, Metadata metadata, ParseContext context)
+    void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata, ParseContext context)
             throws IOException, SAXException, TikaException;
 
 }
diff --git a/tika-core/src/main/java/org/apache/tika/parser/ParserDecorator.java b/tika-core/src/main/java/org/apache/tika/parser/ParserDecorator.java
index 32d6661fb3..7438c99ac7 100644
--- a/tika-core/src/main/java/org/apache/tika/parser/ParserDecorator.java
+++ b/tika-core/src/main/java/org/apache/tika/parser/ParserDecorator.java
@@ -17,7 +17,6 @@
 package org.apache.tika.parser;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.Set;
@@ -26,6 +25,7 @@ import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
 
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 import org.apache.tika.mime.MediaTypeRegistry;
@@ -148,9 +148,9 @@ public class ParserDecorator implements Parser {
      * override this method (and use <code>super.parse()</code> to invoke
      * the decorated parser) to implement extra decoration.
      */
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
-        parser.parse(stream, handler, metadata, context);
+        parser.parse(tis, handler, metadata, context);
     }
 
     /**
diff --git a/tika-core/src/main/java/org/apache/tika/parser/ParserPostProcessor.java b/tika-core/src/main/java/org/apache/tika/parser/ParserPostProcessor.java
index 308fa7ebc0..82855bdab6 100644
--- a/tika-core/src/main/java/org/apache/tika/parser/ParserPostProcessor.java
+++ b/tika-core/src/main/java/org/apache/tika/parser/ParserPostProcessor.java
@@ -17,12 +17,12 @@
 package org.apache.tika.parser;
 
 import java.io.IOException;
-import java.io.InputStream;
 
 import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
 
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.sax.BodyContentHandler;
 import org.apache.tika.sax.TeeContentHandler;
@@ -49,11 +49,11 @@ public class ParserPostProcessor extends ParserDecorator {
      * Forwards the call to the delegated parser and post-processes the
      * results as described above.
      */
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
         ContentHandler body = new BodyContentHandler();
         ContentHandler tee = new TeeContentHandler(handler, body);
-        super.parse(stream, tee, metadata, context);
+        super.parse(tis, tee, metadata, context);
 
         String content = body.toString();
         metadata.set("fulltext", content);
diff --git a/tika-core/src/main/java/org/apache/tika/parser/ParsingReader.java b/tika-core/src/main/java/org/apache/tika/parser/ParsingReader.java
index 60c2cc40d5..15e409c1eb 100644
--- a/tika-core/src/main/java/org/apache/tika/parser/ParsingReader.java
+++ b/tika-core/src/main/java/org/apache/tika/parser/ParsingReader.java
@@ -33,6 +33,7 @@ import java.util.concurrent.Executor;
 import org.xml.sax.ContentHandler;
 
 import org.apache.tika.exception.ZeroByteFileException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
 import org.apache.tika.sax.BodyContentHandler;
@@ -263,21 +264,13 @@ public class ParsingReader extends Reader {
          * stored before the input stream is closed and processing is stopped.
          */
         public void run() {
-            try {
+            try (TikaInputStream tis = TikaInputStream.get(stream)) {
                 ContentHandler handler = new BodyContentHandler(writer);
-                parser.parse(stream, handler, metadata, context);
+                parser.parse(tis, handler, metadata, context);
             } catch (Throwable t) {
                 throwable = t;
             }
 
-            try {
-                stream.close();
-            } catch (Throwable t) {
-                if (throwable == null) {
-                    throwable = t;
-                }
-            }
-
             try {
                 writer.close();
             } catch (Throwable t) {
diff --git a/tika-core/src/main/java/org/apache/tika/parser/RecursiveParserWrapper.java b/tika-core/src/main/java/org/apache/tika/parser/RecursiveParserWrapper.java
index 07eee752ba..0c0599ec76 100644
--- a/tika-core/src/main/java/org/apache/tika/parser/RecursiveParserWrapper.java
+++ b/tika-core/src/main/java/org/apache/tika/parser/RecursiveParserWrapper.java
@@ -17,11 +17,9 @@
 package org.apache.tika.parser;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicInteger;
 
-import org.apache.commons.io.input.CloseShieldInputStream;
 import org.xml.sax.Attributes;
 import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
@@ -33,7 +31,6 @@ import org.apache.tika.exception.WriteLimitReachedException;
 import org.apache.tika.exception.ZeroByteFileException;
 import org.apache.tika.extractor.ParentContentHandler;
 import org.apache.tika.io.FilenameUtils;
-import org.apache.tika.io.TemporaryResources;
 import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
@@ -128,7 +125,7 @@ public class RecursiveParserWrapper extends ParserDecorator {
      * @throws IllegalStateException if the handler is not a {@link RecursiveParserWrapperHandler}
      */
     @Override
-    public void parse(InputStream stream, ContentHandler recursiveParserWrapperHandler,
+    public void parse(TikaInputStream tis, ContentHandler recursiveParserWrapperHandler,
                       Metadata metadata, ParseContext context)
             throws IOException, SAXException, TikaException {
         //this tracks the state of the parent parser, per call to #parse
@@ -147,7 +144,6 @@ public class RecursiveParserWrapper extends ParserDecorator {
                 parserState.recursiveParserWrapperHandler.getNewContentHandler();
         long started = System.currentTimeMillis();
         parserState.recursiveParserWrapperHandler.startDocument();
-        TemporaryResources tmp = new TemporaryResources();
         int writeLimit = -1;
         boolean throwOnWriteLimitReached = true;
 
@@ -160,7 +156,6 @@ public class RecursiveParserWrapper extends ParserDecorator {
             }
         }
         try {
-            TikaInputStream tis = TikaInputStream.get(stream, tmp, metadata);
             RecursivelySecureContentHandler secureContentHandler =
                     new RecursivelySecureContentHandler(localHandler, tis, new SecureHandlerCounter(writeLimit),
                             throwOnWriteLimitReached, context);
@@ -178,7 +173,6 @@ public class RecursiveParserWrapper extends ParserDecorator {
                 throw e;
             }
         } finally {
-            tmp.dispose();
             long elapsedMillis = System.currentTimeMillis() - started;
             metadata.set(TikaCoreProperties.PARSE_TIME_MILLIS, Long.toString(elapsedMillis));
             parserState.recursiveParserWrapperHandler.endDocument(localHandler, metadata);
@@ -226,7 +220,7 @@ public class RecursiveParserWrapper extends ParserDecorator {
         }
 
         @Override
-        public void parse(InputStream stream, ContentHandler ignore, Metadata metadata,
+        public void parse(TikaInputStream tis, ContentHandler ignore, Metadata metadata,
                           ParseContext context) throws IOException, SAXException, TikaException {
 
             //Test to see if we should avoid parsing
@@ -261,12 +255,6 @@ public class RecursiveParserWrapper extends ParserDecorator {
 
             ParentContentHandler preParseParentHandler = context.get(ParentContentHandler.class);
             context.set(ParentContentHandler.class, new ParentContentHandler(preParseHandler));
-            TemporaryResources tmp = null;
-            TikaInputStream tis = TikaInputStream.cast(stream);
-            if (tis == null) {
-                tmp = new TemporaryResources();
-                tis = TikaInputStream.get(CloseShieldInputStream.wrap(stream), tmp, metadata);
-            }
             ContentHandler secureContentHandler =
                     new RecursivelySecureContentHandler(localHandler, tis, preParseHandler.handlerCounter,
                     preParseHandler.throwOnWriteLimitReached, context);
@@ -308,9 +296,6 @@ public class RecursiveParserWrapper extends ParserDecorator {
                 metadata.set(TikaCoreProperties.PARSE_TIME_MILLIS, Long.toString(elapsedMillis));
                 parserState.recursiveParserWrapperHandler
                         .endEmbeddedDocument(localHandler, metadata);
-                if (tmp != null) {
-                    tis.close();
-                }
             }
         }
     }
diff --git a/tika-core/src/main/java/org/apache/tika/parser/RegexCaptureParser.java b/tika-core/src/main/java/org/apache/tika/parser/RegexCaptureParser.java
index be95619efa..28b0431483 100644
--- a/tika-core/src/main/java/org/apache/tika/parser/RegexCaptureParser.java
+++ b/tika-core/src/main/java/org/apache/tika/parser/RegexCaptureParser.java
@@ -18,7 +18,6 @@ package org.apache.tika.parser;
 
 import java.io.BufferedReader;
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.nio.charset.StandardCharsets;
 import java.util.Collections;
@@ -34,6 +33,7 @@ import org.xml.sax.SAXException;
 
 import org.apache.tika.config.TikaComponent;
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 
@@ -54,9 +54,9 @@ public class RegexCaptureParser implements Parser {
     private boolean writeContent = false;
 
     @Override
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
-        try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream,
+        try (BufferedReader reader = new BufferedReader(new InputStreamReader(tis,
                 StandardCharsets.UTF_8))) {
             String line = reader.readLine();
             Map<String, Matcher> localCaptureMap = new HashMap();
diff --git a/tika-core/src/main/java/org/apache/tika/parser/external/ExternalParser.java b/tika-core/src/main/java/org/apache/tika/parser/external/ExternalParser.java
index 429258e461..00e04c1542 100644
--- a/tika-core/src/main/java/org/apache/tika/parser/external/ExternalParser.java
+++ b/tika-core/src/main/java/org/apache/tika/parser/external/ExternalParser.java
@@ -265,19 +265,19 @@ public class ExternalParser implements Parser {
      * Metadata is only extracted if {@link #setMetadataExtractionPatterns(Map)}
      * has been called to set patterns.
      */
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
         XHTMLContentHandler xhtml = new XHTMLContentHandler(handler, metadata);
 
         TemporaryResources tmp = new TemporaryResources();
         try {
-            parse(TikaInputStream.get(stream, tmp, metadata), xhtml, metadata, tmp);
+            parse(tis, xhtml, metadata, tmp);
         } finally {
             tmp.dispose();
         }
     }
 
-    private void parse(TikaInputStream stream, XHTMLContentHandler xhtml, Metadata metadata,
+    private void parse(TikaInputStream tis, XHTMLContentHandler xhtml, Metadata metadata,
                        TemporaryResources tmp) throws IOException, SAXException, TikaException {
         boolean inputToStdIn = true;
         boolean outputFromStdOut = true;
@@ -295,7 +295,7 @@ public class ExternalParser implements Parser {
         }
         for (int i = 0; i < cmd.length; i++) {
             if (cmd[i].contains(INPUT_FILE_TOKEN)) {
-                cmd[i] = cmd[i].replace(INPUT_FILE_TOKEN, stream.getFile().getPath());
+                cmd[i] = cmd[i].replace(INPUT_FILE_TOKEN, tis.getFile().getPath());
                 inputToStdIn = false;
             }
             if (cmd[i].contains(OUTPUT_FILE_TOKEN)) {
@@ -319,7 +319,7 @@ public class ExternalParser implements Parser {
 
         try {
             if (inputToStdIn) {
-                sendInput(process, stream);
+                sendInput(process, tis);
             } else {
                 process.getOutputStream().close();
             }
diff --git a/tika-core/src/main/java/org/apache/tika/parser/external2/ExternalParser.java b/tika-core/src/main/java/org/apache/tika/parser/external2/ExternalParser.java
index fdeedc6d68..b44b7a9f3c 100644
--- a/tika-core/src/main/java/org/apache/tika/parser/external2/ExternalParser.java
+++ b/tika-core/src/main/java/org/apache/tika/parser/external2/ExternalParser.java
@@ -18,7 +18,6 @@ package org.apache.tika.parser.external2;
 
 import java.io.BufferedReader;
 import java.io.IOException;
-import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -95,12 +94,11 @@ public class ExternalParser implements Parser {
     }
 
     @Override
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
         //this may remain null, depending on whether the external parser writes to a file
         Path outFile = null;
         try (TemporaryResources tmp = new TemporaryResources()) {
-            TikaInputStream tis = TikaInputStream.get(stream, tmp, metadata);
             Path p = tis.getPath();
             List<String> thisCommandLine = new ArrayList<>();
             Matcher inputMatcher = INPUT_TOKEN_MATCHER.matcher("");
@@ -178,13 +176,13 @@ public class ExternalParser implements Parser {
             }
         } else {
             if (outFile != null) {
-                try (InputStream is = TikaInputStream.get(outFile)) {
-                    outputParser.parse(is, new BodyContentHandler(xhtml), metadata, parseContext);
+                try (TikaInputStream tis = TikaInputStream.get(outFile)) {
+                    outputParser.parse(tis, new BodyContentHandler(xhtml), metadata, parseContext);
                 }
             } else {
-                try (InputStream is = TikaInputStream.get(
+                try (TikaInputStream tis = TikaInputStream.get(
                         result.getStdout().getBytes(StandardCharsets.UTF_8))) {
-                    outputParser.parse(is, new BodyContentHandler(xhtml), metadata, parseContext);
+                    outputParser.parse(tis, new BodyContentHandler(xhtml), metadata, parseContext);
                 }
             }
         }
diff --git a/tika-core/src/main/java/org/apache/tika/parser/multiple/AbstractMultipleParser.java b/tika-core/src/main/java/org/apache/tika/parser/multiple/AbstractMultipleParser.java
index ecffcc005d..568d61c257 100644
--- a/tika-core/src/main/java/org/apache/tika/parser/multiple/AbstractMultipleParser.java
+++ b/tika-core/src/main/java/org/apache/tika/parser/multiple/AbstractMultipleParser.java
@@ -21,7 +21,6 @@ import static org.apache.tika.utils.ParserUtils.recordParserDetails;
 import static org.apache.tika.utils.ParserUtils.recordParserFailure;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -35,6 +34,7 @@ import org.xml.sax.SAXException;
 
 import org.apache.tika.exception.TikaException;
 import org.apache.tika.io.TemporaryResources;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
 import org.apache.tika.mime.MediaType;
@@ -220,9 +220,9 @@ public abstract class AbstractMultipleParser implements Parser {
      * call the method with a {@link ContentHandlerFactory} instead.
      */
     @Override
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
-        parse(stream, handler, null, metadata, context);
+        parse(tis, handler, null, metadata, context);
     }
 
     /**
@@ -236,12 +236,12 @@ public abstract class AbstractMultipleParser implements Parser {
      * and the method signature is subject to change before Tika 2.0
      */
     @Deprecated
-    public void parse(InputStream stream, ContentHandlerFactory handlers, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandlerFactory handlers, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
-        parse(stream, null, handlers, metadata, context);
+        parse(tis, null, handlers, metadata, context);
     }
 
-    private void parse(InputStream stream, ContentHandler handler,
+    private void parse(TikaInputStream tis, ContentHandler handler,
                        ContentHandlerFactory handlerFactory, Metadata originalMetadata,
                        ParseContext context) throws IOException, SAXException, TikaException {
         // Track the metadata between parsers, so we can apply our policy
@@ -253,7 +253,7 @@ public abstract class AbstractMultipleParser implements Parser {
         try {
             // Ensure we'll be able to re-read safely, buffering to disk if so,
             //  to permit Parsers 2+ to be able to read the same data
-            InputStream taggedStream = ParserUtils.ensureStreamReReadable(stream, tmp, originalMetadata);
+            TikaInputStream taggedStream = ParserUtils.ensureStreamReReadable(tis, tmp, originalMetadata);
 
             for (Parser p : parsers) {
                 // Get a new handler for this parser, if we can
diff --git a/tika-core/src/main/java/org/apache/tika/renderer/CompositeRenderer.java b/tika-core/src/main/java/org/apache/tika/renderer/CompositeRenderer.java
index fff519168f..e7ae6db2dd 100644
--- a/tika-core/src/main/java/org/apache/tika/renderer/CompositeRenderer.java
+++ b/tika-core/src/main/java/org/apache/tika/renderer/CompositeRenderer.java
@@ -17,7 +17,6 @@
 package org.apache.tika.renderer;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
@@ -27,6 +26,7 @@ import java.util.concurrent.ConcurrentHashMap;
 
 import org.apache.tika.config.ServiceLoader;
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
 import org.apache.tika.mime.MediaType;
@@ -57,7 +57,7 @@ public class CompositeRenderer implements Renderer {
     }
 
     @Override
-    public RenderResults render(InputStream is, Metadata metadata, ParseContext parseContext,
+    public RenderResults render(TikaInputStream tis, Metadata metadata, ParseContext parseContext,
                                 RenderRequest... requests) throws IOException, TikaException {
 
         String mediaTypeString = metadata.get(TikaCoreProperties.TYPE);
@@ -72,7 +72,7 @@ public class CompositeRenderer implements Renderer {
         if (renderer == null) {
             throw new TikaException("I regret I can't find a renderer for " + mt);
         }
-        return renderer.render(is, metadata, parseContext, requests);
+        return renderer.render(tis, metadata, parseContext, requests);
     }
 
     public Renderer getLeafRenderer(MediaType mt) {
diff --git a/tika-core/src/main/java/org/apache/tika/renderer/Renderer.java b/tika-core/src/main/java/org/apache/tika/renderer/Renderer.java
index ff0ad40b63..c13e246055 100644
--- a/tika-core/src/main/java/org/apache/tika/renderer/Renderer.java
+++ b/tika-core/src/main/java/org/apache/tika/renderer/Renderer.java
@@ -17,12 +17,12 @@
 package org.apache.tika.renderer;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.Serializable;
 import java.util.Set;
 
 import org.apache.tika.config.SelfConfiguring;
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 import org.apache.tika.parser.ParseContext;
@@ -46,7 +46,7 @@ public interface Renderer extends Serializable, SelfConfiguring {
      */
     Set<MediaType> getSupportedTypes(ParseContext context);
 
-    RenderResults render(InputStream is, Metadata metadata, ParseContext parseContext,
+    RenderResults render(TikaInputStream tis, Metadata metadata, ParseContext parseContext,
                          RenderRequest ... requests) throws IOException,
             TikaException;
 
@@ -55,7 +55,7 @@ public interface Renderer extends Serializable, SelfConfiguring {
     page the requestor or the parser determines that they only want to render e.g. a
     box within a page.
 
-    RenderResults render(InputStream is, int page, Coordinates coordinates, Metadata metadata,
+    RenderResults render(TikaInputStream tis, int page, Coordinates coordinates, Metadata metadata,
                          ParseContext parseContext) throws IOException,
             TikaException;
 
diff --git a/tika-core/src/main/java/org/apache/tika/utils/ParserUtils.java b/tika-core/src/main/java/org/apache/tika/utils/ParserUtils.java
index 837f762955..802902fb73 100644
--- a/tika-core/src/main/java/org/apache/tika/utils/ParserUtils.java
+++ b/tika-core/src/main/java/org/apache/tika/utils/ParserUtils.java
@@ -19,7 +19,6 @@ package org.apache.tika.utils;
 import static org.apache.tika.metadata.TikaCoreProperties.EMBEDDED_EXCEPTION;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.util.Arrays;
 
 import org.apache.tika.io.TemporaryResources;
@@ -111,57 +110,39 @@ public class ParserUtils {
      * Ensures that the Stream will be able to be re-read, by buffering to
      * a temporary file if required.
      * Streams that are automatically OK include {@link TikaInputStream}s
-     * created from Files or InputStreamFactories, and {@link RereadableInputStream}.
+     * created from Files or InputStreamFactories.
      */
-    public static InputStream ensureStreamReReadable(InputStream stream, TemporaryResources tmp,
+    public static TikaInputStream ensureStreamReReadable(TikaInputStream stream, TemporaryResources tmp,
                                                      Metadata metadata)
             throws IOException {
-        // If it's re-readable, we're done
-        if (stream instanceof RereadableInputStream) {
-            return stream;
-        }
-
-        // Make sure it's a TikaInputStream
-        TikaInputStream tstream = TikaInputStream.cast(stream);
-        if (tstream == null) {
-            tstream = TikaInputStream.get(stream, tmp, metadata);
-        }
-
         // If it's factory based, it's ok
-        if (tstream.getInputStreamFactory() != null) {
-            return tstream;
+        if (stream.getInputStreamFactory() != null) {
+            return stream;
         }
 
         // Ensure it's file based
-        tstream.getFile();
+        stream.getFile();
         // Prepare for future re-reads
-        tstream.mark(-1);
-        return tstream;
+        stream.mark(-1);
+        return stream;
     }
 
     /**
      * Resets the given {@link TikaInputStream} (checked by
-     * {@link #ensureStreamReReadable(InputStream, TemporaryResources, Metadata)})
+     * {@link #ensureStreamReReadable(TikaInputStream, TemporaryResources, Metadata)})
      * so that it can be re-read again.
      */
-    public static InputStream streamResetForReRead(InputStream stream, TemporaryResources tmp)
+    public static TikaInputStream streamResetForReRead(TikaInputStream stream, TemporaryResources tmp)
             throws IOException {
-        // If re-readable, rewind to start
-        if (stream instanceof RereadableInputStream) {
-            ((RereadableInputStream) stream).rewind();
-            return stream;
-        }
-
-        // File or Factory based?
-        TikaInputStream tstream = (TikaInputStream) stream;
-        if (tstream.getInputStreamFactory() != null) {
+        // Factory based?
+        if (stream.getInputStreamFactory() != null) {
             // Just get a fresh one each time from the factory
-            return TikaInputStream.get(tstream.getInputStreamFactory(), tmp);
+            return TikaInputStream.get(stream.getInputStreamFactory(), tmp);
         }
 
         // File based, reset stream to beginning of File
-        tstream.reset();
-        tstream.mark(-1);
-        return tstream;
+        stream.reset();
+        stream.mark(-1);
+        return stream;
     }
 }
diff --git a/tika-core/src/test/java/org/apache/custom/detect/MyCustomDetector.java b/tika-core/src/test/java/org/apache/custom/detect/MyCustomDetector.java
index 7237d11766..603cec592a 100644
--- a/tika-core/src/test/java/org/apache/custom/detect/MyCustomDetector.java
+++ b/tika-core/src/test/java/org/apache/custom/detect/MyCustomDetector.java
@@ -17,15 +17,15 @@
 package org.apache.custom.detect;
 
 import java.io.IOException;
-import java.io.InputStream;
 
 import org.apache.tika.detect.Detector;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 
 public class MyCustomDetector implements Detector {
     @Override
-    public MediaType detect(InputStream input, Metadata metadata) throws IOException {
+    public MediaType detect(TikaInputStream tis, Metadata metadata) throws IOException {
         return MediaType.OCTET_STREAM;
     }
 }
diff --git a/tika-core/src/test/java/org/apache/tika/MultiThreadedTikaTest.java b/tika-core/src/test/java/org/apache/tika/MultiThreadedTikaTest.java
index 34f4a0b85c..c36d8b56ca 100644
--- a/tika-core/src/test/java/org/apache/tika/MultiThreadedTikaTest.java
+++ b/tika-core/src/test/java/org/apache/tika/MultiThreadedTikaTest.java
@@ -20,7 +20,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 
 import java.io.FileFilter;
 import java.io.IOException;
-import java.io.InputStream;
 import java.net.URISyntaxException;
 import java.nio.file.FileVisitResult;
 import java.nio.file.Files;
@@ -102,9 +101,9 @@ public class MultiThreadedTikaTest extends TikaTest {
         ConcurrentHashMap<Path, Extract> baseline = new ConcurrentHashMap<>();
 
         for (Path f : files) {
-            try (TikaInputStream is = TikaInputStream.get(f)) {
+            try (TikaInputStream tis = TikaInputStream.get(f)) {
 
-                List<Metadata> metadataList = getRecursiveMetadata(is, parser, parseContext);
+                List<Metadata> metadataList = getRecursiveMetadata(tis, parser, parseContext);
                 baseline.put(f, new Extract(metadataList));
 
             } catch (Exception e) {
@@ -114,7 +113,7 @@ public class MultiThreadedTikaTest extends TikaTest {
         return baseline;
     }
 
-    private static List<Metadata> getRecursiveMetadata(InputStream is, Parser parser,
+    private static List<Metadata> getRecursiveMetadata(TikaInputStream tis, Parser parser,
                                                        ParseContext parseContext) throws Exception {
         //different from parent TikaTest in that this extracts text.
         //can't extract xhtml because "tmp" file names wind up in
@@ -123,7 +122,7 @@ public class MultiThreadedTikaTest extends TikaTest {
         RecursiveParserWrapperHandler handler = new RecursiveParserWrapperHandler(
                 new BasicContentHandlerFactory(BasicContentHandlerFactory.HANDLER_TYPE.TEXT, -1),
                 -1);
-        parser.parse(is, handler, new Metadata(), parseContext);
+        parser.parse(tis, handler, new Metadata(), parseContext);
         return handler.getMetadataList();
     }
 
@@ -352,8 +351,8 @@ public class MultiThreadedTikaTest extends TikaTest {
                 Path testFile = files[randIndex];
                 List<Metadata> metadataList = null;
                 boolean success = false;
-                try (InputStream is = TikaInputStream.get(testFile)) {
-                    metadataList = getRecursiveMetadata(is, parser, new ParseContext());
+                try (TikaInputStream tis = TikaInputStream.get(testFile)) {
+                    metadataList = getRecursiveMetadata(tis, parser, new ParseContext());
                     success = true;
                 } catch (Exception e) {
                     //swallow
diff --git a/tika-core/src/test/java/org/apache/tika/TikaTest.java b/tika-core/src/test/java/org/apache/tika/TikaTest.java
index 8d16a14b43..9749272bc8 100644
--- a/tika-core/src/test/java/org/apache/tika/TikaTest.java
+++ b/tika-core/src/test/java/org/apache/tika/TikaTest.java
@@ -249,12 +249,12 @@ public abstract class TikaTest {
         }
     }
 
-    public InputStream getResourceAsStream(String name) {
-        InputStream stream = this.getClass().getResourceAsStream(name);
-        if (stream == null) {
+    public TikaInputStream getResourceAsStream(String name) {
+        TikaInputStream tis = TikaInputStream.get(this.getClass().getResourceAsStream(name));
+        if (tis == null) {
             fail("Unable to find requested resource " + name);
         }
-        return stream;
+        return tis;
     }
 
     /**
@@ -317,23 +317,21 @@ public abstract class TikaTest {
                 new Metadata(), null);
     }
 
-    protected XMLResult getXML(InputStream input, Parser parser, Metadata metadata)
+    protected XMLResult getXML(TikaInputStream input, Parser parser, Metadata metadata)
             throws Exception {
         return getXML(input, parser, metadata, null);
     }
 
-    protected XMLResult getXML(InputStream input, Parser parser, Metadata metadata,
+    protected XMLResult getXML(TikaInputStream input, Parser parser, Metadata metadata,
                                ParseContext context) throws Exception {
         if (context == null) {
             context = new ParseContext();
         }
 
-        try {
+        try (input) {
             ContentHandler handler = new ToXMLContentHandler();
             parser.parse(input, handler, metadata, context);
             return new XMLResult(handler.toString(), metadata);
-        } finally {
-            input.close();
         }
     }
 
@@ -384,8 +382,8 @@ public abstract class TikaTest {
     protected List<Metadata> getRecursiveMetadata(String filePath, Parser wrapped,
                                                   Metadata metadata, ParseContext context,
                                                   boolean suppressException) throws Exception {
-        try (InputStream is = getResourceAsStream("/test-documents/" + filePath)) {
-            return getRecursiveMetadata(is, wrapped, metadata, context, suppressException);
+        try (TikaInputStream tis = getResourceAsStream("/test-documents/" + filePath)) {
+            return getRecursiveMetadata(tis, wrapped, metadata, context, suppressException);
         }
     }
 
@@ -394,8 +392,8 @@ public abstract class TikaTest {
                                                   boolean suppressException,
                                                   BasicContentHandlerFactory.HANDLER_TYPE handlerType)
             throws Exception {
-        try (InputStream is = getResourceAsStream("/test-documents/" + filePath)) {
-            return getRecursiveMetadata(is, wrapped, metadata, context, suppressException, handlerType);
+        try (TikaInputStream tis = getResourceAsStream("/test-documents/" + filePath)) {
+            return getRecursiveMetadata(tis, wrapped, metadata, context, suppressException, handlerType);
         }
     }
 
@@ -441,31 +439,31 @@ public abstract class TikaTest {
         }
     }
 
-    protected List<Metadata> getRecursiveMetadata(InputStream is, boolean suppressException)
+    protected List<Metadata> getRecursiveMetadata(TikaInputStream tis, boolean suppressException)
             throws Exception {
-        return getRecursiveMetadata(is, new Metadata(), new ParseContext(), suppressException);
+        return getRecursiveMetadata(tis, new Metadata(), new ParseContext(), suppressException);
     }
 
-    protected List<Metadata> getRecursiveMetadata(InputStream is, Parser parser,
+    protected List<Metadata> getRecursiveMetadata(TikaInputStream tis, Parser parser,
                                                   boolean suppressException) throws Exception {
-        return getRecursiveMetadata(is, parser, new Metadata(), new ParseContext(),
+        return getRecursiveMetadata(tis, parser, new Metadata(), new ParseContext(),
                 suppressException);
     }
 
-    protected List<Metadata> getRecursiveMetadata(InputStream is, Metadata metadata,
+    protected List<Metadata> getRecursiveMetadata(TikaInputStream tis, Metadata metadata,
                                                   ParseContext context, boolean suppressException)
             throws Exception {
-        return getRecursiveMetadata(is, AUTO_DETECT_PARSER, metadata, context, suppressException);
+        return getRecursiveMetadata(tis, AUTO_DETECT_PARSER, metadata, context, suppressException);
     }
 
-    protected List<Metadata> getRecursiveMetadata(InputStream is, Parser p, Metadata metadata,
+    protected List<Metadata> getRecursiveMetadata(TikaInputStream tis, Parser p, Metadata metadata,
                                                   ParseContext context, boolean suppressException)
             throws Exception {
         RecursiveParserWrapper wrapper = new RecursiveParserWrapper(p);
         RecursiveParserWrapperHandler handler = new RecursiveParserWrapperHandler(
                 new BasicContentHandlerFactory(BasicContentHandlerFactory.HANDLER_TYPE.XML, -1));
-        try {
-            wrapper.parse(is, handler, metadata, context);
+        try (tis) {
+            wrapper.parse(tis, handler, metadata, context);
         } catch (Exception e) {
             if (!suppressException) {
                 throw e;
@@ -474,15 +472,15 @@ public abstract class TikaTest {
         return handler.getMetadataList();
     }
 
-    protected List<Metadata> getRecursiveMetadata(InputStream is, Parser p, Metadata metadata,
+    protected List<Metadata> getRecursiveMetadata(TikaInputStream tis, Parser p, Metadata metadata,
                                                   ParseContext context, boolean suppressException,
                                                   BasicContentHandlerFactory.HANDLER_TYPE handlerType)
             throws Exception {
         RecursiveParserWrapper wrapper = new RecursiveParserWrapper(p);
         RecursiveParserWrapperHandler handler = new RecursiveParserWrapperHandler(
                 new BasicContentHandlerFactory(handlerType, -1));
-        try {
-            wrapper.parse(is, handler, metadata, context);
+        try (tis) {
+            wrapper.parse(tis, handler, metadata, context);
         } catch (Exception e) {
             if (!suppressException) {
                 throw e;
@@ -497,8 +495,8 @@ public abstract class TikaTest {
 
         RecursiveParserWrapperHandler handler = new RecursiveParserWrapperHandler(
                 new BasicContentHandlerFactory(BasicContentHandlerFactory.HANDLER_TYPE.XML, -1));
-        try (InputStream is = getResourceAsStream("/test-documents/" + filePath)) {
-            wrapper.parse(is, handler, new Metadata(), context);
+        try (TikaInputStream tis = getResourceAsStream("/test-documents/" + filePath)) {
+            wrapper.parse(tis, handler, new Metadata(), context);
         }
         return handler.getMetadataList();
     }
@@ -525,8 +523,8 @@ public abstract class TikaTest {
                 new RecursiveParserWrapperHandler(new BasicContentHandlerFactory(handlerType, -1));
         Metadata metadata = new Metadata();
         metadata.set(TikaCoreProperties.RESOURCE_NAME_KEY, FilenameUtils.getName(filePath));
-        try (InputStream is = getResourceAsStream("/test-documents/" + filePath)) {
-            wrapper.parse(is, handler, metadata, context);
+        try (TikaInputStream tis = getResourceAsStream("/test-documents/" + filePath)) {
+            wrapper.parse(tis, handler, metadata, context);
         }
         return handler.getMetadataList();
     }
@@ -537,8 +535,8 @@ public abstract class TikaTest {
         RecursiveParserWrapperHandler handler = new RecursiveParserWrapperHandler(
                 new BasicContentHandlerFactory(BasicContentHandlerFactory.HANDLER_TYPE.XML, -1));
 
-        try (InputStream is = getResourceAsStream("/test-documents/" + filePath)) {
-            wrapper.parse(is, handler, new Metadata(), parseContext);
+        try (TikaInputStream tis = getResourceAsStream("/test-documents/" + filePath)) {
+            wrapper.parse(tis, handler, new Metadata(), parseContext);
         }
         return handler.getMetadataList();
     }
@@ -575,11 +573,11 @@ public abstract class TikaTest {
      * <p>
      * Tries to close input stream after processing.
      */
-    public String getText(InputStream is, Parser parser, ParseContext context, Metadata metadata)
+    public String getText(TikaInputStream tis, Parser parser, ParseContext context, Metadata metadata)
             throws Exception {
         ContentHandler handler = new BodyContentHandler(1000000);
-        try (is) {
-            parser.parse(is, handler, metadata, context);
+        try (tis) {
+            parser.parse(tis, handler, metadata, context);
         } catch (SAXException e) {
             if (!WriteLimitReachedException.isWriteLimitReached(e)) {
                 throw e;
@@ -588,24 +586,24 @@ public abstract class TikaTest {
         return handler.toString();
     }
 
-    public String getText(InputStream is, Parser parser, Metadata metadata) throws Exception {
+    public String getText(TikaInputStream tis, Parser parser, Metadata metadata) throws Exception {
         ParseContext parseContext = new ParseContext();
         parseContext.set(Parser.class, parser);
-        return getText(is, parser, parseContext, metadata);
+        return getText(tis, parser, parseContext, metadata);
     }
 
-    public String getText(InputStream is, Parser parser, ParseContext context) throws Exception {
-        return getText(is, parser, context, new Metadata());
+    public String getText(TikaInputStream tis, Parser parser, ParseContext context) throws Exception {
+        return getText(tis, parser, context, new Metadata());
     }
 
-    public String getText(InputStream is, Parser parser) throws Exception {
-        return getText(is, parser, new Metadata());
+    public String getText(TikaInputStream tis, Parser parser) throws Exception {
+        return getText(tis, parser, new Metadata());
     }
 
-    public InputStream truncate(String testFileName, int truncatedLength) throws IOException {
+    public TikaInputStream truncate(String testFileName, int truncatedLength) throws IOException {
         ByteArrayOutputStream bos = new ByteArrayOutputStream();
-        try (InputStream is = getResourceAsStream("/test-documents/" + testFileName)) {
-            IOUtils.copy(is, bos);
+        try (TikaInputStream tis = getResourceAsStream("/test-documents/" + testFileName)) {
+            IOUtils.copy(tis, bos);
         }
         if (truncatedLength > bos.toByteArray().length) {
             throw new EOFException(
diff --git a/tika-core/src/test/java/org/apache/tika/detect/FileCommandDetectorTest.java b/tika-core/src/test/java/org/apache/tika/detect/FileCommandDetectorTest.java
index 7f495408f7..bc72f107cc 100644
--- a/tika-core/src/test/java/org/apache/tika/detect/FileCommandDetectorTest.java
+++ b/tika-core/src/test/java/org/apache/tika/detect/FileCommandDetectorTest.java
@@ -19,8 +19,6 @@ package org.apache.tika.detect;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.api.Assumptions.assumeTrue;
 
-import java.io.BufferedInputStream;
-import java.io.InputStream;
 import java.util.Arrays;
 
 import org.junit.jupiter.api.Test;
@@ -47,12 +45,12 @@ public class FileCommandDetectorTest {
                 MimeTypes.getDefaultMimeTypes().getMediaTypeRegistry(),
                 Arrays.asList(fileDetector, defaultDetector));
 
-        try (InputStream is = new BufferedInputStream(getClass()
+        try (TikaInputStream tis = TikaInputStream.get(getClass()
                 .getResourceAsStream(TEST_FILE))) {
             //run more than once to ensure that the input stream is reset
             for (int i = 0; i < 2; i++) {
                 Metadata metadata = new Metadata();
-                MediaType answer = detector.detect(is, metadata);
+                MediaType answer = detector.detect(tis, metadata);
                 String fileMime = metadata.get(FileCommandDetector.FILE_MIME);
                 assertTrue(MediaType.text("xml").equals(answer) ||
                         MediaType.application("xml").equals(answer),
@@ -64,11 +62,11 @@ public class FileCommandDetectorTest {
         }
 
         //now try with TikaInputStream
-        try (InputStream is = TikaInputStream
+        try (TikaInputStream tis = TikaInputStream
                 .get(getClass().getResourceAsStream(TEST_FILE))) {
             //run more than once to ensure that the input stream is reset
             for (int i = 0; i < 2; i++) {
-                MediaType answer = detector.detect(is, new Metadata());
+                MediaType answer = detector.detect(tis, new Metadata());
                 assertTrue(MediaType.text("xml").equals(answer) ||
                         MediaType.application("xml").equals(answer),
                         "Expected text/xml or application/xml but got: " + answer);
diff --git a/tika-core/src/test/java/org/apache/tika/detect/MagicDetectorTest.java b/tika-core/src/test/java/org/apache/tika/detect/MagicDetectorTest.java
index 32d01f5185..7978cc149d 100644
--- a/tika-core/src/test/java/org/apache/tika/detect/MagicDetectorTest.java
+++ b/tika-core/src/test/java/org/apache/tika/detect/MagicDetectorTest.java
@@ -22,7 +22,6 @@ import static java.nio.charset.StandardCharsets.UTF_16LE;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.fail;
 
-import java.io.BufferedInputStream;
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -30,6 +29,7 @@ import java.io.InputStream;
 import org.apache.commons.io.IOUtils;
 import org.junit.jupiter.api.Test;
 
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 
@@ -164,8 +164,9 @@ public class MagicDetectorTest {
         Detector detector = new MagicDetector(testMT, data, null, false, 0, 0);
         // Deliberately prevent InputStream.read(...) from reading the entire
         // buffer in one go
-        InputStream stream = new RestrictiveInputStream(data);
-        assertEquals(testMT, detector.detect(stream, new Metadata()));
+        try (TikaInputStream tis = TikaInputStream.get(new RestrictiveInputStream(data))) {
+            assertEquals(testMT, detector.detect(tis, new Metadata()));
+        }
     }
 
     @Test
@@ -177,8 +178,9 @@ public class MagicDetectorTest {
         Detector detector = new MagicDetector(testMT, data, null, false, 0, 0);
         // Deliberately prevent InputStream.read(...) from reading the entire
         // buffer in one go
-        InputStream stream = new RestrictiveInputStream(data);
-        assertEquals(testMT, detector.detect(stream, new Metadata()));
+        try (TikaInputStream tis = TikaInputStream.get(new RestrictiveInputStream(data))) {
+            assertEquals(testMT, detector.detect(tis, new Metadata()));
+        }
     }
 
     @Test
@@ -211,14 +213,14 @@ public class MagicDetectorTest {
 
     private void assertDetect(Detector detector, MediaType type, byte[] bytes) {
         try {
-            InputStream stream = new ByteArrayInputStream(bytes);
-            assertEquals(type, detector.detect(stream, new Metadata()));
+            TikaInputStream tis = TikaInputStream.get(bytes);
+            assertEquals(type, detector.detect(tis, new Metadata()));
 
             // Test that the stream has been reset
             for (byte aByte : bytes) {
-                assertEquals(aByte, (byte) stream.read());
+                assertEquals(aByte, (byte) tis.read());
             }
-            assertEquals(-1, stream.read());
+            assertEquals(-1, tis.read());
         } catch (IOException e) {
             fail("Unexpected exception from MagicDetector");
         }
@@ -258,10 +260,10 @@ public class MagicDetectorTest {
     }
 
     private String detect(Detector detector, String bz2Name) throws IOException  {
-        try (InputStream is = new BufferedInputStream(
+        try (TikaInputStream tis = TikaInputStream.get(
                 this.getClass().getResourceAsStream(
                         "/test-documents/bz2/" + bz2Name))) {
-            return detector.detect(is, new Metadata()).toString();
+            return detector.detect(tis, new Metadata()).toString();
         }
     }
 }
diff --git a/tika-core/src/test/java/org/apache/tika/detect/MimeDetectionWithNNTest.java b/tika-core/src/test/java/org/apache/tika/detect/MimeDetectionWithNNTest.java
index 293f423d2c..1de1bd090b 100644
--- a/tika-core/src/test/java/org/apache/tika/detect/MimeDetectionWithNNTest.java
+++ b/tika-core/src/test/java/org/apache/tika/detect/MimeDetectionWithNNTest.java
@@ -19,13 +19,12 @@ package org.apache.tika.detect;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
-import java.io.InputStream;
 
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 import org.apache.tika.mime.MimeDetectionTest;
@@ -89,22 +88,19 @@ public class MimeDetectionWithNNTest {
     }
 
     private void testUrl(String expected, String url, String file) throws IOException {
-        InputStream in = MimeDetectionTest.class.getResourceAsStream(file);
-        testStream(expected, url, in);
+        TikaInputStream tis = TikaInputStream.get(MimeDetectionTest.class.getResourceAsStream(file));
+        testStream(expected, url, tis);
     }
 
     private void testFile(String expected, String filename) throws IOException {
 
-        InputStream in = MimeDetectionTest.class.getResourceAsStream(filename);
-        testStream(expected, filename, in);
+        TikaInputStream tis = TikaInputStream.get(MimeDetectionTest.class.getResourceAsStream(filename));
+        testStream(expected, filename, tis);
     }
 
-    private void testStream(String expected, String urlOrFileName, InputStream in)
+    private void testStream(String expected, String urlOrFileName, TikaInputStream in)
             throws IOException {
         assertNotNull(in, "Test stream: [" + urlOrFileName + "] is null!");
-        if (!in.markSupported()) {
-            in = new java.io.BufferedInputStream(in);
-        }
         try {
             Metadata metadata = new Metadata();
             String mime = this.detector.detect(in, metadata).toString();
@@ -127,7 +123,7 @@ public class MimeDetectionWithNNTest {
     @Test
     public void testEmptyDocument() throws IOException {
         assertEquals(MediaType.OCTET_STREAM,
-                detector.detect(new ByteArrayInputStream(new byte[0]), new Metadata()));
+                detector.detect(TikaInputStream.get(new byte[0]), new Metadata()));
 
     }
 
diff --git a/tika-core/src/test/java/org/apache/tika/detect/TextDetectorTest.java b/tika-core/src/test/java/org/apache/tika/detect/TextDetectorTest.java
index 1870033d9e..b6ab64189d 100644
--- a/tika-core/src/test/java/org/apache/tika/detect/TextDetectorTest.java
+++ b/tika-core/src/test/java/org/apache/tika/detect/TextDetectorTest.java
@@ -20,13 +20,12 @@ import static java.nio.charset.StandardCharsets.UTF_8;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.fail;
 
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
-import java.io.InputStream;
 import java.util.Arrays;
 
 import org.junit.jupiter.api.Test;
 
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 
@@ -84,14 +83,14 @@ public class TextDetectorTest {
 
     private void assertText(byte[] data) {
         try {
-            InputStream stream = new ByteArrayInputStream(data);
-            assertEquals(MediaType.TEXT_PLAIN, detector.detect(stream, new Metadata()));
+            TikaInputStream tis = TikaInputStream.get(data);
+            assertEquals(MediaType.TEXT_PLAIN, detector.detect(tis, new Metadata()));
 
             // Test that the stream has been reset
             for (byte aByte : data) {
-                assertEquals(aByte, (byte) stream.read());
+                assertEquals(aByte, (byte) tis.read());
             }
-            assertEquals(-1, stream.read());
+            assertEquals(-1, tis.read());
         } catch (IOException e) {
             fail("Unexpected exception from TextDetector");
         }
@@ -100,7 +99,7 @@ public class TextDetectorTest {
     private void assertNotText(byte[] data) {
         try {
             assertEquals(MediaType.OCTET_STREAM,
-                    detector.detect(new ByteArrayInputStream(data), new Metadata()));
+                    detector.detect(TikaInputStream.get(data), new Metadata()));
         } catch (IOException e) {
             fail("Unexpected exception from TextDetector");
         }
diff --git a/tika-core/src/test/java/org/apache/tika/detect/ZeroSizeFileDetectorTest.java b/tika-core/src/test/java/org/apache/tika/detect/ZeroSizeFileDetectorTest.java
index 852711671d..685fe441d9 100644
--- a/tika-core/src/test/java/org/apache/tika/detect/ZeroSizeFileDetectorTest.java
+++ b/tika-core/src/test/java/org/apache/tika/detect/ZeroSizeFileDetectorTest.java
@@ -20,13 +20,12 @@ import static java.nio.charset.StandardCharsets.UTF_8;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.fail;
 
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
-import java.io.InputStream;
 
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 
@@ -53,8 +52,8 @@ public class ZeroSizeFileDetectorTest {
 
     private void detect(byte[] data, MediaType type) {
         try {
-            InputStream stream = new ByteArrayInputStream(data);
-            assertEquals(type, detector.detect(stream, new Metadata()));
+            TikaInputStream tis = TikaInputStream.get(data);
+            assertEquals(type, detector.detect(tis, new Metadata()));
         } catch (IOException e) {
             fail("Unexpected exception from ZeroSizeFileDetector");
         }
diff --git a/tika-core/src/test/java/org/apache/tika/fork/ForkParserTest.java b/tika-core/src/test/java/org/apache/tika/fork/ForkParserTest.java
index f6ac5335be..fa3c597234 100644
--- a/tika-core/src/test/java/org/apache/tika/fork/ForkParserTest.java
+++ b/tika-core/src/test/java/org/apache/tika/fork/ForkParserTest.java
@@ -20,12 +20,10 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.api.Assertions.fail;
 
-import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.DataOutputStream;
 import java.io.File;
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.PipedInputStream;
 import java.io.PipedOutputStream;
@@ -55,6 +53,7 @@ import org.xml.sax.helpers.DefaultHandler;
 
 import org.apache.tika.TikaTest;
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
 import org.apache.tika.parser.AutoDetectParser;
@@ -79,9 +78,9 @@ public class ForkParserTest extends TikaTest {
                 new ForkTestParser())) {
             Metadata metadata = new Metadata();
             ContentHandler output = new BodyContentHandler();
-            InputStream stream = new ByteArrayInputStream(new byte[0]);
+            TikaInputStream tis = TikaInputStream.get(new byte[0]);
             ParseContext context = new ParseContext();
-            parser.parse(stream, output, metadata, context);
+            parser.parse(tis, output, metadata, context);
             assertEquals("Hello, World!", output.toString().trim());
             assertEquals("text/plain", metadata.get(Metadata.CONTENT_TYPE));
         }
@@ -94,8 +93,8 @@ public class ForkParserTest extends TikaTest {
             ParseContext context = new ParseContext();
             for (int i = 0; i < 10; i++) {
                 ContentHandler output = new BodyContentHandler();
-                InputStream stream = new ByteArrayInputStream(new byte[0]);
-                parser.parse(stream, output, new Metadata(), context);
+                TikaInputStream tis = TikaInputStream.get(new byte[0]);
+                parser.parse(tis, output, new Metadata(), context);
                 assertEquals("Hello, World!", output.toString().trim());
             }
         }
@@ -114,8 +113,8 @@ public class ForkParserTest extends TikaTest {
                 output[i] = o;
                 threads[i] = new Thread(() -> {
                     try {
-                        InputStream stream = new ByteArrayInputStream(new byte[0]);
-                        parser.parse(stream, o, new Metadata(), context);
+                        TikaInputStream tis = TikaInputStream.get(new byte[0]);
+                        parser.parse(tis, o, new Metadata(), context);
                     } catch (Exception e) {
                         e.printStackTrace();
                     }
@@ -151,7 +150,9 @@ public class ForkParserTest extends TikaTest {
                 threads[i] = new Thread(() -> {
                     try {
                         ContentHandler o = new DefaultHandler();
-                        parser.parse(input, o, new Metadata(), context);
+                        try (TikaInputStream tis = TikaInputStream.get(input)) {
+                            parser.parse(tis, o, new Metadata(), context);
+                        }
                     } catch (Exception e) {
                         e.printStackTrace();
                     }
@@ -166,8 +167,9 @@ public class ForkParserTest extends TikaTest {
             Thread blocked = new Thread(() -> {
                 try {
                     barrier.release();
-                    InputStream stream = new ByteArrayInputStream(new byte[0]);
-                    parser.parse(stream, o, new Metadata(), context);
+                    try (TikaInputStream tis = TikaInputStream.get(new byte[0])) {
+                        parser.parse(tis, o, new Metadata(), context);
+                    }
                 } catch (Exception e) {
                     e.printStackTrace();
                 }
@@ -208,7 +210,7 @@ public class ForkParserTest extends TikaTest {
         ParseContext c = new ParseContext();
         try {
             forkParser
-                    .parse(new ByteArrayInputStream(sleepCommand.getBytes(StandardCharsets.UTF_8)),
+                    .parse(TikaInputStream.get(sleepCommand.getBytes(StandardCharsets.UTF_8)),
                             o, m, c);
             fail("should have thrown IOException");
         } catch (TikaException e) {
@@ -229,7 +231,7 @@ public class ForkParserTest extends TikaTest {
         c = new ParseContext();
         try {
             forkParser
-                    .parse(new ByteArrayInputStream(sleepCommand.getBytes(StandardCharsets.UTF_8)),
+                    .parse(TikaInputStream.get(sleepCommand.getBytes(StandardCharsets.UTF_8)),
                             o, m, c);
             fail("Should have thrown exception");
         } catch (IOException | TikaException e) {
@@ -245,9 +247,10 @@ public class ForkParserTest extends TikaTest {
                 new ForkTestParser.ForkTestParserAccessingPackage())) {
             Metadata metadata = new Metadata();
             ContentHandler output = new BodyContentHandler();
-            InputStream stream = new ByteArrayInputStream(new byte[0]);
             ParseContext context = new ParseContext();
-            parser.parse(stream, output, metadata, context);
+            try (TikaInputStream tis = TikaInputStream.get(new byte[0])) {
+                parser.parse(tis, output, metadata, context);
+            }
             assertEquals("Hello, World!", output.toString().trim());
             assertEquals("text/plain", metadata.get(Metadata.CONTENT_TYPE));
         }
@@ -261,10 +264,10 @@ public class ForkParserTest extends TikaTest {
                 new BasicContentHandlerFactory(BasicContentHandlerFactory.HANDLER_TYPE.TEXT,
                         20000));
         try (ForkParser fork = new ForkParser(ForkParserTest.class.getClassLoader(), wrapper);
-                InputStream is = getResourceAsStream("/test-documents/basic_embedded.xml")) {
+                TikaInputStream tis = TikaInputStream.get(getResourceAsStream("/test-documents/basic_embedded.xml"))) {
             Metadata metadata = new Metadata();
             ParseContext context = new ParseContext();
-            fork.parse(is, handler, metadata, context);
+            fork.parse(tis, handler, metadata, context);
         }
         List<Metadata> metadataList = handler.getMetadataList();
         Metadata m0 = metadataList.get(0);
@@ -286,10 +289,10 @@ public class ForkParserTest extends TikaTest {
                 new BasicContentHandlerFactory(BasicContentHandlerFactory.HANDLER_TYPE.TEXT,
                         20000));
         try (ForkParser fork = new ForkParser(ForkParserTest.class.getClassLoader(), wrapper);
-                InputStream is = getResourceAsStream("/test-documents/massive_embedded.xml")) {
+                TikaInputStream tis = TikaInputStream.get(getResourceAsStream("/test-documents/massive_embedded.xml"))) {
             Metadata metadata = new Metadata();
             ParseContext context = new ParseContext();
-            fork.parse(is, handler, metadata, context);
+            fork.parse(tis, handler, metadata, context);
         }
         List<Metadata> metadataList = handler.getMetadataList();
         assertEquals(111, metadataList.size());
@@ -315,10 +318,10 @@ public class ForkParserTest extends TikaTest {
                 new BasicContentHandlerFactory(BasicContentHandlerFactory.HANDLER_TYPE.TEXT,
                         20000));
         try (ForkParser fork = new ForkParser(ForkParserTest.class.getClassLoader(), wrapper);
-                InputStream is = getResourceAsStream("/test-documents/embedded_with_npe.xml")) {
+                TikaInputStream tis = TikaInputStream.get(getResourceAsStream("/test-documents/embedded_with_npe.xml"))) {
             Metadata metadata = new Metadata();
             ParseContext context = new ParseContext();
-            fork.parse(is, handler, metadata, context);
+            fork.parse(tis, handler, metadata, context);
         }
         List<Metadata> metadataList = handler.getMetadataList();
         Metadata m0 = metadataList.get(0);
@@ -342,10 +345,11 @@ public class ForkParserTest extends TikaTest {
                 new BasicContentHandlerFactory(BasicContentHandlerFactory.HANDLER_TYPE.TEXT,
                         20000));
         try (ForkParser fork = new ForkParser(ForkParserTest.class.getClassLoader(), wrapper);
-                InputStream is = getResourceAsStream("/test-documents/embedded_then_npe.xml")) {
+                TikaInputStream tis = TikaInputStream.get(
+                        getResourceAsStream("/test-documents/embedded_then_npe.xml"))) {
             Metadata metadata = new Metadata();
             ParseContext context = new ParseContext();
-            fork.parse(is, handler, metadata, context);
+            fork.parse(tis, handler, metadata, context);
             fail();
         } catch (TikaException e) {
             assertTrue(e.getCause() instanceof NullPointerException);
@@ -368,7 +372,7 @@ public class ForkParserTest extends TikaTest {
         //test that a server-side write-to-file works without proxying back the
         //AbstractContentHandlerFactory
         Path target = Files.createTempFile(tempDir, "fork-to-file-handler-", ".txt");
-        try (InputStream is = getResourceAsStream("/test-documents/basic_embedded.xml")) {
+        try (TikaInputStream tis = getResourceAsStream("/test-documents/basic_embedded.xml")) {
             RecursiveParserWrapper wrapper = new RecursiveParserWrapper(new AutoDetectParser());
             ToFileHandler toFileHandler =
                     new ToFileHandler(new SBContentHandlerFactory(), target.toFile());
@@ -376,7 +380,7 @@ public class ForkParserTest extends TikaTest {
                     wrapper)) {
                 Metadata m = new Metadata();
                 ParseContext context = new ParseContext();
-                forkParser.parse(is, toFileHandler, m, context);
+                forkParser.parse(tis, toFileHandler, m, context);
             }
         }
 
@@ -403,10 +407,10 @@ public class ForkParserTest extends TikaTest {
         RecursiveParserWrapper wrapper = new RecursiveParserWrapper(parser);
         BufferingHandler handler = new BufferingHandler(new SBContentHandlerFactory());
         try (ForkParser fork = new ForkParser(ForkParserTest.class.getClassLoader(), wrapper);
-                InputStream is = getResourceAsStream("/test-documents/basic_embedded.xml")) {
+                TikaInputStream tis = TikaInputStream.get(getResourceAsStream("/test-documents/basic_embedded.xml"))) {
             Metadata metadata = new Metadata();
             ParseContext context = new ParseContext();
-            fork.parse(is, handler, metadata, context);
+            fork.parse(tis, handler, metadata, context);
         }
         List<Metadata> metadataList = handler.getMetadataList();
         List<ContentHandler> contentHandlers = handler.getContentHandlers();
@@ -431,10 +435,10 @@ public class ForkParserTest extends TikaTest {
         RecursiveParserWrapperHandler handler =
                 new RecursiveParserWrapperHandler(new NonSerializableHandlerFactory());
         try (ForkParser fork = new ForkParser(ForkParserTest.class.getClassLoader(), wrapper);
-                InputStream is = getResourceAsStream("/test-documents/embedded_then_npe.xml")) {
+                TikaInputStream tis = TikaInputStream.get(getResourceAsStream("/test-documents/embedded_then_npe.xml"))) {
             Metadata metadata = new Metadata();
             ParseContext context = new ParseContext();
-            fork.parse(is, handler, metadata, context);
+            fork.parse(tis, handler, metadata, context);
             fail();
         } catch (TikaException e) {
             assertTrue(e.getCause() instanceof NullPointerException);
@@ -473,10 +477,10 @@ public class ForkParserTest extends TikaTest {
                     new ForkTestParser.ForkTestParserWaiting())) {
                 Metadata metadata = new Metadata();
                 ContentHandler output = new BodyContentHandler();
-                InputStream stream = new ByteArrayInputStream(new byte[0]);
+                TikaInputStream tis = TikaInputStream.get(new byte[0]);
                 ParseContext context = new ParseContext();
                 cdl.countDown();
-                parser.parse(stream, output, metadata, context);
+                parser.parse(tis, output, metadata, context);
                 // Don't care about output not planning to get this far
             } catch (IOException | SAXException | TikaException e) {
                 throw new RuntimeException(e);
diff --git a/tika-core/src/test/java/org/apache/tika/fork/ForkParserTikaBinTest.java b/tika-core/src/test/java/org/apache/tika/fork/ForkParserTikaBinTest.java
index c6f63f89ba..2f1ac36ce9 100644
--- a/tika-core/src/test/java/org/apache/tika/fork/ForkParserTikaBinTest.java
+++ b/tika-core/src/test/java/org/apache/tika/fork/ForkParserTikaBinTest.java
@@ -42,6 +42,7 @@ import org.xml.sax.SAXException;
 
 import org.apache.tika.TikaTest;
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
 import org.apache.tika.parser.ParseContext;
@@ -76,7 +77,7 @@ public class ForkParserTikaBinTest extends TikaTest {
             try (InputStream input = ForkParserTikaBinTest.class
                     .getResourceAsStream("/org/apache/tika/config/TIKA-2653-vowel-parser-ae.xml")) {
                 jarOs.putNextEntry(
-                        new JarEntry("org/apache/tika/parser/TIKA-2653-vowel-parser-ae.xml"));
+                        new JarEntry("org/apache/tika/fork/TIKA-2653-vowel-parser-ae.xml"));
                 IOUtils.copy(input, jarOs);
             }
             try (InputStream input = ForkParserTikaBinTest.class
@@ -125,7 +126,7 @@ public class ForkParserTikaBinTest extends TikaTest {
     @Test
     public void testVowelParserAsDefault() throws Exception {
         ParserFactoryFactory pff =
-                new ParserFactoryFactory("org.apache.tika.parser.mock.AutoDetectParserFactory",
+                new ParserFactoryFactory("org.apache.tika.fork.AutoDetectParserFactory",
                         EMPTY_MAP);
         XMLResult xmlResult = getXML(pff);
         assertContains("eooeuiooueoeeao", xmlResult.xml);
@@ -138,7 +139,7 @@ public class ForkParserTikaBinTest extends TikaTest {
         //this tests that the content handler was loaded from the parent process.
 
         ParserFactoryFactory pff =
-                new ParserFactoryFactory("org.apache.tika.parser.mock.AutoDetectParserFactory",
+                new ParserFactoryFactory("org.apache.tika.fork.AutoDetectParserFactory",
                         EMPTY_MAP);
         XMLResult xmlResult =
                 getXML(pff, this.getClass().getClassLoader(), new UpperCasingContentHandler());
@@ -171,8 +172,8 @@ public class ForkParserTikaBinTest extends TikaTest {
         ContentHandler handler =
                 (contentHandler == null) ? new ToXMLContentHandler() : contentHandler;
         Metadata m = new Metadata();
-        try (InputStream is = getResourceAsStream("/test-documents/example.xml")) {
-            parser.parse(is, handler, m, new ParseContext());
+        try (TikaInputStream tis = TikaInputStream.get(getResourceAsStream("/test-documents/example.xml"))) {
+            parser.parse(tis, handler, m, new ParseContext());
         } finally {
             parser.close();
         }
diff --git a/tika-core/src/test/java/org/apache/tika/fork/ForkTestParser.java b/tika-core/src/test/java/org/apache/tika/fork/ForkTestParser.java
index e9c6949fa2..cfccf78e9f 100644
--- a/tika-core/src/test/java/org/apache/tika/fork/ForkTestParser.java
+++ b/tika-core/src/test/java/org/apache/tika/fork/ForkTestParser.java
@@ -28,13 +28,14 @@ import org.xml.sax.SAXException;
 
 import org.apache.tika.exception.TikaException;
 import org.apache.tika.fork.unusedpackage.ClassInUnusedPackage;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
+import org.apache.tika.parser.AbstractParser;
 import org.apache.tika.parser.ParseContext;
-import org.apache.tika.parser.Parser;
 import org.apache.tika.sax.XHTMLContentHandler;
 
-class ForkTestParser implements Parser {
+class ForkTestParser extends AbstractParser implements ParserShim  {
 
     /**
      * Serial version UID
@@ -45,8 +46,13 @@ class ForkTestParser implements Parser {
         return Collections.singleton(MediaType.TEXT_PLAIN);
     }
 
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
-                      ParseContext context) throws IOException, SAXException, TikaException {
+    @Override
+    public void parse(TikaInputStream stream, ContentHandler handler, Metadata metadata, ParseContext context) throws IOException, SAXException, TikaException {
+        parseStream(stream, handler, metadata, context);
+    }
+
+    public void parseStream(InputStream stream, ContentHandler handler, Metadata metadata,
+                            ParseContext context) throws IOException, SAXException, TikaException {
         stream.read();
 
         metadata.set(Metadata.CONTENT_TYPE, "text/plain");
@@ -60,23 +66,23 @@ class ForkTestParser implements Parser {
 
     static class ForkTestParserAccessingPackage extends ForkTestParser {
         @Override
-        public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+        public void parseStream(InputStream stream, ContentHandler handler, Metadata metadata,
                           ParseContext context) throws IOException, SAXException, TikaException {
             assertNotNull(ClassInUnusedPackage.class.getPackage());
-            super.parse(stream, handler, metadata, context);
+            super.parseStream(stream, handler, metadata, context);
         }
     }
 
     static class ForkTestParserWaiting extends ForkTestParser {
         @Override
-        public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+        public void parseStream(InputStream stream, ContentHandler handler, Metadata metadata,
                           ParseContext context) throws IOException, SAXException, TikaException {
             try {
                 Thread.sleep(10_000);
             } catch (InterruptedException e) {
                 throw new RuntimeException(e);
             }
-            super.parse(stream, handler, metadata, context);
+            super.parseStream(stream, handler, metadata, context);
         }
     }
 }
diff --git a/tika-core/src/test/java/org/apache/tika/io/TikaInputStreamTest.java b/tika-core/src/test/java/org/apache/tika/io/TikaInputStreamTest.java
index 1f8943e688..4e53e0fddc 100644
--- a/tika-core/src/test/java/org/apache/tika/io/TikaInputStreamTest.java
+++ b/tika-core/src/test/java/org/apache/tika/io/TikaInputStreamTest.java
@@ -45,20 +45,20 @@ public class TikaInputStreamTest {
     @Test
     public void testFileBased() throws IOException {
         Path path = createTempFile("Hello, World!");
-        TikaInputStream stream = TikaInputStream.get(path);
-        assertTrue(stream.hasFile());
-        assertNull(stream.getOpenContainer());
-        assertNull(stream.getInputStreamFactory());
+        TikaInputStream tis = TikaInputStream.get(path);
+        assertTrue(tis.hasFile());
+        assertNull(tis.getOpenContainer());
+        assertNull(tis.getInputStreamFactory());
 
-        assertEquals(path, TikaInputStream.get(stream).getPath(),
+        assertEquals(path, TikaInputStream.get(tis).getPath(),
                 "The file returned by the getFile() method should" +
                                 " be the file used to instantiate a TikaInputStream");
 
-        assertEquals("Hello, World!", readStream(stream),
+        assertEquals("Hello, World!", readStream(tis),
                 "The contents of the TikaInputStream should equal the" +
                         " contents of the underlying file");
 
-        stream.close();
+        tis.close();
         assertTrue(Files.exists(path),
                 "The close() method must not remove the file used to" +
                 " instantiate a TikaInputStream");
@@ -68,41 +68,41 @@ public class TikaInputStreamTest {
     @Test
     public void testStreamBased() throws IOException {
         InputStream input = IOUtils.toInputStream("Hello, World!", UTF_8);
-        TikaInputStream stream = TikaInputStream.get(input);
-        assertFalse(stream.hasFile());
-        assertNull(stream.getOpenContainer());
-        assertNull(stream.getInputStreamFactory());
+        TikaInputStream tis = TikaInputStream.get(input);
+        assertFalse(tis.hasFile());
+        assertNull(tis.getOpenContainer());
+        assertNull(tis.getInputStreamFactory());
 
-        Path file = TikaInputStream.get(stream).getPath();
+        Path file = TikaInputStream.get(tis).getPath();
         assertTrue(file != null && Files.isRegularFile(file));
-        assertTrue(stream.hasFile());
-        assertNull(stream.getOpenContainer());
-        assertNull(stream.getInputStreamFactory());
+        assertTrue(tis.hasFile());
+        assertNull(tis.getOpenContainer());
+        assertNull(tis.getInputStreamFactory());
 
         assertEquals("Hello, World!", readFile(file),
                 "The contents of the file returned by the getFile method" +
                         " should equal the contents of the TikaInputStream");
 
-        assertEquals("Hello, World!", readStream(stream),
+        assertEquals("Hello, World!", readStream(tis),
                 "The contents of the TikaInputStream should not get modified" +
                         " by reading the file first");
 
-        stream.close();
+        tis.close();
         assertFalse(Files.exists(file),
                 "The close() method must remove the temporary file created by a TikaInputStream");
     }
 
     @Test
     public void testInputStreamFactoryBased() throws IOException {
-        TikaInputStream stream = TikaInputStream.get(() -> IOUtils.toInputStream("Hello, World!", UTF_8));
-        assertFalse(stream.hasFile());
-        assertNull(stream.getOpenContainer());
-        assertNotNull(stream.getInputStreamFactory());
+        TikaInputStream tis = TikaInputStream.get(() -> IOUtils.toInputStream("Hello, World!", UTF_8));
+        assertFalse(tis.hasFile());
+        assertNull(tis.getOpenContainer());
+        assertNotNull(tis.getInputStreamFactory());
 
-        assertEquals("Hello, World!", readStream(stream),
+        assertEquals("Hello, World!", readStream(tis),
                 "The contents of the TikaInputStream should not get modified" +
                         " by reading the file first");
-        stream.close();
+        tis.close();
     }
 
     private Path createTempFile(String data) throws IOException {
diff --git a/tika-core/src/test/java/org/apache/tika/mime/MimeDetectionTest.java b/tika-core/src/test/java/org/apache/tika/mime/MimeDetectionTest.java
index 106598ebbf..2b8a5af078 100644
--- a/tika-core/src/test/java/org/apache/tika/mime/MimeDetectionTest.java
+++ b/tika-core/src/test/java/org/apache/tika/mime/MimeDetectionTest.java
@@ -23,16 +23,15 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
 
 import org.apache.commons.io.ByteOrderMark;
-import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
 
@@ -105,11 +104,11 @@ public class MimeDetectionTest {
     @Test
     public void testByteOrderMark() throws Exception {
         assertEquals(MediaType.TEXT_PLAIN, MIME_TYPES
-                .detect(new ByteArrayInputStream("\ufefftest".getBytes(UTF_16LE)), new Metadata()));
+                .detect(TikaInputStream.get("\ufefftest".getBytes(UTF_16LE)), new Metadata()));
         assertEquals(MediaType.TEXT_PLAIN, MIME_TYPES
-                .detect(new ByteArrayInputStream("\ufefftest".getBytes(UTF_16BE)), new Metadata()));
+                .detect(TikaInputStream.get("\ufefftest".getBytes(UTF_16BE)), new Metadata()));
         assertEquals(MediaType.TEXT_PLAIN, MIME_TYPES
-                .detect(new ByteArrayInputStream("\ufefftest".getBytes(UTF_8)), new Metadata()));
+                .detect(TikaInputStream.get("\ufefftest".getBytes(UTF_8)), new Metadata()));
     }
 
     @Test
@@ -118,19 +117,13 @@ public class MimeDetectionTest {
                 "To: someone@somewhere.com\r\n" + "Cc: someone-else@other.com\r\n" +
                 "Subject: Received\r\n";
         MediaType rfc822 = MediaType.parse("message/rfc822");
-        assertEquals(rfc822, MIME_TYPES.detect(UnsynchronizedByteArrayInputStream
-                .builder()
-                .setByteArray(header.getBytes(UTF_8))
-                .get(), new Metadata()));
+        assertEquals(rfc822, MIME_TYPES.detect(TikaInputStream.get(header.getBytes(UTF_8)), new Metadata()));
 
         int utfLength = ByteOrderMark.UTF_8.length();
         byte[] bytes = new byte[header.getBytes(UTF_8).length + utfLength];
         System.arraycopy(ByteOrderMark.UTF_8.getBytes(), 0, bytes, 0, utfLength);
         System.arraycopy(header.getBytes(UTF_8), 0, bytes, 3, header.getBytes(UTF_8).length);
-        assertEquals(rfc822, MIME_TYPES.detect(UnsynchronizedByteArrayInputStream
-                .builder()
-                .setByteArray(bytes)
-                .get(), new Metadata()));
+        assertEquals(rfc822, MIME_TYPES.detect(TikaInputStream.get(bytes), new Metadata()));
     }
 
     @Test
@@ -191,22 +184,17 @@ public class MimeDetectionTest {
     private void testStream(String expected, String urlOrFileName, InputStream in)
             throws IOException {
         assertNotNull(in, "Test stream: [" + urlOrFileName + "] is null!");
-        if (!in.markSupported()) {
-            in = new java.io.BufferedInputStream(in);
-        }
-        try {
+        try (TikaInputStream tis = TikaInputStream.get(in)) {
             Metadata metadata = new Metadata();
-            String mime = this.MIME_TYPES.detect(in, metadata).toString();
+            String mime = this.MIME_TYPES.detect(tis, metadata).toString();
             assertEquals(expected, mime,
                     urlOrFileName + " is not properly detected: detected.");
 
             //Add resource name and test again
             metadata.set(TikaCoreProperties.RESOURCE_NAME_KEY, urlOrFileName);
-            mime = this.MIME_TYPES.detect(in, metadata).toString();
+            mime = this.MIME_TYPES.detect(tis, metadata).toString();
             assertEquals(expected, mime,
                     urlOrFileName + " is not properly detected after adding resource name.");
-        } finally {
-            in.close();
         }
     }
 
@@ -218,17 +206,17 @@ public class MimeDetectionTest {
     @Test
     public void testEmptyDocument() throws IOException {
         assertEquals(MediaType.OCTET_STREAM,
-                MIME_TYPES.detect(new ByteArrayInputStream(new byte[0]), new Metadata()));
+                MIME_TYPES.detect(TikaInputStream.get(new byte[0]), new Metadata()));
 
         Metadata namehint = new Metadata();
         namehint.set(TikaCoreProperties.RESOURCE_NAME_KEY, "test.txt");
         assertEquals(MediaType.TEXT_PLAIN,
-                MIME_TYPES.detect(new ByteArrayInputStream(new byte[0]), namehint));
+                MIME_TYPES.detect(TikaInputStream.get(new byte[0]), namehint));
 
         Metadata typehint = new Metadata();
         typehint.set(Metadata.CONTENT_TYPE, "text/plain");
         assertEquals(MediaType.TEXT_PLAIN,
-                MIME_TYPES.detect(new ByteArrayInputStream(new byte[0]), typehint));
+                MIME_TYPES.detect(TikaInputStream.get(new byte[0]), typehint));
 
     }
 
@@ -241,7 +229,7 @@ public class MimeDetectionTest {
     @Test
     public void testNotXML() throws IOException {
         assertEquals(MediaType.TEXT_PLAIN, MIME_TYPES
-                .detect(new ByteArrayInputStream("<!-- test -->".getBytes(UTF_8)), new Metadata()));
+                .detect(TikaInputStream.get("<!-- test -->".getBytes(UTF_8)), new Metadata()));
     }
 
     /**
@@ -272,16 +260,16 @@ public class MimeDetectionTest {
         // With a filename, picks the right one
         metadata = new Metadata();
         metadata.set(TikaCoreProperties.RESOURCE_NAME_KEY, "test.hello.world");
-        assertEquals(helloType, MIME_TYPES.detect(new ByteArrayInputStream(helloWorld), metadata));
+        assertEquals(helloType, MIME_TYPES.detect(TikaInputStream.get(helloWorld), metadata));
 
         metadata = new Metadata();
         metadata.set(TikaCoreProperties.RESOURCE_NAME_KEY, "test.x-hello-world");
-        assertEquals(helloXType, MIME_TYPES.detect(new ByteArrayInputStream(helloWorld), metadata));
+        assertEquals(helloXType, MIME_TYPES.detect(TikaInputStream.get(helloWorld), metadata));
 
         // Without, goes for the one that sorts last
         metadata = new Metadata();
         metadata.set(TikaCoreProperties.RESOURCE_NAME_KEY, "testingTESTINGtesting");
-        assertEquals(helloXType, MIME_TYPES.detect(new ByteArrayInputStream(helloWorld), metadata));
+        assertEquals(helloXType, MIME_TYPES.detect(TikaInputStream.get(helloWorld), metadata));
     }
 
     /**
diff --git a/tika-core/src/test/java/org/apache/tika/mime/MimeTypesReaderTest.java b/tika-core/src/test/java/org/apache/tika/mime/MimeTypesReaderTest.java
index af7ceef801..7021d5ddc5 100644
--- a/tika-core/src/test/java/org/apache/tika/mime/MimeTypesReaderTest.java
+++ b/tika-core/src/test/java/org/apache/tika/mime/MimeTypesReaderTest.java
@@ -37,6 +37,7 @@ import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
 
@@ -65,7 +66,7 @@ public class MimeTypesReaderTest {
     private static String getTypeAsString(MimeTypes mimeTypes, String text, Metadata metadata)
             throws IOException {
         return mimeTypes
-                .detect(new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8)), metadata)
+                .detect(TikaInputStream.get(new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8))), metadata)
                 .toString();
 
     }
@@ -251,7 +252,7 @@ public class MimeTypesReaderTest {
 
             // By contents - picks the x one as that sorts later
             m = new Metadata();
-            ByteArrayInputStream s = new ByteArrayInputStream("Hello, World!".getBytes(US_ASCII));
+            TikaInputStream s = TikaInputStream.get("Hello, World!".getBytes(US_ASCII));
             assertEquals(hxw.toString(), this.mimeTypes.detect(s, m).toString());
         } catch (Exception e) {
             fail(e.getMessage());
diff --git a/tika-core/src/test/java/org/apache/tika/mime/ProbabilisticMimeDetectionTest.java b/tika-core/src/test/java/org/apache/tika/mime/ProbabilisticMimeDetectionTest.java
index c9d0073c21..e74cef0812 100644
--- a/tika-core/src/test/java/org/apache/tika/mime/ProbabilisticMimeDetectionTest.java
+++ b/tika-core/src/test/java/org/apache/tika/mime/ProbabilisticMimeDetectionTest.java
@@ -23,7 +23,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
@@ -32,6 +31,7 @@ import java.nio.charset.StandardCharsets;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
 
@@ -82,12 +82,12 @@ public class ProbabilisticMimeDetectionTest {
     @Test
     public void testByteOrderMark() throws Exception {
         assertEquals(MediaType.TEXT_PLAIN, proDetector
-                .detect(new ByteArrayInputStream("\ufefftest".getBytes(UTF_16LE)), new Metadata()));
+                .detect(TikaInputStream.get("\ufefftest".getBytes(UTF_16LE)), new Metadata()));
         assertEquals(MediaType.TEXT_PLAIN, proDetector
-                .detect(new ByteArrayInputStream("\ufefftest".getBytes(UTF_16BE)), new Metadata()));
+                .detect(TikaInputStream.get("\ufefftest".getBytes(UTF_16BE)), new Metadata()));
 
         assertEquals(MediaType.TEXT_PLAIN, proDetector
-                .detect(new ByteArrayInputStream("\ufefftest".getBytes(UTF_8)), new Metadata()));
+                .detect(TikaInputStream.get("\ufefftest".getBytes(UTF_8)), new Metadata()));
     }
 
     @Test
@@ -137,22 +137,17 @@ public class ProbabilisticMimeDetectionTest {
     private void testStream(String expected, String urlOrFileName, InputStream in)
             throws IOException {
         assertNotNull(in, "Test stream: [" + urlOrFileName + "] is null!");
-        if (!in.markSupported()) {
-            in = new java.io.BufferedInputStream(in);
-        }
-        try {
+        try (TikaInputStream tis = TikaInputStream.get(in)) {
             Metadata metadata = new Metadata();
-            String mime = this.proDetector.detect(in, metadata).toString();
+            String mime = this.proDetector.detect(tis, metadata).toString();
             assertEquals(expected, mime,
                     urlOrFileName + " is not properly detected: detected.");
 
             // Add resource name and test again
             metadata.set(TikaCoreProperties.RESOURCE_NAME_KEY, urlOrFileName);
-            mime = this.proDetector.detect(in, metadata).toString();
+            mime = this.proDetector.detect(tis, metadata).toString();
             assertEquals(expected, mime,
                     urlOrFileName + " is not properly detected after adding resource name.");
-        } finally {
-            in.close();
         }
     }
 
@@ -165,17 +160,17 @@ public class ProbabilisticMimeDetectionTest {
     @Test
     public void testEmptyDocument() throws IOException {
         assertEquals(MediaType.OCTET_STREAM,
-                proDetector.detect(new ByteArrayInputStream(new byte[0]), new Metadata()));
+                proDetector.detect(TikaInputStream.get(new byte[0]), new Metadata()));
 
         Metadata namehint = new Metadata();
         namehint.set(TikaCoreProperties.RESOURCE_NAME_KEY, "test.txt");
         assertEquals(MediaType.TEXT_PLAIN,
-                proDetector.detect(new ByteArrayInputStream(new byte[0]), namehint));
+                proDetector.detect(TikaInputStream.get(new byte[0]), namehint));
 
         Metadata typehint = new Metadata();
         typehint.set(Metadata.CONTENT_TYPE, "text/plain");
         assertEquals(MediaType.TEXT_PLAIN,
-                proDetector.detect(new ByteArrayInputStream(new byte[0]), typehint));
+                proDetector.detect(TikaInputStream.get(new byte[0]), typehint));
 
     }
 
@@ -189,7 +184,7 @@ public class ProbabilisticMimeDetectionTest {
     @Test
     public void testNotXML() throws IOException {
         assertEquals(MediaType.TEXT_PLAIN, proDetector
-                .detect(new ByteArrayInputStream("<!-- test -->".getBytes(UTF_8)), new Metadata()));
+                .detect(TikaInputStream.get("<!-- test -->".getBytes(UTF_8)), new Metadata()));
     }
 
     /**
@@ -219,29 +214,29 @@ public class ProbabilisticMimeDetectionTest {
         // With a filename, picks the right one
         metadata = new Metadata();
         metadata.set(TikaCoreProperties.RESOURCE_NAME_KEY, "test.hello.world");
-        assertEquals(helloType, proDetector.detect(new ByteArrayInputStream(helloWorld), metadata));
+        assertEquals(helloType, proDetector.detect(TikaInputStream.get(helloWorld), metadata));
 
         metadata = new Metadata();
         metadata.set(TikaCoreProperties.RESOURCE_NAME_KEY, "test.x-hello-world");
         assertEquals(helloXType,
-                proDetector.detect(new ByteArrayInputStream(helloWorld), metadata));
+                proDetector.detect(TikaInputStream.get(helloWorld), metadata));
 
         // Without, goes for the one that sorts last
         metadata = new Metadata();
         metadata.set(TikaCoreProperties.RESOURCE_NAME_KEY, "testingTESTINGtesting");
         assertEquals(helloXType,
-                proDetector.detect(new ByteArrayInputStream(helloWorld), metadata));
+                proDetector.detect(TikaInputStream.get(helloWorld), metadata));
     }
 
     @Test
     public void testTIKA2237() throws IOException {
         Metadata metadata = new Metadata();
         metadata.add(Metadata.CONTENT_TYPE, MediaType.text("javascript").toString());
-        InputStream input = new ByteArrayInputStream(
+        TikaInputStream tis = TikaInputStream.get(
                 ("function() {};\n" + "try {\n" + "    window.location = 'index.html';\n" +
                         "} catch (e) {\n" + "    console.log(e);\n" + "}")
                         .getBytes(StandardCharsets.UTF_8));
-        MediaType detect = new ProbabilisticMimeDetectionSelector().detect(input, metadata);
+        MediaType detect = new ProbabilisticMimeDetectionSelector().detect(tis, metadata);
         assertEquals(MediaType.text("javascript"), detect);
     }
 }
diff --git a/tika-core/src/test/java/org/apache/tika/mime/RFC822DetectionTest.java b/tika-core/src/test/java/org/apache/tika/mime/RFC822DetectionTest.java
index 24cc621015..ada9e2e056 100644
--- a/tika-core/src/test/java/org/apache/tika/mime/RFC822DetectionTest.java
+++ b/tika-core/src/test/java/org/apache/tika/mime/RFC822DetectionTest.java
@@ -21,9 +21,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 
-import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
 import org.junit.jupiter.api.Test;
 
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 
 public class RFC822DetectionTest {
@@ -71,8 +71,7 @@ public class RFC822DetectionTest {
     private void assertMime(String expected, String txt) throws IOException {
 
         MediaType mediaType =
-                MIME_TYPES.detect(UnsynchronizedByteArrayInputStream.builder()
-                        .setByteArray(txt.getBytes(StandardCharsets.UTF_8)).get(), new Metadata());
+                MIME_TYPES.detect(TikaInputStream.get(txt.getBytes(StandardCharsets.UTF_8)), new Metadata());
         assertEquals(expected, mediaType.toString(), txt);
     }
 }
diff --git a/tika-core/src/test/java/org/apache/tika/parser/CompositeParserTest.java b/tika-core/src/test/java/org/apache/tika/parser/CompositeParserTest.java
index 659994b2dd..5414ef63d1 100644
--- a/tika-core/src/test/java/org/apache/tika/parser/CompositeParserTest.java
+++ b/tika-core/src/test/java/org/apache/tika/parser/CompositeParserTest.java
@@ -19,7 +19,6 @@ package org.apache.tika.parser;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 
-import java.io.ByteArrayInputStream;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -30,6 +29,7 @@ import java.util.Set;
 import org.junit.jupiter.api.Test;
 import org.xml.sax.ContentHandler;
 
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 import org.apache.tika.mime.MediaTypeRegistry;
@@ -108,7 +108,7 @@ public class CompositeParserTest {
         // Canonical and Canonical
         metadata = new Metadata();
         metadata.add(Metadata.CONTENT_TYPE, bmpCanonical.toString());
-        canonical.parse(new ByteArrayInputStream(new byte[0]), handler, metadata,
+        canonical.parse(TikaInputStream.get(new byte[0]), handler, metadata,
                 new ParseContext());
         assertEquals("True", metadata.get("BMP"));
         assertEquals("True", metadata.get("Canonical"));
@@ -117,7 +117,7 @@ public class CompositeParserTest {
         // Alias and Alias
         metadata = new Metadata();
         metadata.add(Metadata.CONTENT_TYPE, bmpAlias.toString());
-        alias.parse(new ByteArrayInputStream(new byte[0]), handler, metadata, new ParseContext());
+        alias.parse(TikaInputStream.get(new byte[0]), handler, metadata, new ParseContext());
         assertEquals("True", metadata.get("BMP"));
         assertEquals("True", metadata.get("Alias"));
 
@@ -125,7 +125,7 @@ public class CompositeParserTest {
         // Alias type and Canonical parser
         metadata = new Metadata();
         metadata.add(Metadata.CONTENT_TYPE, bmpAlias.toString());
-        canonical.parse(new ByteArrayInputStream(new byte[0]), handler, metadata,
+        canonical.parse(TikaInputStream.get(new byte[0]), handler, metadata,
                 new ParseContext());
         assertEquals("True", metadata.get("BMP"));
         assertEquals("True", metadata.get("Canonical"));
@@ -134,7 +134,7 @@ public class CompositeParserTest {
         // Canonical type and Alias parser
         metadata = new Metadata();
         metadata.add(Metadata.CONTENT_TYPE, bmpCanonical.toString());
-        alias.parse(new ByteArrayInputStream(new byte[0]), handler, metadata, new ParseContext());
+        alias.parse(TikaInputStream.get(new byte[0]), handler, metadata, new ParseContext());
         assertEquals("True", metadata.get("BMP"));
         assertEquals("True", metadata.get("Alias"));
 
@@ -143,7 +143,7 @@ public class CompositeParserTest {
         //  to be registered (which is the alias one)
         metadata = new Metadata();
         metadata.add(Metadata.CONTENT_TYPE, bmpCanonical.toString());
-        both.parse(new ByteArrayInputStream(new byte[0]), handler, metadata, new ParseContext());
+        both.parse(TikaInputStream.get(new byte[0]), handler, metadata, new ParseContext());
         assertEquals("True", metadata.get("BMP"));
         assertEquals("True", metadata.get("Alias"));
     }
diff --git a/tika-core/src/test/java/org/apache/tika/parser/DummyParser.java b/tika-core/src/test/java/org/apache/tika/parser/DummyParser.java
index 9b1ffcc4e1..c3b4baac5e 100644
--- a/tika-core/src/test/java/org/apache/tika/parser/DummyParser.java
+++ b/tika-core/src/test/java/org/apache/tika/parser/DummyParser.java
@@ -17,7 +17,6 @@
 package org.apache.tika.parser;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
@@ -26,6 +25,7 @@ import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
 
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 import org.apache.tika.sax.XHTMLContentHandler;
@@ -50,7 +50,7 @@ public class DummyParser implements Parser {
         return types;
     }
 
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream stream, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
         for (Entry<String, String> m : this.metadata.entrySet()) {
             metadata.add(m.getKey(), m.getValue());
diff --git a/tika-core/src/test/java/org/apache/tika/parser/ParserDecoratorTest.java b/tika-core/src/test/java/org/apache/tika/parser/ParserDecoratorTest.java
index 141c058af8..bb2235cf1b 100644
--- a/tika-core/src/test/java/org/apache/tika/parser/ParserDecoratorTest.java
+++ b/tika-core/src/test/java/org/apache/tika/parser/ParserDecoratorTest.java
@@ -19,7 +19,6 @@ package org.apache.tika.parser;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
-import java.io.ByteArrayInputStream;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
@@ -28,6 +27,7 @@ import java.util.Set;
 
 import org.junit.jupiter.api.Test;
 
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 import org.apache.tika.sax.BodyContentHandler;
@@ -109,7 +109,7 @@ public class ParserDecoratorTest {
         // Parsing will make it to the second one
         metadata = new Metadata();
         handler = new BodyContentHandler();
-        p.parse(new ByteArrayInputStream(new byte[]{0, 1, 2, 3, 4}), handler, metadata, context);
+        p.parse(TikaInputStream.get(new byte[]{0, 1, 2, 3, 4}), handler, metadata, context);
         assertEquals("Fell back!", handler.toString());
 
 
@@ -117,7 +117,7 @@ public class ParserDecoratorTest {
         p = ParserDecorator.withFallbacks(Arrays.asList(pNothing, pWork), octAndText);
         metadata = new Metadata();
         handler = new BodyContentHandler();
-        p.parse(new ByteArrayInputStream(new byte[]{0, 1, 2, 3, 4}), handler, metadata, context);
+        p.parse(TikaInputStream.get(new byte[]{0, 1, 2, 3, 4}), handler, metadata, context);
         assertEquals("", handler.toString());
     }
 }
diff --git a/tika-core/src/test/java/org/apache/tika/parser/RegexCaptureParserTest.java b/tika-core/src/test/java/org/apache/tika/parser/RegexCaptureParserTest.java
index 13c5eada73..421d3987ea 100644
--- a/tika-core/src/test/java/org/apache/tika/parser/RegexCaptureParserTest.java
+++ b/tika-core/src/test/java/org/apache/tika/parser/RegexCaptureParserTest.java
@@ -18,7 +18,6 @@ package org.apache.tika.parser;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
-import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
 import java.util.Map;
@@ -45,9 +44,9 @@ public class RegexCaptureParserTest {
         regexes.put("title", "^Title: ([^\r\n]+)");
         parser.setCaptureMap(regexes);
 
-        try (InputStream stream =
+        try (TikaInputStream tis =
                      TikaInputStream.get(output.getBytes(StandardCharsets.UTF_8))) {
-            parser.parse(stream, contentHandler, m, new ParseContext());
+            parser.parse(tis, contentHandler, m, new ParseContext());
         }
         assertEquals("the quick brown fox", m.get("title"));
     }
diff --git a/tika-core/src/test/java/org/apache/tika/parser/mock/AutoDetectParserFactory.java b/tika-core/src/test/java/org/apache/tika/parser/mock/AutoDetectParserFactory.java
index d5931846fc..a4d5e3416d 100644
--- a/tika-core/src/test/java/org/apache/tika/parser/mock/AutoDetectParserFactory.java
+++ b/tika-core/src/test/java/org/apache/tika/parser/mock/AutoDetectParserFactory.java
@@ -18,9 +18,9 @@ package org.apache.tika.parser.mock;
 
 import java.util.Map;
 
+import org.apache.tika.fork.ParserFactory;
 import org.apache.tika.parser.AutoDetectParser;
 import org.apache.tika.parser.Parser;
-import org.apache.tika.parser.ParserFactory;
 
 /**
  * Simple factory that returns a default AutoDetectParser.
diff --git a/tika-core/src/test/java/org/apache/tika/parser/mock/MockParser.java b/tika-core/src/test/java/org/apache/tika/parser/mock/MockParser.java
index 84c9b7ab1f..75c3840a54 100644
--- a/tika-core/src/test/java/org/apache/tika/parser/mock/MockParser.java
+++ b/tika-core/src/test/java/org/apache/tika/parser/mock/MockParser.java
@@ -20,7 +20,6 @@ package org.apache.tika.parser.mock;
 import static java.nio.charset.StandardCharsets.UTF_8;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.PrintStream;
 import java.lang.reflect.Constructor;
 import java.nio.charset.StandardCharsets;
@@ -114,7 +113,7 @@ public class MockParser implements Parser {
     }
 
     @Override
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream stream, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
         if (Thread.currentThread().isInterrupted()) {
             throw new TikaException("interrupted", new InterruptedException());
@@ -267,8 +266,8 @@ public class MockParser implements Parser {
         if (!"".equals(contentType)) {
             m.set(Metadata.CONTENT_TYPE, contentType);
         }
-        try (TikaInputStream is = TikaInputStream.get(embeddedText.getBytes(UTF_8))) {
-            extractor.parseEmbedded(is, new EmbeddedContentHandler(handler), m, true);
+        try (TikaInputStream tis = TikaInputStream.get(embeddedText.getBytes(UTF_8))) {
+            extractor.parseEmbedded(tis, new EmbeddedContentHandler(handler), m, true);
         }
     }
 
diff --git a/tika-core/src/test/java/org/apache/tika/parser/mock/MockParserFactory.java b/tika-core/src/test/java/org/apache/tika/parser/mock/MockParserFactory.java
index c7716946f5..321c57bc8a 100644
--- a/tika-core/src/test/java/org/apache/tika/parser/mock/MockParserFactory.java
+++ b/tika-core/src/test/java/org/apache/tika/parser/mock/MockParserFactory.java
@@ -20,8 +20,8 @@ import java.io.IOException;
 import java.util.Map;
 
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.fork.ParserFactory;
 import org.apache.tika.parser.Parser;
-import org.apache.tika.parser.ParserFactory;
 
 
 public class MockParserFactory extends ParserFactory {
diff --git a/tika-core/src/test/java/org/apache/tika/parser/multiple/MultipleParserTest.java b/tika-core/src/test/java/org/apache/tika/parser/multiple/MultipleParserTest.java
index 9462d0cb2e..023eebb4c3 100644
--- a/tika-core/src/test/java/org/apache/tika/parser/multiple/MultipleParserTest.java
+++ b/tika-core/src/test/java/org/apache/tika/parser/multiple/MultipleParserTest.java
@@ -20,7 +20,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.fail;
 
-import java.io.ByteArrayInputStream;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
@@ -30,6 +29,7 @@ import java.util.Set;
 
 import org.junit.jupiter.api.Test;
 
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
 import org.apache.tika.mime.MediaType;
@@ -83,7 +83,7 @@ public class MultipleParserTest {
 
         metadata = new Metadata();
         handler = new BodyContentHandler();
-        p.parse(new ByteArrayInputStream(new byte[]{0, 1, 2, 3, 4}), handler, metadata, context);
+        p.parse(TikaInputStream.get(new byte[]{0, 1, 2, 3, 4}), handler, metadata, context);
         assertEquals("Fell back!", handler.toString());
 
         usedParsers = metadata.getValues(TikaCoreProperties.TIKA_PARSED_BY);
@@ -96,7 +96,7 @@ public class MultipleParserTest {
 
         metadata = new Metadata();
         handler = new BodyContentHandler();
-        p.parse(new ByteArrayInputStream(new byte[]{0, 1, 2, 3, 4}), handler, metadata, context);
+        p.parse(TikaInputStream.get(new byte[]{0, 1, 2, 3, 4}), handler, metadata, context);
         assertEquals("Fell back!", handler.toString());
 
         usedParsers = metadata.getValues(TikaCoreProperties.TIKA_PARSED_BY);
@@ -115,7 +115,7 @@ public class MultipleParserTest {
 
         metadata = new Metadata();
         handler = new BodyContentHandler();
-        p.parse(new ByteArrayInputStream(new byte[]{0, 1, 2, 3, 4}), handler, metadata, context);
+        p.parse(TikaInputStream.get(new byte[]{0, 1, 2, 3, 4}), handler, metadata, context);
         assertEquals("Fell back!", handler.toString());
 
         usedParsers = metadata.getValues(TikaCoreProperties.TIKA_PARSED_BY);
@@ -170,7 +170,7 @@ public class MultipleParserTest {
 
         metadata = new Metadata();
         handler = new BodyContentHandler();
-        p.parse(new ByteArrayInputStream(new byte[]{0, 1, 2, 3, 4}), handler, metadata, context);
+        p.parse(TikaInputStream.get(new byte[]{0, 1, 2, 3, 4}), handler, metadata, context);
         assertEquals("Fell back 1!", handler.toString());
 
         assertEquals("Test1", metadata.get("T1"));
@@ -188,7 +188,7 @@ public class MultipleParserTest {
 
         metadata = new Metadata();
         handler = new BodyContentHandler();
-        p.parse(new ByteArrayInputStream(new byte[]{0, 1, 2, 3, 4}), handler, metadata, context);
+        p.parse(TikaInputStream.get(new byte[]{0, 1, 2, 3, 4}), handler, metadata, context);
         assertEquals("Fell back 1!Fell back 2!", handler.toString());
 
         assertEquals("Test1", metadata.get("T1"));
@@ -208,7 +208,7 @@ public class MultipleParserTest {
 
         metadata = new Metadata();
         handler = new BodyContentHandler();
-        p.parse(new ByteArrayInputStream(new byte[]{0, 1, 2, 3, 4}), handler, metadata, context);
+        p.parse(TikaInputStream.get(new byte[]{0, 1, 2, 3, 4}), handler, metadata, context);
         assertEquals("Fell back 1!Fell back 2!", handler.toString());
 
         assertEquals("Test1", metadata.get("T1"));
@@ -228,7 +228,7 @@ public class MultipleParserTest {
 
         metadata = new Metadata();
         handler = new BodyContentHandler();
-        p.parse(new ByteArrayInputStream(new byte[]{0, 1, 2, 3, 4}), handler, metadata, context);
+        p.parse(TikaInputStream.get(new byte[]{0, 1, 2, 3, 4}), handler, metadata, context);
         assertEquals("Fell back 1!Fell back 2!", handler.toString());
 
         assertEquals("Test1", metadata.get("T1"));
diff --git a/tika-core/src/test/java/org/apache/tika/sax/BasicContentHandlerFactoryTest.java b/tika-core/src/test/java/org/apache/tika/sax/BasicContentHandlerFactoryTest.java
index 111d2ea3cf..8a177c12ed 100644
--- a/tika-core/src/test/java/org/apache/tika/sax/BasicContentHandlerFactoryTest.java
+++ b/tika-core/src/test/java/org/apache/tika/sax/BasicContentHandlerFactoryTest.java
@@ -23,7 +23,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.UnsupportedEncodingException;
 import java.util.Set;
 
@@ -36,6 +35,7 @@ import org.xml.sax.helpers.DefaultHandler;
 
 import org.apache.tika.exception.TikaException;
 import org.apache.tika.exception.WriteLimitReachedException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 import org.apache.tika.parser.ParseContext;
@@ -311,7 +311,7 @@ public class BasicContentHandlerFactoryTest {
         }
 
         @Override
-        public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+        public void parse(TikaInputStream stream, ContentHandler handler, Metadata metadata,
                           ParseContext context) throws IOException, SAXException, TikaException {
             handler.startDocument();
             handler.startPrefixMapping("", XHTML);
diff --git a/tika-core/src/test/java/org/apache/tika/sax/BodyContentHandlerTest.java b/tika-core/src/test/java/org/apache/tika/sax/BodyContentHandlerTest.java
index 19bf853783..80b6315e93 100644
--- a/tika-core/src/test/java/org/apache/tika/sax/BodyContentHandlerTest.java
+++ b/tika-core/src/test/java/org/apache/tika/sax/BodyContentHandlerTest.java
@@ -20,13 +20,13 @@ import static java.nio.charset.StandardCharsets.UTF_8;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 
 import org.junit.jupiter.api.Test;
 
 import org.apache.tika.TikaTest;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.parser.AutoDetectParser;
 import org.apache.tika.parser.ParseContext;
@@ -69,8 +69,8 @@ public class BodyContentHandlerTest extends TikaTest {
         Parser[] parsers = new Parser[1];
         parsers[0] = p;
         Parser autoDetectParser = new AutoDetectParser(parsers);
-        try (InputStream is = getResourceAsStream("/test-documents/example.xml")) {
-            autoDetectParser.parse(is, handler, metadata, parseContext);
+        try (TikaInputStream tis = getResourceAsStream("/test-documents/example.xml")) {
+            autoDetectParser.parse(tis, handler, metadata, parseContext);
         } catch (Exception e) {
             tryToFindIllegalStateException(e);
         }
diff --git a/tika-core/src/test/java/org/apache/tika/sax/CustomErrorHandlerTest.java b/tika-core/src/test/java/org/apache/tika/sax/CustomErrorHandlerTest.java
index 88643147f5..d0b532c311 100644
--- a/tika-core/src/test/java/org/apache/tika/sax/CustomErrorHandlerTest.java
+++ b/tika-core/src/test/java/org/apache/tika/sax/CustomErrorHandlerTest.java
@@ -33,6 +33,7 @@ import org.xml.sax.SAXException;
 
 import org.apache.tika.TikaTest;
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.parser.ParseContext;
 import org.apache.tika.utils.XMLReaderUtils;
 
@@ -80,9 +81,9 @@ public class CustomErrorHandlerTest extends TikaTest {
 
     private String extractTestData(String name)
             throws IOException, SAXException, TikaException, ParserConfigurationException {
-        try (InputStream is = getResourceAsStream("/test-documents/" + name)) {
+        try (TikaInputStream tis = getResourceAsStream("/test-documents/" + name)) {
             ByteArrayOutputStream out = new ByteArrayOutputStream();
-            extractXml(is, out);
+            extractXml(tis, out);
             return out.toString(StandardCharsets.UTF_8);
         }
     }
diff --git a/tika-detectors/tika-detector-magika/src/main/java/org/apache/tika/detect/magika/MagikaDetector.java b/tika-detectors/tika-detector-magika/src/main/java/org/apache/tika/detect/magika/MagikaDetector.java
index 0c3a08f4d2..f8fe118b4a 100644
--- a/tika-detectors/tika-detector-magika/src/main/java/org/apache/tika/detect/magika/MagikaDetector.java
+++ b/tika-detectors/tika-detector-magika/src/main/java/org/apache/tika/detect/magika/MagikaDetector.java
@@ -16,11 +16,7 @@
  */
 package org.apache.tika.detect.magika;
 
-import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
-
 import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -35,8 +31,6 @@ import org.apache.tika.config.ConfigDeserializer;
 import org.apache.tika.config.JsonConfig;
 import org.apache.tika.config.TikaComponent;
 import org.apache.tika.detect.Detector;
-import org.apache.tika.io.BoundedInputStream;
-import org.apache.tika.io.TemporaryResources;
 import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.ExternalProcess;
 import org.apache.tika.metadata.Metadata;
@@ -155,13 +149,13 @@ public class MagikaDetector implements Detector {
     }
 
     /**
-     * @param input    document input stream, or <code>null</code>
+     * @param tis      document input stream, or <code>null</code>
      * @param metadata input metadata for the document
      * @return mime as identified by the file command or application/octet-stream otherwise
      * @throws IOException
      */
     @Override
-    public MediaType detect(InputStream input, Metadata metadata) throws IOException {
+    public MediaType detect(TikaInputStream tis, Metadata metadata) throws IOException {
         if (hasMagika == null) {
             hasMagika = checkHasMagika(this.config.magikaPath);
         }
@@ -172,21 +166,8 @@ public class MagikaDetector implements Detector {
             }
             return MediaType.OCTET_STREAM;
         }
-        TikaInputStream tis = TikaInputStream.cast(input);
-        if (tis != null) {
-            //spool the full file to disk, if called with a TikaInputStream
-            //and there is no underlying file
-            return detectOnPath(tis.getPath(), metadata);
-        }
-
-        input.mark(config.maxBytes);
-        try (TemporaryResources tmp = new TemporaryResources()) {
-            Path tmpFile = tmp.createTempFile();
-            Files.copy(new BoundedInputStream(config.maxBytes, input), tmpFile, REPLACE_EXISTING);
-            return detectOnPath(tmpFile, metadata);
-        } finally {
-            input.reset();
-        }
+        //spool the full file to disk if there is no underlying file
+        return detectOnPath(tis.getPath(), metadata);
     }
 
     /**
diff --git a/tika-detectors/tika-detector-siegfried/src/main/java/org/apache/tika/detect/siegfried/SiegfriedDetector.java b/tika-detectors/tika-detector-siegfried/src/main/java/org/apache/tika/detect/siegfried/SiegfriedDetector.java
index 3e274c4a6a..3397a848b9 100644
--- a/tika-detectors/tika-detector-siegfried/src/main/java/org/apache/tika/detect/siegfried/SiegfriedDetector.java
+++ b/tika-detectors/tika-detector-siegfried/src/main/java/org/apache/tika/detect/siegfried/SiegfriedDetector.java
@@ -16,11 +16,7 @@
  */
 package org.apache.tika.detect.siegfried;
 
-import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
-
 import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Files;
 import java.nio.file.Path;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
@@ -33,8 +29,6 @@ import org.apache.tika.config.ConfigDeserializer;
 import org.apache.tika.config.JsonConfig;
 import org.apache.tika.config.TikaComponent;
 import org.apache.tika.detect.Detector;
-import org.apache.tika.io.BoundedInputStream;
-import org.apache.tika.io.TemporaryResources;
 import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.ExternalProcess;
 import org.apache.tika.metadata.Metadata;
@@ -129,13 +123,13 @@ public class SiegfriedDetector implements Detector {
     }
 
     /**
-     * @param input    document input stream, or <code>null</code>
+     * @param tis      document input stream, or <code>null</code>
      * @param metadata input metadata for the document
      * @return mime as identified by the file command or application/octet-stream otherwise
      * @throws IOException
      */
     @Override
-    public MediaType detect(InputStream input, Metadata metadata) throws IOException {
+    public MediaType detect(TikaInputStream tis, Metadata metadata) throws IOException {
         if (hasSiegfriedCommand == null) {
             hasSiegfriedCommand = checkHasSiegfried(this.config.siegfriedPath);
         }
@@ -146,21 +140,8 @@ public class SiegfriedDetector implements Detector {
             }
             return MediaType.OCTET_STREAM;
         }
-        TikaInputStream tis = TikaInputStream.cast(input);
-        if (tis != null) {
-            //spool the full file to disk, if called with a TikaInputStream
-            //and there is no underlying file
-            return detectOnPath(tis.getPath(), metadata);
-        }
-
-        input.mark(config.maxBytes);
-        try (TemporaryResources tmp = new TemporaryResources()) {
-            Path tmpFile = tmp.createTempFile();
-            Files.copy(new BoundedInputStream(config.maxBytes, input), tmpFile, REPLACE_EXISTING);
-            return detectOnPath(tmpFile, metadata);
-        } finally {
-            input.reset();
-        }
+        //spool the full file to disk if there is no underlying file
+        return detectOnPath(tis.getPath(), metadata);
     }
 
     /**
diff --git a/tika-example/src/main/java/org/apache/tika/example/AdvancedTypeDetector.java b/tika-example/src/main/java/org/apache/tika/example/AdvancedTypeDetector.java
index 191162a28a..e9716e8244 100755
--- a/tika-example/src/main/java/org/apache/tika/example/AdvancedTypeDetector.java
+++ b/tika-example/src/main/java/org/apache/tika/example/AdvancedTypeDetector.java
@@ -16,11 +16,10 @@
  */
 package org.apache.tika.example;
 
-import java.io.InputStream;
-
 import org.apache.tika.Tika;
 import org.apache.tika.detect.CompositeDetector;
 import org.apache.tika.detect.Detector;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 import org.apache.tika.mime.MimeTypesFactory;
@@ -39,7 +38,7 @@ public class AdvancedTypeDetector {
         Detector custom = new Detector() {
             private static final long serialVersionUID = -5420638839201540749L;
 
-            public MediaType detect(InputStream input, Metadata metadata) {
+            public MediaType detect(TikaInputStream tis, Metadata metadata) {
                 String type = metadata.get("my-custom-type-override");
                 if (type != null) {
                     return MediaType.parse(type);
diff --git a/tika-example/src/main/java/org/apache/tika/example/ContentHandlerExample.java b/tika-example/src/main/java/org/apache/tika/example/ContentHandlerExample.java
index 4cad7eaa96..fc8ff2d2a9 100644
--- a/tika-example/src/main/java/org/apache/tika/example/ContentHandlerExample.java
+++ b/tika-example/src/main/java/org/apache/tika/example/ContentHandlerExample.java
@@ -25,6 +25,7 @@ import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
 
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.parser.AutoDetectParser;
 import org.apache.tika.sax.BodyContentHandler;
@@ -52,7 +53,7 @@ public class ContentHandlerExample {
         AutoDetectParser parser = new AutoDetectParser();
         Metadata metadata = new Metadata();
         try (InputStream stream = ContentHandlerExample.class.getResourceAsStream("test.doc")) {
-            parser.parse(stream, handler, metadata);
+            parser.parse(TikaInputStream.get(stream), handler, metadata);
             return handler.toString();
         }
     }
@@ -66,7 +67,7 @@ public class ContentHandlerExample {
         AutoDetectParser parser = new AutoDetectParser();
         Metadata metadata = new Metadata();
         try (InputStream stream = ContentHandlerExample.class.getResourceAsStream("test.doc")) {
-            parser.parse(stream, handler, metadata);
+            parser.parse(TikaInputStream.get(stream), handler, metadata);
             return handler.toString();
         }
     }
@@ -81,7 +82,7 @@ public class ContentHandlerExample {
         AutoDetectParser parser = new AutoDetectParser();
         Metadata metadata = new Metadata();
         try (InputStream stream = ContentHandlerExample.class.getResourceAsStream("test.doc")) {
-            parser.parse(stream, handler, metadata);
+            parser.parse(TikaInputStream.get(stream), handler, metadata);
             return handler.toString();
         }
     }
@@ -99,7 +100,7 @@ public class ContentHandlerExample {
         AutoDetectParser parser = new AutoDetectParser();
         Metadata metadata = new Metadata();
         try (InputStream stream = ContentHandlerExample.class.getResourceAsStream("test2.doc")) {
-            parser.parse(stream, handler, metadata);
+            parser.parse(TikaInputStream.get(stream), handler, metadata);
             return handler.toString();
         }
     }
@@ -128,7 +129,7 @@ public class ContentHandlerExample {
         AutoDetectParser parser = new AutoDetectParser();
         Metadata metadata = new Metadata();
         try (InputStream stream = ContentHandlerExample.class.getResourceAsStream("test2.doc")) {
-            parser.parse(stream, handler, metadata);
+            parser.parse(TikaInputStream.get(stream), handler, metadata);
             return chunks;
         }
     }
diff --git a/tika-example/src/main/java/org/apache/tika/example/DirListParser.java b/tika-example/src/main/java/org/apache/tika/example/DirListParser.java
index 0f31bdcf38..a94ff0ea14 100755
--- a/tika-example/src/main/java/org/apache/tika/example/DirListParser.java
+++ b/tika-example/src/main/java/org/apache/tika/example/DirListParser.java
@@ -19,7 +19,6 @@ package org.apache.tika.example;
 import static java.nio.charset.StandardCharsets.UTF_8;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
@@ -50,7 +49,7 @@ public class DirListParser implements Parser {
     public static void main(String[] args) throws IOException, SAXException, TikaException {
         DirListParser parser = new DirListParser();
         Metadata met = new Metadata();
-        parser.parse(System.in, new BodyContentHandler(), met);
+        parser.parse(TikaInputStream.get(System.in), new BodyContentHandler(), met);
 
         System.out.println("Num files: " + met.getValues("Filename").length);
         System.out.println("Num executables: " + met.get("NumExecutables"));
@@ -72,8 +71,8 @@ public class DirListParser implements Parser {
      * @see org.apache.tika.parser.Parser#parse(java.io.InputStream,
      * org.xml.sax.ContentHandler, org.apache.tika.metadata.Metadata)
      */
-    public void parse(InputStream is, ContentHandler handler, Metadata metadata) throws IOException, SAXException, TikaException {
-        this.parse(is, handler, metadata, new ParseContext());
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata) throws IOException, SAXException, TikaException {
+        this.parse(tis, handler, metadata, new ParseContext());
     }
 
     /*
@@ -83,11 +82,9 @@ public class DirListParser implements Parser {
      * org.xml.sax.ContentHandler, org.apache.tika.metadata.Metadata,
      * org.apache.tika.parser.ParseContext)
      */
-    public void parse(InputStream is, ContentHandler handler, Metadata metadata, ParseContext context) throws IOException, SAXException, TikaException {
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata, ParseContext context) throws IOException, SAXException, TikaException {
 
-        List<String> lines = FileUtils.readLines(TikaInputStream
-                .get(is)
-                .getFile(), UTF_8);
+        List<String> lines = FileUtils.readLines(tis.getFile(), UTF_8);
         for (String line : lines) {
             String[] fileToks = line.split("\\s+");
             if (fileToks.length < 8) {
diff --git a/tika-example/src/main/java/org/apache/tika/example/DisplayMetInstance.java b/tika-example/src/main/java/org/apache/tika/example/DisplayMetInstance.java
index e516c60c57..202bf7982f 100755
--- a/tika-example/src/main/java/org/apache/tika/example/DisplayMetInstance.java
+++ b/tika-example/src/main/java/org/apache/tika/example/DisplayMetInstance.java
@@ -22,6 +22,7 @@ import java.net.URL;
 import org.xml.sax.SAXException;
 
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.parser.ParseContext;
 import org.apache.tika.parser.pdf.PDFParser;
@@ -34,7 +35,7 @@ public class DisplayMetInstance {
     public static Metadata getMet(URL url) throws IOException, SAXException, TikaException {
         Metadata met = new Metadata();
         PDFParser parser = new PDFParser();
-        parser.parse(url.openStream(), new BodyContentHandler(), met, new ParseContext());
+        parser.parse(TikaInputStream.get(url.openStream()), new BodyContentHandler(), met, new ParseContext());
         return met;
     }
 
diff --git a/tika-example/src/main/java/org/apache/tika/example/EncryptedPrescriptionDetector.java b/tika-example/src/main/java/org/apache/tika/example/EncryptedPrescriptionDetector.java
index 09179fe244..3339a3cd95 100755
--- a/tika-example/src/main/java/org/apache/tika/example/EncryptedPrescriptionDetector.java
+++ b/tika-example/src/main/java/org/apache/tika/example/EncryptedPrescriptionDetector.java
@@ -27,17 +27,18 @@ import javax.xml.namespace.QName;
 import org.apache.tika.detect.Detector;
 import org.apache.tika.detect.XmlRootExtractor;
 import org.apache.tika.io.LookaheadInputStream;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 
 public class EncryptedPrescriptionDetector implements Detector {
     private static final long serialVersionUID = -1709652690773421147L;
 
-    public MediaType detect(InputStream stream, Metadata metadata) throws IOException {
+    public MediaType detect(TikaInputStream tis, Metadata metadata) throws IOException {
         Key key = Pharmacy.getKey();
         MediaType type = MediaType.OCTET_STREAM;
 
-        try (InputStream lookahead = new LookaheadInputStream(stream, 1024)) {
+        try (InputStream lookahead = new LookaheadInputStream(tis, 1024)) {
             Cipher cipher = Cipher.getInstance("RSA");
 
             cipher.init(Cipher.DECRYPT_MODE, key);
diff --git a/tika-example/src/main/java/org/apache/tika/example/EncryptedPrescriptionParser.java b/tika-example/src/main/java/org/apache/tika/example/EncryptedPrescriptionParser.java
index dfc8a1f8ec..6651170036 100755
--- a/tika-example/src/main/java/org/apache/tika/example/EncryptedPrescriptionParser.java
+++ b/tika-example/src/main/java/org/apache/tika/example/EncryptedPrescriptionParser.java
@@ -29,6 +29,7 @@ import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
 
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 import org.apache.tika.parser.ParseContext;
@@ -37,14 +38,14 @@ import org.apache.tika.parser.Parser;
 public class EncryptedPrescriptionParser implements Parser {
     private static final long serialVersionUID = -7816987249611278541L;
 
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata, ParseContext context) throws IOException, SAXException, TikaException {
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata, ParseContext context) throws IOException, SAXException, TikaException {
         try {
             Key key = Pharmacy.getKey();
             Cipher cipher = Cipher.getInstance("RSA");
             cipher.init(Cipher.DECRYPT_MODE, key);
-            InputStream decrypted = new CipherInputStream(stream, cipher);
+            InputStream decrypted = new CipherInputStream(tis, cipher);
 
-            new PrescriptionParser().parse(decrypted, handler, metadata, context);
+            new PrescriptionParser().parse(TikaInputStream.get(decrypted), handler, metadata, context);
         } catch (GeneralSecurityException e) {
             throw new TikaException("Unable to decrypt a digital prescription", e);
         }
diff --git a/tika-example/src/main/java/org/apache/tika/example/ExtractEmbeddedFiles.java b/tika-example/src/main/java/org/apache/tika/example/ExtractEmbeddedFiles.java
index 46966337f2..ee14226a37 100644
--- a/tika-example/src/main/java/org/apache/tika/example/ExtractEmbeddedFiles.java
+++ b/tika-example/src/main/java/org/apache/tika/example/ExtractEmbeddedFiles.java
@@ -17,7 +17,6 @@
 package org.apache.tika.example;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.UUID;
@@ -50,7 +49,7 @@ public class ExtractEmbeddedFiles {
     public ExtractEmbeddedFiles() throws TikaConfigException, IOException {
     }
 
-    public void extract(InputStream is, Path outputDir) throws SAXException, TikaException, IOException {
+    public void extract(TikaInputStream tis, Path outputDir) throws SAXException, TikaException, IOException {
         Metadata m = new Metadata();
         ParseContext c = new ParseContext();
         ContentHandler h = new BodyContentHandler(-1);
@@ -59,7 +58,7 @@ public class ExtractEmbeddedFiles {
         EmbeddedDocumentExtractor ex = new MyEmbeddedDocumentExtractor(outputDir, c);
         c.set(EmbeddedDocumentExtractor.class, ex);
 
-        parser.parse(is, h, m, c);
+        parser.parse(tis, h, m, c);
     }
 
     private class MyEmbeddedDocumentExtractor extends ParsingEmbeddedDocumentExtractor {
diff --git a/tika-example/src/main/java/org/apache/tika/example/GrabPhoneNumbersExample.java b/tika-example/src/main/java/org/apache/tika/example/GrabPhoneNumbersExample.java
index cb24d264fb..8ecef5c111 100644
--- a/tika-example/src/main/java/org/apache/tika/example/GrabPhoneNumbersExample.java
+++ b/tika-example/src/main/java/org/apache/tika/example/GrabPhoneNumbersExample.java
@@ -28,6 +28,7 @@ import java.nio.file.attribute.BasicFileAttributes;
 import java.util.Collections;
 import java.util.HashSet;
 
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.parser.AutoDetectParser;
 import org.apache.tika.parser.ParseContext;
@@ -94,7 +95,7 @@ public class GrabPhoneNumbersExample {
         // to the underlying Handler.
         PhoneExtractingContentHandler handler = new PhoneExtractingContentHandler(new BodyContentHandler(), metadata);
         try (InputStream stream = new BufferedInputStream(Files.newInputStream(path))) {
-            parser.parse(stream, handler, metadata, new ParseContext());
+            parser.parse(TikaInputStream.get(stream), handler, metadata, new ParseContext());
         }
         String[] numbers = metadata.getValues("phonenumbers");
         Collections.addAll(phoneNumbers, numbers);
diff --git a/tika-example/src/main/java/org/apache/tika/example/ImportContextImpl.java b/tika-example/src/main/java/org/apache/tika/example/ImportContextImpl.java
index 1461aead21..c6b4fd636b 100755
--- a/tika-example/src/main/java/org/apache/tika/example/ImportContextImpl.java
+++ b/tika-example/src/main/java/org/apache/tika/example/ImportContextImpl.java
@@ -33,6 +33,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import org.apache.tika.detect.Detector;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
 import org.apache.tika.mime.MediaType;
@@ -83,7 +84,7 @@ public class ImportContextImpl implements ImportContext {
         if (stream != null && !stream.markSupported()) {
             stream = new BufferedInputStream(stream);
         }
-        type = detector.detect(stream, metadata);
+        type = detector.detect(TikaInputStream.get(stream), metadata);
 
         this.inputFile = IOUtil.getTempFile(stream);
     }
diff --git a/tika-example/src/main/java/org/apache/tika/example/InterruptableParsingExample.java b/tika-example/src/main/java/org/apache/tika/example/InterruptableParsingExample.java
index 686718b489..16c8a63a2c 100644
--- a/tika-example/src/main/java/org/apache/tika/example/InterruptableParsingExample.java
+++ b/tika-example/src/main/java/org/apache/tika/example/InterruptableParsingExample.java
@@ -16,10 +16,7 @@
  */
 package org.apache.tika.example;
 
-import java.io.BufferedInputStream;
 import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.Locale;
 
@@ -28,6 +25,7 @@ import org.xml.sax.helpers.DefaultHandler;
 
 import org.apache.tika.Tika;
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.parser.ParseContext;
 import org.apache.tika.parser.Parser;
@@ -51,10 +49,10 @@ public class InterruptableParsingExample {
         ParseContext context = new ParseContext();
         context.set(Parser.class, tika.getParser());
 
-        try (InputStream is = new BufferedInputStream(Files.newInputStream(path))) {
+        try (TikaInputStream tis = TikaInputStream.get(path, metadata)) {
             tika
                     .getParser()
-                    .parse(is, handler, metadata, context);
+                    .parse(tis, handler, metadata, context);
         } catch (QueryMatchedException e) {
             return true;
         } catch (SAXException | TikaException | IOException e) {
diff --git a/tika-example/src/main/java/org/apache/tika/example/Language.java b/tika-example/src/main/java/org/apache/tika/example/Language.java
index d3058dd956..1573001e26 100755
--- a/tika-example/src/main/java/org/apache/tika/example/Language.java
+++ b/tika-example/src/main/java/org/apache/tika/example/Language.java
@@ -18,6 +18,7 @@ package org.apache.tika.example;
 
 import java.io.IOException;
 
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.langdetect.optimaize.OptimaizeLangDetector;
 import org.apache.tika.language.detect.LanguageDetector;
 import org.apache.tika.language.detect.LanguageHandler;
@@ -51,7 +52,7 @@ public class Language {
 
     public static void languageDetectionWithHandler() throws Exception {
         LanguageHandler handler = new LanguageHandler();
-        new AutoDetectParser().parse(System.in, handler, new Metadata(), new ParseContext());
+        new AutoDetectParser().parse(TikaInputStream.get(System.in), handler, new Metadata(), new ParseContext());
 
         LanguageResult result = handler.getLanguage();
         System.out.println(result.getLanguage());
diff --git a/tika-example/src/main/java/org/apache/tika/example/LanguageDetectingParser.java b/tika-example/src/main/java/org/apache/tika/example/LanguageDetectingParser.java
index a910962f6c..191e9908c9 100755
--- a/tika-example/src/main/java/org/apache/tika/example/LanguageDetectingParser.java
+++ b/tika-example/src/main/java/org/apache/tika/example/LanguageDetectingParser.java
@@ -17,12 +17,12 @@
 package org.apache.tika.example;
 
 import java.io.IOException;
-import java.io.InputStream;
 
 import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
 
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.language.detect.LanguageHandler;
 import org.apache.tika.language.detect.LanguageResult;
 import org.apache.tika.metadata.Metadata;
@@ -34,11 +34,11 @@ import org.apache.tika.sax.TeeContentHandler;
 public class LanguageDetectingParser extends DelegatingParser {
     private static final long serialVersionUID = 4291320409396502774L;
 
-    public void parse(InputStream stream, ContentHandler handler, final Metadata metadata, ParseContext context) throws SAXException, IOException, TikaException {
+    public void parse(TikaInputStream tis, ContentHandler handler, final Metadata metadata, ParseContext context) throws SAXException, IOException, TikaException {
         LanguageHandler langHandler = new LanguageHandler();
         ContentHandler tee = new TeeContentHandler(handler, langHandler);
 
-        super.parse(stream, tee, metadata, context);
+        super.parse(tis, tee, metadata, context);
 
         LanguageResult result = langHandler.getLanguage();
         if (result.isReasonablyCertain()) {
diff --git a/tika-example/src/main/java/org/apache/tika/example/MetadataAwareLuceneIndexer.java b/tika-example/src/main/java/org/apache/tika/example/MetadataAwareLuceneIndexer.java
index 781c8aa7de..132aea27fb 100755
--- a/tika-example/src/main/java/org/apache/tika/example/MetadataAwareLuceneIndexer.java
+++ b/tika-example/src/main/java/org/apache/tika/example/MetadataAwareLuceneIndexer.java
@@ -17,8 +17,6 @@
 package org.apache.tika.example;
 
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.InputStream;
 import java.util.Date;
 
 import org.apache.lucene.document.Document;
@@ -27,6 +25,7 @@ import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriter;
 
 import org.apache.tika.Tika;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.DublinCore;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.Property;
@@ -48,8 +47,8 @@ public class MetadataAwareLuceneIndexer {
 
     public void indexContentSpecificMet(File file) throws Exception {
         Metadata met = new Metadata();
-        try (InputStream is = new FileInputStream(file)) {
-            tika.parse(is, met);
+        try (TikaInputStream tis = TikaInputStream.get(file.toPath(), met)) {
+            tika.parse(tis, met);
             Document document = new Document();
             for (String key : met.names()) {
                 String[] values = met.getValues(key);
@@ -75,8 +74,8 @@ public class MetadataAwareLuceneIndexer {
         met.add(TikaCoreProperties.SUBJECT, "Indexing");
         met.add(TikaCoreProperties.SUBJECT, "Metadata");
         met.set(Property.externalClosedChoise(TikaCoreProperties.RIGHTS.getName(), "public", "private"), "public");
-        try (InputStream is = new FileInputStream(file)) {
-            tika.parse(is, met);
+        try (TikaInputStream tis = TikaInputStream.get(file.toPath(), met)) {
+            tika.parse(tis, met);
             Document document = new Document();
             for (String key : met.names()) {
                 String[] values = met.getValues(key);
diff --git a/tika-example/src/main/java/org/apache/tika/example/MyFirstTika.java b/tika-example/src/main/java/org/apache/tika/example/MyFirstTika.java
index 05c9fa2ce0..d37e7d5dad 100755
--- a/tika-example/src/main/java/org/apache/tika/example/MyFirstTika.java
+++ b/tika-example/src/main/java/org/apache/tika/example/MyFirstTika.java
@@ -19,7 +19,6 @@ package org.apache.tika.example;
 import static java.nio.charset.StandardCharsets.UTF_8;
 
 import java.io.File;
-import java.io.InputStream;
 import java.nio.file.Paths;
 
 import org.apache.commons.io.FileUtils;
@@ -74,8 +73,8 @@ public class MyFirstTika {
 
         Parser parser = tikaLoader.loadAutoDetectParser();
         ContentHandler handler = new BodyContentHandler();
-        TikaInputStream stream = TikaInputStream.get(Paths.get(filename), metadata);
-        parser.parse(stream, handler, metadata, new ParseContext());
+        TikaInputStream tis = TikaInputStream.get(Paths.get(filename), metadata);
+        parser.parse(tis, handler, metadata, new ParseContext());
         return handler.toString();
     }
 
@@ -87,12 +86,12 @@ public class MyFirstTika {
         metadata.set(TikaCoreProperties.RESOURCE_NAME_KEY, filename);
         System.out.println("The MIME type (based on filename) is: [" + mimeRegistry.detect(null, metadata) + "]");
 
-        InputStream stream = TikaInputStream.get(Paths.get(filename));
-        System.out.println("The MIME type (based on MAGIC) is: [" + mimeRegistry.detect(stream, metadata) + "]");
+        TikaInputStream tis = TikaInputStream.get(Paths.get(filename));
+        System.out.println("The MIME type (based on MAGIC) is: [" + mimeRegistry.detect(tis, metadata) + "]");
 
-        stream = TikaInputStream.get(Paths.get(filename));
+        tis = TikaInputStream.get(Paths.get(filename));
         Detector detector = tikaLoader.loadDetectors();
-        System.out.println("The MIME type (based on the Detector interface) is: [" + detector.detect(stream, metadata) + "]");
+        System.out.println("The MIME type (based on the Detector interface) is: [" + detector.detect(tis, metadata) + "]");
 
         LanguageDetector langDetector = new OptimaizeLangDetector().loadModels();
         LanguageResult lang = langDetector.detect(FileUtils.readFileToString(new File(filename), UTF_8));
@@ -102,11 +101,11 @@ public class MyFirstTika {
         // Get a non-detecting parser that handles all the types it can
         Parser parser = tikaLoader.loadParsers();
         // Tell it what we think the content is
-        MediaType type = detector.detect(stream, metadata);
+        MediaType type = detector.detect(tis, metadata);
         metadata.set(Metadata.CONTENT_TYPE, type.toString());
         // Have the file parsed to get the content and metadata
         ContentHandler handler = new BodyContentHandler();
-        parser.parse(stream, handler, metadata, new ParseContext());
+        parser.parse(tis, handler, metadata, new ParseContext());
 
         return handler.toString();
     }
diff --git a/tika-example/src/main/java/org/apache/tika/example/ParsingExample.java b/tika-example/src/main/java/org/apache/tika/example/ParsingExample.java
index 5914e66c59..58f730806e 100644
--- a/tika-example/src/main/java/org/apache/tika/example/ParsingExample.java
+++ b/tika-example/src/main/java/org/apache/tika/example/ParsingExample.java
@@ -90,7 +90,7 @@ public class ParsingExample {
         BodyContentHandler handler = new BodyContentHandler();
         Metadata metadata = new Metadata();
         try (InputStream stream = ParsingExample.class.getResourceAsStream("test.doc")) {
-            parser.parse(stream, handler, metadata);
+            parser.parse(TikaInputStream.get(stream), handler, metadata);
             return handler.toString();
         }
     }
@@ -109,7 +109,7 @@ public class ParsingExample {
         ParseContext parseContext = new ParseContext();
         parseContext.set(Parser.class, new EmptyParser());
         try (InputStream stream = ParsingExample.class.getResourceAsStream("test_recursive_embedded.docx")) {
-            parser.parse(stream, handler, metadata, parseContext);
+            parser.parse(TikaInputStream.get(stream), handler, metadata, parseContext);
             return handler.toString();
         }
     }
@@ -131,7 +131,7 @@ public class ParsingExample {
         ParseContext context = new ParseContext();
         context.set(Parser.class, parser);
         try (InputStream stream = ParsingExample.class.getResourceAsStream("test_recursive_embedded.docx")) {
-            parser.parse(stream, handler, metadata, context);
+            parser.parse(TikaInputStream.get(stream), handler, metadata, context);
             return handler.toString();
         }
     }
@@ -168,7 +168,7 @@ public class ParsingExample {
         ParseContext context = new ParseContext();
         RecursiveParserWrapperHandler handler = new RecursiveParserWrapperHandler(factory, -1);
         try (InputStream stream = ParsingExample.class.getResourceAsStream("test_recursive_embedded.docx")) {
-            wrapper.parse(stream, handler, metadata, context);
+            wrapper.parse(TikaInputStream.get(stream), handler, metadata, context);
         }
 
         return handler.getMetadataList();
@@ -207,8 +207,8 @@ public class ParsingExample {
     public List<Path> extractEmbeddedDocumentsExample(Path outputPath) throws IOException, SAXException, TikaException {
         ExtractEmbeddedFiles ex = new ExtractEmbeddedFiles();
         List<Path> ret = new ArrayList<>();
-        try (TikaInputStream stream = TikaInputStream.get(ParsingExample.class.getResourceAsStream("test_recursive_embedded.docx"))) {
-            ex.extract(stream, outputPath);
+        try (TikaInputStream tis = TikaInputStream.get(ParsingExample.class.getResourceAsStream("test_recursive_embedded.docx"))) {
+            ex.extract(tis, outputPath);
             try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(outputPath)) {
                 for (Path entry : dirStream) {
                     ret.add(entry);
diff --git a/tika-example/src/main/java/org/apache/tika/example/PickBestTextEncodingParser.java b/tika-example/src/main/java/org/apache/tika/example/PickBestTextEncodingParser.java
index fb6e48d6e3..4796401ebf 100644
--- a/tika-example/src/main/java/org/apache/tika/example/PickBestTextEncodingParser.java
+++ b/tika-example/src/main/java/org/apache/tika/example/PickBestTextEncodingParser.java
@@ -17,7 +17,6 @@
 package org.apache.tika.example;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.OutputStream;
 import java.nio.charset.Charset;
 import java.util.ArrayList;
@@ -31,6 +30,7 @@ import org.xml.sax.SAXException;
 import org.apache.tika.detect.EncodingDetector;
 import org.apache.tika.detect.OverrideEncodingDetector;
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaTypeRegistry;
 import org.apache.tika.parser.ParseContext;
@@ -130,7 +130,7 @@ public class PickBestTextEncodingParser extends AbstractMultipleParser {
     }
 
     @Override
-    public void parse(InputStream stream, ContentHandler handler, Metadata originalMetadata, ParseContext context) throws IOException, SAXException, TikaException {
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata originalMetadata, ParseContext context) throws IOException, SAXException, TikaException {
         // Use a BodyContentHandler for each of the charset test,
         //  then their real ContentHandler for the last one
         CharsetContentHandlerFactory handlerFactory = new CharsetContentHandlerFactory();
@@ -140,14 +140,14 @@ public class PickBestTextEncodingParser extends AbstractMultipleParser {
         context.set(CharsetTester.class, new CharsetTester());
 
         // Have the parsing done
-        super.parse(stream, handlerFactory, originalMetadata, context);
+        super.parse(tis, handlerFactory, originalMetadata, context);
     }
 
     @Override
-    public void parse(InputStream stream, ContentHandlerFactory handlers, Metadata metadata, ParseContext context) throws IOException, SAXException, TikaException {
+    public void parse(TikaInputStream tis, ContentHandlerFactory handlers, Metadata metadata, ParseContext context) throws IOException, SAXException, TikaException {
         // We only work with one ContentHandler as far as the user is
         //  concerned, any others are purely internal!
-        parse(stream, handlers.getNewContentHandler(), metadata, context);
+        parse(tis, handlers.getNewContentHandler(), metadata, context);
     }
 
     protected class CharsetContentHandlerFactory implements ContentHandlerFactory {
diff --git a/tika-example/src/main/java/org/apache/tika/example/RollbackSoftware.java b/tika-example/src/main/java/org/apache/tika/example/RollbackSoftware.java
index 708c421276..67ac389a2b 100755
--- a/tika-example/src/main/java/org/apache/tika/example/RollbackSoftware.java
+++ b/tika-example/src/main/java/org/apache/tika/example/RollbackSoftware.java
@@ -20,7 +20,6 @@ import static java.nio.charset.StandardCharsets.UTF_8;
 
 import java.io.File;
 import java.io.IOException;
-import java.io.InputStream;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashSet;
@@ -32,6 +31,7 @@ import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
 
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 import org.apache.tika.parser.ParseContext;
@@ -53,7 +53,7 @@ public class RollbackSoftware {
         LinkContentHandler handler = new LinkContentHandler();
         Metadata met = new Metadata();
         DeploymentAreaParser parser = new DeploymentAreaParser();
-        parser.parse(IOUtils.toInputStream(deployArea.getAbsolutePath(), UTF_8), handler, met);
+        parser.parse(TikaInputStream.get(IOUtils.toInputStream(deployArea.getAbsolutePath(), UTF_8)), handler, met);
         List<Link> links = handler.getLinks();
         if (links.size() < 2) {
             throw new IOException("Must have installed at least 2 versions!");
@@ -94,8 +94,8 @@ public class RollbackSoftware {
          * @see org.apache.tika.parser.Parser#parse(java.io.InputStream,
          * org.xml.sax.ContentHandler, org.apache.tika.metadata.Metadata)
          */
-        public void parse(InputStream is, ContentHandler handler, Metadata metadata) throws IOException, SAXException, TikaException {
-            parse(is, handler, metadata, new ParseContext());
+        public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata) throws IOException, SAXException, TikaException {
+            parse(tis, handler, metadata, new ParseContext());
         }
 
         /*
@@ -105,9 +105,9 @@ public class RollbackSoftware {
          * org.xml.sax.ContentHandler, org.apache.tika.metadata.Metadata,
          * org.apache.tika.parser.ParseContext)
          */
-        public void parse(InputStream is, ContentHandler handler, Metadata metadata, ParseContext context) throws IOException, SAXException, TikaException {
+        public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata, ParseContext context) throws IOException, SAXException, TikaException {
 
-            File deployArea = new File(IOUtils.toString(is, UTF_8));
+            File deployArea = new File(IOUtils.toString(tis, UTF_8));
             File[] versions = deployArea.listFiles(pathname -> !pathname
                     .getName()
                     .startsWith("current"));
diff --git a/tika-example/src/main/java/org/apache/tika/example/SpringExample.java b/tika-example/src/main/java/org/apache/tika/example/SpringExample.java
index 99ebba9b1b..35c9c5106a 100755
--- a/tika-example/src/main/java/org/apache/tika/example/SpringExample.java
+++ b/tika-example/src/main/java/org/apache/tika/example/SpringExample.java
@@ -18,12 +18,12 @@ package org.apache.tika.example;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 
-import java.io.ByteArrayInputStream;
 import java.io.OutputStreamWriter;
 
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.support.ClassPathXmlApplicationContext;
 
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.parser.ParseContext;
 import org.apache.tika.parser.Parser;
@@ -33,7 +33,7 @@ public class SpringExample {
     public static void main(String[] args) throws Exception {
         ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"org/apache/tika/example/spring.xml"});
         Parser parser = context.getBean("tika", Parser.class);
-        parser.parse(new ByteArrayInputStream("Hello, World!".getBytes(UTF_8)), new WriteOutContentHandler(new OutputStreamWriter(System.out, UTF_8)), new Metadata(),
+        parser.parse(TikaInputStream.get("Hello, World!".getBytes(UTF_8)), new WriteOutContentHandler(new OutputStreamWriter(System.out, UTF_8)), new Metadata(),
                 new ParseContext());
     }
 }
diff --git a/tika-example/src/main/java/org/apache/tika/example/StandardsExtractionExample.java b/tika-example/src/main/java/org/apache/tika/example/StandardsExtractionExample.java
index a9f12e127a..d3b5d1346f 100644
--- a/tika-example/src/main/java/org/apache/tika/example/StandardsExtractionExample.java
+++ b/tika-example/src/main/java/org/apache/tika/example/StandardsExtractionExample.java
@@ -28,6 +28,7 @@ import java.nio.file.attribute.BasicFileAttributes;
 import java.util.Collections;
 import java.util.HashSet;
 
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.parser.AutoDetectParser;
 import org.apache.tika.parser.ParseContext;
@@ -101,7 +102,7 @@ public class StandardsExtractionExample {
         StandardsExtractingContentHandler handler = new StandardsExtractingContentHandler(new BodyContentHandler(-1), metadata);
         handler.setThreshold(0.75);
         try (InputStream stream = new BufferedInputStream(Files.newInputStream(path))) {
-            parser.parse(stream, handler, metadata, new ParseContext());
+            parser.parse(TikaInputStream.get(stream), handler, metadata, new ParseContext());
         }
         String[] references = metadata.getValues(StandardsExtractingContentHandler.STANDARD_REFERENCES);
         Collections.addAll(standardReferences, references);
diff --git a/tika-example/src/main/java/org/apache/tika/example/TIAParsingExample.java b/tika-example/src/main/java/org/apache/tika/example/TIAParsingExample.java
index 6b1042824b..3823de2b2c 100755
--- a/tika-example/src/main/java/org/apache/tika/example/TIAParsingExample.java
+++ b/tika-example/src/main/java/org/apache/tika/example/TIAParsingExample.java
@@ -16,11 +16,8 @@
  */
 package org.apache.tika.example;
 
-import java.io.ByteArrayInputStream;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.Reader;
 import java.io.Writer;
 import java.net.URL;
@@ -81,8 +78,8 @@ public class TIAParsingExample {
         ContentHandler handler = new DefaultHandler();
         Metadata metadata = new Metadata();
         ParseContext context = new ParseContext();
-        try (InputStream stream = new FileInputStream(new File(filename))) {
-            parser.parse(stream, handler, metadata, context);
+        try (TikaInputStream tis = TikaInputStream.get(Paths.get(filename))) {
+            parser.parse(tis, handler, metadata, context);
         }
     }
 
@@ -91,8 +88,8 @@ public class TIAParsingExample {
         ContentHandler handler = new DefaultHandler();
         Metadata metadata = new Metadata();
         ParseContext context = new ParseContext();
-        try (InputStream stream = new GZIPInputStream(new URL(address).openStream())) {
-            parser.parse(stream, handler, metadata, context);
+        try (TikaInputStream tis = TikaInputStream.get(new GZIPInputStream(new URL(address).openStream()))) {
+            parser.parse(tis, handler, metadata, context);
         }
     }
 
@@ -101,99 +98,105 @@ public class TIAParsingExample {
         ContentHandler handler = new DefaultHandler();
         Metadata metadata = new Metadata();
         ParseContext context = new ParseContext();
-        try (InputStream stream = TikaInputStream.get(Paths.get(filename))) {
-            parser.parse(stream, handler, metadata, context);
+        try (TikaInputStream tis = TikaInputStream.get(Paths.get(filename))) {
+            parser.parse(tis, handler, metadata, context);
         }
     }
 
     public static File tikaInputStreamGetFile(String filename) throws Exception {
-        try (InputStream stream = TikaInputStream.get(Paths.get(filename))) {
-            TikaInputStream tikaInputStream = TikaInputStream.get(stream);
-            return tikaInputStream.getFile();
+        try (TikaInputStream tis = TikaInputStream.get(Paths.get(filename))) {
+            return tis.getFile();
         }
     }
 
     public static void useHtmlParser() throws Exception {
-        InputStream stream = new ByteArrayInputStream(new byte[0]);
-        ContentHandler handler = new DefaultHandler();
-        Metadata metadata = new Metadata();
-        ParseContext context = new ParseContext();
-        Parser parser = new JSoupParser();
-        parser.parse(stream, handler, metadata, context);
+        try (TikaInputStream tis = TikaInputStream.get(new byte[0])) {
+            ContentHandler handler = new DefaultHandler();
+            Metadata metadata = new Metadata();
+            ParseContext context = new ParseContext();
+            Parser parser = new JSoupParser();
+            parser.parse(tis, handler, metadata, context);
+        }
     }
 
     public static void useCompositeParser() throws Exception {
-        InputStream stream = new ByteArrayInputStream(new byte[0]);
-        ContentHandler handler = new DefaultHandler();
-        ParseContext context = new ParseContext();
-        Map<MediaType, Parser> parsersByType = new HashMap<>();
-        parsersByType.put(MediaType.parse("text/html"), new JSoupParser());
-        parsersByType.put(MediaType.parse("application/xml"), new XMLParser());
-
-        CompositeParser parser = new CompositeParser();
-        parser.setParsers(parsersByType);
-        parser.setFallback(new TXTParser());
-
-        Metadata metadata = new Metadata();
-        metadata.set(Metadata.CONTENT_TYPE, "text/html");
-        parser.parse(stream, handler, metadata, context);
+        try (TikaInputStream tis = TikaInputStream.get(new byte[0])) {
+            ContentHandler handler = new DefaultHandler();
+            ParseContext context = new ParseContext();
+            Map<MediaType, Parser> parsersByType = new HashMap<>();
+            parsersByType.put(MediaType.parse("text/html"), new JSoupParser());
+            parsersByType.put(MediaType.parse("application/xml"), new XMLParser());
+
+            CompositeParser parser = new CompositeParser();
+            parser.setParsers(parsersByType);
+            parser.setFallback(new TXTParser());
+
+            Metadata metadata = new Metadata();
+            metadata.set(Metadata.CONTENT_TYPE, "text/html");
+            parser.parse(tis, handler, metadata, context);
+        }
     }
 
     public static void useAutoDetectParser() throws Exception {
-        InputStream stream = new ByteArrayInputStream(new byte[0]);
-        ContentHandler handler = new DefaultHandler();
-        Metadata metadata = new Metadata();
-        ParseContext context = new ParseContext();
-        Parser parser = new AutoDetectParser();
-        parser.parse(stream, handler, metadata, context);
+        try (TikaInputStream tis = TikaInputStream.get(new byte[0])) {
+            ContentHandler handler = new DefaultHandler();
+            Metadata metadata = new Metadata();
+            ParseContext context = new ParseContext();
+            Parser parser = new AutoDetectParser();
+            parser.parse(tis, handler, metadata, context);
+        }
     }
 
     public static void testTeeContentHandler(String filename) throws Exception {
-        InputStream stream = new ByteArrayInputStream(new byte[0]);
-        Metadata metadata = new Metadata();
-        ParseContext context = new ParseContext();
-        Parser parser = new AutoDetectParser();
-        LinkContentHandler linkCollector = new LinkContentHandler();
-        try (Writer writer = Files.newBufferedWriter(Paths.get(filename), StandardCharsets.UTF_8)) {
-            ContentHandler handler = new TeeContentHandler(new BodyContentHandler(writer), linkCollector);
-            parser.parse(stream, handler, metadata, context);
+        try (TikaInputStream tis = TikaInputStream.get(new byte[0])) {
+            Metadata metadata = new Metadata();
+            ParseContext context = new ParseContext();
+            Parser parser = new AutoDetectParser();
+            LinkContentHandler linkCollector = new LinkContentHandler();
+            try (Writer writer = Files.newBufferedWriter(Paths.get(filename), StandardCharsets.UTF_8)) {
+                ContentHandler handler = new TeeContentHandler(new BodyContentHandler(writer), linkCollector);
+                parser.parse(tis, handler, metadata, context);
+            }
         }
     }
 
     public static void testLocale() throws Exception {
-        InputStream stream = new ByteArrayInputStream(new byte[0]);
-        ContentHandler handler = new DefaultHandler();
-        Metadata metadata = new Metadata();
-        Parser parser = new AutoDetectParser();
-        ParseContext context = new ParseContext();
-        context.set(Locale.class, Locale.ENGLISH);
-        parser.parse(stream, handler, metadata, context);
+        try (TikaInputStream tis = TikaInputStream.get(new byte[0])) {
+            ContentHandler handler = new DefaultHandler();
+            Metadata metadata = new Metadata();
+            Parser parser = new AutoDetectParser();
+            ParseContext context = new ParseContext();
+            context.set(Locale.class, Locale.ENGLISH);
+            parser.parse(tis, handler, metadata, context);
+        }
     }
 
     public static void testHtmlMapper() throws Exception {
-        InputStream stream = new ByteArrayInputStream(new byte[0]);
-        ContentHandler handler = new DefaultHandler();
-        Metadata metadata = new Metadata();
-        Parser parser = new AutoDetectParser();
-        ParseContext context = new ParseContext();
-        context.set(HtmlMapper.class, new IdentityHtmlMapper());
-        parser.parse(stream, handler, metadata, context);
+        try (TikaInputStream tis = TikaInputStream.get(new byte[0])) {
+            ContentHandler handler = new DefaultHandler();
+            Metadata metadata = new Metadata();
+            Parser parser = new AutoDetectParser();
+            ParseContext context = new ParseContext();
+            context.set(HtmlMapper.class, new IdentityHtmlMapper());
+            parser.parse(tis, handler, metadata, context);
+        }
     }
 
     public static void testCompositeDocument() throws Exception {
-        InputStream stream = new ByteArrayInputStream(new byte[0]);
-        ContentHandler handler = new DefaultHandler();
-        Metadata metadata = new Metadata();
-        Parser parser = new AutoDetectParser();
-        ParseContext context = new ParseContext();
-        context.set(Parser.class, new ParserDecorator(parser) {
-            private static final long serialVersionUID = 4424210691523343833L;
-
-            @Override
-            public void parse(InputStream stream, ContentHandler handler, Metadata metadata, ParseContext context) throws IOException, SAXException, TikaException {
-                // custom processing of the component document
-            }
-        });
-        parser.parse(stream, handler, metadata, context);
+        try (TikaInputStream tis = TikaInputStream.get(new byte[0])) {
+            ContentHandler handler = new DefaultHandler();
+            Metadata metadata = new Metadata();
+            Parser parser = new AutoDetectParser();
+            ParseContext context = new ParseContext();
+            context.set(Parser.class, new ParserDecorator(parser) {
+                private static final long serialVersionUID = 4424210691523343833L;
+
+                @Override
+                public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata, ParseContext context) throws IOException, SAXException, TikaException {
+                    // custom processing of the component document
+                }
+            });
+            parser.parse(tis, handler, metadata, context);
+        }
     }
 }
diff --git a/tika-grpc/src/test/java/org/apache/tika/pipes/grpc/ExpiringFetcherStoreTest.java b/tika-grpc/src/test/java/org/apache/tika/pipes/grpc/ExpiringFetcherStoreTest.java
index 21356a5ca5..d5a25844c8 100644
--- a/tika-grpc/src/test/java/org/apache/tika/pipes/grpc/ExpiringFetcherStoreTest.java
+++ b/tika-grpc/src/test/java/org/apache/tika/pipes/grpc/ExpiringFetcherStoreTest.java
@@ -19,7 +19,6 @@ package org.apache.tika.pipes.grpc;
 import static org.junit.jupiter.api.Assertions.assertNull;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.time.Duration;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -28,6 +27,7 @@ import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.parser.ParseContext;
 import org.apache.tika.pipes.api.fetcher.Fetcher;
@@ -42,7 +42,7 @@ class ExpiringFetcherStoreTest {
         try (ExpiringFetcherStore expiringFetcherStore = new ExpiringFetcherStore(1, 5)) {
             Fetcher fetcher = new Fetcher() {
                 @Override
-                public InputStream fetch(String fetchKey, Metadata metadata, ParseContext parseContext) throws TikaException, IOException {
+                public TikaInputStream fetch(String fetchKey, Metadata metadata, ParseContext parseContext) throws TikaException, IOException {
                     return null;
                 }
 
diff --git a/tika-integration-tests/tika-resource-loading-tests/src/test/java/org/apache/custom/parser/MyCustomParser.java b/tika-integration-tests/tika-resource-loading-tests/src/test/java/org/apache/custom/parser/MyCustomParser.java
index bddf0afe0a..1bb9bb0ba8 100644
--- a/tika-integration-tests/tika-resource-loading-tests/src/test/java/org/apache/custom/parser/MyCustomParser.java
+++ b/tika-integration-tests/tika-resource-loading-tests/src/test/java/org/apache/custom/parser/MyCustomParser.java
@@ -17,7 +17,6 @@
 package org.apache.custom.parser;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.util.Collections;
 import java.util.Set;
 
@@ -25,6 +24,7 @@ import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
 
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 import org.apache.tika.parser.ParseContext;
@@ -39,7 +39,7 @@ public class MyCustomParser implements Parser {
     }
 
     @Override
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream stream, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
         XHTMLContentHandler xhtml = new XHTMLContentHandler(handler, metadata);
         xhtml.startDocument();
diff --git a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/envi/EnviHeaderParser.java b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/envi/EnviHeaderParser.java
index 68c3802310..d39b51271c 100644
--- a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/envi/EnviHeaderParser.java
+++ b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/envi/EnviHeaderParser.java
@@ -17,7 +17,6 @@
 package org.apache.tika.parser.envi;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.nio.charset.Charset;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -34,6 +33,7 @@ import org.apache.tika.config.TikaComponent;
 import org.apache.tika.detect.AutoDetectReader;
 import org.apache.tika.detect.EncodingDetector;
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 import org.apache.tika.parser.AbstractEncodingDetectorParser;
@@ -67,7 +67,7 @@ public class EnviHeaderParser extends AbstractEncodingDetectorParser {
     }
 
     @Override
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
 
         // Only outputting the MIME type as metadata
@@ -75,7 +75,7 @@ public class EnviHeaderParser extends AbstractEncodingDetectorParser {
 
         // The following code was taken from the TXTParser
         // Automatically detect the character encoding
-        try (AutoDetectReader reader = new AutoDetectReader(CloseShieldInputStream.wrap(stream),
+        try (AutoDetectReader reader = new AutoDetectReader(CloseShieldInputStream.wrap(tis),
                 metadata, getEncodingDetector(context))) {
             Charset charset = reader.getCharset();
             // deprecated, see TIKA-431
@@ -85,7 +85,7 @@ public class EnviHeaderParser extends AbstractEncodingDetectorParser {
             readLines(reader, metadata);
             xhtml.endDocument();
         } catch (IOException | TikaException e) {
-            LOG.error("Error reading input data stream.", e);
+            LOG.error("Error reading input data tis.", e);
         }
 
     }
diff --git a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/gdal/GDALParser.java b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/gdal/GDALParser.java
index 6f85eb9965..8d964e0cce 100644
--- a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/gdal/GDALParser.java
+++ b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/gdal/GDALParser.java
@@ -21,7 +21,6 @@ package org.apache.tika.parser.gdal;
 import static org.apache.tika.parser.external.ExternalParser.INPUT_FILE_TOKEN;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.Reader;
 import java.io.StringReader;
 import java.util.Arrays;
@@ -163,8 +162,7 @@ public class GDALParser implements Parser {
         this.command = command;
     }
 
-    public String processCommand(InputStream stream) {
-        TikaInputStream tis = (TikaInputStream) stream;
+    public String processCommand(TikaInputStream tis) {
         String pCommand = this.command;
         try {
             if (this.command.contains(INPUT_FILE_TOKEN)) {
@@ -183,7 +181,7 @@ public class GDALParser implements Parser {
     }
 
     @Override
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
 
         if (!ExternalParser.check("gdalinfo")) {
@@ -192,8 +190,7 @@ public class GDALParser implements Parser {
 
         // first set up and run GDAL
         // process the command
-        TemporaryResources tmp = new TemporaryResources();
-        TikaInputStream tis = TikaInputStream.get(stream, tmp, metadata);
+        TemporaryResources tmp = null;
 
         String[] runCommand = processCommand(tis).split("\\s+", -1);
 
diff --git a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/geoinfo/GeographicInformationParser.java b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/geoinfo/GeographicInformationParser.java
index 41c61d2087..66064e7eb7 100644
--- a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/geoinfo/GeographicInformationParser.java
+++ b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/geoinfo/GeographicInformationParser.java
@@ -18,7 +18,6 @@ package org.apache.tika.parser.geoinfo;
 
 import java.io.File;
 import java.io.IOException;
-import java.io.InputStream;
 import java.nio.charset.Charset;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -86,15 +85,14 @@ public class GeographicInformationParser implements Parser {
     }
 
     @Override
-    public void parse(InputStream inputStream, ContentHandler contentHandler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler contentHandler, Metadata metadata,
                       ParseContext parseContext) throws IOException, SAXException, TikaException {
         metadata.set(Metadata.CONTENT_TYPE, geoInfoType);
         XHTMLContentHandler xhtmlContentHandler = new XHTMLContentHandler(contentHandler, metadata);
 
-        TemporaryResources tmp =
-                TikaInputStream.isTikaInputStream(inputStream) ? null : new TemporaryResources();
-        try (TikaInputStream tikaInputStream = TikaInputStream.get(inputStream, tmp, metadata)) {
-            File file = tikaInputStream.getFile();
+        TemporaryResources tmp = null;
+        try (tis) {
+            File file = tis.getFile();
             try (DataStore dataStore = DataStores.open(file)) {
                 DefaultMetadata defaultMetadata = new DefaultMetadata(dataStore.getMetadata());
                 extract(xhtmlContentHandler, metadata, defaultMetadata);
diff --git a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/grib/GribParser.java b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/grib/GribParser.java
index 695a703e20..ea5dd14442 100644
--- a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/grib/GribParser.java
+++ b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/grib/GribParser.java
@@ -17,7 +17,6 @@
 package org.apache.tika.parser.grib;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.StandardCopyOption;
@@ -35,6 +34,7 @@ import ucar.nc2.dataset.NetcdfDataset;
 
 import org.apache.tika.config.TikaComponent;
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.Property;
 import org.apache.tika.metadata.TikaCoreProperties;
@@ -55,7 +55,7 @@ public class GribParser implements Parser {
         return SUPPORTED_TYPES;
     }
 
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
 
         //Set MIME type as grib2
@@ -68,7 +68,7 @@ public class GribParser implements Parser {
         try {
             XHTMLContentHandler xhtml;
             Path gribFile = Files.createTempFile(tmpDir, "tika-file", ".grib2");
-            Files.copy(stream, gribFile, StandardCopyOption.REPLACE_EXISTING);
+            Files.copy(tis, gribFile, StandardCopyOption.REPLACE_EXISTING);
 
             try (NetcdfFile ncFile = NetcdfDataset.openFile(gribFile.toString(), null)) {
 
diff --git a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/hdf/HDFParser.java b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/hdf/HDFParser.java
index 96f4302b2b..a98f743a67 100644
--- a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/hdf/HDFParser.java
+++ b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/hdf/HDFParser.java
@@ -19,7 +19,6 @@ package org.apache.tika.parser.hdf;
 //JDK imports
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.util.Collections;
 import java.util.Set;
 
@@ -33,6 +32,7 @@ import ucar.nc2.NetcdfFile;
 
 import org.apache.tika.config.TikaComponent;
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
 import org.apache.tika.mime.MediaType;
@@ -78,10 +78,10 @@ public class HDFParser implements Parser {
      * org.xml.sax.ContentHandler, org.apache.tika.metadata.Metadata,
      * org.apache.tika.parser.ParseContext)
      */
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
         UnsynchronizedByteArrayOutputStream os = UnsynchronizedByteArrayOutputStream.builder().get();
-        IOUtils.copy(stream, os);
+        IOUtils.copy(tis, os);
 
         String name = metadata.get(TikaCoreProperties.RESOURCE_NAME_KEY);
         if (name == null) {
diff --git a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/isatab/ISArchiveParser.java b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/isatab/ISArchiveParser.java
index 8c0777b688..3a7929542f 100644
--- a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/isatab/ISArchiveParser.java
+++ b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/isatab/ISArchiveParser.java
@@ -74,13 +74,11 @@ public class ISArchiveParser implements Parser {
     }
 
     @Override
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
 
-        TemporaryResources tmp =
-                TikaInputStream.isTikaInputStream(stream) ? null : new TemporaryResources();
+        TemporaryResources tmp = null;
 
-        TikaInputStream tis = TikaInputStream.get(stream, tmp, metadata);
         try {
             if (this.location == null) {
                 this.location = tis.getFile().getParent() + File.separator;
@@ -94,7 +92,7 @@ public class ISArchiveParser implements Parser {
             xhtml.startDocument();
 
             parseInvestigation(investigationList, xhtml, metadata, context);
-            parseStudy(stream, xhtml, metadata, context);
+            parseStudy(tis, xhtml, metadata, context);
             parseAssay(xhtml, metadata, context);
 
             xhtml.endDocument();
@@ -124,11 +122,11 @@ public class ISArchiveParser implements Parser {
         xhtml.element("h1", "INVESTIGATION " + metadata.get("Investigation Identifier"));
     }
 
-    private void parseStudy(InputStream stream, XHTMLContentHandler xhtml, Metadata metadata,
+    private void parseStudy(InputStream tis, XHTMLContentHandler xhtml, Metadata metadata,
                             ParseContext context) throws IOException, SAXException, TikaException {
         xhtml.element("h2", "STUDY " + metadata.get("Study Identifier"));
 
-        ISATabUtils.parseStudy(stream, xhtml, metadata, context);
+        ISATabUtils.parseStudy(tis, xhtml, metadata, context);
     }
 
     private void parseAssay(XHTMLContentHandler xhtml, Metadata metadata, ParseContext context)
diff --git a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/netcdf/NetCDFParser.java b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/netcdf/NetCDFParser.java
index 464ea68034..a4a9282e60 100644
--- a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/netcdf/NetCDFParser.java
+++ b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/netcdf/NetCDFParser.java
@@ -19,7 +19,6 @@ package org.apache.tika.parser.netcdf;
 //JDK imports
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.util.Collections;
 import java.util.List;
 import java.util.Set;
@@ -79,12 +78,10 @@ public class NetCDFParser implements Parser {
      * org.xml.sax.ContentHandler, org.apache.tika.metadata.Metadata,
      * org.apache.tika.parser.ParseContext)
      */
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
 
-        TemporaryResources tmp =
-                TikaInputStream.isTikaInputStream(stream) ? null : new TemporaryResources();
-        TikaInputStream tis = TikaInputStream.get(stream, tmp, metadata);
+        TemporaryResources tmp = null;
         try (NetcdfFile ncFile = NetcdfFile.open(tis.getFile().getAbsolutePath())) {
             metadata.set("File-Type-Description", ncFile.getFileTypeDescription());
             // first parse out the set of global attributes
diff --git a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/test/java/org/apache/tika/parser/envi/EnviHeaderParserTest.java b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/test/java/org/apache/tika/parser/envi/EnviHeaderParserTest.java
index 1f746983b6..736157bce6 100644
--- a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/test/java/org/apache/tika/parser/envi/EnviHeaderParserTest.java
+++ b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/test/java/org/apache/tika/parser/envi/EnviHeaderParserTest.java
@@ -20,7 +20,6 @@ import static org.apache.tika.TikaTest.assertContains;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 
 import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
 
 import org.apache.commons.io.IOUtils;
@@ -28,6 +27,7 @@ import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.parser.ParseContext;
 import org.apache.tika.parser.Parser;
@@ -59,10 +59,10 @@ public class EnviHeaderParserTest {
     @Test
     public void testParseGlobalMetadata() throws Exception {
 
-        try (InputStream stream = EnviHeaderParser.class
-                .getResourceAsStream("/test-documents/envi_test_header.hdr")) {
-            assertNotNull(stream, "Test ENVI file 'envi_test_header.hdr' not found");
-            parser.parse(stream, handler, metadata, new ParseContext());
+        try (TikaInputStream tis = TikaInputStream.get(EnviHeaderParser.class
+                .getResourceAsStream("/test-documents/envi_test_header.hdr"))) {
+            assertNotNull(tis, "Test ENVI file 'envi_test_header.hdr' not found");
+            parser.parse(tis, handler, metadata, new ParseContext());
         }
 
         // Check content of test file
@@ -90,10 +90,10 @@ public class EnviHeaderParserTest {
         ToXMLContentHandler handler = new ToXMLContentHandler();
         Metadata metadata = new Metadata();
 
-        try (InputStream stream = EnviHeaderParser.class
-                .getResourceAsStream("/test-documents/ang20150420t182050_corr_v1e_img.hdr")) {
-            assertNotNull(stream, "Test ENVI file 'ang20150420t182050_corr_v1e_img.hdr' not found");
-            parser.parse(stream, handler, metadata, new ParseContext());
+        try (TikaInputStream tis = TikaInputStream.get(EnviHeaderParser.class
+                .getResourceAsStream("/test-documents/ang20150420t182050_corr_v1e_img.hdr"))) {
+            assertNotNull(tis, "Test ENVI file 'ang20150420t182050_corr_v1e_img.hdr' not found");
+            parser.parse(tis, handler, metadata, new ParseContext());
         }
 
         // Check content of test file
diff --git a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/test/java/org/apache/tika/parser/gdal/TestGDALParser.java b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/test/java/org/apache/tika/parser/gdal/TestGDALParser.java
index 58612b2f8b..420a911984 100644
--- a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/test/java/org/apache/tika/parser/gdal/TestGDALParser.java
+++ b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/test/java/org/apache/tika/parser/gdal/TestGDALParser.java
@@ -22,11 +22,10 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.api.Assertions.fail;
 import static org.junit.jupiter.api.Assumptions.assumeTrue;
 
-import java.io.InputStream;
-
 import org.junit.jupiter.api.Test;
 
 import org.apache.tika.TikaTest;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.parser.ParseContext;
 import org.apache.tika.parser.external.ExternalParser;
@@ -55,12 +54,12 @@ public class TestGDALParser extends TikaTest {
         final String expectedSize = "512, 512";
 
         GDALParser parser = new GDALParser();
-        InputStream stream = TestGDALParser.class
-                .getResourceAsStream("/test-documents/sresa1b_ncar_ccsm3_0_run1_200001.nc");
+        TikaInputStream tis = TikaInputStream.get(TestGDALParser.class
+                .getResourceAsStream("/test-documents/sresa1b_ncar_ccsm3_0_run1_200001.nc"));
         Metadata met = new Metadata();
         BodyContentHandler handler = new BodyContentHandler();
         try {
-            parser.parse(stream, handler, met, new ParseContext());
+            parser.parse(tis, handler, met, new ParseContext());
         } catch (Exception e) {
             e.printStackTrace();
             fail(e.getMessage());
@@ -101,12 +100,12 @@ public class TestGDALParser extends TikaTest {
         final String expectedSub8Desc = "[1x17x128x256] eastward_wind (32-bit floating-point)";
 
         GDALParser parser = new GDALParser();
-        InputStream stream = TestGDALParser.class
-                .getResourceAsStream("/test-documents/sresa1b_ncar_ccsm3_0_run1_200001.nc");
+        TikaInputStream tis = TikaInputStream.get(TestGDALParser.class
+                .getResourceAsStream("/test-documents/sresa1b_ncar_ccsm3_0_run1_200001.nc"));
         Metadata met = new Metadata();
         BodyContentHandler handler = new BodyContentHandler();
         try {
-            parser.parse(stream, handler, met, new ParseContext());
+            parser.parse(tis, handler, met, new ParseContext());
             assertNotNull(met);
             assertNotNull(met.get("NC_GLOBAL#institution"));
             assertEquals(expectedNcInst, met.get("NC_GLOBAL#institution"));
@@ -149,11 +148,11 @@ public class TestGDALParser extends TikaTest {
         String expectedCalibDef = "1466";
 
         GDALParser parser = new GDALParser();
-        InputStream stream = TestGDALParser.class.getResourceAsStream(fitsFilename);
+        TikaInputStream tis = TikaInputStream.get(TestGDALParser.class.getResourceAsStream(fitsFilename));
         Metadata met = new Metadata();
         BodyContentHandler handler = new BodyContentHandler();
         try {
-            parser.parse(stream, handler, met, new ParseContext());
+            parser.parse(tis, handler, met, new ParseContext());
             assertNotNull(met);
             assertNotNull(met.get("ALLG-MIN"));
             assertEquals(expectedAllgMin, met.get("ALLG-MIN"));
diff --git a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/test/java/org/apache/tika/parser/grib/GribParserTest.java b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/test/java/org/apache/tika/parser/grib/GribParserTest.java
index 0bd00f8151..7768eda1fc 100644
--- a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/test/java/org/apache/tika/parser/grib/GribParserTest.java
+++ b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/test/java/org/apache/tika/parser/grib/GribParserTest.java
@@ -19,11 +19,10 @@ package org.apache.tika.parser.grib;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
-import java.io.InputStream;
-
 import org.junit.jupiter.api.Test;
 import org.xml.sax.ContentHandler;
 
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.parser.ParseContext;
 import org.apache.tika.parser.Parser;
@@ -40,9 +39,9 @@ public class GribParserTest {
         Parser parser = new GribParser();
         Metadata metadata = new Metadata();
         ContentHandler handler = new BodyContentHandler();
-        try (InputStream stream = GribParser.class
-                .getResourceAsStream("/test-documents/gdas1.forecmwf.2014062612.grib2")) {
-            parser.parse(stream, handler, metadata, new ParseContext());
+        try (TikaInputStream tis = TikaInputStream.get(GribParser.class
+                .getResourceAsStream("/test-documents/gdas1.forecmwf.2014062612.grib2"))) {
+            parser.parse(tis, handler, metadata, new ParseContext());
         }
         assertNotNull(metadata);
         String content = handler.toString();
diff --git a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/test/java/org/apache/tika/parser/hdf/HDFParserTest.java b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/test/java/org/apache/tika/parser/hdf/HDFParserTest.java
index 3aaea28c1a..fa486d4041 100644
--- a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/test/java/org/apache/tika/parser/hdf/HDFParserTest.java
+++ b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/test/java/org/apache/tika/parser/hdf/HDFParserTest.java
@@ -19,11 +19,10 @@ package org.apache.tika.parser.hdf;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 
-import java.io.InputStream;
-
 import org.junit.jupiter.api.Test;
 import org.xml.sax.ContentHandler;
 
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.parser.ParseContext;
 import org.apache.tika.parser.Parser;
@@ -50,8 +49,8 @@ public class HDFParserTest {
          * ftp://acdisc.gsfc.nasa.gov/data/s4pa///Aura_MLS_Level2/ML2O3.002//2009
          * /MLS-Aura_L2GP-O3_v02-23-c01_2009d122.he5
          */
-        try (InputStream stream = HDFParser.class.getResourceAsStream("/test-documents/test.he5")) {
-            parser.parse(stream, handler, metadata, new ParseContext());
+        try (TikaInputStream tis = TikaInputStream.get(HDFParser.class.getResourceAsStream("/test-documents/test.he5"))) {
+            parser.parse(tis, handler, metadata, new ParseContext());
         }
 
         assertNotNull(metadata);
@@ -72,8 +71,8 @@ public class HDFParserTest {
          *
          * http://www.hdfgroup.org/training/hdf4_chunking/Chunkit/bin/input54kmdata.hdf
          */
-        try (InputStream stream = HDFParser.class.getResourceAsStream("/test-documents/test.hdf")) {
-            parser.parse(stream, handler, metadata, new ParseContext());
+        try (TikaInputStream tis = TikaInputStream.get(HDFParser.class.getResourceAsStream("/test-documents/test.hdf"))) {
+            parser.parse(tis, handler, metadata, new ParseContext());
         }
 
         assertNotNull(metadata);
diff --git a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/test/java/org/apache/tika/parser/isatab/ISArchiveParserTest.java b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/test/java/org/apache/tika/parser/isatab/ISArchiveParserTest.java
index de9cf25ed0..07ca95f1c9 100644
--- a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/test/java/org/apache/tika/parser/isatab/ISArchiveParserTest.java
+++ b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/test/java/org/apache/tika/parser/isatab/ISArchiveParserTest.java
@@ -18,11 +18,10 @@ package org.apache.tika.parser.isatab;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
-import java.io.InputStream;
-
 import org.junit.jupiter.api.Test;
 import org.xml.sax.ContentHandler;
 
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.parser.ParseContext;
 import org.apache.tika.parser.Parser;
@@ -42,8 +41,8 @@ public class ISArchiveParserTest {
         ContentHandler handler = new BodyContentHandler();
         Metadata metadata = new Metadata();
         ParseContext context = new ParseContext();
-        try (InputStream stream = ISArchiveParserTest.class.getResourceAsStream(path)) {
-            parser.parse(stream, handler, metadata, context);
+        try (TikaInputStream tis = TikaInputStream.get(ISArchiveParserTest.class.getResourceAsStream(path))) {
+            parser.parse(tis, handler, metadata, context);
         }
 
         // INVESTIGATION
diff --git a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/test/java/org/apache/tika/parser/netcdf/NetCDFParserTest.java b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/test/java/org/apache/tika/parser/netcdf/NetCDFParserTest.java
index 92dc0733e4..2e04296c80 100644
--- a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/test/java/org/apache/tika/parser/netcdf/NetCDFParserTest.java
+++ b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/test/java/org/apache/tika/parser/netcdf/NetCDFParserTest.java
@@ -19,11 +19,10 @@ package org.apache.tika.parser.netcdf;
 import static org.apache.tika.TikaTest.assertContains;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
-import java.io.InputStream;
-
 import org.junit.jupiter.api.Test;
 import org.xml.sax.ContentHandler;
 
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
 import org.apache.tika.parser.ParseContext;
@@ -41,9 +40,9 @@ public class NetCDFParserTest {
         ContentHandler handler = new BodyContentHandler();
         Metadata metadata = new Metadata();
 
-        try (InputStream stream = NetCDFParser.class
-                .getResourceAsStream("/test-documents/sresa1b_ncar_ccsm3_0_run1_200001.nc")) {
-            parser.parse(stream, handler, metadata, new ParseContext());
+        try (TikaInputStream tis = TikaInputStream.get(NetCDFParser.class
+                .getResourceAsStream("/test-documents/sresa1b_ncar_ccsm3_0_run1_200001.nc"))) {
+            parser.parse(tis, handler, metadata, new ParseContext());
         }
 
         assertEquals(metadata.get(TikaCoreProperties.TITLE), "model output prepared for IPCC AR4");
diff --git a/tika-parsers/tika-parsers-extended/tika-parser-scientific-package/src/test/resources/2.4.0-no-tesseract.txt b/tika-parsers/tika-parsers-extended/tika-parser-scientific-package/src/test/resources/2.4.0-no-tesseract.txt
index ca772e5985..9ec29d0e1c 100644
--- a/tika-parsers/tika-parsers-extended/tika-parser-scientific-package/src/test/resources/2.4.0-no-tesseract.txt
+++ b/tika-parsers/tika-parsers-extended/tika-parser-scientific-package/src/test/resources/2.4.0-no-tesseract.txt
@@ -17,13 +17,13 @@ application/java-archive	class org.apache.tika.parser.pkg.PackageParser
 application/java-vm	class org.apache.tika.parser.asm.ClassParser
 application/jaxa-pal-sar	class org.apache.tika.parser.gdal.GDALParser
 application/jdem	class org.apache.tika.parser.gdal.GDALParser
-application/kate	class org.gagravarr.tika.OggParser
+application/kate	class org.apache.tika.parser.ogg.OggParser
 application/leveller	class org.apache.tika.parser.gdal.GDALParser
 application/mbox	class org.apache.tika.parser.mbox.MboxParser
 application/mock+xml	class org.apache.tika.parser.mock.MockParser
 application/mp4	class org.apache.tika.parser.mp4.MP4Parser
 application/msword	class org.apache.tika.parser.microsoft.OfficeParser
-application/ogg	class org.gagravarr.tika.OggParser
+application/ogg	class org.apache.tika.parser.ogg.OggParser
 application/onenote; format=one	class org.apache.tika.parser.microsoft.onenote.OneNoteParser
 application/pcisdk	class org.apache.tika.parser.gdal.GDALParser
 application/pdf	class org.apache.tika.parser.pdf.PDFParser
@@ -257,17 +257,17 @@ audio/basic	class org.apache.tika.parser.audio.AudioParser
 audio/midi	class org.apache.tika.parser.audio.MidiParser
 audio/mp4	class org.apache.tika.parser.mp4.MP4Parser
 audio/mpeg	class org.apache.tika.parser.mp3.Mp3Parser
-audio/ogg	class org.gagravarr.tika.OggParser
-audio/ogg; codecs=opus	class org.gagravarr.tika.OpusParser
-audio/ogg; codecs=speex	class org.gagravarr.tika.SpeexParser
-audio/opus	class org.gagravarr.tika.OpusParser
-audio/speex	class org.gagravarr.tika.SpeexParser
+audio/ogg	class org.apache.tika.parser.ogg.OggParser
+audio/ogg; codecs=opus	class org.apache.tika.parser.ogg.OpusParser
+audio/ogg; codecs=speex	class org.apache.tika.parser.ogg.SpeexParser
+audio/opus	class org.apache.tika.parser.ogg.OpusParser
+audio/speex	class org.apache.tika.parser.ogg.SpeexParser
 audio/vnd.wave	class org.apache.tika.parser.audio.AudioParser
-audio/vorbis	class org.gagravarr.tika.VorbisParser
+audio/vorbis	class org.apache.tika.parser.ogg.VorbisParser
 audio/x-aiff	class org.apache.tika.parser.audio.AudioParser
-audio/x-flac	class org.gagravarr.tika.FlacParser
-audio/x-oggflac	class org.gagravarr.tika.FlacParser
-audio/x-oggpcm	class org.gagravarr.tika.OggParser
+audio/x-flac	class org.apache.tika.parser.ogg.FlacParser
+audio/x-oggflac	class org.apache.tika.parser.ogg.FlacParser
+audio/x-oggpcm	class org.apache.tika.parser.ogg.OggParser
 image/adrg	class org.apache.tika.parser.gdal.GDALParser
 image/arg	class org.apache.tika.parser.gdal.GDALParser
 image/big-gif	class org.apache.tika.parser.gdal.GDALParser
@@ -332,17 +332,17 @@ text/x-groovy	class org.apache.tika.parser.code.SourceCodeParser
 text/x-java-source	class org.apache.tika.parser.code.SourceCodeParser
 video/3gpp	class org.apache.tika.parser.mp4.MP4Parser
 video/3gpp2	class org.apache.tika.parser.mp4.MP4Parser
-video/daala	class org.gagravarr.tika.OggParser
+video/daala	class org.apache.tika.parser.ogg.OggParser
 video/mp4	class org.apache.tika.parser.mp4.MP4Parser
 video/mpeg	class org.apache.tika.parser.external.CompositeExternalParser
-video/ogg	class org.gagravarr.tika.OggParser
+video/ogg	class org.apache.tika.parser.ogg.OggParser
 video/quicktime	class org.apache.tika.parser.mp4.MP4Parser
-video/theora	class org.gagravarr.tika.TheoraParser
-video/x-dirac	class org.gagravarr.tika.OggParser
+video/theora	class org.apache.tika.parser.ogg.TheoraParser
+video/x-dirac	class org.apache.tika.parser.ogg.OggParser
 video/x-flv	class org.apache.tika.parser.video.FLVParser
 video/x-m4v	class org.apache.tika.parser.mp4.MP4Parser
 video/x-msvideo	class org.apache.tika.parser.external.CompositeExternalParser
-video/x-oggrgb	class org.gagravarr.tika.OggParser
-video/x-ogguvs	class org.gagravarr.tika.OggParser
-video/x-oggyuv	class org.gagravarr.tika.OggParser
-video/x-ogm	class org.gagravarr.tika.OggParser
\ No newline at end of file
+video/x-oggrgb	class org.apache.tika.parser.ogg.OggParser
+video/x-ogguvs	class org.apache.tika.parser.ogg.OggParser
+video/x-oggyuv	class org.apache.tika.parser.ogg.OggParser
+video/x-ogm	class org.apache.tika.parser.ogg.OggParser
\ No newline at end of file
diff --git a/tika-parsers/tika-parsers-extended/tika-parser-scientific-package/src/test/resources/2.4.0-tesseract.txt b/tika-parsers/tika-parsers-extended/tika-parser-scientific-package/src/test/resources/2.4.0-tesseract.txt
index 423832e4ae..976719b241 100644
--- a/tika-parsers/tika-parsers-extended/tika-parser-scientific-package/src/test/resources/2.4.0-tesseract.txt
+++ b/tika-parsers/tika-parsers-extended/tika-parser-scientific-package/src/test/resources/2.4.0-tesseract.txt
@@ -17,13 +17,13 @@ application/java-archive	class org.apache.tika.parser.pkg.PackageParser
 application/java-vm	class org.apache.tika.parser.asm.ClassParser
 application/jaxa-pal-sar	class org.apache.tika.parser.gdal.GDALParser
 application/jdem	class org.apache.tika.parser.gdal.GDALParser
-application/kate	class org.gagravarr.tika.OggParser
+application/kate	class org.apache.tika.parser.ogg.OggParser
 application/leveller	class org.apache.tika.parser.gdal.GDALParser
 application/mbox	class org.apache.tika.parser.mbox.MboxParser
 application/mock+xml	class org.apache.tika.parser.mock.MockParser
 application/mp4	class org.apache.tika.parser.mp4.MP4Parser
 application/msword	class org.apache.tika.parser.microsoft.OfficeParser
-application/ogg	class org.gagravarr.tika.OggParser
+application/ogg	class org.apache.tika.parser.ogg.OggParser
 application/onenote; format=one	class org.apache.tika.parser.microsoft.onenote.OneNoteParser
 application/pcisdk	class org.apache.tika.parser.gdal.GDALParser
 application/pdf	class org.apache.tika.parser.pdf.PDFParser
@@ -257,17 +257,17 @@ audio/basic	class org.apache.tika.parser.audio.AudioParser
 audio/midi	class org.apache.tika.parser.audio.MidiParser
 audio/mp4	class org.apache.tika.parser.mp4.MP4Parser
 audio/mpeg	class org.apache.tika.parser.mp3.Mp3Parser
-audio/ogg	class org.gagravarr.tika.OggParser
-audio/ogg; codecs=opus	class org.gagravarr.tika.OpusParser
-audio/ogg; codecs=speex	class org.gagravarr.tika.SpeexParser
-audio/opus	class org.gagravarr.tika.OpusParser
-audio/speex	class org.gagravarr.tika.SpeexParser
+audio/ogg	class org.apache.tika.parser.ogg.OggParser
+audio/ogg; codecs=opus	class org.apache.tika.parser.ogg.OpusParser
+audio/ogg; codecs=speex	class org.apache.tika.parser.ogg.SpeexParser
+audio/opus	class org.apache.tika.parser.ogg.OpusParser
+audio/speex	class org.apache.tika.parser.ogg.SpeexParser
 audio/vnd.wave	class org.apache.tika.parser.audio.AudioParser
-audio/vorbis	class org.gagravarr.tika.VorbisParser
+audio/vorbis	class org.apache.tika.parser.ogg.VorbisParser
 audio/x-aiff	class org.apache.tika.parser.audio.AudioParser
-audio/x-flac	class org.gagravarr.tika.FlacParser
-audio/x-oggflac	class org.gagravarr.tika.FlacParser
-audio/x-oggpcm	class org.gagravarr.tika.OggParser
+audio/x-flac	class org.apache.tika.parser.ogg.FlacParser
+audio/x-oggflac	class org.apache.tika.parser.ogg.FlacParser
+audio/x-oggpcm	class org.apache.tika.parser.ogg.OggParser
 image/adrg	class org.apache.tika.parser.gdal.GDALParser
 image/arg	class org.apache.tika.parser.gdal.GDALParser
 image/big-gif	class org.apache.tika.parser.gdal.GDALParser
@@ -342,17 +342,17 @@ text/x-groovy	class org.apache.tika.parser.code.SourceCodeParser
 text/x-java-source	class org.apache.tika.parser.code.SourceCodeParser
 video/3gpp	class org.apache.tika.parser.mp4.MP4Parser
 video/3gpp2	class org.apache.tika.parser.mp4.MP4Parser
-video/daala	class org.gagravarr.tika.OggParser
+video/daala	class org.apache.tika.parser.ogg.OggParser
 video/mp4	class org.apache.tika.parser.mp4.MP4Parser
 video/mpeg	class org.apache.tika.parser.external.CompositeExternalParser
-video/ogg	class org.gagravarr.tika.OggParser
+video/ogg	class org.apache.tika.parser.ogg.OggParser
 video/quicktime	class org.apache.tika.parser.mp4.MP4Parser
-video/theora	class org.gagravarr.tika.TheoraParser
-video/x-dirac	class org.gagravarr.tika.OggParser
+video/theora	class org.apache.tika.parser.ogg.TheoraParser
+video/x-dirac	class org.apache.tika.parser.ogg.OggParser
 video/x-flv	class org.apache.tika.parser.video.FLVParser
 video/x-m4v	class org.apache.tika.parser.mp4.MP4Parser
 video/x-msvideo	class org.apache.tika.parser.external.CompositeExternalParser
-video/x-oggrgb	class org.gagravarr.tika.OggParser
-video/x-ogguvs	class org.gagravarr.tika.OggParser
-video/x-oggyuv	class org.gagravarr.tika.OggParser
-video/x-ogm	class org.gagravarr.tika.OggParser
\ No newline at end of file
+video/x-oggrgb	class org.apache.tika.parser.ogg.OggParser
+video/x-ogguvs	class org.apache.tika.parser.ogg.OggParser
+video/x-oggyuv	class org.apache.tika.parser.ogg.OggParser
+video/x-ogm	class org.apache.tika.parser.ogg.OggParser
\ No newline at end of file
diff --git a/tika-parsers/tika-parsers-extended/tika-parser-scientific-package/src/test/resources/2.4.1-no-tesseract.txt b/tika-parsers/tika-parsers-extended/tika-parser-scientific-package/src/test/resources/2.4.1-no-tesseract.txt
index dec428750c..fed32bd863 100644
--- a/tika-parsers/tika-parsers-extended/tika-parser-scientific-package/src/test/resources/2.4.1-no-tesseract.txt
+++ b/tika-parsers/tika-parsers-extended/tika-parser-scientific-package/src/test/resources/2.4.1-no-tesseract.txt
@@ -17,13 +17,13 @@ application/java-archive	class org.apache.tika.parser.pkg.PackageParser
 application/java-vm	class org.apache.tika.parser.asm.ClassParser
 application/jaxa-pal-sar	class org.apache.tika.parser.gdal.GDALParser
 application/jdem	class org.apache.tika.parser.gdal.GDALParser
-application/kate	class org.gagravarr.tika.OggParser
+application/kate	class org.apache.tika.parser.ogg.OggParser
 application/leveller	class org.apache.tika.parser.gdal.GDALParser
 application/mbox	class org.apache.tika.parser.mbox.MboxParser
 application/mock+xml	class org.apache.tika.parser.mock.MockParser
 application/mp4	class org.apache.tika.parser.mp4.MP4Parser
 application/msword	class org.apache.tika.parser.microsoft.OfficeParser
-application/ogg	class org.gagravarr.tika.OggParser
+application/ogg	class org.apache.tika.parser.ogg.OggParser
 application/onenote; format=one	class org.apache.tika.parser.microsoft.onenote.OneNoteParser
 application/pcisdk	class org.apache.tika.parser.gdal.GDALParser
 application/pdf	class org.apache.tika.parser.pdf.PDFParser
@@ -257,17 +257,17 @@ audio/basic	class org.apache.tika.parser.audio.AudioParser
 audio/midi	class org.apache.tika.parser.audio.MidiParser
 audio/mp4	class org.apache.tika.parser.mp4.MP4Parser
 audio/mpeg	class org.apache.tika.parser.mp3.Mp3Parser
-audio/ogg	class org.gagravarr.tika.OggParser
-audio/ogg; codecs=opus	class org.gagravarr.tika.OpusParser
-audio/ogg; codecs=speex	class org.gagravarr.tika.SpeexParser
-audio/opus	class org.gagravarr.tika.OpusParser
-audio/speex	class org.gagravarr.tika.SpeexParser
+audio/ogg	class org.apache.tika.parser.ogg.OggParser
+audio/ogg; codecs=opus	class org.apache.tika.parser.ogg.OpusParser
+audio/ogg; codecs=speex	class org.apache.tika.parser.ogg.SpeexParser
+audio/opus	class org.apache.tika.parser.ogg.OpusParser
+audio/speex	class org.apache.tika.parser.ogg.SpeexParser
 audio/vnd.wave	class org.apache.tika.parser.audio.AudioParser
-audio/vorbis	class org.gagravarr.tika.VorbisParser
+audio/vorbis	class org.apache.tika.parser.ogg.VorbisParser
 audio/x-aiff	class org.apache.tika.parser.audio.AudioParser
-audio/x-flac	class org.gagravarr.tika.FlacParser
-audio/x-oggflac	class org.gagravarr.tika.FlacParser
-audio/x-oggpcm	class org.gagravarr.tika.OggParser
+audio/x-flac	class org.apache.tika.parser.ogg.FlacParser
+audio/x-oggflac	class org.apache.tika.parser.ogg.FlacParser
+audio/x-oggpcm	class org.apache.tika.parser.ogg.OggParser
 image/adrg	class org.apache.tika.parser.gdal.GDALParser
 image/arg	class org.apache.tika.parser.gdal.GDALParser
 image/big-gif	class org.apache.tika.parser.gdal.GDALParser
@@ -332,15 +332,15 @@ text/x-groovy	class org.apache.tika.parser.code.SourceCodeParser
 text/x-java-source	class org.apache.tika.parser.code.SourceCodeParser
 video/3gpp	class org.apache.tika.parser.mp4.MP4Parser
 video/3gpp2	class org.apache.tika.parser.mp4.MP4Parser
-video/daala	class org.gagravarr.tika.OggParser
+video/daala	class org.apache.tika.parser.ogg.OggParser
 video/mp4	class org.apache.tika.parser.mp4.MP4Parser
-video/ogg	class org.gagravarr.tika.OggParser
+video/ogg	class org.apache.tika.parser.ogg.OggParser
 video/quicktime	class org.apache.tika.parser.mp4.MP4Parser
-video/theora	class org.gagravarr.tika.TheoraParser
-video/x-dirac	class org.gagravarr.tika.OggParser
+video/theora	class org.apache.tika.parser.ogg.TheoraParser
+video/x-dirac	class org.apache.tika.parser.ogg.OggParser
 video/x-flv	class org.apache.tika.parser.video.FLVParser
 video/x-m4v	class org.apache.tika.parser.mp4.MP4Parser
-video/x-oggrgb	class org.gagravarr.tika.OggParser
-video/x-ogguvs	class org.gagravarr.tika.OggParser
-video/x-oggyuv	class org.gagravarr.tika.OggParser
-video/x-ogm	class org.gagravarr.tika.OggParser
\ No newline at end of file
+video/x-oggrgb	class org.apache.tika.parser.ogg.OggParser
+video/x-ogguvs	class org.apache.tika.parser.ogg.OggParser
+video/x-oggyuv	class org.apache.tika.parser.ogg.OggParser
+video/x-ogm	class org.apache.tika.parser.ogg.OggParser
\ No newline at end of file
diff --git a/tika-parsers/tika-parsers-extended/tika-parser-scientific-package/src/test/resources/2.4.1-tesseract.txt b/tika-parsers/tika-parsers-extended/tika-parser-scientific-package/src/test/resources/2.4.1-tesseract.txt
index ec74699e76..2777f81386 100644
--- a/tika-parsers/tika-parsers-extended/tika-parser-scientific-package/src/test/resources/2.4.1-tesseract.txt
+++ b/tika-parsers/tika-parsers-extended/tika-parser-scientific-package/src/test/resources/2.4.1-tesseract.txt
@@ -17,13 +17,13 @@ application/java-archive	class org.apache.tika.parser.pkg.PackageParser
 application/java-vm	class org.apache.tika.parser.asm.ClassParser
 application/jaxa-pal-sar	class org.apache.tika.parser.gdal.GDALParser
 application/jdem	class org.apache.tika.parser.gdal.GDALParser
-application/kate	class org.gagravarr.tika.OggParser
+application/kate	class org.apache.tika.parser.ogg.OggParser
 application/leveller	class org.apache.tika.parser.gdal.GDALParser
 application/mbox	class org.apache.tika.parser.mbox.MboxParser
 application/mock+xml	class org.apache.tika.parser.mock.MockParser
 application/mp4	class org.apache.tika.parser.mp4.MP4Parser
 application/msword	class org.apache.tika.parser.microsoft.OfficeParser
-application/ogg	class org.gagravarr.tika.OggParser
+application/ogg	class org.apache.tika.parser.ogg.OggParser
 application/onenote; format=one	class org.apache.tika.parser.microsoft.onenote.OneNoteParser
 application/pcisdk	class org.apache.tika.parser.gdal.GDALParser
 application/pdf	class org.apache.tika.parser.pdf.PDFParser
@@ -257,17 +257,17 @@ audio/basic	class org.apache.tika.parser.audio.AudioParser
 audio/midi	class org.apache.tika.parser.audio.MidiParser
 audio/mp4	class org.apache.tika.parser.mp4.MP4Parser
 audio/mpeg	class org.apache.tika.parser.mp3.Mp3Parser
-audio/ogg	class org.gagravarr.tika.OggParser
-audio/ogg; codecs=opus	class org.gagravarr.tika.OpusParser
-audio/ogg; codecs=speex	class org.gagravarr.tika.SpeexParser
-audio/opus	class org.gagravarr.tika.OpusParser
-audio/speex	class org.gagravarr.tika.SpeexParser
+audio/ogg	class org.apache.tika.parser.ogg.OggParser
+audio/ogg; codecs=opus	class org.apache.tika.parser.ogg.OpusParser
+audio/ogg; codecs=speex	class org.apache.tika.parser.ogg.SpeexParser
+audio/opus	class org.apache.tika.parser.ogg.OpusParser
+audio/speex	class org.apache.tika.parser.ogg.SpeexParser
 audio/vnd.wave	class org.apache.tika.parser.audio.AudioParser
-audio/vorbis	class org.gagravarr.tika.VorbisParser
+audio/vorbis	class org.apache.tika.parser.ogg.VorbisParser
 audio/x-aiff	class org.apache.tika.parser.audio.AudioParser
-audio/x-flac	class org.gagravarr.tika.FlacParser
-audio/x-oggflac	class org.gagravarr.tika.FlacParser
-audio/x-oggpcm	class org.gagravarr.tika.OggParser
+audio/x-flac	class org.apache.tika.parser.ogg.FlacParser
+audio/x-oggflac	class org.apache.tika.parser.ogg.FlacParser
+audio/x-oggpcm	class org.apache.tika.parser.ogg.OggParser
 image/adrg	class org.apache.tika.parser.gdal.GDALParser
 image/arg	class org.apache.tika.parser.gdal.GDALParser
 image/big-gif	class org.apache.tika.parser.gdal.GDALParser
@@ -342,15 +342,15 @@ text/x-groovy	class org.apache.tika.parser.code.SourceCodeParser
 text/x-java-source	class org.apache.tika.parser.code.SourceCodeParser
 video/3gpp	class org.apache.tika.parser.mp4.MP4Parser
 video/3gpp2	class org.apache.tika.parser.mp4.MP4Parser
-video/daala	class org.gagravarr.tika.OggParser
+video/daala	class org.apache.tika.parser.ogg.OggParser
 video/mp4	class org.apache.tika.parser.mp4.MP4Parser
-video/ogg	class org.gagravarr.tika.OggParser
+video/ogg	class org.apache.tika.parser.ogg.OggParser
 video/quicktime	class org.apache.tika.parser.mp4.MP4Parser
-video/theora	class org.gagravarr.tika.TheoraParser
-video/x-dirac	class org.gagravarr.tika.OggParser
+video/theora	class org.apache.tika.parser.ogg.TheoraParser
+video/x-dirac	class org.apache.tika.parser.ogg.OggParser
 video/x-flv	class org.apache.tika.parser.video.FLVParser
 video/x-m4v	class org.apache.tika.parser.mp4.MP4Parser
-video/x-oggrgb	class org.gagravarr.tika.OggParser
-video/x-ogguvs	class org.gagravarr.tika.OggParser
-video/x-oggyuv	class org.gagravarr.tika.OggParser
-video/x-ogm	class org.gagravarr.tika.OggParser
\ No newline at end of file
+video/x-oggrgb	class org.apache.tika.parser.ogg.OggParser
+video/x-ogguvs	class org.apache.tika.parser.ogg.OggParser
+video/x-oggyuv	class org.apache.tika.parser.ogg.OggParser
+video/x-ogm	class org.apache.tika.parser.ogg.OggParser
\ No newline at end of file
diff --git a/tika-parsers/tika-parsers-extended/tika-parser-sqlite3-module/src/main/java/org/apache/tika/parser/geopkg/GeoPkgParser.java b/tika-parsers/tika-parsers-extended/tika-parser-sqlite3-module/src/main/java/org/apache/tika/parser/geopkg/GeoPkgParser.java
index 65b1b071ad..778f4f6eb0 100644
--- a/tika-parsers/tika-parsers-extended/tika-parser-sqlite3-module/src/main/java/org/apache/tika/parser/geopkg/GeoPkgParser.java
+++ b/tika-parsers/tika-parsers-extended/tika-parser-sqlite3-module/src/main/java/org/apache/tika/parser/geopkg/GeoPkgParser.java
@@ -18,7 +18,6 @@ package org.apache.tika.parser.geopkg;
 
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
@@ -29,6 +28,7 @@ import org.xml.sax.SAXException;
 
 import org.apache.tika.config.TikaComponent;
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 import org.apache.tika.parser.ParseContext;
@@ -95,10 +95,10 @@ public class GeoPkgParser extends SQLite3Parser {
     }
 
     @Override
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
         GeoPkgDBParser p = new GeoPkgDBParser(ignoreBlobColumns);
-        p.parse(stream, handler, metadata, context);
+        p.parse(tis, handler, metadata, context);
     }
 
     public void setIgnoreBlobColumns(List<String> ignoreBlobColumns) {
diff --git a/tika-parsers/tika-parsers-extended/tika-parser-sqlite3-module/src/main/java/org/apache/tika/parser/sqlite3/SQLite3DBParser.java b/tika-parsers/tika-parsers-extended/tika-parser-sqlite3-module/src/main/java/org/apache/tika/parser/sqlite3/SQLite3DBParser.java
index fd8c2e8a43..6cd3999953 100644
--- a/tika-parsers/tika-parsers-extended/tika-parser-sqlite3-module/src/main/java/org/apache/tika/parser/sqlite3/SQLite3DBParser.java
+++ b/tika-parsers/tika-parsers-extended/tika-parser-sqlite3-module/src/main/java/org/apache/tika/parser/sqlite3/SQLite3DBParser.java
@@ -17,10 +17,8 @@
 package org.apache.tika.parser.sqlite3;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.nio.file.StandardCopyOption;
 import java.sql.Connection;
 import java.sql.ResultSet;
 import java.sql.SQLException;
@@ -69,7 +67,7 @@ public class SQLite3DBParser extends AbstractDBParser {
     }
 
     @Override
-    protected Connection getConnection(InputStream stream, Metadata metadata, ParseContext context)
+    protected Connection getConnection(TikaInputStream stream, Metadata metadata, ParseContext context)
             throws IOException {
         String connectionString = getConnectionString(stream, metadata, context);
 
@@ -93,20 +91,10 @@ public class SQLite3DBParser extends AbstractDBParser {
     }
 
     @Override
-    protected String getConnectionString(InputStream is, Metadata metadata, ParseContext context)
+    protected String getConnectionString(TikaInputStream stream, Metadata metadata, ParseContext context)
             throws IOException {
-        TikaInputStream tis = TikaInputStream.cast(is);
-        //if this is a TikaInputStream, use that to spool is to disk or
-        //use original underlying file.
-        if (tis != null) {
-            Path dbFile = tis.getPath();
-            return "jdbc:sqlite:" + dbFile.toAbsolutePath().toString();
-        } else {
-            //if not TikaInputStream, create own tmpResources.
-            tmpFile = Files.createTempFile("tika-sqlite-tmp", "");
-            Files.copy(is, tmpFile, StandardCopyOption.REPLACE_EXISTING);
-            return "jdbc:sqlite:" + tmpFile.toAbsolutePath().toString();
-        }
+        Path dbFile = stream.getPath();
+        return "jdbc:sqlite:" + dbFile.toAbsolutePath();
     }
 
     @Override
diff --git a/tika-parsers/tika-parsers-extended/tika-parser-sqlite3-module/src/main/java/org/apache/tika/parser/sqlite3/SQLite3Parser.java b/tika-parsers/tika-parsers-extended/tika-parser-sqlite3-module/src/main/java/org/apache/tika/parser/sqlite3/SQLite3Parser.java
index e6b19090e2..37df809ffb 100644
--- a/tika-parsers/tika-parsers-extended/tika-parser-sqlite3-module/src/main/java/org/apache/tika/parser/sqlite3/SQLite3Parser.java
+++ b/tika-parsers/tika-parsers-extended/tika-parser-sqlite3-module/src/main/java/org/apache/tika/parser/sqlite3/SQLite3Parser.java
@@ -18,7 +18,6 @@ package org.apache.tika.parser.sqlite3;
 
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.util.Collections;
 import java.util.Set;
 
@@ -27,6 +26,7 @@ import org.xml.sax.SAXException;
 
 import org.apache.tika.config.TikaComponent;
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.Property;
 import org.apache.tika.mime.MediaType;
@@ -94,10 +94,10 @@ public class SQLite3Parser implements Parser {
     }
 
     @Override
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
         SQLite3DBParser p = new SQLite3DBParser();
-        p.parse(stream, handler, metadata, context);
+        p.parse(tis, handler, metadata, context);
     }
 
 }
diff --git a/tika-parsers/tika-parsers-extended/tika-parser-sqlite3-module/src/test/java/org/apache/tika/parser/sqlite3/SQLite3ParserTest.java b/tika-parsers/tika-parsers-extended/tika-parser-sqlite3-module/src/test/java/org/apache/tika/parser/sqlite3/SQLite3ParserTest.java
index 49dfcd0bab..9961b1aaa9 100644
--- a/tika-parsers/tika-parsers-extended/tika-parser-sqlite3-module/src/test/java/org/apache/tika/parser/sqlite3/SQLite3ParserTest.java
+++ b/tika-parsers/tika-parsers-extended/tika-parser-sqlite3-module/src/test/java/org/apache/tika/parser/sqlite3/SQLite3ParserTest.java
@@ -19,12 +19,11 @@ package org.apache.tika.parser.sqlite3;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
-import java.io.InputStream;
-
 import org.junit.jupiter.api.Test;
 import org.xml.sax.ContentHandler;
 
 import org.apache.tika.TikaTest;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
 import org.apache.tika.parser.ParseContext;
@@ -42,8 +41,8 @@ public class SQLite3ParserTest extends TikaTest {
         metadata.set(TikaCoreProperties.RESOURCE_NAME_KEY, TEST_FILE_NAME);
         ContentHandler handler = new BodyContentHandler(-1);
         ParseContext ctx = new ParseContext();
-        try (InputStream stream = getResourceAsStream(TEST_FILE1)) {
-            TikaTest.AUTO_DETECT_PARSER.parse(stream, handler, metadata, ctx);
+        try (TikaInputStream tis = getResourceAsStream(TEST_FILE1)) {
+            TikaTest.AUTO_DETECT_PARSER.parse(tis, handler, metadata, ctx);
         }
         String s = handler.toString();
         TikaTest.assertContains("0\t2.3\t2.4\tlorem", s);
diff --git a/tika-parsers/tika-parsers-extended/tika-parsers-extended-integration-tests/src/test/java/org/apache/tika/mime/TestMimeTypesExtended.java b/tika-parsers/tika-parsers-extended/tika-parsers-extended-integration-tests/src/test/java/org/apache/tika/mime/TestMimeTypesExtended.java
index 943d30e525..b0313bc3da 100644
--- a/tika-parsers/tika-parsers-extended/tika-parsers-extended-integration-tests/src/test/java/org/apache/tika/mime/TestMimeTypesExtended.java
+++ b/tika-parsers/tika-parsers-extended/tika-parsers-extended-integration-tests/src/test/java/org/apache/tika/mime/TestMimeTypesExtended.java
@@ -20,16 +20,16 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 
 import java.io.IOException;
-import java.io.InputStream;
 
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
+import org.apache.tika.TikaTest;
 import org.apache.tika.config.loader.TikaLoader;
 import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 
-public class TestMimeTypesExtended {
+public class TestMimeTypesExtended extends TikaTest {
 
     MimeTypes repo;
 
@@ -44,11 +44,10 @@ public class TestMimeTypesExtended {
     }
 
     private void assertTypeByData(String expected, String filename) throws IOException {
-        try (InputStream stream = TikaInputStream.get(TestMimeTypesExtended.class
-                .getResourceAsStream("/test-documents/" + filename))) {
-            assertNotNull(stream, "Test file not found: " + filename);
+        try (TikaInputStream tis = getResourceAsStream("/test-documents/" + filename)) {
+            assertNotNull(tis, "Test file not found: " + filename);
             Metadata metadata = new Metadata();
-            assertEquals(expected, repo.detect(stream, metadata).toString());
+            assertEquals(expected, repo.detect(tis, metadata).toString());
         }
     }
 }
diff --git a/tika-parsers/tika-parsers-extended/tika-parsers-extended-integration-tests/src/test/java/org/apache/tika/parser/sqlite3/SQLite3ParserTest.java b/tika-parsers/tika-parsers-extended/tika-parsers-extended-integration-tests/src/test/java/org/apache/tika/parser/sqlite3/SQLite3ParserTest.java
index 65e752bc1f..9a53c85b2b 100644
--- a/tika-parsers/tika-parsers-extended/tika-parsers-extended-integration-tests/src/test/java/org/apache/tika/parser/sqlite3/SQLite3ParserTest.java
+++ b/tika-parsers/tika-parsers-extended/tika-parsers-extended-integration-tests/src/test/java/org/apache/tika/parser/sqlite3/SQLite3ParserTest.java
@@ -19,7 +19,6 @@ package org.apache.tika.parser.sqlite3;
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
-import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -56,15 +55,15 @@ public class SQLite3ParserTest extends TikaTest {
 
         //test different types of input streams
         //actual inputstream, memory buffered bytearray and literal file
-        try (InputStream stream = getResourceAsStream(TEST_FILE1)) {
-            _testBasic(stream);
+        try (TikaInputStream tis = getResourceAsStream(TEST_FILE1)) {
+            _testBasic(tis);
         }
 
-        try (InputStream is = getResourceAsStream(TEST_FILE1);
+        try (TikaInputStream tis = getResourceAsStream(TEST_FILE1);
                 ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
-            IOUtils.copy(is, bos);
-            try (InputStream stream = new ByteArrayInputStream(bos.toByteArray())) {
-                _testBasic(stream);
+            IOUtils.copy(tis, bos);
+            try (TikaInputStream innerTis = TikaInputStream.get(bos.toByteArray())) {
+                _testBasic(innerTis);
             }
         }
         try (TikaInputStream outer = TikaInputStream.get(getResourceAsStream(TEST_FILE1))) {
@@ -74,12 +73,12 @@ public class SQLite3ParserTest extends TikaTest {
         }
     }
 
-    private void _testBasic(InputStream stream) throws Exception {
+    private void _testBasic(TikaInputStream tis) throws Exception {
         Metadata metadata = new Metadata();
         metadata.set(TikaCoreProperties.RESOURCE_NAME_KEY, TEST_FILE_NAME);
         //1) getXML closes the stream
         //2) getXML runs recursively on the contents, so the embedded docs should show up
-        XMLResult result = getXML(stream, AUTO_DETECT_PARSER, metadata);
+        XMLResult result = getXML(tis, AUTO_DETECT_PARSER, metadata);
         String x = result.xml;
         //first table name
         assertContains("<table name=\"my_table1\"><thead><tr>\t<th>PK</th>", x);
@@ -112,9 +111,9 @@ public class SQLite3ParserTest extends TikaTest {
         Metadata metadata = new Metadata();
         ParseContext parseContext = new ParseContext();
         parseContext.set(Parser.class, new EmptyParser());
-        try (InputStream is = getResourceAsStream(TEST_FILE1)) {
+        try (TikaInputStream tis = getResourceAsStream(TEST_FILE1)) {
             metadata.set(TikaCoreProperties.RESOURCE_NAME_KEY, TEST_FILE_NAME);
-            AUTO_DETECT_PARSER.parse(is, handler, metadata, parseContext);
+            AUTO_DETECT_PARSER.parse(tis, handler, metadata, parseContext);
         }
         String xml = handler.toString();
         //just includes headers for embedded documents
@@ -138,9 +137,9 @@ public class SQLite3ParserTest extends TikaTest {
         RecursiveParserWrapperHandler handler = new RecursiveParserWrapperHandler(
                 new BasicContentHandlerFactory(BasicContentHandlerFactory.HANDLER_TYPE.BODY, -1));
 
-        try (InputStream is = getResourceAsStream(TEST_FILE1)) {
+        try (TikaInputStream tis = getResourceAsStream(TEST_FILE1)) {
             metadata.set(TikaCoreProperties.RESOURCE_NAME_KEY, TEST_FILE_NAME);
-            wrapper.parse(is, handler, metadata, new ParseContext());
+            wrapper.parse(tis, handler, metadata, new ParseContext());
         }
         List<Metadata> metadataList = handler.getMetadataList();
         assertEquals(5, metadataList.size());
@@ -174,9 +173,9 @@ public class SQLite3ParserTest extends TikaTest {
         ParserContainerExtractor ex = new ParserContainerExtractor();
         ByteCopyingHandler byteCopier = new ByteCopyingHandler();
         Metadata metadata = new Metadata();
-        try (TikaInputStream is = TikaInputStream.get(getResourceAsStream(TEST_FILE1))) {
+        try (TikaInputStream tis = TikaInputStream.get(getResourceAsStream(TEST_FILE1))) {
             metadata.set(TikaCoreProperties.RESOURCE_NAME_KEY, TEST_FILE_NAME);
-            ex.extract(is, ex, byteCopier);
+            ex.extract(tis, ex, byteCopier);
         }
         assertEquals(4, byteCopier.bytes.size());
         String[] strings = new String[4];
diff --git a/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/ctakes/CTAKESParser.java b/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/ctakes/CTAKESParser.java
index 4f634f6cb4..b7ea07d0a0 100644
--- a/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/ctakes/CTAKESParser.java
+++ b/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/ctakes/CTAKESParser.java
@@ -17,13 +17,13 @@
 package org.apache.tika.parser.ctakes;
 
 import java.io.IOException;
-import java.io.InputStream;
 
 import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
 
 import org.apache.tika.config.loader.TikaLoader;
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.parser.AutoDetectParser;
 import org.apache.tika.parser.ParseContext;
@@ -79,11 +79,11 @@ public class CTAKESParser extends ParserDecorator {
     }
 
     @Override
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
         CTAKESConfig config = context.get(CTAKESConfig.class, new CTAKESConfig());
         CTAKESContentHandler ctakesHandler = new CTAKESContentHandler(handler, metadata, config);
-        super.parse(stream, ctakesHandler, metadata, context);
+        super.parse(tis, ctakesHandler, metadata, context);
     }
 
     //@Override
diff --git a/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/geo/topic/GeoParser.java b/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/geo/topic/GeoParser.java
index 88bb1be6d7..a797601e2a 100644
--- a/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/geo/topic/GeoParser.java
+++ b/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/geo/topic/GeoParser.java
@@ -17,7 +17,6 @@
 package org.apache.tika.parser.geo.topic;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.net.MalformedURLException;
 import java.net.URISyntaxException;
 import java.net.URL;
@@ -36,6 +35,7 @@ import org.xml.sax.SAXException;
 
 import org.apache.tika.config.TikaComponent;
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 import org.apache.tika.parser.ParseContext;
@@ -97,7 +97,7 @@ public class GeoParser implements Parser {
     }
 
     @Override
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
 
         /*----------------configure this parser by ParseContext Object---------------------*/
@@ -118,7 +118,7 @@ public class GeoParser implements Parser {
 
         /*----------------get locationNameEntities and best nameEntity for the
         input stream---------------------*/
-        extractor.getAllNameEntitiesfromInput(stream);
+        extractor.getAllNameEntitiesfromInput(tis);
         extractor.getBestNameEntity();
         ArrayList<String> locationNameEntities = extractor.locationNameEntities;
         String bestner = extractor.bestNameEntity;
diff --git a/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/journal/JournalParser.java b/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/journal/JournalParser.java
index 2116d566ae..a96ccf8646 100644
--- a/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/journal/JournalParser.java
+++ b/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/journal/JournalParser.java
@@ -17,9 +17,7 @@
 package org.apache.tika.parser.journal;
 
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
-import java.io.InputStream;
 import java.util.Collections;
 import java.util.Set;
 
@@ -28,7 +26,6 @@ import org.xml.sax.SAXException;
 
 import org.apache.tika.config.TikaComponent;
 import org.apache.tika.exception.TikaException;
-import org.apache.tika.io.TemporaryResources;
 import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
@@ -52,15 +49,14 @@ public class JournalParser implements Parser {
         return SUPPORTED_TYPES;
     }
 
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
-        TikaInputStream tis = TikaInputStream.get(stream, new TemporaryResources(), metadata);
         File tmpFile = tis.getFile();
 
         GrobidRESTParser grobidParser = new GrobidRESTParser();
         grobidParser.parse(tmpFile.getAbsolutePath(), handler, metadata, context);
 
-        try (InputStream pdfStream = new FileInputStream(tmpFile)) {
+        try (TikaInputStream pdfStream = TikaInputStream.get(tmpFile)) {
             PDFParser parser = new PDFParser();
             parser.parse(pdfStream, handler, metadata, context);
         }
diff --git a/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/ner/NamedEntityParser.java b/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/ner/NamedEntityParser.java
index 27ac83da8f..5f951eba7f 100644
--- a/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/ner/NamedEntityParser.java
+++ b/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/ner/NamedEntityParser.java
@@ -17,7 +17,6 @@
 package org.apache.tika.parser.ner;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
 import java.nio.charset.StandardCharsets;
@@ -36,6 +35,7 @@ import org.xml.sax.SAXException;
 import org.apache.tika.Tika;
 import org.apache.tika.config.loader.TikaLoader;
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 import org.apache.tika.parser.ParseContext;
@@ -112,7 +112,7 @@ public class NamedEntityParser implements Parser {
         return MEDIA_TYPES;
     }
 
-    public void parse(InputStream inputStream, ContentHandler contentHandler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler contentHandler, Metadata metadata,
                       ParseContext parseContext) throws IOException, SAXException, TikaException {
 
         if (!initialized) {
@@ -124,8 +124,8 @@ public class NamedEntityParser implements Parser {
 
         Reader reader =
                 MediaType.TEXT_PLAIN.toString().equals(metadata.get(Metadata.CONTENT_TYPE)) ?
-                        new InputStreamReader(inputStream, StandardCharsets.UTF_8) :
-                        secondaryParser.parse(inputStream);
+                        new InputStreamReader(tis, StandardCharsets.UTF_8) :
+                        secondaryParser.parse(tis);
 
         String text = IOUtils.toString(reader);
         IOUtils.closeQuietly(reader);
diff --git a/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/sentiment/SentimentAnalysisParser.java b/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/sentiment/SentimentAnalysisParser.java
index 712d92a7ad..16a4b81ab9 100644
--- a/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/sentiment/SentimentAnalysisParser.java
+++ b/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/sentiment/SentimentAnalysisParser.java
@@ -18,7 +18,6 @@ package org.apache.tika.parser.sentiment;
 
 import java.io.File;
 import java.io.IOException;
-import java.io.InputStream;
 import java.net.URL;
 import java.util.Collections;
 import java.util.Set;
@@ -35,6 +34,7 @@ import org.apache.tika.config.Initializable;
 import org.apache.tika.config.TikaComponent;
 import org.apache.tika.exception.TikaConfigException;
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 import org.apache.tika.parser.ParseContext;
@@ -124,13 +124,13 @@ public class SentimentAnalysisParser implements Parser, Initializable {
      * @param context  the context for the parser
      */
     @Override
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
         if (classifier == null) {
             LOG.warn(getClass().getSimpleName() + " is not configured properly.");
             return;
         }
-        String inputString = IOUtils.toString(stream, "UTF-8");
+        String inputString = IOUtils.toString(tis, "UTF-8");
         String sentiment = classifier.predict(inputString);
         metadata.add("Sentiment", sentiment);
     }
diff --git a/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/test/java/org/apache/tika/parser/geo/topic/GeoParserTest.java b/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/test/java/org/apache/tika/parser/geo/topic/GeoParserTest.java
index 3e9201fcd3..938e6f7cde 100644
--- a/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/test/java/org/apache/tika/parser/geo/topic/GeoParserTest.java
+++ b/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/test/java/org/apache/tika/parser/geo/topic/GeoParserTest.java
@@ -21,9 +21,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNull;
 
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
-import java.io.InputStream;
 import java.net.URI;
 
 import org.junit.jupiter.api.Test;
@@ -32,6 +30,7 @@ import org.xml.sax.SAXException;
 import org.apache.tika.TikaTest;
 import org.apache.tika.config.loader.TikaLoader;
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.parser.ParseContext;
 import org.apache.tika.parser.Parser;
@@ -65,13 +64,14 @@ public class GeoParserTest extends TikaTest {
         GeoParserConfig config = new GeoParserConfig();
         context.set(GeoParserConfig.class, config);
 
-        InputStream s = new ByteArrayInputStream(text.getBytes(UTF_8));
         /* if it's not available no tests to run */
         if (!((GeoParser) geoparser).isAvailable(config)) {
             return;
         }
 
-        geoparser.parse(s, new BodyContentHandler(), metadata, context);
+        try (TikaInputStream tis = TikaInputStream.get(text.getBytes(UTF_8))) {
+            geoparser.parse(tis, new BodyContentHandler(), metadata, context);
+        }
 
         assertNotNull(metadata.get("Geographic_NAME"));
         assertNotNull(metadata.get("Geographic_LONGITUDE"));
@@ -93,8 +93,9 @@ public class GeoParserTest extends TikaTest {
         ParseContext context = new ParseContext();
         GeoParserConfig config = new GeoParserConfig();
         context.set(GeoParserConfig.class, config);
-        geoparser.parse(new ByteArrayInputStream(text.getBytes(UTF_8)), new BodyContentHandler(),
-                metadata, context);
+        try (TikaInputStream tis = TikaInputStream.get(text.getBytes(UTF_8))) {
+            geoparser.parse(tis, new BodyContentHandler(), metadata, context);
+        }
         assertNull(metadata.get("Geographic_NAME"));
         assertNull(metadata.get("Geographic_LONGITUDE"));
         assertNull(metadata.get("Geographic_LATITUDE"));
diff --git a/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/test/java/org/apache/tika/parser/journal/JournalParserTest.java b/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/test/java/org/apache/tika/parser/journal/JournalParserTest.java
index 72488170ad..6faa2a705b 100644
--- a/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/test/java/org/apache/tika/parser/journal/JournalParserTest.java
+++ b/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/test/java/org/apache/tika/parser/journal/JournalParserTest.java
@@ -21,11 +21,10 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.fail;
 import static org.junit.jupiter.api.Assumptions.assumeTrue;
 
-import java.io.InputStream;
-
 import org.junit.jupiter.api.Test;
 import org.xml.sax.ContentHandler;
 
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.parser.ParseContext;
 import org.apache.tika.sax.BodyContentHandler;
@@ -40,10 +39,10 @@ public class JournalParserTest {
 
         assumeTrue(canRun());
 
-        InputStream stream = JournalParserTest.class.getResourceAsStream(path);
+        TikaInputStream tis = TikaInputStream.get(JournalParserTest.class.getResourceAsStream(path));
         JournalParser jParser = new JournalParser();
         try {
-            jParser.parse(stream, handler, metadata, new ParseContext());
+            jParser.parse(tis, handler, metadata, new ParseContext());
         } catch (Exception e) {
             e.printStackTrace();
             fail(e.getMessage());
diff --git a/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/test/java/org/apache/tika/parser/journal/TEITest.java b/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/test/java/org/apache/tika/parser/journal/TEITest.java
index 3190e7e829..f3b392a488 100644
--- a/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/test/java/org/apache/tika/parser/journal/TEITest.java
+++ b/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/test/java/org/apache/tika/parser/journal/TEITest.java
@@ -20,13 +20,13 @@ import static org.junit.jupiter.api.Assertions.assertArrayEquals;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
 
 import org.apache.commons.io.IOUtils;
 import org.junit.jupiter.api.Test;
 
 import org.apache.tika.TikaTest;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.parser.ParseContext;
 
@@ -37,8 +37,8 @@ public class TEITest extends TikaTest {
     public void testBasic() throws Exception {
         TEIDOMParser teiParser = new TEIDOMParser();
         ByteArrayOutputStream bos = new ByteArrayOutputStream();
-        try (InputStream is = getResourceAsStream("/test-documents/testTEI.xml")) {
-            IOUtils.copy(is, bos);
+        try (TikaInputStream tis = getResourceAsStream("/test-documents/testTEI.xml")) {
+            IOUtils.copy(tis, bos);
         }
         String xml = new String(bos.toByteArray(), StandardCharsets.UTF_8);
         Metadata metadata = teiParser.parse(xml, new ParseContext());
diff --git a/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/test/java/org/apache/tika/parser/ner/NamedEntityParserTest.java b/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/test/java/org/apache/tika/parser/ner/NamedEntityParserTest.java
index 02a9249328..79ae0d5fcc 100644
--- a/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/test/java/org/apache/tika/parser/ner/NamedEntityParserTest.java
+++ b/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/test/java/org/apache/tika/parser/ner/NamedEntityParserTest.java
@@ -19,16 +19,15 @@ package org.apache.tika.parser.ner;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.api.Assumptions.assumeTrue;
 
-import java.io.ByteArrayInputStream;
 import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
 import java.util.HashSet;
 
-import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
 import org.junit.jupiter.api.Test;
 
 import org.apache.tika.TikaTest;
 import org.apache.tika.config.loader.TikaLoader;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
 import org.apache.tika.parser.Parser;
@@ -52,7 +51,7 @@ public class NamedEntityParserTest extends TikaTest {
                 " located in Los Angeles . USC's football team is called by name Trojans." +
                 " Mr. John McKay was a head coach of the team from 1960 - 1975";
         Metadata md = getXML(
-                new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8)),
+                TikaInputStream.get(text.getBytes(StandardCharsets.UTF_8)),
                 parser, new Metadata()).metadata;
 
         HashSet<String> set = new HashSet<>(
@@ -87,7 +86,7 @@ public class NamedEntityParserTest extends TikaTest {
         String text = "University of Southern California (USC), is located in Los Angeles ." +
                 " Campus is busy from monday to saturday";
         Metadata md = getXML(
-                UnsynchronizedByteArrayInputStream.builder().setByteArray(text.getBytes(StandardCharsets.UTF_8)).get(),
+                TikaInputStream.get(text.getBytes(StandardCharsets.UTF_8)),
                 parser, new Metadata()).metadata;
         HashSet<String> keys = new HashSet<>(Arrays.asList(md.names()));
         assertTrue(keys.contains("NER_WEEK_DAY"));
diff --git a/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/test/java/org/apache/tika/parser/ner/nltk/NLTKNERecogniserTest.java b/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/test/java/org/apache/tika/parser/ner/nltk/NLTKNERecogniserTest.java
index c931c26764..a565d06cf4 100644
--- a/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/test/java/org/apache/tika/parser/ner/nltk/NLTKNERecogniserTest.java
+++ b/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/test/java/org/apache/tika/parser/ner/nltk/NLTKNERecogniserTest.java
@@ -18,7 +18,6 @@ package org.apache.tika.parser.ner.nltk;
 
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
-import java.io.ByteArrayInputStream;
 import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
 import java.util.HashSet;
@@ -28,6 +27,7 @@ import org.junit.jupiter.api.Test;
 
 import org.apache.tika.TikaTest;
 import org.apache.tika.config.loader.TikaLoader;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.parser.Parser;
 import org.apache.tika.parser.ner.NamedEntityParser;
@@ -43,7 +43,7 @@ public class NLTKNERecogniserTest extends TikaTest {
                         getConfigPath(NLTKNERecogniserTest.class, "tika-config.json"))
                 .loadAutoDetectParser();
         Metadata md = getXML(
-                new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8)),
+                TikaInputStream.get(text.getBytes(StandardCharsets.UTF_8)),
                 parser, new Metadata()).metadata;
 
         Set<String> names = new HashSet<>(Arrays.asList(md.getValues("NER_NAMES")));
diff --git a/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/test/java/org/apache/tika/parser/ner/regex/RegexNERecogniserTest.java b/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/test/java/org/apache/tika/parser/ner/regex/RegexNERecogniserTest.java
index 0daf8ac85d..0a9dd7b05c 100644
--- a/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/test/java/org/apache/tika/parser/ner/regex/RegexNERecogniserTest.java
+++ b/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/test/java/org/apache/tika/parser/ner/regex/RegexNERecogniserTest.java
@@ -18,7 +18,6 @@ package org.apache.tika.parser.ner.regex;
 
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
-import java.io.ByteArrayInputStream;
 import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
 import java.util.HashSet;
@@ -28,6 +27,7 @@ import org.junit.jupiter.api.Test;
 
 import org.apache.tika.TikaTest;
 import org.apache.tika.config.loader.TikaLoader;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.parser.Parser;
 import org.apache.tika.parser.ner.NamedEntityParser;
@@ -44,7 +44,7 @@ public class RegexNERecogniserTest extends TikaTest {
                         getConfigPath(RegexNERecogniserTest.class, "tika-config.json"))
                 .loadAutoDetectParser();
         Metadata md = getXML(
-                new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8)),
+                TikaInputStream.get(text.getBytes(StandardCharsets.UTF_8)),
                 parser, new Metadata()).metadata;
 
         Set<String> days = new HashSet<>(Arrays.asList(md.getValues("NER_WEEK_DAY")));
diff --git a/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/test/java/org/apache/tika/parser/sentiment/SentimentAnalysisParserTest.java b/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/test/java/org/apache/tika/parser/sentiment/SentimentAnalysisParserTest.java
index d9b4a6677a..8380bcc819 100644
--- a/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/test/java/org/apache/tika/parser/sentiment/SentimentAnalysisParserTest.java
+++ b/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/test/java/org/apache/tika/parser/sentiment/SentimentAnalysisParserTest.java
@@ -19,7 +19,6 @@ package org.apache.tika.parser.sentiment;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.net.URISyntaxException;
 import java.nio.charset.StandardCharsets;
@@ -30,6 +29,7 @@ import org.apache.tika.TikaTest;
 import org.apache.tika.config.loader.TikaLoader;
 import org.apache.tika.exception.TikaConfigException;
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.parser.Parser;
 
@@ -47,9 +47,8 @@ public class SentimentAnalysisParserTest extends TikaTest {
 
         String text = "What a wonderful thought it is that" +
                 " some of the best days of our lives haven't happened yet.";
-        ByteArrayInputStream stream =
-                new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8));
-        Metadata md = getXML(stream, parser, new Metadata()).metadata;
+        Metadata md = getXML(TikaInputStream.get(text.getBytes(StandardCharsets.UTF_8)),
+                parser, new Metadata()).metadata;
         String sentiment = md.get("Sentiment");
         assertNotNull(sentiment);
         assertEquals("positive", sentiment);
@@ -62,9 +61,8 @@ public class SentimentAnalysisParserTest extends TikaTest {
             return;
         }
         String text = "Whatever, I need some cooling off time!";
-        ByteArrayInputStream stream =
-                new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8));
-        Metadata md = getXML(stream, parser, new Metadata()).metadata;
+        Metadata md = getXML(TikaInputStream.get(text.getBytes(StandardCharsets.UTF_8)),
+                parser, new Metadata()).metadata;
         String sentiment = md.get("Sentiment");
         assertNotNull(sentiment);
         assertEquals("angry", sentiment);
diff --git a/tika-parsers/tika-parsers-ml/tika-transcribe-aws/src/main/java/org/apache/tika/parser/transcribe/aws/AmazonTranscribe.java b/tika-parsers/tika-parsers-ml/tika-transcribe-aws/src/main/java/org/apache/tika/parser/transcribe/aws/AmazonTranscribe.java
index 1d0e650a32..b741fb6b86 100644
--- a/tika-parsers/tika-parsers-ml/tika-transcribe-aws/src/main/java/org/apache/tika/parser/transcribe/aws/AmazonTranscribe.java
+++ b/tika-parsers/tika-parsers-ml/tika-transcribe-aws/src/main/java/org/apache/tika/parser/transcribe/aws/AmazonTranscribe.java
@@ -65,6 +65,7 @@ import org.apache.tika.config.Initializable;
 import org.apache.tika.config.TikaComponent;
 import org.apache.tika.exception.TikaConfigException;
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 import org.apache.tika.parser.ParseContext;
@@ -115,7 +116,7 @@ public class AmazonTranscribe implements Parser, Initializable {
     /**
      * Starts AWS Transcribe Job with language specification.
      *
-     * @param stream   the source input stream.
+     * @param stream   the source input tis.
      * @param handler  handler to use
      * @param metadata
      * @param context  -- set the {@link LanguageCode} in the ParseContext if known
@@ -126,7 +127,7 @@ public class AmazonTranscribe implements Parser, Initializable {
      * Language Code</a>
      */
     @Override
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
 
         if (!isAvailable) {
@@ -138,7 +139,7 @@ public class AmazonTranscribe implements Parser, Initializable {
         }
         String jobName = getJobKey();
         LanguageCode languageCode = context.get(LanguageCode.class);
-        uploadFileToBucket(stream, jobName);
+        uploadFileToBucket(tis, jobName);
         StartTranscriptionJobRequest startTranscriptionJobRequest =
                 StartTranscriptionJobRequest.builder()
                         .build();
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/detect/apple/BPListDetector.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/detect/apple/BPListDetector.java
index 35244435f1..6bfe007cfc 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/detect/apple/BPListDetector.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/detect/apple/BPListDetector.java
@@ -17,7 +17,6 @@
 package org.apache.tika.detect.apple;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.text.ParseException;
 import java.util.HashMap;
 import java.util.Map;
@@ -91,28 +90,28 @@ public class BPListDetector implements Detector {
     }
 
     /**
-     * @param input    input stream must support reset
+     * @param tis      input stream must support reset
      * @param metadata input metadata for the document
      * @return
      * @throws IOException
      */
     @Override
-    public MediaType detect(InputStream input, Metadata metadata) throws IOException {
-        if (input == null) {
+    public MediaType detect(TikaInputStream tis, Metadata metadata) throws IOException {
+        if (tis == null) {
             return MediaType.OCTET_STREAM;
         }
-        input.mark(8);
+        tis.mark(8);
         byte[] bytes = new byte[8];
 
         try {
-            int read = IOUtils.read(input, bytes);
+            int read = IOUtils.read(tis, bytes);
             if (read < 6) {
                 return MediaType.OCTET_STREAM;
             }
         } catch (IOException e) {
             return MediaType.OCTET_STREAM;
         } finally {
-            input.reset();
+            tis.reset();
         }
 
         int i = 0;
@@ -123,14 +122,12 @@ public class BPListDetector implements Detector {
         //TODO: extract the version with the next two bytes if they were read
         NSObject rootObj = null;
         try {
-            if (input instanceof TikaInputStream && ((TikaInputStream) input).hasFile()) {
-                rootObj = PropertyListParser.parse(((TikaInputStream) input).getFile());
+            if (tis.hasFile()) {
+                rootObj = PropertyListParser.parse(tis.getFile());
             } else {
-                rootObj = PropertyListParser.parse(input);
-            }
-            if (input instanceof TikaInputStream) {
-                ((TikaInputStream) input).setOpenContainer(rootObj);
+                rootObj = PropertyListParser.parse(tis);
             }
+            tis.setOpenContainer(rootObj);
         } catch (PropertyListFormatException | ParseException |
                 ParserConfigurationException | SAXException e) {
             throw new IOException("problem parsing root", e);
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/apple/AppleSingleFileParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/apple/AppleSingleFileParser.java
index 87b1b8b6e7..008d19f64b 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/apple/AppleSingleFileParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/apple/AppleSingleFileParser.java
@@ -35,7 +35,6 @@ import org.apache.tika.exception.TikaMemoryLimitException;
 import org.apache.tika.extractor.EmbeddedDocumentExtractor;
 import org.apache.tika.extractor.EmbeddedDocumentUtil;
 import org.apache.tika.io.EndianUtils;
-import org.apache.tika.io.TemporaryResources;
 import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
@@ -81,40 +80,28 @@ public class AppleSingleFileParser implements Parser {
     }
 
     @Override
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
 
         EmbeddedDocumentExtractor ex = EmbeddedDocumentUtil.getEmbeddedDocumentExtractor(context);
 
-        short numEntries = readThroughNumEntries(stream);
+        short numEntries = readThroughNumEntries(tis);
         long bytesRead = 26;
-        List<FieldInfo> fieldInfoList = getSortedFieldInfoList(stream, numEntries);
+        List<FieldInfo> fieldInfoList = getSortedFieldInfoList(tis, numEntries);
         bytesRead += 12 * numEntries;
         Metadata embeddedMetadata = new Metadata();
-        bytesRead = processFieldEntries(stream, fieldInfoList, embeddedMetadata, bytesRead);
+        bytesRead = processFieldEntries(tis, fieldInfoList, embeddedMetadata, bytesRead);
         FieldInfo contentFieldInfo = getContentFieldInfo(fieldInfoList);
         XHTMLContentHandler xhtml = new XHTMLContentHandler(handler, metadata);
         xhtml.startDocument();
         if (contentFieldInfo != null) {
             long diff = contentFieldInfo.offset - bytesRead;
-            IOUtils.skipFully(stream, diff);
+            IOUtils.skipFully(tis, diff);
             if (ex.shouldParseEmbedded(embeddedMetadata)) {
                 // TODO: we should probably add a readlimiting wrapper around this
                 // stream to ensure that not more than contentFieldInfo.length bytes
                 // are read
-                TikaInputStream tis = TikaInputStream.cast(stream);
-                TemporaryResources tmp = null;
-                if (tis == null) {
-                    tmp = new TemporaryResources();
-                    tis = TikaInputStream.get(stream, tmp, embeddedMetadata);
-                }
-                try {
-                    ex.parseEmbedded(tis, xhtml, embeddedMetadata, true);
-                } finally {
-                    if (tmp != null) {
-                        tmp.close();
-                    }
-                }
+                ex.parseEmbedded(tis, xhtml, embeddedMetadata, true);
             }
         }
         xhtml.endDocument();
@@ -130,27 +117,27 @@ public class AppleSingleFileParser implements Parser {
         return null;
     }
 
-    private long processFieldEntries(InputStream stream, List<FieldInfo> fieldInfoList,
+    private long processFieldEntries(InputStream tis, List<FieldInfo> fieldInfoList,
                                      Metadata embeddedMetadata, long bytesRead)
             throws IOException, TikaException {
         byte[] buffer = null;
         for (FieldInfo f : fieldInfoList) {
             long diff = f.offset - bytesRead;
             //just in case
-            IOUtils.skipFully(stream, diff);
+            IOUtils.skipFully(tis, diff);
             bytesRead += diff;
             if (f.entryId == REAL_NAME) {
                 if (f.length > MAX_FIELD_LENGTH) {
                     throw new TikaMemoryLimitException(f.length, MAX_FIELD_LENGTH);
                 }
                 buffer = new byte[(int) f.length];
-                IOUtils.readFully(stream, buffer);
+                IOUtils.readFully(tis, buffer);
                 bytesRead += f.length;
                 String originalFileName =
                         new String(buffer, 0, buffer.length, StandardCharsets.US_ASCII);
                 embeddedMetadata.set(TikaCoreProperties.ORIGINAL_RESOURCE_NAME, originalFileName);
             } else if (f.entryId != DATA_FORK) {
-                IOUtils.skipFully(stream, f.length);
+                IOUtils.skipFully(tis, f.length);
                 bytesRead += f.length;
             }
         }
@@ -158,16 +145,16 @@ public class AppleSingleFileParser implements Parser {
     }
 
 
-    private List<FieldInfo> getSortedFieldInfoList(InputStream stream, short numEntries)
+    private List<FieldInfo> getSortedFieldInfoList(InputStream tis, short numEntries)
             throws IOException, TikaException {
         //this is probably overkill.  I'd hope that these were already
         //in order.  This ensures it.
         List<FieldInfo> fieldInfoList = new ArrayList<>(numEntries);
         for (int i = 0; i < numEntries; i++) {
             //convert 32-bit unsigned ints to longs
-            fieldInfoList.add(new FieldInfo(EndianUtils.readUIntBE(stream), //entry id
-                    EndianUtils.readUIntBE(stream), //offset
-                    EndianUtils.readUIntBE(stream) //length
+            fieldInfoList.add(new FieldInfo(EndianUtils.readUIntBE(tis), //entry id
+                    EndianUtils.readUIntBE(tis), //offset
+                    EndianUtils.readUIntBE(tis) //length
             ));
         }
         if (fieldInfoList.size() == 0) {
@@ -179,16 +166,16 @@ public class AppleSingleFileParser implements Parser {
     }
 
     //read through header until you hit the number of entries
-    private short readThroughNumEntries(InputStream stream) throws TikaException, IOException {
+    private short readThroughNumEntries(InputStream tis) throws TikaException, IOException {
         //mime
-        EndianUtils.readIntBE(stream);
+        EndianUtils.readIntBE(tis);
         //version
-        long version = EndianUtils.readIntBE(stream);
+        long version = EndianUtils.readIntBE(tis);
         if (version != 0x00020000) {
             throw new TikaException("Version should have been 0x00020000, but was:" + version);
         }
-        IOUtils.skipFully(stream, 16);//filler
-        return EndianUtils.readShortBE(stream);//number of entries
+        IOUtils.skipFully(tis, 16);//filler
+        return EndianUtils.readShortBE(tis);//number of entries
     }
 
     private static class FieldInfo {
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/apple/PListParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/apple/PListParser.java
index 66ff971bd8..b60eca34a0 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/apple/PListParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/apple/PListParser.java
@@ -17,7 +17,6 @@
 package org.apache.tika.parser.apple;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.text.DateFormat;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
@@ -89,7 +88,7 @@ public class PListParser implements Parser {
     }
 
     @Override
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
 
         EmbeddedDocumentExtractor embeddedDocumentExtractor =
@@ -98,16 +97,14 @@ public class PListParser implements Parser {
         NSObject rootObj = null;
         //if this already went through the PListDetector,
         //there should be an NSObject in the open container
-        if (stream instanceof TikaInputStream) {
-            rootObj = (NSObject) ((TikaInputStream) stream).getOpenContainer();
-        }
+        rootObj = (NSObject) tis.getOpenContainer();
 
         if (rootObj == null) {
             try {
-                if (stream instanceof TikaInputStream && ((TikaInputStream) stream).hasFile()) {
-                    rootObj = PropertyListParser.parse(((TikaInputStream) stream).getFile());
+                if (tis.hasFile()) {
+                    rootObj = PropertyListParser.parse(tis.getFile());
                 } else {
-                    rootObj = PropertyListParser.parse(stream);
+                    rootObj = PropertyListParser.parse(tis);
                 }
             } catch (PropertyListFormatException | ParseException |
                     ParserConfigurationException e) {
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/iwork/IWorkPackageParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/iwork/IWorkPackageParser.java
index 8af51bce97..1591ad2fb2 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/iwork/IWorkPackageParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/iwork/IWorkPackageParser.java
@@ -38,6 +38,7 @@ import org.xml.sax.SAXException;
 import org.apache.tika.config.TikaComponent;
 import org.apache.tika.detect.XmlRootExtractor;
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 import org.apache.tika.parser.ParseContext;
@@ -85,9 +86,9 @@ public class IWorkPackageParser implements Parser {
         return supportedTypes;
     }
 
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
-        ZipArchiveInputStream zip = new ZipArchiveInputStream(stream);
+        ZipArchiveInputStream zip = new ZipArchiveInputStream(tis);
         ZipArchiveEntry entry = zip.getNextEntry();
 
         while (entry != null) {
@@ -198,8 +199,8 @@ public class IWorkPackageParser implements Parser {
             return detectType(zip);
         }
 
-        public static IWORKDocumentType detectType(InputStream stream) {
-            QName qname = new XmlRootExtractor().extractRootElement(stream);
+        public static IWORKDocumentType detectType(InputStream tis) {
+            QName qname = new XmlRootExtractor().extractRootElement(tis);
             if (qname != null) {
                 String uri = qname.getNamespaceURI();
                 String local = qname.getLocalPart();
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/iwork/iwana/IWork13PackageParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/iwork/iwana/IWork13PackageParser.java
index 93b695dca2..42fa211220 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/iwork/iwana/IWork13PackageParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/iwork/iwana/IWork13PackageParser.java
@@ -80,24 +80,19 @@ public class IWork13PackageParser implements Parser {
     }
 
     @Override
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
         // Open the Zip stream
         // Use a File if we can, and an already open zip is even better
         ZipFile zipFile = null;
         ZipInputStream zipStream = null;
-        if (stream instanceof TikaInputStream) {
-            TikaInputStream tis = (TikaInputStream) stream;
-            Object container = ((TikaInputStream) stream).getOpenContainer();
-            if (container instanceof ZipFile) {
-                zipFile = (ZipFile) container;
-            } else if (tis.hasFile()) {
-                zipFile = ZipFile.builder().setFile(tis.getFile()).get();
-            } else {
-                zipStream = new ZipInputStream(stream);
-            }
+        Object container = tis.getOpenContainer();
+        if (container instanceof ZipFile) {
+            zipFile = (ZipFile) container;
+        } else if (tis.hasFile()) {
+            zipFile = ZipFile.builder().setFile(tis.getFile()).get();
         } else {
-            zipStream = new ZipInputStream(stream);
+            zipStream = new ZipInputStream(tis);
         }
         XHTMLContentHandler xhtml = new XHTMLContentHandler(handler, metadata);
         xhtml.startDocument();
@@ -321,7 +316,7 @@ public class IWork13PackageParser implements Parser {
 
             // Is it the main document?
             if (name.equals(IWORK13_MAIN_ENTRY)) {
-                // TODO Decode the snappy stream, and check for the Message Type
+                // TODO Decode the snappy tis, and check for the Message Type
                 // =     2 (TN::SheetArchive), it is a numbers file;
                 // = 10000 (TP::DocumentArchive), that's a pages file
                 return null;
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/iwork/iwana/IWork18PackageParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/iwork/iwana/IWork18PackageParser.java
index 09974773bc..de6aff0296 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/iwork/iwana/IWork18PackageParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/main/java/org/apache/tika/parser/iwork/iwana/IWork18PackageParser.java
@@ -17,7 +17,6 @@
 package org.apache.tika.parser.iwork.iwana;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Enumeration;
@@ -56,24 +55,19 @@ public class IWork18PackageParser implements Parser {
     }
 
     @Override
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
         // Open the Zip stream
         // Use a File if we can, and an already open zip is even better
         ZipFile zipFile = null;
         ZipInputStream zipStream = null;
-        if (stream instanceof TikaInputStream) {
-            TikaInputStream tis = (TikaInputStream) stream;
-            Object container = ((TikaInputStream) stream).getOpenContainer();
-            if (container instanceof ZipFile) {
-                zipFile = (ZipFile) container;
-            } else if (tis.hasFile()) {
-                zipFile = ZipFile.builder().setFile(tis.getFile()).get();
-            } else {
-                zipStream = new ZipInputStream(stream);
-            }
+        Object container = tis.getOpenContainer();
+        if (container instanceof ZipFile) {
+            zipFile = (ZipFile) container;
+        } else if (tis.hasFile()) {
+            zipFile = ZipFile.builder().setFile(tis.getFile()).get();
         } else {
-            zipStream = new ZipInputStream(stream);
+            zipStream = new ZipInputStream(tis);
         }
 
         // For now, just detect
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/test/java/org/apache/tika/parser/iwork/IWorkParserTest.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/test/java/org/apache/tika/parser/iwork/IWorkParserTest.java
index fffc38f9a8..c5b551689b 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/test/java/org/apache/tika/parser/iwork/IWorkParserTest.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/test/java/org/apache/tika/parser/iwork/IWorkParserTest.java
@@ -34,6 +34,7 @@ import org.apache.tika.detect.Detector;
 import org.apache.tika.detect.apple.IWorkDetector;
 import org.apache.tika.detect.zip.DefaultZipContainerDetector;
 import org.apache.tika.detect.zip.ZipContainerDetector;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.Office;
 import org.apache.tika.metadata.TikaCoreProperties;
@@ -63,7 +64,7 @@ public class IWorkParserTest extends TikaTest {
         InputStream input = getResourceAsStream("/test-documents/testKeynote.key");
         Metadata metadata = new Metadata();
         ContentHandler handler = new BodyContentHandler();
-        iWorkParser.parse(input, handler, metadata, new ParseContext());
+        iWorkParser.parse(TikaInputStream.get(input), handler, metadata, new ParseContext());
         input.read();   // Will throw an Exception if the stream was already closed.
     }
 
@@ -424,7 +425,7 @@ public class IWorkParserTest extends TikaTest {
         Detector d = new CompositeDetector(new DefaultZipContainerDetector(zips));
         try (InputStream is = this.getClass()
                 .getResourceAsStream("/test-documents/testIWorksNPEDetector.zip")) {
-            MediaType mt = d.detect(is, new Metadata());
+            MediaType mt = d.detect(TikaInputStream.get(is), new Metadata());
             assertEquals(MediaType.application("zip"), mt);
         }
     }
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/test/java/org/apache/tika/parser/iwork/iwana/IWork13ParserTest.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/test/java/org/apache/tika/parser/iwork/iwana/IWork13ParserTest.java
index c36260a696..0337543f65 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/test/java/org/apache/tika/parser/iwork/iwana/IWork13ParserTest.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-apple-module/src/test/java/org/apache/tika/parser/iwork/iwana/IWork13ParserTest.java
@@ -26,6 +26,7 @@ import org.junit.jupiter.api.Test;
 import org.xml.sax.ContentHandler;
 
 import org.apache.tika.TikaTest;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
 import org.apache.tika.parser.ParseContext;
@@ -53,7 +54,7 @@ public class IWork13ParserTest extends TikaTest {
         InputStream input = getResourceAsStream("/test-documents/testKeynote2013.key");
         Metadata metadata = new Metadata();
         ContentHandler handler = new BodyContentHandler();
-        iWorkParser.parse(input, handler, metadata, parseContext);
+        iWorkParser.parse(TikaInputStream.get(input), handler, metadata, parseContext);
 
         assertEquals(9, metadata.size());
         assertEquals(IWork13PackageParser.IWork13DocumentType.KEYNOTE13.getType().toString(),
@@ -65,7 +66,7 @@ public class IWork13ParserTest extends TikaTest {
         InputStream input = getResourceAsStream("/test-documents/testNumbers2013.numbers");
         Metadata metadata = new Metadata();
         ContentHandler handler = new BodyContentHandler();
-        iWorkParser.parse(input, handler, metadata, parseContext);
+        iWorkParser.parse(TikaInputStream.get(input), handler, metadata, parseContext);
 
         // Currently parsing is a no-op, and we can't get the type without
         //  decoding the Snappy stream
@@ -81,7 +82,7 @@ public class IWork13ParserTest extends TikaTest {
         InputStream input = getResourceAsStream("/test-documents/testPages2013.pages");
         Metadata metadata = new Metadata();
         ContentHandler handler = new BodyContentHandler();
-        iWorkParser.parse(input, handler, metadata, parseContext);
+        iWorkParser.parse(TikaInputStream.get(input), handler, metadata, parseContext);
 
         // Currently parsing is a no-op, and we can't get the type without
         //  decoding the Snappy stream
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/pom.xml b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/pom.xml
index f13f301d4f..7538b19850 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/pom.xml
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/pom.xml
@@ -35,17 +35,6 @@
       <groupId>com.drewnoakes</groupId>
       <artifactId>metadata-extractor</artifactId>
     </dependency>
-    <dependency>
-      <groupId>org.gagravarr</groupId>
-      <artifactId>vorbis-java-tika</artifactId>
-      <version>${vorbis.version}</version>
-      <exclusions>
-        <exclusion>
-          <groupId>org.apache.tika</groupId>
-          <artifactId>tika-core</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
     <dependency>
       <groupId>org.gagravarr</groupId>
       <artifactId>vorbis-java-core</artifactId>
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/detect/MatroskaDetector.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/detect/MatroskaDetector.java
index 9cdb792ed5..35a8e6b65f 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/detect/MatroskaDetector.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/detect/MatroskaDetector.java
@@ -17,11 +17,11 @@
 package org.apache.tika.detect;
 
 import java.io.IOException;
-import java.io.InputStream;
 
 import org.apache.commons.io.IOUtils;
 
 import org.apache.tika.config.TikaComponent;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 
@@ -46,24 +46,24 @@ public class MatroskaDetector implements Detector {
     /**
      * Detects the media type of the input stream by inspecting EBML headers.
      *
-     * @param input    the input stream
+     * @param tis      the input stream
      * @param metadata the metadata to populate
      * @return detected MediaType (WEBM, Matroska, or OCTET_STREAM)
      * @throws IOException if an I/O error occurs
      */
     @Override
-    public MediaType detect(InputStream input, Metadata metadata) throws IOException {
-        if (input == null) {
+    public MediaType detect(TikaInputStream tis, Metadata metadata) throws IOException {
+        if (tis == null) {
             return MediaType.OCTET_STREAM;
         }
-        input.mark(64);
+        tis.mark(64);
 
         byte[] header = new byte[64];
         int bytesRead = -1;
         try {
-            bytesRead = IOUtils.read(input, header, 0, 64);
+            bytesRead = IOUtils.read(tis, header, 0, 64);
         } finally {
-            input.reset();
+            tis.reset();
         }
 
         if (bytesRead < EBML_HEADER.length) {
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/detect/ogg/OggDetector.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/detect/ogg/OggDetector.java
new file mode 100644
index 0000000000..e05e707de6
--- /dev/null
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/detect/ogg/OggDetector.java
@@ -0,0 +1,235 @@
+/*
+ * 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.tika.detect.ogg;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.gagravarr.ogg.OggFile;
+import org.gagravarr.ogg.OggPacket;
+import org.gagravarr.ogg.OggPacketReader;
+import org.gagravarr.ogg.OggStreamIdentifier;
+import org.gagravarr.ogg.OggStreamIdentifier.OggStreamType;
+import org.gagravarr.skeleton.SkeletonPacket;
+import org.gagravarr.skeleton.SkeletonPacketFactory;
+
+import org.apache.tika.config.TikaComponent;
+import org.apache.tika.detect.Detector;
+import org.apache.tika.io.TikaInputStream;
+import org.apache.tika.metadata.Metadata;
+import org.apache.tika.mime.MediaType;
+
+/**
+ * Detector for identifying specific file types stored
+ * within an Ogg container.
+ * Xiph provide a fairly unhelpful guide to mimetypes at
+ * https://wiki.xiph.org/index.php/MIME_Types_and_File_Extensions
+ * but we try to use more specific ones, as given by the Tika
+ * mimetypes xml file.
+ */
+@TikaComponent
+public class OggDetector implements Detector {
+    private static final long serialVersionUID = 591382028699008553L;
+
+    public static final MediaType OGG_GENERAL = MediaType.application("ogg");
+    public static final MediaType OGG_AUDIO = MediaType.audio("ogg");
+    public static final MediaType OGG_VIDEO = MediaType.video("ogg");
+
+    @Override
+    public MediaType detect(TikaInputStream tis, Metadata metadata)
+            throws IOException {
+        // Check if we have access to the document
+        if (tis == null) {
+            return MediaType.OCTET_STREAM;
+        }
+
+        // Check if the document starts with the OGG header
+        tis.mark(4);
+        try {
+            if (tis.read() != (byte)'O' || tis.read() != (byte)'g'
+                    || tis.read() != (byte)'g' || tis.read() != (byte)'S') {
+                return MediaType.OCTET_STREAM;
+            }
+        } finally {
+            tis.reset();
+        }
+
+        // We could potentially need to go a long way through the
+        // file in order to figure out what it is
+        tis.mark((int)tis.getLength() + 1);
+
+        try {
+            // Open the Ogg file - underlying stream stays open as detecting only
+            @SuppressWarnings("resource")
+            OggFile ogg = new OggFile(tis);
+
+            // The things we'll want to keep track of
+            int totalStreams = 0;
+            List<Integer> sids = new ArrayList<>();
+            Map<OggStreamType, Integer> streams = new HashMap<>();
+            Map<Integer, List<SkeletonPacket>> skeletonStreams = new HashMap<>();
+
+            // Check the streams in turn
+            OggPacketReader r = ogg.getPacketReader();
+            OggPacket p;
+            Integer sid;
+            try {
+                while ((p = r.getNextPacket()) != null) {
+                    if (p.isBeginningOfStream()) {
+                        totalStreams++;
+                        sids.add(p.getSid());
+
+                        OggStreamType type = OggStreamIdentifier.identifyType(p);
+
+                        // If it's a Skeleton stream, start tracking
+                        if (type == OggStreamIdentifier.SKELETON) {
+                            List<SkeletonPacket> sp = new ArrayList<>();
+                            sp.add(SkeletonPacketFactory.create(p));
+                            skeletonStreams.put(p.getSid(), sp);
+                        }
+
+                        // Increment the per-type count
+                        Integer num = streams.get(type);
+                        if (num == null) {
+                            num = 1;
+                        } else {
+                            num = num + 1;
+                        }
+                        streams.put(type, num);
+                    } else {
+                        sid = p.getSid();
+
+                        // Is it a skeleton stream?
+                        if (skeletonStreams.containsKey(sid)) {
+                            skeletonStreams.get(sid).add(SkeletonPacketFactory.create(p));
+                        }
+                    }
+                }
+            } catch (UnsupportedOperationException e) {
+                // Silently swallow this problem with the file,
+                // and just say "not ours"
+                return MediaType.OCTET_STREAM;
+            }
+
+            // Can we identify what it really is?
+            // First up, is it a simple single stream file?
+            if (totalStreams == 1) {
+                OggStreamType type = streams.keySet().iterator().next();
+                return toMediaType(type);
+            }
+
+            // Is it one with a single non-metadata stream?
+            int nonMetadataStreams = 0;
+            for (OggStreamType type : streams.keySet()) {
+                if (type.kind != OggStreamType.Kind.METADATA) {
+                    nonMetadataStreams += streams.get(type);
+                }
+            }
+
+            if (nonMetadataStreams == 0) {
+                // Pure metadata, report as general ogg
+                return OGG_GENERAL;
+            }
+
+            if (nonMetadataStreams == 1) {
+                // Report as the non metadata kind
+                for (OggStreamType type : streams.keySet()) {
+                    if (type.kind != OggStreamType.Kind.METADATA) {
+                        return toMediaType(type);
+                    }
+                }
+            }
+
+            // Is it a single video stream, with zero or more audio streams?
+            int videoCount = 0;
+            int audioCount = 0;
+            int kateCount = 0;
+            Set<OggStreamType> audioTypes = new HashSet<>();
+            Set<OggStreamType> videoTypes = new HashSet<>();
+            for (OggStreamType type : streams.keySet()) {
+                if (type.kind == OggStreamType.Kind.VIDEO) {
+                    videoCount += streams.get(type);
+                    videoTypes.add(type);
+                } else if (type.kind == OggStreamType.Kind.AUDIO) {
+                    audioCount += streams.get(type);
+                    audioTypes.add(type);
+                } else if (type == OggStreamIdentifier.KATE) {
+                    kateCount++;
+                }
+            }
+            if (videoCount == 1) {
+                // Report it as the video type, not the audio within that
+                return toMediaType(videoTypes.iterator().next());
+            }
+
+            // Is it multiple audio streams, with no video?
+            if (videoCount == 0 && audioCount > 1) {
+                // Are they all the same audio kind?
+                if (audioTypes.size() == 1) {
+                    // All the same kind, report it as that
+                    return toMediaType(audioTypes.iterator().next());
+                } else {
+                    // Mixture of audio types, report as general audio
+                    return OGG_AUDIO;
+                }
+            }
+
+            // Is it multiple video streams?
+            if (videoCount > 1) {
+                // Are they all the same video kind?
+                if (videoTypes.size() == 1) {
+                    // All the same kind, report it as that video
+                    return toMediaType(videoTypes.iterator().next());
+                } else {
+                    // Mixture of video types, report as general video
+                    return OGG_VIDEO;
+                }
+            }
+
+            // Is it only Kate streams, but no video nor audio?
+            if (kateCount > 0) {
+                return toMediaType(OggStreamIdentifier.KATE);
+            }
+
+            // If we get here, then we can't work out what it is
+        } finally {
+            // Tidy up - reset the stream
+            tis.reset();
+        }
+
+        // Couldn't determine a more specific type
+        return OGG_GENERAL;
+    }
+
+    /**
+     * Converts from vorbis-java type to Tika's type
+     */
+    protected static MediaType toMediaType(OggStreamType type) {
+        if (type == OggStreamIdentifier.UNKNOWN) {
+            // We don't have a specific type available to return
+            return OGG_GENERAL;
+        } else {
+            // Say it's the specific type we found
+            return MediaType.parse(type.mimetype);
+        }
+    }
+}
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/audio/AudioParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/audio/AudioParser.java
index a00573a59a..1fc9a7c53b 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/audio/AudioParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/audio/AudioParser.java
@@ -16,7 +16,6 @@
  */
 package org.apache.tika.parser.audio;
 
-import java.io.BufferedInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Arrays;
@@ -38,6 +37,7 @@ import org.xml.sax.SAXException;
 
 import org.apache.tika.config.TikaComponent;
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
 import org.apache.tika.metadata.XMPDM;
@@ -69,15 +69,12 @@ public class AudioParser implements Parser {
         return SUPPORTED_TYPES;
     }
 
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
-        // AudioSystem expects the stream to support the mark feature
-        if (!stream.markSupported()) {
-            stream = new BufferedInputStream(stream);
-        }
-        stream = new SkipFullyInputStream(stream);
+        // TikaInputStream always supports mark, wrap in SkipFullyInputStream for audio parsing
+        InputStream audioStream = new SkipFullyInputStream(tis);
         try {
-            AudioFileFormat fileFormat = AudioSystem.getAudioFileFormat(stream);
+            AudioFileFormat fileFormat = AudioSystem.getAudioFileFormat(audioStream);
             Type type = fileFormat.getType();
             if (type == Type.AIFC || type == Type.AIFF) {
                 metadata.set(Metadata.CONTENT_TYPE, "audio/x-aiff");
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/audio/MidiParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/audio/MidiParser.java
index 4ae7e657bb..4480146481 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/audio/MidiParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/audio/MidiParser.java
@@ -18,9 +18,7 @@ package org.apache.tika.parser.audio;
 
 import static java.nio.charset.StandardCharsets.ISO_8859_1;
 
-import java.io.BufferedInputStream;
 import java.io.IOException;
-import java.io.InputStream;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
@@ -38,6 +36,7 @@ import org.xml.sax.SAXException;
 
 import org.apache.tika.config.TikaComponent;
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 import org.apache.tika.parser.ParseContext;
@@ -60,19 +59,16 @@ public class MidiParser implements Parser {
         return SUPPORTED_TYPES;
     }
 
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
         metadata.set(Metadata.CONTENT_TYPE, "audio/midi");
 
         XHTMLContentHandler xhtml = new XHTMLContentHandler(handler, metadata);
         xhtml.startDocument();
 
-        // MidiSystem expects the stream to support the mark feature
-        if (!stream.markSupported()) {
-            stream = new BufferedInputStream(stream);
-        }
+        // TikaInputStream always supports mark
         try {
-            Sequence sequence = MidiSystem.getSequence(stream);
+            Sequence sequence = MidiSystem.getSequence(tis);
 
             Track[] tracks = sequence.getTracks();
             metadata.set("tracks", String.valueOf(tracks.length));
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp3/Mp3Parser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp3/Mp3Parser.java
index 2514ca04b5..948dba2ebc 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp3/Mp3Parser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp3/Mp3Parser.java
@@ -29,6 +29,7 @@ import org.xml.sax.SAXException;
 import org.apache.tika.config.TikaComponent;
 import org.apache.tika.exception.TikaException;
 import org.apache.tika.io.TailStream;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
 import org.apache.tika.metadata.XMPDM;
@@ -61,7 +62,7 @@ public class Mp3Parser implements Parser {
      * Scans the MP3 frames for ID3 tags, and creates ID3Tag Handlers
      * for each supported set of tags.
      */
-    protected static ID3TagsAndAudio getAllTagHandlers(InputStream stream, ContentHandler handler)
+    protected static ID3TagsAndAudio getAllTagHandlers(InputStream tis, ContentHandler handler)
             throws IOException, SAXException, TikaException {
         ID3v24Handler v24 = null;
         ID3v23Handler v23 = null;
@@ -70,7 +71,7 @@ public class Mp3Parser implements Parser {
         LyricsHandler lyrics = null;
         AudioFrame firstAudio = null;
 
-        TailStream tailStream = new TailStream(stream, 10240 + 128);
+        TailStream tailStream = new TailStream(tis, 10240 + 128);
         MpegStream mpegStream = new MpegStream(tailStream);
 
         // ID3v2 tags live at the start of the file
@@ -140,7 +141,7 @@ public class Mp3Parser implements Parser {
         return SUPPORTED_TYPES;
     }
 
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
         metadata.set(Metadata.CONTENT_TYPE, "audio/mpeg");
         metadata.set(XMPDM.AUDIO_COMPRESSOR, "MP3");
@@ -148,7 +149,7 @@ public class Mp3Parser implements Parser {
         XHTMLContentHandler xhtml = new XHTMLContentHandler(handler, metadata);
 
         // Create handlers for the various kinds of ID3 tags
-        ID3TagsAndAudio audioAndTags = getAllTagHandlers(stream, handler);
+        ID3TagsAndAudio audioAndTags = getAllTagHandlers(tis, handler);
 
         // Before we start on the XHTML output, process and store
         //  as much metadata as possible
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp4/MP4Parser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp4/MP4Parser.java
index a52758e1bb..496f9b298d 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp4/MP4Parser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp4/MP4Parser.java
@@ -46,7 +46,6 @@ import org.xml.sax.SAXException;
 import org.apache.tika.config.TikaComponent;
 import org.apache.tika.exception.RuntimeSAXException;
 import org.apache.tika.exception.TikaException;
-import org.apache.tika.io.TemporaryResources;
 import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.Property;
@@ -96,13 +95,10 @@ public class MP4Parser implements Parser {
         return SUPPORTED_TYPES;
     }
 
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
 
-        TemporaryResources tmp = new TemporaryResources();
-        TikaInputStream tstream = TikaInputStream.get(stream, tmp, metadata);
-
-        try (InputStream is = Files.newInputStream(tstream.getPath())) {
+        try (InputStream is = Files.newInputStream(tis.getPath())) {
 
             XHTMLContentHandler xhtml = new XHTMLContentHandler(handler, metadata);
             xhtml.startDocument();
@@ -129,8 +125,6 @@ public class MP4Parser implements Parser {
                 metadata.add(TikaCoreProperties.TIKA_META_EXCEPTION_WARNING, m);
             }
             xhtml.endDocument();
-        } finally {
-            tmp.dispose();
         }
     }
 
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/ogg/FlacParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/ogg/FlacParser.java
new file mode 100644
index 0000000000..23ff660fe6
--- /dev/null
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/ogg/FlacParser.java
@@ -0,0 +1,104 @@
+/*
+ * 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.tika.parser.ogg;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.gagravarr.flac.FlacFile;
+import org.gagravarr.flac.FlacInfo;
+import org.gagravarr.flac.FlacOggFile;
+import org.gagravarr.ogg.OggStreamIdentifier;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+import org.apache.tika.config.TikaComponent;
+import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
+import org.apache.tika.metadata.Metadata;
+import org.apache.tika.metadata.XMPDM;
+import org.apache.tika.mime.MediaType;
+import org.apache.tika.parser.AbstractParser;
+import org.apache.tika.parser.ParseContext;
+import org.apache.tika.sax.XHTMLContentHandler;
+
+/**
+ * Parser for FLAC audio files (both native FLAC and OGG-FLAC).
+ */
+@TikaComponent
+public class FlacParser extends AbstractParser {
+    private static final long serialVersionUID = -7546577301474546694L;
+
+    protected static final MediaType NATIVE_FLAC =
+            MediaType.parse(OggStreamIdentifier.NATIVE_FLAC.mimetype);
+    protected static final MediaType OGG_FLAC =
+            MediaType.parse(OggStreamIdentifier.OGG_FLAC.mimetype);
+
+    private static List<MediaType> TYPES = Arrays.asList(NATIVE_FLAC, OGG_FLAC);
+
+    @Override
+    public Set<MediaType> getSupportedTypes(ParseContext context) {
+        return new HashSet<>(TYPES);
+    }
+
+    @Override
+    public void parse(TikaInputStream tis, ContentHandler handler,
+            Metadata metadata, ParseContext context)
+            throws IOException, TikaException, SAXException {
+        metadata.set(XMPDM.AUDIO_COMPRESSOR, "FLAC");
+
+        // Open the FLAC file
+        FlacFile flac = FlacFile.open(tis);
+
+        // Start
+        XHTMLContentHandler xhtml = new XHTMLContentHandler(handler, metadata);
+        xhtml.startDocument();
+
+        // Extract the common FLAC info
+        extractInfo(metadata, flac.getInfo());
+        if (flac instanceof FlacOggFile) {
+            FlacOggFile ogg = (FlacOggFile) flac;
+            metadata.add("version", "Flac " + ogg.getFirstPacket().getMajorVersion() +
+                    "." + ogg.getFirstPacket().getMinorVersion());
+            metadata.set(Metadata.CONTENT_TYPE, OGG_FLAC.toString());
+        } else {
+            metadata.set(Metadata.CONTENT_TYPE, NATIVE_FLAC.toString());
+        }
+
+        // Extract any Vorbis-style comments
+        OggAudioParser.extractComments(metadata, xhtml, flac.getTags());
+
+        // Extract duration if available from header
+        FlacInfo info = flac.getInfo();
+        if (info.getNumberOfSamples() > 0 && info.getSampleRate() > 0) {
+            double duration = (double) info.getNumberOfSamples() / info.getSampleRate();
+            OggAudioParser.extractDuration(metadata, xhtml, duration);
+        }
+
+        // Finish
+        xhtml.endDocument();
+        flac.close();
+    }
+
+    protected void extractInfo(Metadata metadata, FlacInfo info) throws TikaException {
+        metadata.set(XMPDM.AUDIO_SAMPLE_RATE, (int) info.getSampleRate());
+        OggAudioParser.extractChannelInfo(metadata, info.getNumChannels());
+    }
+}
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/ogg/OggAudioParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/ogg/OggAudioParser.java
new file mode 100644
index 0000000000..563bf40bed
--- /dev/null
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/ogg/OggAudioParser.java
@@ -0,0 +1,158 @@
+/*
+ * 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.tika.parser.ogg;
+
+import java.io.IOException;
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+
+import org.gagravarr.ogg.audio.OggAudioHeaders;
+import org.gagravarr.ogg.audio.OggAudioInfoHeader;
+import org.gagravarr.ogg.audio.OggAudioStatistics;
+import org.gagravarr.ogg.audio.OggAudioStream;
+import org.gagravarr.vorbis.VorbisComments;
+import org.gagravarr.vorbis.VorbisStyleComments;
+import org.xml.sax.SAXException;
+
+import org.apache.tika.exception.TikaException;
+import org.apache.tika.metadata.Metadata;
+import org.apache.tika.metadata.TikaCoreProperties;
+import org.apache.tika.metadata.XMP;
+import org.apache.tika.metadata.XMPDM;
+import org.apache.tika.parser.AbstractParser;
+import org.apache.tika.sax.XHTMLContentHandler;
+
+/**
+ * Parent parser for the various Ogg Audio formats, such as
+ * Vorbis and Opus.
+ */
+public abstract class OggAudioParser extends AbstractParser {
+    private static final long serialVersionUID = 5168743829615945633L;
+
+    private static final DecimalFormat DURATION_FORMAT =
+            (DecimalFormat) NumberFormat.getNumberInstance(Locale.ROOT);
+    static {
+        DURATION_FORMAT.applyPattern("0.0#");
+    }
+
+    protected static void extractChannelInfo(Metadata metadata, OggAudioInfoHeader info) {
+        extractChannelInfo(metadata, info.getNumChannels());
+    }
+
+    protected static void extractChannelInfo(Metadata metadata, int channelCount) {
+        if (channelCount == 1) {
+            metadata.set(XMPDM.AUDIO_CHANNEL_TYPE, "Mono");
+        } else if (channelCount == 2) {
+            metadata.set(XMPDM.AUDIO_CHANNEL_TYPE, "Stereo");
+        } else if (channelCount == 5) {
+            metadata.set(XMPDM.AUDIO_CHANNEL_TYPE, "5.1");
+        } else if (channelCount == 7) {
+            metadata.set(XMPDM.AUDIO_CHANNEL_TYPE, "7.1");
+        }
+    }
+
+    protected static void extractComments(Metadata metadata, XHTMLContentHandler xhtml,
+            VorbisStyleComments comments) throws TikaException, SAXException {
+        // Get the specific known comments
+        metadata.set(TikaCoreProperties.TITLE, comments.getTitle());
+        metadata.set(TikaCoreProperties.CREATOR, comments.getArtist());
+        metadata.set(XMPDM.ARTIST, comments.getArtist());
+        metadata.set(XMPDM.ALBUM, comments.getAlbum());
+        metadata.set(XMPDM.GENRE, comments.getGenre());
+        metadata.set(XMPDM.RELEASE_DATE, comments.getDate());
+        metadata.add(XMP.CREATOR_TOOL, comments.getVendor());
+        metadata.add("vendor", comments.getVendor());
+
+        for (String comment : comments.getComments("comment")) {
+            metadata.add(XMPDM.LOG_COMMENT.getName(), comment);
+        }
+
+        // Grab the rest just in case
+        List<String> done = Arrays.asList(
+                VorbisComments.KEY_TITLE, VorbisComments.KEY_ARTIST,
+                VorbisComments.KEY_ALBUM, VorbisComments.KEY_GENRE,
+                VorbisComments.KEY_DATE, VorbisComments.KEY_TRACKNUMBER,
+                "vendor", "comment"
+        );
+        for (String key : comments.getAllComments().keySet()) {
+            if (!done.contains(key)) {
+                for (String value : comments.getAllComments().get(key)) {
+                    metadata.add(key, value);
+                }
+            }
+        }
+
+        // Output as text too
+        xhtml.element("h1", comments.getTitle());
+        xhtml.element("p", comments.getArtist());
+
+        // Album and Track number
+        if (comments.getTrackNumber() != null) {
+            xhtml.element("p", comments.getAlbum() + ", track " + comments.getTrackNumber());
+            metadata.set(XMPDM.TRACK_NUMBER, comments.getTrackNumber());
+        } else {
+            xhtml.element("p", comments.getAlbum());
+        }
+
+        // A few other bits
+        xhtml.element("p", comments.getDate());
+        for (String comment : comments.getComments("comment")) {
+            xhtml.element("p", comment);
+        }
+        xhtml.element("p", comments.getGenre());
+    }
+
+    protected static void extractDuration(Metadata metadata, XHTMLContentHandler xhtml,
+            OggAudioHeaders headers, OggAudioStream audio) throws IOException, SAXException {
+        // Have the statistics calculated
+        OggAudioStatistics stats = new OggAudioStatistics(headers, audio);
+        stats.calculate();
+
+        // Record the duration, if available
+        extractDuration(metadata, xhtml, stats.getDurationSeconds());
+    }
+
+    protected static void extractDuration(Metadata metadata, XHTMLContentHandler xhtml,
+            double duration) throws SAXException {
+        // Record the duration, if available
+        if (duration > 0) {
+            // Save as metadata to the nearest .01 seconds
+            metadata.add(XMPDM.DURATION, DURATION_FORMAT.format(duration));
+
+            // Output as Hours / Minutes / Seconds / Parts
+            String durationStr = formatDuration(duration);
+            xhtml.element("p", durationStr);
+        }
+    }
+
+    private static String formatDuration(double durationSeconds) {
+        long totalSeconds = (long) durationSeconds;
+        long hours = totalSeconds / 3600;
+        long minutes = (totalSeconds % 3600) / 60;
+        long seconds = totalSeconds % 60;
+        double fraction = durationSeconds - totalSeconds;
+
+        if (hours > 0) {
+            return String.format(Locale.ROOT, "%d:%02d:%02d", hours, minutes, seconds);
+        } else {
+            return String.format(Locale.ROOT, "%d:%02d", minutes, seconds);
+        }
+    }
+}
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/ogg/OggParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/ogg/OggParser.java
new file mode 100644
index 0000000000..9d03be1fe7
--- /dev/null
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/ogg/OggParser.java
@@ -0,0 +1,156 @@
+/*
+ * 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.tika.parser.ogg;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import org.gagravarr.ogg.OggFile;
+import org.gagravarr.ogg.OggPacket;
+import org.gagravarr.ogg.OggPacketReader;
+import org.gagravarr.ogg.OggStreamIdentifier;
+import org.gagravarr.ogg.OggStreamIdentifier.OggStreamType;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+import org.apache.tika.config.TikaComponent;
+import org.apache.tika.detect.ogg.OggDetector;
+import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
+import org.apache.tika.metadata.Metadata;
+import org.apache.tika.mime.MediaType;
+import org.apache.tika.parser.AbstractParser;
+import org.apache.tika.parser.ParseContext;
+import org.apache.tika.sax.XHTMLContentHandler;
+
+/**
+ * General parser for Ogg files where we don't know what
+ * the specific kind is.
+ *
+ * We provide a detector which should help specialise the more
+ * common kinds of Ogg files, based on their streams, to their
+ * appropriate types. This just handles the rest, as best we can.
+ */
+@TikaComponent
+public class OggParser extends AbstractParser {
+    private static final long serialVersionUID = -5686095376587813226L;
+
+    protected static final MediaType OGG_GENERAL = OggDetector.OGG_GENERAL;
+    protected static final MediaType OGG_AUDIO = OggDetector.OGG_AUDIO;
+    protected static final MediaType OGG_VIDEO = OggDetector.OGG_VIDEO;
+
+    protected static final MediaType KATE =
+            MediaType.parse(OggStreamIdentifier.KATE.mimetype);
+
+    protected static final MediaType DAALA_VIDEO =
+            MediaType.parse(OggStreamIdentifier.DAALA_VIDEO.mimetype);
+    protected static final MediaType DIRAC_VIDEO =
+            MediaType.parse(OggStreamIdentifier.DIRAC_VIDEO.mimetype);
+    protected static final MediaType OGM_VIDEO =
+            MediaType.parse(OggStreamIdentifier.OGM_VIDEO.mimetype);
+    protected static final MediaType OGG_UVS =
+            MediaType.parse(OggStreamIdentifier.OGG_UVS.mimetype);
+    protected static final MediaType OGG_YUV =
+            MediaType.parse(OggStreamIdentifier.OGG_YUV.mimetype);
+    protected static final MediaType OGG_RGB =
+            MediaType.parse(OggStreamIdentifier.OGG_RGB.mimetype);
+    protected static final MediaType OGG_PCM =
+            MediaType.parse(OggStreamIdentifier.OGG_PCM.mimetype);
+
+    private static List<MediaType> TYPES = Arrays.asList(
+            // General ones
+            OGG_GENERAL, OGG_AUDIO, OGG_VIDEO,
+            // Ones we lack a proper parser for
+            DAALA_VIDEO, DIRAC_VIDEO, OGM_VIDEO,
+            OGG_UVS, OGG_YUV, OGG_RGB, OGG_PCM,
+            KATE
+    );
+
+    @Override
+    public Set<MediaType> getSupportedTypes(ParseContext context) {
+        return new HashSet<>(TYPES);
+    }
+
+    @Override
+    public void parse(TikaInputStream tis, ContentHandler handler,
+            Metadata metadata, ParseContext context)
+            throws IOException, TikaException, SAXException {
+        // Process the file straight through once
+        OggFile ogg = new OggFile(tis);
+
+        // To track the streams we find
+        Map<OggStreamType, Integer> streams = new HashMap<>();
+        Map<OggStreamType.Kind, Integer> streamKinds = new HashMap<>();
+        List<Integer> sids = new ArrayList<>();
+        int totalStreams = 0;
+
+        // Start
+        XHTMLContentHandler xhtml = new XHTMLContentHandler(handler, metadata);
+        xhtml.startDocument();
+
+        // Check the streams in turn
+        OggPacketReader r = ogg.getPacketReader();
+        OggPacket p;
+        while ((p = r.getNextPacket()) != null) {
+            if (p.isBeginningOfStream()) {
+                totalStreams++;
+                sids.add(p.getSid());
+
+                OggStreamType type = OggStreamIdentifier.identifyType(p);
+                Integer prevValue = streams.get(type);
+                if (prevValue == null) {
+                    prevValue = 0;
+                }
+                streams.put(type, (prevValue + 1));
+
+                prevValue = streamKinds.get(type.kind);
+                if (prevValue == null) {
+                    prevValue = 0;
+                }
+                streamKinds.put(type.kind, (prevValue + 1));
+            }
+        }
+
+        // Report about the streams
+        metadata.add("streams-total", Integer.toString(totalStreams));
+        for (OggStreamType type : streams.keySet()) {
+            String key = type.mimetype.substring(type.mimetype.indexOf('/') + 1);
+            if (key.startsWith("x-")) {
+                key = key.substring(2);
+            }
+            if (type == OggStreamIdentifier.UNKNOWN) {
+                key = "unknown";
+            }
+            metadata.add("streams-" + key, Integer.toString(streams.get(type)));
+        }
+        for (OggStreamType.Kind kind : streamKinds.keySet()) {
+            String key = kind.name().toLowerCase(Locale.ROOT);
+            metadata.add("streams-" + key, Integer.toString(streamKinds.get(kind)));
+        }
+
+        // Finish
+        xhtml.endDocument();
+        ogg.close();
+    }
+}
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/ogg/OpusParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/ogg/OpusParser.java
new file mode 100644
index 0000000000..184184629d
--- /dev/null
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/ogg/OpusParser.java
@@ -0,0 +1,95 @@
+/*
+ * 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.tika.parser.ogg;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.gagravarr.ogg.OggFile;
+import org.gagravarr.ogg.OggStreamIdentifier;
+import org.gagravarr.opus.OpusFile;
+import org.gagravarr.opus.OpusInfo;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+import org.apache.tika.config.TikaComponent;
+import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
+import org.apache.tika.metadata.Metadata;
+import org.apache.tika.metadata.XMPDM;
+import org.apache.tika.mime.MediaType;
+import org.apache.tika.parser.ParseContext;
+import org.apache.tika.sax.XHTMLContentHandler;
+
+/**
+ * Parser for OGG Opus audio files.
+ */
+@TikaComponent
+public class OpusParser extends OggAudioParser {
+    private static final long serialVersionUID = 5904981674814527529L;
+
+    protected static final MediaType OPUS_AUDIO =
+            MediaType.parse(OggStreamIdentifier.OPUS_AUDIO.mimetype);
+    protected static final MediaType OPUS_AUDIO_ALT =
+            MediaType.parse(OggStreamIdentifier.OPUS_AUDIO_ALT.mimetype);
+
+    private static List<MediaType> TYPES = Arrays.asList(OPUS_AUDIO, OPUS_AUDIO_ALT);
+
+    @Override
+    public Set<MediaType> getSupportedTypes(ParseContext context) {
+        return new HashSet<>(TYPES);
+    }
+
+    @Override
+    public void parse(TikaInputStream tis, ContentHandler handler,
+            Metadata metadata, ParseContext context)
+            throws IOException, TikaException, SAXException {
+        metadata.set(Metadata.CONTENT_TYPE, OPUS_AUDIO.toString());
+        metadata.set(XMPDM.AUDIO_COMPRESSOR, "Opus");
+
+        // Open and process the files
+        OggFile ogg = new OggFile(tis);
+        OpusFile opus = new OpusFile(ogg);
+
+        // Start
+        XHTMLContentHandler xhtml = new XHTMLContentHandler(handler, metadata);
+        xhtml.startDocument();
+
+        // Extract the common Opus info
+        extractInfo(metadata, opus.getInfo());
+
+        // Extract any Vorbis comments
+        extractComments(metadata, xhtml, opus.getTags());
+
+        // Extract the audio length
+        extractDuration(metadata, xhtml, opus, opus);
+
+        // Finish
+        xhtml.endDocument();
+        opus.close();
+    }
+
+    protected void extractInfo(Metadata metadata, OpusInfo info) throws TikaException {
+        metadata.set(XMPDM.AUDIO_SAMPLE_RATE, (int) info.getRate());
+        metadata.add("version", "Opus " + info.getMajorVersion() + "." + info.getMinorVersion());
+
+        extractChannelInfo(metadata, info);
+    }
+}
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/ogg/SpeexParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/ogg/SpeexParser.java
new file mode 100644
index 0000000000..cc15b235e0
--- /dev/null
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/ogg/SpeexParser.java
@@ -0,0 +1,95 @@
+/*
+ * 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.tika.parser.ogg;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.gagravarr.ogg.OggFile;
+import org.gagravarr.ogg.OggStreamIdentifier;
+import org.gagravarr.speex.SpeexFile;
+import org.gagravarr.speex.SpeexInfo;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+import org.apache.tika.config.TikaComponent;
+import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
+import org.apache.tika.metadata.Metadata;
+import org.apache.tika.metadata.XMPDM;
+import org.apache.tika.mime.MediaType;
+import org.apache.tika.parser.ParseContext;
+import org.apache.tika.sax.XHTMLContentHandler;
+
+/**
+ * Parser for OGG Speex audio files.
+ */
+@TikaComponent
+public class SpeexParser extends OggAudioParser {
+    private static final long serialVersionUID = 5904981674814527529L;
+
+    protected static final MediaType SPEEX_AUDIO =
+            MediaType.parse(OggStreamIdentifier.SPEEX_AUDIO.mimetype);
+    protected static final MediaType SPEEX_AUDIO_ALT =
+            MediaType.parse(OggStreamIdentifier.SPEEX_AUDIO_ALT.mimetype);
+
+    private static List<MediaType> TYPES = Arrays.asList(SPEEX_AUDIO, SPEEX_AUDIO_ALT);
+
+    @Override
+    public Set<MediaType> getSupportedTypes(ParseContext context) {
+        return new HashSet<>(TYPES);
+    }
+
+    @Override
+    public void parse(TikaInputStream tis, ContentHandler handler,
+            Metadata metadata, ParseContext context)
+            throws IOException, TikaException, SAXException {
+        metadata.set(Metadata.CONTENT_TYPE, SPEEX_AUDIO.toString());
+        metadata.set(XMPDM.AUDIO_COMPRESSOR, "Speex");
+
+        // Open and process the files
+        OggFile ogg = new OggFile(tis);
+        SpeexFile speex = new SpeexFile(ogg);
+
+        // Start
+        XHTMLContentHandler xhtml = new XHTMLContentHandler(handler, metadata);
+        xhtml.startDocument();
+
+        // Extract the common Speex info
+        extractInfo(metadata, speex.getInfo());
+
+        // Extract any Vorbis comments
+        extractComments(metadata, xhtml, speex.getTags());
+
+        // Extract the audio length
+        extractDuration(metadata, xhtml, speex, speex);
+
+        // Finish
+        xhtml.endDocument();
+        speex.close();
+    }
+
+    protected void extractInfo(Metadata metadata, SpeexInfo info) throws TikaException {
+        metadata.set(XMPDM.AUDIO_SAMPLE_RATE, (int) info.getRate());
+        metadata.add("version", "Speex " + info.getVersionId() + " - " + info.getVersionString());
+
+        extractChannelInfo(metadata, info);
+    }
+}
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/ogg/TheoraParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/ogg/TheoraParser.java
new file mode 100644
index 0000000000..0838ba34cb
--- /dev/null
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/ogg/TheoraParser.java
@@ -0,0 +1,95 @@
+/*
+ * 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.tika.parser.ogg;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.gagravarr.ogg.OggFile;
+import org.gagravarr.ogg.OggStreamIdentifier;
+import org.gagravarr.ogg.audio.OggAudioHeaders;
+import org.gagravarr.theora.TheoraFile;
+import org.gagravarr.theora.TheoraInfo;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+import org.apache.tika.config.TikaComponent;
+import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
+import org.apache.tika.metadata.Metadata;
+import org.apache.tika.metadata.XMPDM;
+import org.apache.tika.mime.MediaType;
+import org.apache.tika.parser.AbstractParser;
+import org.apache.tika.parser.ParseContext;
+import org.apache.tika.sax.XHTMLContentHandler;
+
+/**
+ * Parser for OGG Theora video files, which may also
+ * contain one or more soundtrack streams.
+ */
+@TikaComponent
+public class TheoraParser extends AbstractParser {
+    private static final long serialVersionUID = -5459916822092342944L;
+
+    protected static final MediaType THEORA_VIDEO =
+            MediaType.parse(OggStreamIdentifier.THEORA_VIDEO.mimetype);
+
+    private static List<MediaType> TYPES = Arrays.asList(THEORA_VIDEO);
+
+    @Override
+    public Set<MediaType> getSupportedTypes(ParseContext context) {
+        return new HashSet<>(TYPES);
+    }
+
+    @Override
+    public void parse(TikaInputStream tis, ContentHandler handler,
+            Metadata metadata, ParseContext context)
+            throws IOException, TikaException, SAXException {
+        metadata.set(Metadata.CONTENT_TYPE, THEORA_VIDEO.toString());
+        metadata.set(XMPDM.VIDEO_COMPRESSOR, "Theora");
+
+        // Open and process the files
+        OggFile ogg = new OggFile(tis);
+        TheoraFile theora = new TheoraFile(ogg);
+
+        // Start
+        XHTMLContentHandler xhtml = new XHTMLContentHandler(handler, metadata);
+        xhtml.startDocument();
+
+        // Extract the common Theora info
+        extractInfo(metadata, theora.getInfo());
+
+        // Extract the common Theora comments
+        OggAudioParser.extractComments(metadata, xhtml, theora.getComments());
+
+        // Extract any soundtracks
+        for (OggAudioHeaders audio : theora.getSoundtracks()) {
+            // Future: extract soundtrack metadata
+        }
+
+        // Finish
+        xhtml.endDocument();
+        theora.close();
+    }
+
+    protected void extractInfo(Metadata metadata, TheoraInfo info) throws TikaException {
+        metadata.add("version", "Theora " + info.getVersion());
+    }
+}
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/ogg/VorbisParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/ogg/VorbisParser.java
new file mode 100644
index 0000000000..2daee53341
--- /dev/null
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/ogg/VorbisParser.java
@@ -0,0 +1,93 @@
+/*
+ * 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.tika.parser.ogg;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.gagravarr.ogg.OggFile;
+import org.gagravarr.ogg.OggStreamIdentifier;
+import org.gagravarr.vorbis.VorbisFile;
+import org.gagravarr.vorbis.VorbisInfo;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+import org.apache.tika.config.TikaComponent;
+import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
+import org.apache.tika.metadata.Metadata;
+import org.apache.tika.metadata.XMPDM;
+import org.apache.tika.mime.MediaType;
+import org.apache.tika.parser.ParseContext;
+import org.apache.tika.sax.XHTMLContentHandler;
+
+/**
+ * Parser for OGG Vorbis audio files.
+ */
+@TikaComponent
+public class VorbisParser extends OggAudioParser {
+    private static final long serialVersionUID = 5904981674814527529L;
+
+    protected static final MediaType OGG_VORBIS =
+            MediaType.parse(OggStreamIdentifier.OGG_VORBIS.mimetype);
+
+    private static List<MediaType> TYPES = Arrays.asList(OGG_VORBIS);
+
+    @Override
+    public Set<MediaType> getSupportedTypes(ParseContext context) {
+        return new HashSet<>(TYPES);
+    }
+
+    @Override
+    public void parse(TikaInputStream tis, ContentHandler handler,
+            Metadata metadata, ParseContext context)
+            throws IOException, TikaException, SAXException {
+        metadata.set(Metadata.CONTENT_TYPE, OGG_VORBIS.toString());
+        metadata.set(XMPDM.AUDIO_COMPRESSOR, "Vorbis");
+
+        // Open and process the files
+        OggFile ogg = new OggFile(tis);
+        VorbisFile vorbis = new VorbisFile(ogg);
+
+        // Start
+        XHTMLContentHandler xhtml = new XHTMLContentHandler(handler, metadata);
+        xhtml.startDocument();
+
+        // Extract the common Vorbis info
+        extractInfo(metadata, vorbis.getInfo());
+
+        // Extract any Vorbis comments
+        extractComments(metadata, xhtml, vorbis.getComment());
+
+        // Extract the audio length
+        extractDuration(metadata, xhtml, vorbis, vorbis);
+
+        // Finish
+        xhtml.endDocument();
+        vorbis.close();
+    }
+
+    protected void extractInfo(Metadata metadata, VorbisInfo info) throws TikaException {
+        metadata.set(XMPDM.AUDIO_SAMPLE_RATE, (int) info.getRate());
+        metadata.add("version", "Vorbis " + info.getVersion());
+
+        extractChannelInfo(metadata, info);
+    }
+}
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/video/FLVParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/video/FLVParser.java
index 51c7f9cdb6..9cae569a8c 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/video/FLVParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/video/FLVParser.java
@@ -20,7 +20,6 @@ import static java.nio.charset.StandardCharsets.UTF_8;
 
 import java.io.DataInputStream;
 import java.io.IOException;
-import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Date;
@@ -35,6 +34,7 @@ import org.xml.sax.SAXException;
 
 import org.apache.tika.config.TikaComponent;
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 import org.apache.tika.parser.ParseContext;
@@ -166,9 +166,9 @@ public class FLVParser implements Parser {
         return fis.read() == 'F' && fis.read() == 'L' && fis.read() == 'V';
     }
 
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
-        DataInputStream datainput = new DataInputStream(stream);
+        DataInputStream datainput = new DataInputStream(tis);
         if (!checkSignature(datainput)) {
             throw new TikaException("FLV signature not detected");
         }
@@ -217,7 +217,7 @@ public class FLVParser implements Parser {
                 // found metadata Tag, read content to buffer
                 byte[] metaBytes = new byte[datalen];
                 for (int readCount = 0; readCount < datalen; ) {
-                    int r = stream.read(metaBytes, readCount, datalen - readCount);
+                    int r = tis.read(metaBytes, readCount, datalen - readCount);
                     if (r != -1) {
                         readCount += r;
 
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/test/java/org/apache/tika/detect/MatroskaDetectorTest.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/test/java/org/apache/tika/detect/MatroskaDetectorTest.java
index 69f33331a1..bc769bb116 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/test/java/org/apache/tika/detect/MatroskaDetectorTest.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/test/java/org/apache/tika/detect/MatroskaDetectorTest.java
@@ -20,11 +20,10 @@ package org.apache.tika.detect;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 import java.io.IOException;
-import java.io.InputStream;
 
-import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
 import org.junit.jupiter.api.Test;
 
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 
@@ -32,8 +31,8 @@ public class MatroskaDetectorTest {
 
     private final MatroskaDetector detector = new MatroskaDetector();
 
-    private InputStream getResourceAsStream(String resourcePath) {
-        return this.getClass().getResourceAsStream(resourcePath);
+    private TikaInputStream getResourceAsStream(String resourcePath) {
+        return TikaInputStream.get(this.getClass().getResourceAsStream(resourcePath));
     }
 
     @Test
@@ -63,11 +62,11 @@ public class MatroskaDetectorTest {
 
         byte[] bytes = new byte[10];
         assertEquals(MediaType.OCTET_STREAM,
-                detector.detect(UnsynchronizedByteArrayInputStream.builder().setByteArray(bytes).get(), new Metadata()));
+                detector.detect(TikaInputStream.get(bytes), new Metadata()));
 
         bytes = new byte[0];
         assertEquals(MediaType.OCTET_STREAM,
-                detector.detect(UnsynchronizedByteArrayInputStream.builder().setByteArray(bytes).get(), new Metadata()));
+                detector.detect(TikaInputStream.get(bytes), new Metadata()));
 
     }
 }
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/test/java/org/apache/tika/parser/mp3/Mp3ParserTest.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/test/java/org/apache/tika/parser/mp3/Mp3ParserTest.java
index 7f54bd2b9c..40a9870408 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/test/java/org/apache/tika/parser/mp3/Mp3ParserTest.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/test/java/org/apache/tika/parser/mp3/Mp3ParserTest.java
@@ -19,11 +19,10 @@ package org.apache.tika.parser.mp3;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assumptions.assumeTrue;
 
-import java.io.ByteArrayInputStream;
-
 import org.junit.jupiter.api.Test;
 
 import org.apache.tika.TikaTest;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
 import org.apache.tika.metadata.XMPDM;
@@ -283,7 +282,7 @@ public class Mp3ParserTest extends TikaTest {
         assertEquals(257, ID3v2Frame.getInt(new byte[]{0, 0, 1, 1}));
 
         ID3v2Frame f =
-                (ID3v2Frame) ID3v2Frame.createFrameIfPresent(new ByteArrayInputStream(empty));
+                (ID3v2Frame) ID3v2Frame.createFrameIfPresent(TikaInputStream.get(empty));
         assertEquals(3, f.getMajorVersion());
         assertEquals(1, f.getMinorVersion());
         assertEquals(0, f.getFlags());
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/test/java/org/apache/tika/parser/mp3/MpegStreamTest.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/test/java/org/apache/tika/parser/mp3/MpegStreamTest.java
index bb408fc8fd..25dc65563e 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/test/java/org/apache/tika/parser/mp3/MpegStreamTest.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/test/java/org/apache/tika/parser/mp3/MpegStreamTest.java
@@ -22,7 +22,6 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNull;
 
-import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
@@ -30,6 +29,8 @@ import java.io.OutputStream;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Test;
 
+import org.apache.tika.io.TikaInputStream;
+
 /**
  * Test class for {@code MpegStream}.
  */
@@ -83,8 +84,8 @@ public class MpegStreamTest {
      * @throws IOException if an error occurs
      */
     private void checkDefaultHeader(ByteArrayOutputStream bos) throws IOException {
-        ByteArrayInputStream in = new ByteArrayInputStream(bos.toByteArray());
-        stream = new MpegStream(in);
+        TikaInputStream tis = TikaInputStream.get(bos.toByteArray());
+        stream = new MpegStream(tis);
         AudioFrame header = stream.nextFrame();
         assertNotNull(header, "No header found");
         assertEquals(AudioFrame.MPEG_V2, header.getVersionCode(), "Wrong MPEG version");
@@ -134,8 +135,8 @@ public class MpegStreamTest {
         bos.write(0xFF);
         bos.write(0xF3);
         bos.write(0x96);
-        ByteArrayInputStream in = new ByteArrayInputStream(bos.toByteArray());
-        stream = new MpegStream(in);
+        TikaInputStream tis = TikaInputStream.get(bos.toByteArray());
+        stream = new MpegStream(tis);
         assertNull(stream.nextFrame(), "Got a frame");
     }
 
@@ -146,8 +147,8 @@ public class MpegStreamTest {
     public void testSkipNoCurrentHeader() throws IOException {
         ByteArrayOutputStream bos = new ByteArrayOutputStream();
         bos.write("This is a test".getBytes(UTF_8));
-        ByteArrayInputStream in = new ByteArrayInputStream(bos.toByteArray());
-        stream = new MpegStream(in);
+        TikaInputStream tis = TikaInputStream.get(bos.toByteArray());
+        stream = new MpegStream(tis);
         assertFalse(stream.skipFrame(), "Wrong result");
     }
 }
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/main/java/org/apache/tika/parser/dgn/DGN8Parser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/main/java/org/apache/tika/parser/dgn/DGN8Parser.java
index a5f3914390..7570abcb8f 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/main/java/org/apache/tika/parser/dgn/DGN8Parser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/main/java/org/apache/tika/parser/dgn/DGN8Parser.java
@@ -17,7 +17,6 @@
 package org.apache.tika.parser.dgn;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.util.Collections;
 import java.util.Set;
 
@@ -52,17 +51,17 @@ public class DGN8Parser implements Parser {
     }
 
     @Override
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
         XHTMLContentHandler xhtml = new XHTMLContentHandler(handler, metadata);
         xhtml.startDocument();
         SummaryExtractor summaryExtractor = new SummaryExtractor(metadata);
         final DirectoryNode root;
-        TikaInputStream tstream = TikaInputStream.cast(stream);
+        TikaInputStream tstream = tis;
         POIFSFileSystem mustCloseFs = null;
         try {
             if (tstream == null) {
-                mustCloseFs = new POIFSFileSystem(CloseShieldInputStream.wrap(stream));
+                mustCloseFs = new POIFSFileSystem(CloseShieldInputStream.wrap(tis));
                 root = mustCloseFs.getRoot();
             } else {
                 final Object container = tstream.getOpenContainer();
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/main/java/org/apache/tika/parser/dwg/DWGParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/main/java/org/apache/tika/parser/dwg/DWGParser.java
index 40e5bfcf76..d8e085bf55 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/main/java/org/apache/tika/parser/dwg/DWGParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/main/java/org/apache/tika/parser/dwg/DWGParser.java
@@ -29,6 +29,7 @@ import org.xml.sax.SAXException;
 import org.apache.tika.config.TikaComponent;
 import org.apache.tika.exception.TikaException;
 import org.apache.tika.io.EndianUtils;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.Property;
 import org.apache.tika.metadata.TikaCoreProperties;
@@ -89,7 +90,7 @@ public class DWGParser extends AbstractDWGParser {
         return Collections.singleton(TYPE);
     }
 
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata, ParseContext context)
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata, ParseContext context)
             throws IOException, TikaException, SAXException {
 
         configure(context);
@@ -97,11 +98,11 @@ public class DWGParser extends AbstractDWGParser {
 
         if (!dwgc.getDwgReadExecutable().isEmpty()) {
             DWGReadParser dwr = new DWGReadParser();
-            dwr.parse(stream, handler, metadata, context);
+            dwr.parse(tis, handler, metadata, context);
         } else {
             // First up, which version of the format are we handling?
             byte[] header = new byte[128];
-            IOUtils.readFully(stream, header);
+            IOUtils.readFully(tis, header);
             String version = new String(header, 0, 6, "US-ASCII");
 
             XHTMLContentHandler xhtml = new XHTMLContentHandler(handler, metadata);
@@ -110,14 +111,14 @@ public class DWGParser extends AbstractDWGParser {
             switch (version) {
                 case "AC1015":
                     metadata.set(Metadata.CONTENT_TYPE, TYPE.toString());
-                    if (skipTo2000PropertyInfoSection(stream, header)) {
-                        get2000Props(stream, metadata, xhtml);
+                    if (skipTo2000PropertyInfoSection(tis, header)) {
+                        get2000Props(tis, metadata, xhtml);
                     }
                     break;
                 case "AC1018":
                     metadata.set(Metadata.CONTENT_TYPE, TYPE.toString());
-                    if (skipToPropertyInfoSection(stream, header)) {
-                        get2004Props(stream, metadata, xhtml);
+                    if (skipToPropertyInfoSection(tis, header)) {
+                        get2004Props(tis, metadata, xhtml);
                     }
                     break;
                 case "AC1027":
@@ -125,8 +126,8 @@ public class DWGParser extends AbstractDWGParser {
                 case "AC1021":
                 case "AC1024":
                     metadata.set(Metadata.CONTENT_TYPE, TYPE.toString());
-                    if (skipToPropertyInfoSection(stream, header)) {
-                        get2007and2010Props(stream, metadata, xhtml);
+                    if (skipToPropertyInfoSection(tis, header)) {
+                        get2007and2010Props(tis, metadata, xhtml);
                     }
                     break;
                 default:
@@ -140,30 +141,30 @@ public class DWGParser extends AbstractDWGParser {
     /**
      * Stored as US-ASCII
      */
-    private void get2004Props(InputStream stream, Metadata metadata, XHTMLContentHandler xhtml)
+    private void get2004Props(InputStream tis, Metadata metadata, XHTMLContentHandler xhtml)
             throws IOException, TikaException, SAXException {
         // Standard properties
         for (int i = 0; i < HEADER_PROPERTIES_ENTRIES.length; i++) {
-            String headerValue = read2004String(stream);
+            String headerValue = read2004String(tis);
             handleHeader(i, headerValue, metadata, xhtml);
         }
 
         // Custom properties
-        int customCount = skipToCustomProperties(stream);
+        int customCount = skipToCustomProperties(tis);
         for (int i = 0; i < customCount; i++) {
-            String propName = read2004String(stream);
-            String propValue = read2004String(stream);
+            String propName = read2004String(tis);
+            String propValue = read2004String(tis);
             if (propName.length() > 0 && propValue.length() > 0) {
                 metadata.add(DWG_CUSTOM_META_PREFIX + propName, propValue);
             }
         }
     }
 
-    private String read2004String(InputStream stream) throws IOException, TikaException {
-        int stringLen = EndianUtils.readUShortLE(stream);
+    private String read2004String(InputStream tis) throws IOException, TikaException {
+        int stringLen = EndianUtils.readUShortLE(tis);
 
         byte[] stringData = new byte[stringLen];
-        IOUtils.readFully(stream, stringData);
+        IOUtils.readFully(tis, stringData);
 
         // Often but not always null terminated
         if (stringData[stringLen - 1] == 0) {
@@ -175,30 +176,30 @@ public class DWGParser extends AbstractDWGParser {
     /**
      * Stored as UCS2, so 16 bit "unicode"
      */
-    private void get2007and2010Props(InputStream stream, Metadata metadata, XHTMLContentHandler xhtml)
+    private void get2007and2010Props(InputStream tis, Metadata metadata, XHTMLContentHandler xhtml)
             throws IOException, TikaException, SAXException {
         // Standard properties
         for (int i = 0; i < HEADER_PROPERTIES_ENTRIES.length; i++) {
-            String headerValue = read2007and2010String(stream);
+            String headerValue = read2007and2010String(tis);
             handleHeader(i, headerValue, metadata, xhtml);
         }
 
         // Custom properties
-        int customCount = skipToCustomProperties(stream);
+        int customCount = skipToCustomProperties(tis);
         for (int i = 0; i < customCount; i++) {
-            String propName = read2007and2010String(stream);
-            String propValue = read2007and2010String(stream);
+            String propName = read2007and2010String(tis);
+            String propValue = read2007and2010String(tis);
             if (propName.length() > 0 && propValue.length() > 0) {
                 metadata.add(DWG_CUSTOM_META_PREFIX + propName, propValue);
             }
         }
     }
 
-    private String read2007and2010String(InputStream stream) throws IOException, TikaException {
-        int stringLen = EndianUtils.readUShortLE(stream);
+    private String read2007and2010String(InputStream tis) throws IOException, TikaException {
+        int stringLen = EndianUtils.readUShortLE(tis);
 
         byte[] stringData = new byte[stringLen * 2];
-        IOUtils.readFully(stream, stringData);
+        IOUtils.readFully(tis, stringData);
         String value = StringUtil.getFromUnicodeLE(stringData);
 
         // Some strings are null terminated
@@ -209,13 +210,13 @@ public class DWGParser extends AbstractDWGParser {
         return value;
     }
 
-    private void get2000Props(InputStream stream, Metadata metadata, XHTMLContentHandler xhtml)
+    private void get2000Props(InputStream tis, Metadata metadata, XHTMLContentHandler xhtml)
             throws IOException, TikaException, SAXException {
         int propCount = 0;
         while (propCount < 30) {
-            int propIdx = EndianUtils.readUShortLE(stream);
-            int length = EndianUtils.readUShortLE(stream);
-            int valueType = stream.read();
+            int propIdx = EndianUtils.readUShortLE(tis);
+            int length = EndianUtils.readUShortLE(tis);
+            int valueType = tis.read();
 
             if (propIdx == 0x28) {
                 // This one seems not to follow the pattern
@@ -226,7 +227,7 @@ public class DWGParser extends AbstractDWGParser {
             }
 
             byte[] value = new byte[length];
-            IOUtils.readFully(stream, value);
+            IOUtils.readFully(tis, value);
             if (valueType == 0x1e) {
                 // Normal string, good
                 String val = StringUtil.getFromCompressedUnicode(value, 0, length);
@@ -268,7 +269,7 @@ public class DWGParser extends AbstractDWGParser {
     /**
      * Grab the offset, then skip there
      */
-    private boolean skipToPropertyInfoSection(InputStream stream, byte[] header) throws IOException, TikaException {
+    private boolean skipToPropertyInfoSection(InputStream tis, byte[] header) throws IOException, TikaException {
         // The offset is stored in the header from 0x20 onwards
         long offsetToSection = EndianUtils.getLongLE(header, 0x20);
 
@@ -285,7 +286,7 @@ public class DWGParser extends AbstractDWGParser {
         if (offsetToSection == 0) {
             return false;
         }
-        IOUtils.skipFully(stream, toSkip);
+        IOUtils.skipFully(tis, toSkip);
 
         return true;
     }
@@ -293,14 +294,14 @@ public class DWGParser extends AbstractDWGParser {
     /**
      * We think it can be anywhere...
      */
-    private boolean skipTo2000PropertyInfoSection(InputStream stream, byte[] header) throws IOException {
+    private boolean skipTo2000PropertyInfoSection(InputStream tis, byte[] header) throws IOException {
         int val = 0;
         while (val != -1) {
-            val = stream.read();
+            val = tis.read();
             if (val == HEADER_2000_PROPERTIES_MARKER[0]) {
                 boolean going = true;
                 for (int i = 1; i < HEADER_2000_PROPERTIES_MARKER.length && going; i++) {
-                    val = stream.read();
+                    val = tis.read();
                     if (val != HEADER_2000_PROPERTIES_MARKER[i]) {
                         going = false;
                     }
@@ -314,10 +315,10 @@ public class DWGParser extends AbstractDWGParser {
         return false;
     }
 
-    private int skipToCustomProperties(InputStream stream) throws IOException, TikaException {
+    private int skipToCustomProperties(InputStream tis) throws IOException, TikaException {
         // There should be 4 zero bytes or CUSTOM_PROPERTIES_ALT_PADDING_VALUES next
         byte[] padding = new byte[4];
-        IOUtils.readFully(stream, padding);
+        IOUtils.readFully(tis, padding);
         if ((padding[0] == 0 && padding[1] == 0 && padding[2] == 0 && padding[3] == 0)
                 || (padding[0] == CUSTOM_PROPERTIES_ALT_PADDING_VALUES[0]
                         && padding[1] == CUSTOM_PROPERTIES_ALT_PADDING_VALUES[1]
@@ -326,10 +327,10 @@ public class DWGParser extends AbstractDWGParser {
 
             // Looks hopeful, skip on
             padding = new byte[CUSTOM_PROPERTIES_SKIP];
-            IOUtils.readFully(stream, padding);
+            IOUtils.readFully(tis, padding);
 
             // We should now have the count
-            int count = EndianUtils.readUShortLE(stream);
+            int count = EndianUtils.readUShortLE(tis);
 
             // Plausibilitu check it
             if (count > 0 && count < 0x7f) {
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/main/java/org/apache/tika/parser/dwg/DWGReadParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/main/java/org/apache/tika/parser/dwg/DWGReadParser.java
index 50e4ce1b51..2ad4196090 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/main/java/org/apache/tika/parser/dwg/DWGReadParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/main/java/org/apache/tika/parser/dwg/DWGReadParser.java
@@ -21,7 +21,6 @@ import java.io.BufferedWriter;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.OutputStreamWriter;
 import java.nio.charset.StandardCharsets;
@@ -49,6 +48,7 @@ import org.xml.sax.SAXException;
 
 import org.apache.tika.config.TikaComponent;
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
 import org.apache.tika.mime.MediaType;
@@ -96,7 +96,7 @@ public class DWGReadParser extends AbstractDWGParser {
     }
 
     @Override
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata, ParseContext context)
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata, ParseContext context)
             throws IOException, SAXException, TikaException {
 
         configure(context);
@@ -111,7 +111,7 @@ public class DWGReadParser extends AbstractDWGParser {
         try {
             
 
-            FileUtils.copyInputStreamToFile(stream, tmpFileIn);
+            FileUtils.copyInputStreamToFile(tis, tmpFileIn);
 
             List<String> command = Arrays.asList(dwgc.getDwgReadExecutable(), "-O", "JSON", "-o",
                     tmpFileOut.getCanonicalPath(), tmpFileIn.getCanonicalPath());
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/main/java/org/apache/tika/parser/prt/PRTParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/main/java/org/apache/tika/parser/prt/PRTParser.java
index 4eee2abf82..8fd33eea63 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/main/java/org/apache/tika/parser/prt/PRTParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/main/java/org/apache/tika/parser/prt/PRTParser.java
@@ -31,6 +31,7 @@ import org.xml.sax.SAXException;
 import org.apache.tika.config.TikaComponent;
 import org.apache.tika.exception.TikaException;
 import org.apache.tika.io.EndianUtils;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
 import org.apache.tika.mime.MediaType;
@@ -72,7 +73,7 @@ public class PRTParser implements Parser {
      *  Note - all text is null terminated
      */
 
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
 
         XHTMLContentHandler xhtml = new XHTMLContentHandler(handler, metadata);
@@ -81,9 +82,9 @@ public class PRTParser implements Parser {
 
         // Try to get the creation date, which is YYYYMMDDhhmm
         byte[] header = new byte[30];
-        IOUtils.readFully(stream, header);
+        IOUtils.readFully(tis, header);
         byte[] date = new byte[12];
-        IOUtils.readFully(stream, date);
+        IOUtils.readFully(tis, date);
 
         String dateStr = new String(date, US_ASCII);
         if (dateStr.startsWith("19") || dateStr.startsWith("20")) {
@@ -98,26 +99,26 @@ public class PRTParser implements Parser {
 
         // The description, if set, is the next up-to-500 bytes
         byte[] desc = new byte[500];
-        IOUtils.readFully(stream, desc);
+        IOUtils.readFully(tis, desc);
         String description = extractText(desc, true);
         if (description.length() > 0) {
             metadata.set(TikaCoreProperties.DESCRIPTION, description);
         }
 
         // Now look for text
-        while ((read = stream.read()) > -1) {
+        while ((read = tis.read()) > -1) {
             if (read == 0xe0 || read == 0xe3 || read == 0xf0) {
-                int nread = stream.read();
+                int nread = tis.read();
                 if (nread == 0x3f || nread == 0xbf) {
                     // Looks promising, check back for a suitable value
                     if (read == 0xe3 && nread == 0x3f) {
                         if (l5.is33()) {
                             // Bingo, note text
-                            handleNoteText(stream, xhtml);
+                            handleNoteText(tis, xhtml);
                         }
                     } else if (l5.is00()) {
                         // Likely view name
-                        handleViewName(read, nread, stream, xhtml, l5);
+                        handleViewName(read, nread, tis, xhtml, l5);
                     }
                 }
             } else {
@@ -126,12 +127,12 @@ public class PRTParser implements Parser {
         }
     }
 
-    private void handleNoteText(InputStream stream, XHTMLContentHandler xhtml)
+    private void handleNoteText(InputStream tis, XHTMLContentHandler xhtml)
             throws IOException, SAXException, TikaException {
         // Ensure we have the right padding text
         int read;
         for (int i = 0; i < 10; i++) {
-            read = stream.read();
+            read = tis.read();
             if (read >= 0 && read <= 0x0f) {
                 // Promising
             } else {
@@ -139,27 +140,27 @@ public class PRTParser implements Parser {
                 return;
             }
         }
-        read = stream.read();
+        read = tis.read();
         if (read != 0x1f) {
             // Wrong, false detection
             return;
         }
 
-        int length = EndianUtils.readUShortLE(stream);
+        int length = EndianUtils.readUShortLE(tis);
         if (length <= MAX_TEXT_LENGTH) {
             // Length check passed
-            handleText(length, stream, xhtml);
+            handleText(length, tis, xhtml);
         }
     }
 
-    private void handleViewName(int typeA, int typeB, InputStream stream, XHTMLContentHandler xhtml,
+    private void handleViewName(int typeA, int typeB, InputStream tis, XHTMLContentHandler xhtml,
                                 Last5 l5) throws IOException, SAXException, TikaException {
         // Is it 8 byte zero padded?
-        int maybeLength = EndianUtils.readUShortLE(stream);
+        int maybeLength = EndianUtils.readUShortLE(tis);
         if (maybeLength == 0) {
             // Check the next 6 bytes too
             for (int i = 0; i < 6; i++) {
-                int read = stream.read();
+                int read = tis.read();
                 if (read >= 0 && read <= 0x0f) {
                     // Promising
                 } else {
@@ -169,11 +170,11 @@ public class PRTParser implements Parser {
             }
 
             byte[] b2 = new byte[2];
-            IOUtils.readFully(stream, b2);
+            IOUtils.readFully(tis, b2);
             int length = EndianUtils.getUShortLE(b2);
             if (length > 1 && length <= MAX_TEXT_LENGTH) {
                 // Length check passed
-                handleText(length, stream, xhtml);
+                handleText(length, tis, xhtml);
             } else {
                 // Was probably something else
                 l5.record(b2[0]);
@@ -181,14 +182,14 @@ public class PRTParser implements Parser {
             }
         } else if (maybeLength > 0 && maybeLength < MAX_TEXT_LENGTH) {
             // Looks like it's straight into the text
-            handleText(maybeLength, stream, xhtml);
+            handleText(maybeLength, tis, xhtml);
         }
     }
 
-    private void handleText(int length, InputStream stream, XHTMLContentHandler xhtml)
+    private void handleText(int length, InputStream tis, XHTMLContentHandler xhtml)
             throws IOException, SAXException, TikaException {
         byte[] str = new byte[length];
-        IOUtils.readFully(stream, str);
+        IOUtils.readFully(tis, str);
         if (str[length - 1] != 0) {
             // Not properly null terminated, must be wrong
             return;
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/test/java/org/apache/tika/parser/dwg/DWGParserTest.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/test/java/org/apache/tika/parser/dwg/DWGParserTest.java
index a6dbf34219..7c04e8b856 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/test/java/org/apache/tika/parser/dwg/DWGParserTest.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/test/java/org/apache/tika/parser/dwg/DWGParserTest.java
@@ -24,7 +24,6 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.api.Assumptions.assumeTrue;
 
-import java.io.InputStream;
 import java.nio.file.Files;
 import java.nio.file.Paths;
 import java.util.Arrays;
@@ -35,6 +34,7 @@ import org.xml.sax.ContentHandler;
 import org.apache.tika.TikaTest;
 import org.apache.tika.config.loader.TikaLoader;
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
 import org.apache.tika.parser.CompositeParser;
@@ -58,49 +58,49 @@ public class DWGParserTest extends TikaTest {
     }
     @Test
     public void testDWG2000Parser() throws Exception {
-        InputStream input =
-                DWGParserTest.class.getResourceAsStream("/test-documents/testDWG2000.dwg");
+        TikaInputStream input = TikaInputStream.get(
+                DWGParserTest.class.getResourceAsStream("/test-documents/testDWG2000.dwg"));
         testParserAlt(input);
     }
 
     @Test
     public void testDWG2004Parser() throws Exception {
-        InputStream input =
-                DWGParserTest.class.getResourceAsStream("/test-documents/testDWG2004.dwg");
+        TikaInputStream input = TikaInputStream.get(
+                DWGParserTest.class.getResourceAsStream("/test-documents/testDWG2004.dwg"));
         testParser(input);
     }
 
     @Test
     public void testDWG2004ParserNoHeaderAddress() throws Exception {
-        InputStream input = DWGParserTest.class
-                .getResourceAsStream("/test-documents/testDWG2004_no_header.dwg");
+        TikaInputStream input = TikaInputStream.get(DWGParserTest.class
+                .getResourceAsStream("/test-documents/testDWG2004_no_header.dwg"));
         testParserNoHeader(input);
     }
 
     @Test
     public void testDWG2007Parser() throws Exception {
-        InputStream input =
-                DWGParserTest.class.getResourceAsStream("/test-documents/testDWG2007.dwg");
+        TikaInputStream input = TikaInputStream.get(
+                DWGParserTest.class.getResourceAsStream("/test-documents/testDWG2007.dwg"));
         testParser(input);
     }
 
     @Test
     public void testDWG2010Parser() throws Exception {
-        InputStream input =
-                DWGParserTest.class.getResourceAsStream("/test-documents/testDWG2010.dwg");
+        TikaInputStream input = TikaInputStream.get(
+                DWGParserTest.class.getResourceAsStream("/test-documents/testDWG2010.dwg"));
         testParser(input);
     }
 
     @Test
     public void testDWG2010CustomPropertiesParser() throws Exception {
         // Check that standard parsing works
-        InputStream testInput = DWGParserTest.class
-                .getResourceAsStream("/test-documents/testDWG2010_custom_props.dwg");
+        TikaInputStream testInput = TikaInputStream.get(DWGParserTest.class
+                .getResourceAsStream("/test-documents/testDWG2010_custom_props.dwg"));
         testParser(testInput);
 
         // Check that custom properties with alternate padding work
-        try (InputStream input = DWGParserTest.class
-                .getResourceAsStream("/test-documents/testDWG2010_custom_props.dwg")) {
+        try (TikaInputStream input = TikaInputStream.get(DWGParserTest.class
+                .getResourceAsStream("/test-documents/testDWG2010_custom_props.dwg"))) {
             Metadata metadata = new Metadata();
             ContentHandler handler = new BodyContentHandler();
             new DWGParser().parse(input, handler, metadata,new ParseContext());
@@ -118,14 +118,14 @@ public class DWGParserTest extends TikaTest {
                 new String[]{"6", "2004", "2004DX", "2005", "2006", "2007", "2008", "2009", "2010",
                         "2011"};
         for (String type : types) {
-            InputStream input = DWGParserTest.class
-                    .getResourceAsStream("/test-documents/testDWGmech" + type + ".dwg");
+            TikaInputStream input = TikaInputStream.get(DWGParserTest.class
+                    .getResourceAsStream("/test-documents/testDWGmech" + type + ".dwg"));
             testParserAlt(input);
         }
     }
 
 
-    private void testParser(InputStream input) throws Exception {
+    private void testParser(TikaInputStream input) throws Exception {
         try {
             Metadata metadata = new Metadata();
             ContentHandler handler = new BodyContentHandler();
@@ -153,7 +153,7 @@ public class DWGParserTest extends TikaTest {
     }
 
 
-    private void testParserNoHeader(InputStream input) throws Exception {
+    private void testParserNoHeader(TikaInputStream input) throws Exception {
         try {
             Metadata metadata = new Metadata();
             ContentHandler handler = new BodyContentHandler();
@@ -175,7 +175,7 @@ public class DWGParserTest extends TikaTest {
         }
     }
 
-    private void testParserAlt(InputStream input) throws Exception {
+    private void testParserAlt(TikaInputStream input) throws Exception {
         try {
             Metadata metadata = new Metadata();
             ContentHandler handler = new BodyContentHandler();
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/test/java/org/apache/tika/parser/prt/PRTParserTest.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/test/java/org/apache/tika/parser/prt/PRTParserTest.java
index d1243fd722..9cacadb47b 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/test/java/org/apache/tika/parser/prt/PRTParserTest.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-cad-module/src/test/java/org/apache/tika/parser/prt/PRTParserTest.java
@@ -18,12 +18,11 @@ package org.apache.tika.parser.prt;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
-import java.io.InputStream;
-
 import org.junit.jupiter.api.Test;
 import org.xml.sax.ContentHandler;
 
 import org.apache.tika.TikaTest;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
 import org.apache.tika.parser.ParseContext;
@@ -35,7 +34,7 @@ public class PRTParserTest extends TikaTest {
      */
     @Test
     public void testPRTParserBasics() throws Exception {
-        try (InputStream input = getResourceAsStream("/test-documents/testCADKEY.prt")) {
+        try (TikaInputStream input = getResourceAsStream("/test-documents/testCADKEY.prt")) {
             Metadata metadata = new Metadata();
             ContentHandler handler = new BodyContentHandler();
             new PRTParser().parse(input, handler, metadata, new ParseContext());
@@ -69,7 +68,7 @@ public class PRTParserTest extends TikaTest {
      */
     @Test
     public void testPRTParserComplex() throws Exception {
-        try (InputStream input = getResourceAsStream("/test-documents/testCADKEY2.prt")) {
+        try (TikaInputStream input = getResourceAsStream("/test-documents/testCADKEY2.prt")) {
             Metadata metadata = new Metadata();
             ContentHandler handler = new BodyContentHandler();
             new PRTParser().parse(input, handler, metadata, new ParseContext());
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/java/org/apache/tika/parser/asm/ClassParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/java/org/apache/tika/parser/asm/ClassParser.java
index 58c488df72..d06f3dcd5d 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/java/org/apache/tika/parser/asm/ClassParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/java/org/apache/tika/parser/asm/ClassParser.java
@@ -17,7 +17,6 @@
 package org.apache.tika.parser.asm;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.util.Collections;
 import java.util.Set;
 
@@ -26,6 +25,7 @@ import org.xml.sax.SAXException;
 
 import org.apache.tika.config.TikaComponent;
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
 import org.apache.tika.parser.ParseContext;
@@ -49,9 +49,9 @@ public class ClassParser implements Parser {
         return SUPPORTED_TYPES;
     }
 
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
-        new XHTMLClassVisitor(handler, metadata).parse(stream);
+        new XHTMLClassVisitor(handler, metadata).parse(tis);
     }
 
 }
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/java/org/apache/tika/parser/code/SourceCodeParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/java/org/apache/tika/parser/code/SourceCodeParser.java
index e6580a6ce7..97802427bc 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/java/org/apache/tika/parser/code/SourceCodeParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/java/org/apache/tika/parser/code/SourceCodeParser.java
@@ -21,7 +21,6 @@ import static org.codelibs.jhighlight.renderer.XhtmlRendererFactory.GROOVY;
 import static org.codelibs.jhighlight.renderer.XhtmlRendererFactory.JAVA;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.nio.charset.Charset;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -50,6 +49,7 @@ import org.apache.tika.config.TikaComponent;
 import org.apache.tika.detect.AutoDetectReader;
 import org.apache.tika.detect.EncodingDetector;
 import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
 import org.apache.tika.mime.MediaType;
@@ -95,9 +95,9 @@ public class SourceCodeParser extends AbstractEncodingDetectorParser {
     }
 
     @Override
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata, ParseContext context)
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata, ParseContext context)
             throws IOException, SAXException, TikaException {
-        try (AutoDetectReader reader = new AutoDetectReader(CloseShieldInputStream.wrap(stream),
+        try (AutoDetectReader reader = new AutoDetectReader(CloseShieldInputStream.wrap(tis),
                 metadata, getEncodingDetector(context))) {
             Charset charset = reader.getCharset();
             String mediaType = metadata.get(Metadata.CONTENT_TYPE);
diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/java/org/apache/tika/parser/executable/ExecutableParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/java/org/apache/tika/parser/executable/ExecutableParser.java
index 18a1b40533..6ef0baa876 100644
--- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/java/org/apache/tika/parser/executable/ExecutableParser.java
+++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-code-module/src/main/java/org/apache/tika/parser/executable/ExecutableParser.java
@@ -31,6 +31,7 @@ import org.xml.sax.SAXException;
 import org.apache.tika.config.TikaComponent;
 import org.apache.tika.exception.TikaException;
 import org.apache.tika.io.EndianUtils;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.MachineMetadata;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
@@ -81,27 +82,27 @@ public class ExecutableParser implements Parser, MachineMetadata {
         return SUPPORTED_TYPES;
     }
 
-    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata,
                       ParseContext context) throws IOException, SAXException, TikaException {
         // We only do metadata, for now
         XHTMLContentHandler xhtml = new XHTMLContentHandler(handler, metadata);
         xhtml.startDocument();
         // What kind is it?
         byte[] first4 = new byte[4];
-        IOUtils.readFully(stream, first4);
+        IOUtils.readFully(tis, first4);
 
         if (first4[0] == (byte) 'M' && first4[1] == (byte) 'Z') {
-            parsePE(xhtml, metadata, stream, first4);
+            parsePE(xhtml, metadata, tis, first4);
         } else if (first4[0] == (byte) 0x7f && first4[1] == (byte) 'E' && first4[2] == (byte) 'L' &&
                 first4[3] == (byte) 'F') {
-            parseELF(xhtml, metadata, stream, first4);
+            parseELF(xhtml, metadata, tis, first4);
         } else if ((first4[0] == (byte) 0xCF || first4[0] == (byte) 0xCE) &&
                 first4[1] == (byte) 0xFA && first4[2] == (byte) 0xED && first4[3] == (byte) 0xFE) {
-            parseMachO(xhtml, metadata, stream, first4);
+            parseMachO(xhtml, metadata, tis, first4);
         } else if (first4[0] == (byte) 0xFE && first4[1] == (byte) 0xED &&
                 first4[2] == (byte) 0xFA &&
                 (first4[3] == (byte) 0xCF || first4[3] == (byte) 0xCE)) {
-            parseMachO(xhtml, metadata, stream, first4);
+            parseMachO(xhtml, metadata, tis, first4);
         }
 
 
@@ -112,17 +113,17 @@ public class ExecutableParser implements Parser, MachineMetadata {
     /**
      * Parses a DOS or Windows PE file
      */
-    public void parsePE(XHTMLContentHandler xhtml, Metadata metadata, InputStream stream,
+    public void parsePE(XHTMLContentHandler xhtml, Metadata metadata, InputStream tis,
                         byte[] first4) throws TikaException, IOException {
         metadata.set(Metadata.CONTENT_TYPE, PE_EXE.toString());
         metadata.set(PLATFORM, PLATFORM_WINDOWS);
 
         // Skip over the MS-DOS bit
         byte[] msdosSection = new byte[0x3c - 4];
-        IOUtils.readFully(stream, msdosSection);
+        IOUtils.readFully(tis, msdosSection);
 
         // Grab the PE header offset
-        int peOffset = EndianUtils.readIntLE(stream);
+        int peOffset = EndianUtils.readIntLE(tis);
 
... 11860 lines suppressed ...