// Path: api/src/main/java/xyz/docbleach/api/bleach/Bleach.java
// public interface Bleach {
// 
//   /**
//    * Checks the magic header of the file and returns true if this bleach is able to sanitize this
//    * InputStream. The stream has to {@link InputStream#markSupported support mark}.
//    *
//    * <p>The Bleach is responsible for the error handling to prevent exceptions.
//    *
//    * @param stream file from wich we will read the data
//    * @return true if this bleach may handle this file, false otherwise
//    */
//   boolean handlesMagic(InputStream stream);
// 
//   /**
//    * @return this bleach's name
//    */
//   String getName();
// 
//   /**
//    * @param inputStream the file we want to sanitize
//    * @param outputStream the sanitized file this bleach will write to
//    * @param session the bleach session that stores threats
//    * @throws BleachException Any fatal error that might occur during the bleach
//    */
//   void sanitize(InputStream inputStream, OutputStream outputStream, BleachSession session)
//       throws BleachException;
// }
// 
// Path: api/src/main/java/xyz/docbleach/api/exception/BleachException.java
// public class BleachException extends Exception {
// 
//   public BleachException(Throwable e) {
//     super(e);
//   }
// 
//   public BleachException(String message) {
//     super(message);
//   }
// }
// 
// Path: api/src/main/java/xyz/docbleach/api/exception/RecursionBleachException.java
// public class RecursionBleachException extends BleachException {
// 
//   /**
//    * @param depth The depth of the recursion
//    */
//   public RecursionBleachException(int depth) {
//     super("Recursion exploit? There are already " + depth + " sanitation tasks.");
//   }
// }
// 
// Path: api/src/main/java/xyz/docbleach/api/threat/Threat.java
// @AutoValue
// public abstract class Threat {
// 
//   public static Builder builder() {
//     return new AutoValue_Threat.Builder();
//   }
// 
//   @AutoValue.Builder
//   public abstract static class Builder {
// 
//     public abstract Builder type(ThreatType value);
// 
//     public abstract Builder severity(ThreatSeverity value);
// 
//     public abstract Builder action(ThreatAction value);
// 
//     public abstract Builder location(String value);
// 
//     public abstract Builder details(String value);
// 
//     public abstract Threat build();
//   }
// 
//   public abstract ThreatType type();
// 
//   public abstract ThreatSeverity severity();
// 
//   public abstract ThreatAction action();
// 
//   public abstract String location();
// 
//   public abstract String details();
// }


import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import xyz.docbleach.api.bleach.Bleach;
import xyz.docbleach.api.exception.BleachException;
import xyz.docbleach.api.exception.RecursionBleachException;
import xyz.docbleach.api.threat.Threat;
package xyz.docbleach.api;


/**
 * A Bleach Session handles the data a bleach needs to store: list of the threats removed, for
 * instance May be used in the future to store configuration (file's password, for instance) or
 * callbacks
 */
public class BleachSession implements Serializable {

  private static final Logger LOGGER = LoggerFactory.getLogger(BleachSession.class);
  private static final int MAX_ONGOING_TASKS = 10;
  private final transient Bleach bleach;
  private final Collection<Threat> threats = new ArrayList<>();
  /**
   * Counts ongoing tasks, to prevent fork bombs when handling zip archives for instance)
   */
  private int ongoingTasks = 0;

  public BleachSession(Bleach bleach) {
    this.bleach = bleach;
  }

  /**
   * The BleachSession is able to record threats encountered by the bleach.
   *
   * @param threat The removed threat object, containing the threat type and more information
   */
  public void recordThreat(Threat threat) {
// Path: api/src/main/java/xyz/docbleach/api/bleach/Bleach.java
// public interface Bleach {
// 
//   /**
//    * Checks the magic header of the file and returns true if this bleach is able to sanitize this
//    * InputStream. The stream has to {@link InputStream#markSupported support mark}.
//    *
//    * <p>The Bleach is responsible for the error handling to prevent exceptions.
//    *
//    * @param stream file from wich we will read the data
//    * @return true if this bleach may handle this file, false otherwise
//    */
//   boolean handlesMagic(InputStream stream);
// 
//   /**
//    * @return this bleach's name
//    */
//   String getName();
// 
//   /**
//    * @param inputStream the file we want to sanitize
//    * @param outputStream the sanitized file this bleach will write to
//    * @param session the bleach session that stores threats
//    * @throws BleachException Any fatal error that might occur during the bleach
//    */
//   void sanitize(InputStream inputStream, OutputStream outputStream, BleachSession session)
//       throws BleachException;
// }
// 
// Path: api/src/main/java/xyz/docbleach/api/exception/BleachException.java
// public class BleachException extends Exception {
// 
//   public BleachException(Throwable e) {
//     super(e);
//   }
// 
//   public BleachException(String message) {
//     super(message);
//   }
// }
// 
// Path: api/src/main/java/xyz/docbleach/api/exception/RecursionBleachException.java
// public class RecursionBleachException extends BleachException {
// 
//   /**
//    * @param depth The depth of the recursion
//    */
//   public RecursionBleachException(int depth) {
//     super("Recursion exploit? There are already " + depth + " sanitation tasks.");
//   }
// }
// 
// Path: api/src/main/java/xyz/docbleach/api/threat/Threat.java
// @AutoValue
// public abstract class Threat {
// 
//   public static Builder builder() {
//     return new AutoValue_Threat.Builder();
//   }
// 
//   @AutoValue.Builder
//   public abstract static class Builder {
// 
//     public abstract Builder type(ThreatType value);
// 
//     public abstract Builder severity(ThreatSeverity value);
// 
//     public abstract Builder action(ThreatAction value);
// 
//     public abstract Builder location(String value);
// 
//     public abstract Builder details(String value);
// 
//     public abstract Threat build();
//   }
// 
//   public abstract ThreatType type();
// 
//   public abstract ThreatSeverity severity();
// 
//   public abstract ThreatAction action();
// 
//   public abstract String location();
// 
//   public abstract String details();
// }


// Path: api/src/main/java/xyz/docbleach/api/BleachSession.java
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import xyz.docbleach.api.bleach.Bleach;
import xyz.docbleach.api.exception.BleachException;
import xyz.docbleach.api.exception.RecursionBleachException;
import xyz.docbleach.api.threat.Threat;

package xyz.docbleach.api;


/**
 * A Bleach Session handles the data a bleach needs to store: list of the threats removed, for
 * instance May be used in the future to store configuration (file's password, for instance) or
 * callbacks
 */
public class BleachSession implements Serializable {

  private static final Logger LOGGER = LoggerFactory.getLogger(BleachSession.class);
  private static final int MAX_ONGOING_TASKS = 10;
  private final transient Bleach bleach;
  private final Collection<Threat> threats = new ArrayList<>();
  /**
   * Counts ongoing tasks, to prevent fork bombs when handling zip archives for instance)
   */
  private int ongoingTasks = 0;

  public BleachSession(Bleach bleach) {
    this.bleach = bleach;
  }

  /**
   * The BleachSession is able to record threats encountered by the bleach.
   *
   * @param threat The removed threat object, containing the threat type and more information
   */
  public void recordThreat(Threat threat) {
    if (threat == null) {