001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.commons.compress.compressors; 020 021import java.io.IOException; 022import java.io.InputStream; 023import java.io.OutputStream; 024import java.security.AccessController; 025import java.security.PrivilegedAction; 026import java.util.ArrayList; 027import java.util.Collections; 028import java.util.Iterator; 029import java.util.Locale; 030import java.util.Set; 031import java.util.SortedMap; 032import java.util.TreeMap; 033 034import org.apache.commons.compress.compressors.brotli.BrotliCompressorInputStream; 035import org.apache.commons.compress.compressors.brotli.BrotliUtils; 036import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream; 037import org.apache.commons.compress.compressors.bzip2.BZip2CompressorOutputStream; 038import org.apache.commons.compress.compressors.deflate.DeflateCompressorInputStream; 039import org.apache.commons.compress.compressors.deflate.DeflateCompressorOutputStream; 040import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; 041import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream; 042import org.apache.commons.compress.compressors.lz4.BlockLZ4CompressorInputStream; 043import org.apache.commons.compress.compressors.lz4.BlockLZ4CompressorOutputStream; 044import org.apache.commons.compress.compressors.lz4.FramedLZ4CompressorInputStream; 045import org.apache.commons.compress.compressors.lz4.FramedLZ4CompressorOutputStream; 046import org.apache.commons.compress.compressors.lzma.LZMACompressorInputStream; 047import org.apache.commons.compress.compressors.lzma.LZMACompressorOutputStream; 048import org.apache.commons.compress.compressors.lzma.LZMAUtils; 049import org.apache.commons.compress.compressors.pack200.Pack200CompressorInputStream; 050import org.apache.commons.compress.compressors.pack200.Pack200CompressorOutputStream; 051import org.apache.commons.compress.compressors.snappy.FramedSnappyCompressorInputStream; 052import org.apache.commons.compress.compressors.snappy.FramedSnappyCompressorOutputStream; 053import org.apache.commons.compress.compressors.snappy.SnappyCompressorInputStream; 054import org.apache.commons.compress.compressors.xz.XZCompressorInputStream; 055import org.apache.commons.compress.compressors.xz.XZCompressorOutputStream; 056import org.apache.commons.compress.compressors.xz.XZUtils; 057import org.apache.commons.compress.compressors.z.ZCompressorInputStream; 058import org.apache.commons.compress.utils.IOUtils; 059import org.apache.commons.compress.utils.Lists; 060import org.apache.commons.compress.utils.ServiceLoaderIterator; 061import org.apache.commons.compress.utils.Sets; 062 063/** 064 * <p> 065 * Factory to create Compressor[In|Out]putStreams from names. To add other 066 * implementations you should extend CompressorStreamFactory and override the 067 * appropriate methods (and call their implementation from super of course). 068 * </p> 069 * 070 * Example (Compressing a file): 071 * 072 * <pre> 073 * final OutputStream out = Files.newOutputStream(output.toPath()); 074 * CompressorOutputStream cos = new CompressorStreamFactory() 075 * .createCompressorOutputStream(CompressorStreamFactory.BZIP2, out); 076 * IOUtils.copy(Files.newInputStream(input.toPath()), cos); 077 * cos.close(); 078 * </pre> 079 * 080 * Example (Decompressing a file): 081 * 082 * <pre> 083 * final InputStream is = Files.newInputStream(input.toPath()); 084 * CompressorInputStream in = new CompressorStreamFactory().createCompressorInputStream(CompressorStreamFactory.BZIP2, 085 * is); 086 * IOUtils.copy(in, Files.newOutputStream(output.toPath())); 087 * in.close(); 088 * </pre> 089 * 090 * @Immutable provided that the deprecated method setDecompressConcatenated is 091 * not used. 092 * @ThreadSafe even if the deprecated method setDecompressConcatenated is used 093 */ 094public class CompressorStreamFactory implements CompressorStreamProvider { 095 096 private static final CompressorStreamFactory SINGLETON = new CompressorStreamFactory(); 097 098 099 100 /** 101 * Constant (value {@value}) used to identify the BROTLI compression 102 * algorithm. 103 * 104 * @since 1.14 105 */ 106 public static final String BROTLI = "br"; 107 108 /** 109 * Constant (value {@value}) used to identify the BZIP2 compression 110 * algorithm. 111 * 112 * @since 1.1 113 */ 114 public static final String BZIP2 = "bzip2"; 115 116 /** 117 * Constant (value {@value}) used to identify the GZIP compression 118 * algorithm. 119 * 120 * @since 1.1 121 */ 122 public static final String GZIP = "gz"; 123 124 /** 125 * Constant (value {@value}) used to identify the PACK200 compression 126 * algorithm. 127 * 128 * @since 1.3 129 */ 130 public static final String PACK200 = "pack200"; 131 132 /** 133 * Constant (value {@value}) used to identify the XZ compression method. 134 * 135 * @since 1.4 136 */ 137 public static final String XZ = "xz"; 138 139 /** 140 * Constant (value {@value}) used to identify the LZMA compression method. 141 * 142 * @since 1.6 143 */ 144 public static final String LZMA = "lzma"; 145 146 /** 147 * Constant (value {@value}) used to identify the "framed" Snappy 148 * compression method. 149 * 150 * @since 1.7 151 */ 152 public static final String SNAPPY_FRAMED = "snappy-framed"; 153 154 /** 155 * Constant (value {@value}) used to identify the "raw" Snappy compression 156 * method. Not supported as an output stream type. 157 * 158 * @since 1.7 159 */ 160 public static final String SNAPPY_RAW = "snappy-raw"; 161 162 /** 163 * Constant (value {@value}) used to identify the traditional Unix compress 164 * method. Not supported as an output stream type. 165 * 166 * @since 1.7 167 */ 168 public static final String Z = "z"; 169 170 /** 171 * Constant (value {@value}) used to identify the Deflate compress method. 172 * 173 * @since 1.9 174 */ 175 public static final String DEFLATE = "deflate"; 176 177 /** 178 * Constant (value {@value}) used to identify the block LZ4 179 * compression method. 180 * 181 * @since 1.14 182 */ 183 public static final String LZ4_BLOCK = "lz4-block"; 184 185 /** 186 * Constant (value {@value}) used to identify the frame LZ4 187 * compression method. 188 * 189 * @since 1.14 190 */ 191 public static final String LZ4_FRAMED = "lz4-framed"; 192 193 /** 194 * Constructs a new sorted map from input stream provider names to provider 195 * objects. 196 * 197 * <p> 198 * The map returned by this method will have one entry for each provider for 199 * which support is available in the current Java virtual machine. If two or 200 * more supported provider have the same name then the resulting map will 201 * contain just one of them; which one it will contain is not specified. 202 * </p> 203 * 204 * <p> 205 * The invocation of this method, and the subsequent use of the resulting 206 * map, may cause time-consuming disk or network I/O operations to occur. 207 * This method is provided for applications that need to enumerate all of 208 * the available providers, for example to allow user provider selection. 209 * </p> 210 * 211 * <p> 212 * This method may return different results at different times if new 213 * providers are dynamically made available to the current Java virtual 214 * machine. 215 * </p> 216 * 217 * @return An immutable, map from names to provider objects 218 * @since 1.13 219 */ 220 public static SortedMap<String, CompressorStreamProvider> findAvailableCompressorInputStreamProviders() { 221 return AccessController.doPrivileged(new PrivilegedAction<SortedMap<String, CompressorStreamProvider>>() { 222 @Override 223 public SortedMap<String, CompressorStreamProvider> run() { 224 final TreeMap<String, CompressorStreamProvider> map = new TreeMap<>(); 225 putAll(SINGLETON.getInputStreamCompressorNames(), SINGLETON, map); 226 for (final CompressorStreamProvider provider : findCompressorStreamProviders()) { 227 putAll(provider.getInputStreamCompressorNames(), provider, map); 228 } 229 return map; 230 } 231 }); 232 } 233 234 /** 235 * Constructs a new sorted map from output stream provider names to provider 236 * objects. 237 * 238 * <p> 239 * The map returned by this method will have one entry for each provider for 240 * which support is available in the current Java virtual machine. If two or 241 * more supported provider have the same name then the resulting map will 242 * contain just one of them; which one it will contain is not specified. 243 * </p> 244 * 245 * <p> 246 * The invocation of this method, and the subsequent use of the resulting 247 * map, may cause time-consuming disk or network I/O operations to occur. 248 * This method is provided for applications that need to enumerate all of 249 * the available providers, for example to allow user provider selection. 250 * </p> 251 * 252 * <p> 253 * This method may return different results at different times if new 254 * providers are dynamically made available to the current Java virtual 255 * machine. 256 * </p> 257 * 258 * @return An immutable, map from names to provider objects 259 * @since 1.13 260 */ 261 public static SortedMap<String, CompressorStreamProvider> findAvailableCompressorOutputStreamProviders() { 262 return AccessController.doPrivileged(new PrivilegedAction<SortedMap<String, CompressorStreamProvider>>() { 263 @Override 264 public SortedMap<String, CompressorStreamProvider> run() { 265 final TreeMap<String, CompressorStreamProvider> map = new TreeMap<>(); 266 putAll(SINGLETON.getOutputStreamCompressorNames(), SINGLETON, map); 267 for (final CompressorStreamProvider provider : findCompressorStreamProviders()) { 268 putAll(provider.getOutputStreamCompressorNames(), provider, map); 269 } 270 return map; 271 } 272 273 }); 274 } 275 private static ArrayList<CompressorStreamProvider> findCompressorStreamProviders() { 276 return Lists.newArrayList(serviceLoaderIterator()); 277 } 278 279 public static String getBrotli() { 280 return BROTLI; 281 } 282 283 public static String getBzip2() { 284 return BZIP2; 285 } 286 287 public static String getDeflate() { 288 return DEFLATE; 289 } 290 291 public static String getGzip() { 292 return GZIP; 293 } 294 295 public static String getLzma() { 296 return LZMA; 297 } 298 299 public static String getPack200() { 300 return PACK200; 301 } 302 303 public static CompressorStreamFactory getSingleton() { 304 return SINGLETON; 305 } 306 307 public static String getSnappyFramed() { 308 return SNAPPY_FRAMED; 309 } 310 311 public static String getSnappyRaw() { 312 return SNAPPY_RAW; 313 } 314 315 public static String getXz() { 316 return XZ; 317 } 318 319 public static String getZ() { 320 return Z; 321 } 322 323 public static String getLZ4Framed() { 324 return LZ4_FRAMED; 325 } 326 327 public static String getLZ4Block() { 328 return LZ4_BLOCK; 329 } 330 331 static void putAll(final Set<String> names, final CompressorStreamProvider provider, 332 final TreeMap<String, CompressorStreamProvider> map) { 333 for (final String name : names) { 334 map.put(toKey(name), provider); 335 } 336 } 337 338 private static Iterator<CompressorStreamProvider> serviceLoaderIterator() { 339 return new ServiceLoaderIterator<>(CompressorStreamProvider.class); 340 } 341 342 private static String toKey(final String name) { 343 return name.toUpperCase(Locale.ROOT); 344 } 345 346 /** 347 * If true, decompress until the end of the input. If false, stop after the 348 * first stream and leave the input position to point to the next byte after 349 * the stream 350 */ 351 private final Boolean decompressUntilEOF; 352 // This is Boolean so setDecompressConcatenated can determine whether it has 353 // been set by the ctor 354 // once the setDecompressConcatenated method has been removed, it can revert 355 // to boolean 356 357 private SortedMap<String, CompressorStreamProvider> compressorInputStreamProviders; 358 359 private SortedMap<String, CompressorStreamProvider> compressorOutputStreamProviders; 360 361 /** 362 * If true, decompress until the end of the input. If false, stop after the 363 * first stream and leave the input position to point to the next byte after 364 * the stream 365 */ 366 private volatile boolean decompressConcatenated = false; 367 368 private final int memoryLimitInKb; 369 /** 370 * Create an instance with the decompress Concatenated option set to false. 371 */ 372 public CompressorStreamFactory() { 373 this.decompressUntilEOF = null; 374 this.memoryLimitInKb = -1; 375 } 376 377 /** 378 * Create an instance with the provided decompress Concatenated option. 379 * 380 * @param decompressUntilEOF 381 * if true, decompress until the end of the input; if false, stop 382 * after the first stream and leave the input position to point 383 * to the next byte after the stream. This setting applies to the 384 * gzip, bzip2 and xz formats only. 385 * 386 * @param memoryLimitInKb 387 * Some streams require allocation of potentially significant 388 * byte arrays/tables, and they can offer checks to prevent OOMs 389 * on corrupt files. Set the maximum allowed memory allocation in KBs. 390 * 391 * @since 1.14 392 */ 393 public CompressorStreamFactory(final boolean decompressUntilEOF, final int memoryLimitInKb) { 394 this.decompressUntilEOF = Boolean.valueOf(decompressUntilEOF); 395 // Also copy to existing variable so can continue to use that as the 396 // current value 397 this.decompressConcatenated = decompressUntilEOF; 398 this.memoryLimitInKb = memoryLimitInKb; 399 } 400 401 402 /** 403 * Create an instance with the provided decompress Concatenated option. 404 * 405 * @param decompressUntilEOF 406 * if true, decompress until the end of the input; if false, stop 407 * after the first stream and leave the input position to point 408 * to the next byte after the stream. This setting applies to the 409 * gzip, bzip2 and xz formats only. 410 * @since 1.10 411 */ 412 public CompressorStreamFactory(final boolean decompressUntilEOF) { 413 this(decompressUntilEOF, -1); 414 } 415 416 /** 417 * Try to detect the type of compressor stream. 418 * 419 * @param in input stream 420 * @return type of compressor stream detected 421 * @throws CompressorException if no compressor stream type was detected 422 * or if something else went wrong 423 * @throws IllegalArgumentException if stream is null or does not support mark 424 * 425 * @since 1.14 426 */ 427 public static String detect(final InputStream in) throws CompressorException { 428 if (in == null) { 429 throw new IllegalArgumentException("Stream must not be null."); 430 } 431 432 if (!in.markSupported()) { 433 throw new IllegalArgumentException("Mark is not supported."); 434 } 435 436 final byte[] signature = new byte[12]; 437 in.mark(signature.length); 438 int signatureLength = -1; 439 try { 440 signatureLength = IOUtils.readFully(in, signature); 441 in.reset(); 442 } catch (IOException e) { 443 throw new CompressorException("IOException while reading signature.", e); 444 } 445 446 if (BZip2CompressorInputStream.matches(signature, signatureLength)) { 447 return BZIP2; 448 } 449 450 if (GzipCompressorInputStream.matches(signature, signatureLength)) { 451 return GZIP; 452 } 453 454 if (Pack200CompressorInputStream.matches(signature, signatureLength)) { 455 return PACK200; 456 } 457 458 if (FramedSnappyCompressorInputStream.matches(signature, signatureLength)) { 459 return SNAPPY_FRAMED; 460 } 461 462 if (ZCompressorInputStream.matches(signature, signatureLength)) { 463 return Z; 464 } 465 466 if (DeflateCompressorInputStream.matches(signature, signatureLength)) { 467 return DEFLATE; 468 } 469 470 if (XZUtils.matches(signature, signatureLength)) { 471 return XZ; 472 } 473 474 if (LZMAUtils.matches(signature, signatureLength)) { 475 return LZMA; 476 } 477 478 if (FramedLZ4CompressorInputStream.matches(signature, signatureLength)) { 479 return LZ4_FRAMED; 480 } 481 482 throw new CompressorException("No Compressor found for the stream signature."); 483 } 484 /** 485 * Create an compressor input stream from an input stream, autodetecting the 486 * compressor type from the first few bytes of the stream. The InputStream 487 * must support marks, like BufferedInputStream. 488 * 489 * @param in 490 * the input stream 491 * @return the compressor input stream 492 * @throws CompressorException 493 * if the compressor name is not known 494 * @throws IllegalArgumentException 495 * if the stream is null or does not support mark 496 * @since 1.1 497 */ 498 public CompressorInputStream createCompressorInputStream(final InputStream in) throws CompressorException { 499 return createCompressorInputStream(detect(in), in); 500 } 501 502 /** 503 * Creates a compressor input stream from a compressor name and an input 504 * stream. 505 * 506 * @param name 507 * of the compressor, i.e. {@value #GZIP}, {@value #BZIP2}, 508 * {@value #XZ}, {@value #LZMA}, {@value #PACK200}, 509 * {@value #SNAPPY_RAW}, {@value #SNAPPY_FRAMED}, {@value #Z}, 510 * {@value #LZ4_BLOCK}, {@value #LZ4_FRAMED} 511 * or {@value #DEFLATE} 512 * @param in 513 * the input stream 514 * @return compressor input stream 515 * @throws CompressorException 516 * if the compressor name is not known or not available, 517 * or if there's an IOException or MemoryLimitException thrown 518 * during initialization 519 * @throws IllegalArgumentException 520 * if the name or input stream is null 521 */ 522 public CompressorInputStream createCompressorInputStream(final String name, final InputStream in) 523 throws CompressorException { 524 return createCompressorInputStream(name, in, decompressConcatenated); 525 } 526 527 @Override 528 public CompressorInputStream createCompressorInputStream(final String name, final InputStream in, 529 final boolean actualDecompressConcatenated) throws CompressorException { 530 if (name == null || in == null) { 531 throw new IllegalArgumentException("Compressor name and stream must not be null."); 532 } 533 534 try { 535 536 if (GZIP.equalsIgnoreCase(name)) { 537 return new GzipCompressorInputStream(in, actualDecompressConcatenated); 538 } 539 540 if (BZIP2.equalsIgnoreCase(name)) { 541 return new BZip2CompressorInputStream(in, actualDecompressConcatenated); 542 } 543 544 if (BROTLI.equalsIgnoreCase(name)) { 545 if (!BrotliUtils.isBrotliCompressionAvailable()) { 546 throw new CompressorException("Brotli compression is not available."); 547 } 548 return new BrotliCompressorInputStream(in); 549 } 550 551 if (XZ.equalsIgnoreCase(name)) { 552 if (!XZUtils.isXZCompressionAvailable()) { 553 throw new CompressorException("XZ compression is not available."); 554 } 555 return new XZCompressorInputStream(in, actualDecompressConcatenated, memoryLimitInKb); 556 } 557 558 if (LZMA.equalsIgnoreCase(name)) { 559 if (!LZMAUtils.isLZMACompressionAvailable()) { 560 throw new CompressorException("LZMA compression is not available"); 561 } 562 return new LZMACompressorInputStream(in, memoryLimitInKb); 563 } 564 565 if (PACK200.equalsIgnoreCase(name)) { 566 return new Pack200CompressorInputStream(in); 567 } 568 569 if (SNAPPY_RAW.equalsIgnoreCase(name)) { 570 return new SnappyCompressorInputStream(in); 571 } 572 573 if (SNAPPY_FRAMED.equalsIgnoreCase(name)) { 574 return new FramedSnappyCompressorInputStream(in); 575 } 576 577 if (Z.equalsIgnoreCase(name)) { 578 return new ZCompressorInputStream(in, memoryLimitInKb); 579 } 580 581 if (DEFLATE.equalsIgnoreCase(name)) { 582 return new DeflateCompressorInputStream(in); 583 } 584 585 if (LZ4_BLOCK.equalsIgnoreCase(name)) { 586 return new BlockLZ4CompressorInputStream(in); 587 } 588 589 if (LZ4_FRAMED.equalsIgnoreCase(name)) { 590 return new FramedLZ4CompressorInputStream(in, actualDecompressConcatenated); 591 } 592 593 } catch (final IOException e) { 594 throw new CompressorException("Could not create CompressorInputStream.", e); 595 } 596 final CompressorStreamProvider compressorStreamProvider = getCompressorInputStreamProviders().get(toKey(name)); 597 if (compressorStreamProvider != null) { 598 return compressorStreamProvider.createCompressorInputStream(name, in, actualDecompressConcatenated); 599 } 600 601 throw new CompressorException("Compressor: " + name + " not found."); 602 } 603 604 /** 605 * Creates an compressor output stream from an compressor name and an output 606 * stream. 607 * 608 * @param name 609 * the compressor name, i.e. {@value #GZIP}, {@value #BZIP2}, 610 * {@value #XZ}, {@value #PACK200}, {@value #SNAPPY_FRAMED}, 611 * {@value #LZ4_BLOCK}, {@value #LZ4_FRAMED} 612 * or {@value #DEFLATE} 613 * @param out 614 * the output stream 615 * @return the compressor output stream 616 * @throws CompressorException 617 * if the archiver name is not known 618 * @throws IllegalArgumentException 619 * if the archiver name or stream is null 620 */ 621 @Override 622 public CompressorOutputStream createCompressorOutputStream(final String name, final OutputStream out) 623 throws CompressorException { 624 if (name == null || out == null) { 625 throw new IllegalArgumentException("Compressor name and stream must not be null."); 626 } 627 628 try { 629 630 if (GZIP.equalsIgnoreCase(name)) { 631 return new GzipCompressorOutputStream(out); 632 } 633 634 if (BZIP2.equalsIgnoreCase(name)) { 635 return new BZip2CompressorOutputStream(out); 636 } 637 638 if (XZ.equalsIgnoreCase(name)) { 639 return new XZCompressorOutputStream(out); 640 } 641 642 if (PACK200.equalsIgnoreCase(name)) { 643 return new Pack200CompressorOutputStream(out); 644 } 645 646 if (LZMA.equalsIgnoreCase(name)) { 647 return new LZMACompressorOutputStream(out); 648 } 649 650 if (DEFLATE.equalsIgnoreCase(name)) { 651 return new DeflateCompressorOutputStream(out); 652 } 653 654 if (SNAPPY_FRAMED.equalsIgnoreCase(name)) { 655 return new FramedSnappyCompressorOutputStream(out); 656 } 657 658 if (LZ4_BLOCK.equalsIgnoreCase(name)) { 659 return new BlockLZ4CompressorOutputStream(out); 660 } 661 662 if (LZ4_FRAMED.equalsIgnoreCase(name)) { 663 return new FramedLZ4CompressorOutputStream(out); 664 } 665 666 } catch (final IOException e) { 667 throw new CompressorException("Could not create CompressorOutputStream", e); 668 } 669 final CompressorStreamProvider compressorStreamProvider = getCompressorOutputStreamProviders().get(toKey(name)); 670 if (compressorStreamProvider != null) { 671 return compressorStreamProvider.createCompressorOutputStream(name, out); 672 } 673 throw new CompressorException("Compressor: " + name + " not found."); 674 } 675 676 public SortedMap<String, CompressorStreamProvider> getCompressorInputStreamProviders() { 677 if (compressorInputStreamProviders == null) { 678 compressorInputStreamProviders = Collections 679 .unmodifiableSortedMap(findAvailableCompressorInputStreamProviders()); 680 } 681 return compressorInputStreamProviders; 682 } 683 684 public SortedMap<String, CompressorStreamProvider> getCompressorOutputStreamProviders() { 685 if (compressorOutputStreamProviders == null) { 686 compressorOutputStreamProviders = Collections 687 .unmodifiableSortedMap(findAvailableCompressorOutputStreamProviders()); 688 } 689 return compressorOutputStreamProviders; 690 } 691 692 // For Unit tests 693 boolean getDecompressConcatenated() { 694 return decompressConcatenated; 695 } 696 697 public Boolean getDecompressUntilEOF() { 698 return decompressUntilEOF; 699 } 700 701 @Override 702 public Set<String> getInputStreamCompressorNames() { 703 return Sets.newHashSet(GZIP, BROTLI, BZIP2, XZ, LZMA, PACK200, DEFLATE, SNAPPY_RAW, SNAPPY_FRAMED, Z, LZ4_BLOCK, 704 LZ4_FRAMED); 705 } 706 707 @Override 708 public Set<String> getOutputStreamCompressorNames() { 709 return Sets.newHashSet(GZIP, BZIP2, XZ, LZMA, PACK200, DEFLATE, SNAPPY_FRAMED, LZ4_BLOCK, LZ4_FRAMED); 710 } 711 712 /** 713 * Whether to decompress the full input or only the first stream in formats 714 * supporting multiple concatenated input streams. 715 * 716 * <p> 717 * This setting applies to the gzip, bzip2 and xz formats only. 718 * </p> 719 * 720 * @param decompressConcatenated 721 * if true, decompress until the end of the input; if false, stop 722 * after the first stream and leave the input position to point 723 * to the next byte after the stream 724 * @since 1.5 725 * @deprecated 1.10 use the {@link #CompressorStreamFactory(boolean)} 726 * constructor instead 727 * @throws IllegalStateException 728 * if the constructor {@link #CompressorStreamFactory(boolean)} 729 * was used to create the factory 730 */ 731 @Deprecated 732 public void setDecompressConcatenated(final boolean decompressConcatenated) { 733 if (this.decompressUntilEOF != null) { 734 throw new IllegalStateException("Cannot override the setting defined by the constructor"); 735 } 736 this.decompressConcatenated = decompressConcatenated; 737 } 738 739}