All Downloads are FREE. Search and download functionalities are using the official Maven repository.

tachyon.web.WebInterfaceBrowseServlet Maven / Gradle / Ivy

/*
 * Licensed to the University of California, Berkeley 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 tachyon.web;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.common.collect.Lists;

import tachyon.Constants;
import tachyon.TachyonURI;
import tachyon.client.TachyonStorageType;
import tachyon.client.file.FileInStream;
import tachyon.client.file.TachyonFile;
import tachyon.client.file.TachyonFileSystem;
import tachyon.client.file.TachyonFileSystem.TachyonFileSystemFactory;
import tachyon.client.file.options.InStreamOptions;
import tachyon.conf.TachyonConf;
import tachyon.exception.FileDoesNotExistException;
import tachyon.exception.InvalidPathException;
import tachyon.exception.TachyonException;
import tachyon.master.TachyonMaster;
import tachyon.thrift.BlockLocation;
import tachyon.thrift.FileBlockInfo;
import tachyon.thrift.FileInfo;
import tachyon.thrift.NetAddress;
import tachyon.util.io.PathUtils;

/**
 * Servlet that provides data for browsing the file system.
 */
public final class WebInterfaceBrowseServlet extends HttpServlet {

  private static final long serialVersionUID = 6121623049981468871L;

  private final transient TachyonMaster mMaster;
  private final transient TachyonConf mTachyonConf;

  public WebInterfaceBrowseServlet(TachyonMaster master) {
    mMaster = master;
    mTachyonConf = new TachyonConf();
  }

  /**
   * This function displays 5KB of a file from a specific offset if it is in ASCII format.
   *
   * @param path The path of the file to display
   * @param request The HttpServletRequest object
   * @param offset Where the file starts to display.
   * @throws FileDoesNotExistException
   * @throws IOException
   * @throws InvalidPathException
   */
  private void displayFile(TachyonURI path, HttpServletRequest request, long offset)
      throws FileDoesNotExistException, InvalidPathException, IOException, TachyonException {
    TachyonFileSystem tFS = TachyonFileSystemFactory.get();
    TachyonFile tFile = tFS.open(path);
    String fileData = null;
    FileInfo fileInfo = tFS.getInfo(tFile);
    if (fileInfo.isCompleted) {
      InStreamOptions readNoCache = new InStreamOptions.Builder(mTachyonConf)
          .setTachyonStorageType(TachyonStorageType.NO_STORE).build();
      FileInStream is = tFS.getInStream(tFile, readNoCache);
      try {
        int len = (int) Math.min(5 * Constants.KB, fileInfo.length - offset);
        byte[] data = new byte[len];
        long skipped = is.skip(offset);
        if (skipped < 0) {
          // nothing was skipped
          fileData = "Unable to traverse to offset; is file empty?";
        } else if (skipped < offset) {
          // couldn't skip all the way to offset
          fileData = "Unable to traverse to offset; is offset larger than the file?";
        } else {
          // read may not read up to len, so only convert what was read
          int read = is.read(data, 0, len);
          if (read < 0) {
            // stream couldn't read anything, skip went to EOF?
            fileData = "Unable to read file";
          } else {
            fileData = Utils.convertByteArrayToStringWithoutEscape(data, 0, read);
          }
        }
      } finally {
        is.close();
      }
    } else {
      fileData = "The requested file is not complete yet.";
    }
    List uiBlockInfo = new ArrayList();
    for (FileBlockInfo fileBlockInfo : mMaster.getFileSystemMaster().getFileBlockInfoList(path)) {
      uiBlockInfo.add(new UiBlockInfo(fileBlockInfo));
    }
    request.setAttribute("fileBlocks", uiBlockInfo);
    request.setAttribute("fileData", fileData);
  }

  /**
   * Populates attribute fields with data from the MasterInfo associated with this servlet. Errors
   * will be displayed in an error field. Debugging can be enabled to display additional data. Will
   * eventually redirect the request to a jsp.
   *
   * @param request The HttpServletRequest object
   * @param response The HttpServletResponse object
   * @throws ServletException
   * @throws IOException
   */
  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    request.setAttribute("debug", Constants.DEBUG);

    request.setAttribute("masterNodeAddress", mMaster.getMasterAddress().toString());
    request.setAttribute("invalidPathError", "");
    List filesInfo;
    String requestPath = request.getParameter("path");
    if (requestPath == null || requestPath.isEmpty()) {
      requestPath = TachyonURI.SEPARATOR;
    }
    TachyonURI currentPath = new TachyonURI(requestPath);
    request.setAttribute("currentPath", currentPath.toString());
    request.setAttribute("viewingOffset", 0);

