ArchiveService.java [src/csip] Revision:   Date:
/*
 * $Id$
 *
 * This file is part of the Cloud Services Integration Platform (CSIP),
 * a Model-as-a-Service framework, API and application suite.
 *
 * 2012-2022, Olaf David and others, OMSLab, Colorado State University.
 *
 * OMSLab licenses this file to you under the MIT license.
 * See the LICENSE file in the project root for more information.
 */
package csip;

import csip.utils.Dates;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import csip.utils.JSONUtils;
import java.text.DateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.core.Response;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;

/**
 * Archive service.
 *
 * @author od
 */
@Path("/a")
public class ArchiveService {

  static final Logger LOG = Config.LOG;


  /**
   * Download an archive.
   * @param uriInfo the URI info
   * @param req the request
   * @param suid the SUID
   * @return the archive to download.
   */
  @GET
  @Produces(MediaType.APPLICATION_OCTET_STREAM)
  @Path("download/{suid}")
  public Response downloadArchive(@Context UriInfo uriInfo,
      @Context HttpServletRequest req, @PathParam("suid") final String suid) {
    // disable ACL check for direct download.
    if (!Config.getBoolean("csip.archive.anonymous.download", false)) 
      Utils.checkRemoteAccessACL(req);
    
    if (!Config.isArchiveEnabled()) {
      String o = JSONUtils.error("archive disabled").toString();
      return Response.status(404).entity(o).type(MediaType.APPLICATION_JSON).build();
    }
    try {
      ModelArchive archive = Config.getArchiveStore().getArchive(suid);
      if (archive != null) {
        byte[] b = Config.getArchiveStore().getFile(suid);
        if (b != null) {
          String ext = ".zip";
          if (Arrays.equals(ArchiveStore.ARCHIVE_TOO_BIG.getBytes(), b)) {
            ext = ".txt";
          }
          return Response.ok(QueryService.output(b)).header(
              "Content-Disposition", "attachment; filename="
              + ArchiveStore.ARCHIVE_PREFIX + suid + ext).build();
        }
      }
    } catch (Exception ex) {
      LOG.log(Level.SEVERE, null, ex);
    }
    String o = JSONUtils.error("archive not found, suid unknown : " + suid).toString();
    return Response.status(404).entity(o).type(MediaType.APPLICATION_JSON).build();
  }


  @GET
  @Produces(MediaType.APPLICATION_JSON)
  @Path("remove/{suid}")
  public String removeArchive(@Context UriInfo uriInfo,
      @Context HttpServletRequest req, @PathParam("suid") final String suid) {
    Utils.checkRemoteAccessACL(req);
    try {
      if (!Config.isArchiveEnabled()) 
        return JSONUtils.error("archive disabled. ").toString();
      
      // try to find the file.
      if (Config.getArchiveStore().hasArchive(suid)) {
        Config.getArchiveStore().removeArchive(suid);
        return JSONUtils.ok("removed: " + suid).toString();
      }
      return JSONUtils.error("suid unknown").toString();
    } catch (Exception e) {
      return JSONUtils.error("archive access problem: " + e.getMessage()).toString();
    }
  }


  /**
   * Clean the archive.
   *
   * @param uriInfo uri information
   * @param req servlet request
   * @return number of removed or invalid archives
   * @throws JSONException JSONObject requires JSONException
   */
  @GET
  @Produces(MediaType.APPLICATION_JSON)
  @Path("clean")
  public String clean(@Context UriInfo uriInfo,
      @Context HttpServletRequest req) throws JSONException {
    Utils.checkRemoteAccessACL(req);

    if (!Config.isArchiveEnabled()) 
      return JSONUtils.error("archive disabled. ").toString();
    

    JSONObject json = new JSONObject();
    int removed = 0;
    int invalid = 0;

    Set<String> keys = Config.getArchiveStore().keys(0, Integer.MAX_VALUE, null, true);
    json.put("archive.total", Config.getArchiveStore().getCount());
    DateFormat df = Dates.newISOFormat();
    Date now = new Date();
    for (String key : keys) {
      try {
        ModelArchive archive = Config.getArchiveStore().getArchive(key);
        if (archive == null) 
          continue;
        
        Date etime = df.parse(archive.getEtime());
        if (now.after(etime)) {
          removed++;
          Config.getArchiveStore().removeArchive(key);
        }
      } catch (Exception e) {
        invalid++;
      }
    }
    json.put("archive.removed", removed);
    json.put("archive.invalid", invalid);
    return json.toString(4);
  }
}