@Override
 public Resource getResource(String host, String sPath)
     throws NotAuthorizedException, BadRequestException {
   Path p = Path.path(sPath);
   if (p.getName().startsWith("alt-")) {
     Resource r = wrapped.getResource(host, p.getParent().toString());
     if (r instanceof FileResource) {
       FileResource fr = (FileResource) r;
       String sourceHash = fr.getHash();
       String formatName = p.getName().replace("alt-", "");
       AltFormat f = AltFormat.find(sourceHash, formatName, SessionManager.session());
       FormatSpec format = altFormatGenerator.findFormat(formatName);
       if (f != null) {
         return new AltFormatResource((FileResource) r, p.getName(), f, format);
       } else {
         log.warn(
             "getResource: pre-generated alt format not found: "
                 + sourceHash
                 + " - "
                 + p.getName());
         // if the format is valid then create a resource which will generate on demand
         if (format != null) {
           System.out.println("created resource for format: " + format);
           return new AltFormatResource((FileResource) r, p.getName(), format);
         } else {
           log.warn("getResource: unrecognised format: " + formatName);
         }
         return null;
       }
     } else {
       return null;
     }
   } else {
     return wrapped.getResource(host, sPath);
   }
 }
 @Override
 public Date getModifiedDate() {
   return rPrimary.getModifiedDate();
 }
 @Override
 public boolean isDigestAllowed() {
   return rPrimary.isDigestAllowed();
 }
 @Override
 public String getRealm() {
   return rPrimary.getRealm();
 }
 @Override
 public boolean authorise(Request request, Method method, Auth auth) {
   return rPrimary.authorise(request, method, auth);
 }
 @Override
 public Object authenticate(DigestResponse digestRequest) {
   return rPrimary.authenticate(digestRequest);
 }
 @Override
 public Object authenticate(String user, String password) {
   return rPrimary.authenticate(user, password);
 }
    @Override
    public void sendContent(
        OutputStream out, Range range, Map<String, String> params, String contentType)
        throws IOException, NotAuthorizedException, BadRequestException, NotFoundException {
      MediaMetaData mmd = MediaMetaData.find(rPrimary.getHash(), SessionManager.session());
      if (mmd != null) {
        Integer durationSecs = mmd.getDurationSecs();
        if (durationSecs != null) {
          Response resp = HttpManager.response();
          if (resp != null) {
            System.out.println("set duration header: " + durationSecs);
            resp.setNonStandardHeader("X-Content-Duration", durationSecs.toString());
          }
        }
      } else {
        System.out.println("no metadata for: " + rPrimary.getHash());
      }
      try {
        boolean force = params.containsKey("force");
        if (altFormat == null || force) {
          // hack start
          if (params.containsKey("args")) {
            List<String> args = new ArrayList<>();
            for (String s : params.get("args").split(",")) {
              args.add(s);
            }
            String[] arr = new String[args.size()];
            args.toArray(arr);
            formatSpec.setConverterArgs(arr);
            System.out.println("set args: " + arr);
          }

          // hack end
          System.out.println("generate: " + getName());
          GenerateJob j =
              altFormatGenerator.getOrEnqueueJob(
                  rPrimary.getHash(), rPrimary.getName(), formatSpec);
          System.out.println("got job: " + j);

          // Wait until the file exists
          int cnt = 0;
          System.out.println("check if exists...");
          while (!j.getDestFile().exists() && !j.done()) {
            cnt++;
            System.out.println(
                "sleep..." + cnt + " .. " + j.getDestFile().exists() + " - " + j.done());
            doSleep(cnt++, 200, 70);
          }
          System.out.println("finished sleepy check");
          if (!j.getDestFile().exists()) {
            throw new RuntimeException(
                "Job did not create a destination file: " + j.getDestFile().getAbsolutePath());
          }
          System.out.println(
              "use dest file: "
                  + j.getDestFile().getAbsolutePath()
                  + " size: "
                  + j.getDestFile().length());

          FileInputStream fin = new FileInputStream(j.getDestFile());
          byte[] buf = new byte[1024];
          System.out.println("send file...");
          // Read the file until the job is done, or we run out of bytes
          int s = fin.read(buf);
          System.out.println("send file... " + s);
          long bytes = 0;
          while (!j.done() || s > 0) {
            if (s < 0) { // no bytes available, but job is not done, so wait
              System.out.println("sleep...");
              doSleep(100);
            } else {
              System.out.println("write bytes: " + s);
              bytes += s;
              out.write(buf, 0, s);
            }
            s = fin.read(buf);
          }
          System.out.println("finished sending file: " + bytes);
        } else {
          System.out.println("using pre-existing al-format");
          Combiner combiner = new Combiner();
          List<String> fanoutCrcs = getFanout().getHashes();
          combiner.combine(fanoutCrcs, hashStore, blobStore, out);
          out.flush();
        }
      } catch (Throwable e) {
        log.error("Exception sending content", e);
        throw new IOException("Exception sending content");
      }
    }