    try {
      long fileId = mMaster.getFileSystemMaster().getFileId(currentPath);
      FileInfo fileInfo = mMaster.getFileSystemMaster().getFileInfo(fileId);
      UiFileInfo currentFileInfo = new UiFileInfo(fileInfo);
      if (currentFileInfo.getAbsolutePath() == null) {
        throw new FileDoesNotExistException(currentPath.toString());
      }
      request.setAttribute("currentDirectory", currentFileInfo);
      request.setAttribute("blockSizeBytes", currentFileInfo.getBlockSizeBytes());
      request.setAttribute("workerWebPort", mTachyonConf.getInt(Constants.WORKER_WEB_PORT));
      if (!currentFileInfo.getIsDirectory()) {
        String offsetParam = request.getParameter("offset");
        long relativeOffset = 0;
        long offset;
        try {
          if (offsetParam != null) {
            relativeOffset = Long.valueOf(offsetParam);
          }
        } catch (NumberFormatException nfe) {
          relativeOffset = 0;
        }
        String endParam = request.getParameter("end");
        // If no param "end" presents, the offset is relative to the beginning; otherwise, it is
        // relative to the end of the file.
        if (endParam == null) {
          offset = relativeOffset;
        } else {
          offset = fileInfo.getLength() - relativeOffset;
        }
        if (offset < 0) {
          offset = 0;
        } else if (offset > fileInfo.getLength()) {
          offset = fileInfo.getLength();
        }
        try {
          displayFile(new TachyonURI(currentFileInfo.getAbsolutePath()), request, offset);
        } catch (TachyonException e) {
          throw new IOException(e.getMessage());
        }
        request.setAttribute("viewingOffset", offset);
        getServletContext().getRequestDispatcher("/viewFile.jsp").forward(request, response);
        return;
      }
      setPathDirectories(currentPath, request);
      fileId = mMaster.getFileSystemMaster().getFileId(currentPath);
      filesInfo = mMaster.getFileSystemMaster().getFileInfoList(fileId);
    } catch (FileDoesNotExistException fdne) {
      request.setAttribute("invalidPathError", "Error: Invalid Path " + fdne.getMessage());
      getServletContext().getRequestDispatcher("/browse.jsp").forward(request, response);
      return;
    } catch (InvalidPathException ipe) {
      request.setAttribute("invalidPathError", "Error: Invalid Path " + ipe.getLocalizedMessage());
      getServletContext().getRequestDispatcher("/browse.jsp").forward(request, response);
      return;
    } catch (IOException ie) {
      request.setAttribute("invalidPathError",
          "Error: File " + currentPath + " is not available " + ie.getMessage());
      getServletContext().getRequestDispatcher("/browse.jsp").forward(request, response);
      return;
    }

    List fileInfos = new ArrayList(filesInfo.size());
    for (FileInfo fileInfo : filesInfo) {
      UiFileInfo toAdd = new UiFileInfo(fileInfo);
      try {
        if (!toAdd.getIsDirectory() && fileInfo.getLength() > 0) {
          FileBlockInfo blockInfo =
              mMaster.getFileSystemMaster().getFileBlockInfoList(toAdd.getId()).get(0);
          List addrs = Lists.newArrayList();
          // add the in-memory block locations
          for (BlockLocation location : blockInfo.getBlockInfo().getLocations()) {
            addrs.add(location.getWorkerAddress());
          }
          // add underFS locations
          addrs.addAll(blockInfo.getUfsLocations());
          toAdd.setFileLocations(addrs);
        }
      } catch (FileDoesNotExistException fdne) {
        request.setAttribute("FileDoesNotExistException",
            "Error: non-existing file " + fdne.getMessage());
        getServletContext().getRequestDispatcher("/browse.jsp").forward(request, response);
        return;
      } catch (InvalidPathException ipe) {
        request.setAttribute("InvalidPathException",
            "Error: invalid path " + ipe.getMessage());
        getServletContext().getRequestDispatcher("/browse.jsp").forward(request, response);
      }
      fileInfos.add(toAdd);
    }
    Collections.sort(fileInfos, UiFileInfo.PATH_STRING_COMPARE);

    request.setAttribute("nTotalFile", fileInfos.size());

    // URL can not determine offset and limit, let javascript in jsp determine and redirect
    if (request.getParameter("offset") == null && request.getParameter("limit") == null) {
      getServletContext().getRequestDispatcher("/browse.jsp").forward(request, response);
      return;
    }

    try {
      int offset = Integer.parseInt(request.getParameter("offset"));
      int limit = Integer.parseInt(request.getParameter("limit"));
      List sub = fileInfos.subList(offset, offset + limit);
      request.setAttribute("fileInfos", sub);
    } catch (NumberFormatException nfe) {
      request.setAttribute("fatalError",
          "Error: offset or limit parse error, " + nfe.getLocalizedMessage());
      getServletContext().getRequestDispatcher("/browse.jsp").forward(request, response);
      return;
    } catch (IndexOutOfBoundsException iobe) {
      request.setAttribute("fatalError",
          "Error: offset or offset + limit is out of bound, " + iobe.getLocalizedMessage());
      getServletContext().getRequestDispatcher("/browse.jsp").forward(request, response);
      return;
    } catch (IllegalArgumentException iae) {
      request.setAttribute("fatalError", iae.getLocalizedMessage());
      getServletContext().getRequestDispatcher("/browse.jsp").forward(request, response);
      return;
    }

    getServletContext().getRequestDispatcher("/browse.jsp").forward(request, response);
  }

  /**
   * This function sets the fileinfos for folders that are in the path to the current directory.
   *
   * @param path The path of the current directory.
   * @param request The HttpServletRequest object
   * @throws FileDoesNotExistException
   * @throws InvalidPathException
   */
  private void setPathDirectories(TachyonURI path, HttpServletRequest request)
      throws FileDoesNotExistException, InvalidPathException, IOException {
    if (path.isRoot()) {
      request.setAttribute("pathInfos", new UiFileInfo[0]);
      return;
    }

    String[] splitPath = PathUtils.getPathComponents(path.toString());
    UiFileInfo[] pathInfos = new UiFileInfo[splitPath.length - 1];
    TachyonURI currentPath = new TachyonURI(TachyonURI.SEPARATOR);
    long fileId = mMaster.getFileSystemMaster().getFileId(currentPath);
    pathInfos[0] = new UiFileInfo(mMaster.getFileSystemMaster().getFileInfo(fileId));
    for (int i = 1; i < splitPath.length - 1; i ++) {
      currentPath = currentPath.join(splitPath[i]);
      fileId = mMaster.getFileSystemMaster().getFileId(currentPath);
      pathInfos[i] = new UiFileInfo(mMaster.getFileSystemMaster().getFileInfo(fileId));
    }
    request.setAttribute("pathInfos", pathInfos);
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy