Exemplo n.º 1
0
/**
 * This is a step of the item submission processes. The upload stages allow the user to upload files
 * into the submission. The form is optimized for one file, but allows the user to upload more if
 * needed.
 *
 * <p>The form is broken up into three sections:
 *
 * <p>Part A: Ask the user to upload a file Part B: List previously uploaded files Part C: The
 * standard action bar
 *
 * @author Scott Phillips
 * @author Tim Donohue (updated for Configurable Submission)
 */
public class UploadStep extends AbstractSubmissionStep {
  private static Logger log = Logger.getLogger(UploadStep.class);

  /** Language Strings for Uploading * */
  protected static final Message T_head = message("xmlui.Submission.submit.UploadStep.head");

  protected static final Message T_file = message("xmlui.Submission.submit.UploadStep.file");
  protected static final Message T_file_help =
      message("xmlui.Submission.submit.UploadStep.file_help");
  protected static final Message T_file_error =
      message("xmlui.Submission.submit.UploadStep.file_error");
  protected static final Message T_upload_error =
      message("xmlui.Submission.submit.UploadStep.upload_error");

  protected static final Message T_virus_checker_error =
      message("xmlui.Submission.submit.UploadStep.virus_checker_error");
  protected static final Message T_virus_error =
      message("xmlui.Submission.submit.UploadStep.virus_error");

  protected static final Message T_description =
      message("xmlui.Submission.submit.UploadStep.description");
  protected static final Message T_description_help =
      message("xmlui.Submission.submit.UploadStep.description_help");
  protected static final Message T_submit_upload =
      message("xmlui.Submission.submit.UploadStep.submit_upload");
  protected static final Message T_head2 = message("xmlui.Submission.submit.UploadStep.head2");
  protected static final Message T_column0 = message("xmlui.Submission.submit.UploadStep.column0");
  protected static final Message T_column1 = message("xmlui.Submission.submit.UploadStep.column1");
  protected static final Message T_column2 = message("xmlui.Submission.submit.UploadStep.column2");
  protected static final Message T_column3 = message("xmlui.Submission.submit.UploadStep.column3");
  protected static final Message T_column4 = message("xmlui.Submission.submit.UploadStep.column4");
  protected static final Message T_column5 = message("xmlui.Submission.submit.UploadStep.column5");
  protected static final Message T_column6 = message("xmlui.Submission.submit.UploadStep.column6");
  protected static final Message T_unknown_name =
      message("xmlui.Submission.submit.UploadStep.unknown_name");
  protected static final Message T_unknown_format =
      message("xmlui.Submission.submit.UploadStep.unknown_format");
  protected static final Message T_supported =
      message("xmlui.Submission.submit.UploadStep.supported");
  protected static final Message T_known = message("xmlui.Submission.submit.UploadStep.known");
  protected static final Message T_unsupported =
      message("xmlui.Submission.submit.UploadStep.unsupported");
  protected static final Message T_submit_edit =
      message("xmlui.Submission.submit.UploadStep.submit_edit");
  protected static final Message T_checksum =
      message("xmlui.Submission.submit.UploadStep.checksum");
  protected static final Message T_submit_remove =
      message("xmlui.Submission.submit.UploadStep.submit_remove");
  protected static final Message T_rioxx_version =
      message("xmlui.Submission.submit.UploadStep.rioxx_version");

  protected static final Message T_sherpa_consult =
      message("xmlui.aspect.sherpa.submission.consult");

  protected static final Message T_sherpa_title = message("xmlui.aspect.sherpa.submission.title");

  protected static final Message T_sherpa_journal =
      message("xmlui.aspect.sherpa.submission.journal");

  protected static final Message T_sherpa_publisher =
      message("xmlui.aspect.sherpa.submission.publisher");

  protected static final Message T_sherpa_colour = message("xmlui.aspect.sherpa.submission.colour");

  protected static final Message T_sherpa_more = message("xmlui.aspect.sherpa.submission.more");

  /** Global reference to edit file page (this is used when a user requests to edit a bitstream) */
  private EditFileStep editFile = null;

  /** Establish our required parameters, abstractStep will enforce these. */
  public UploadStep() {
    this.requireSubmission = true;
    this.requireStep = true;
  }

  /** Check if user has requested to edit information about an uploaded file */
  public void setup(SourceResolver resolver, Map objectModel, String src, Parameters parameters)
      throws ProcessingException, SAXException, IOException {
    super.setup(resolver, objectModel, src, parameters);

    // If this page for editing an uploaded file's information
    // was requested, then we need to load EditFileStep instead!
    if (this.errorFlag == org.dspace.submit.step.UploadStep.STATUS_EDIT_BITSTREAM) {
      this.editFile = new EditFileStep();
      this.editFile.setup(resolver, objectModel, src, parameters);
    } else {
      this.editFile = null;
    }
  }

  public void addBody(Body body)
      throws SAXException, WingException, UIException, SQLException, IOException,
          AuthorizeException {
    // If we are actually editing information of an uploaded file,
    // then display that body instead!
    if (this.editFile != null) {
      editFile.addBody(body);
      return;
    }

    // Get a list of all files in the original bundle
    Item item = submission.getItem();
    Collection collection = submission.getCollection();
    String actionURL =
        contextPath + "/handle/" + collection.getHandle() + "/submit/" + knot.getId() + ".continue";
    boolean disableFileEditing =
        (submissionInfo.isInWorkflow())
            && !ConfigurationManager.getBooleanProperty("workflow", "reviewer.file-edit");
    Bundle[] bundles = item.getBundles("ORIGINAL");
    Bitstream[] bitstreams = new Bitstream[0];
    if (bundles.length > 0) {
      bitstreams = bundles[0].getBitstreams();
    }

    // Part A:
    //  First ask the user if they would like to upload a new file (may be the first one)
    Division div =
        body.addInteractiveDivision(
            "submit-upload", actionURL, Division.METHOD_MULTIPART, "primary submission");
    div.setHead(T_submission_head);
    addSubmissionProgressList(div);

    List upload = null;
    if (!disableFileEditing) {
      // Only add the upload capabilities for new item submissions
      upload = div.addList("submit-upload-new", List.TYPE_FORM);
      upload.setHead(T_head);
      addRioxxVersionSection(upload, item);

      File file = upload.addItem().addFile("file");
      file.setLabel(T_file);
      file.setHelp(T_file_help);
      file.setRequired();

      // if no files found error was thrown by processing class, display it!
      if (this.errorFlag == org.dspace.submit.step.UploadStep.STATUS_NO_FILES_ERROR) {
        file.addError(T_file_error);
      }

      // if an upload error was thrown by processing class, display it!
      if (this.errorFlag == org.dspace.submit.step.UploadStep.STATUS_UPLOAD_ERROR) {
        file.addError(T_upload_error);
      }

      // if virus checking was attempted and failed in error then let the user know
      if (this.errorFlag == org.dspace.submit.step.UploadStep.STATUS_VIRUS_CHECKER_UNAVAILABLE) {
        file.addError(T_virus_checker_error);
      }

      // if virus checking was attempted and a virus found then let the user know
      if (this.errorFlag == org.dspace.submit.step.UploadStep.STATUS_CONTAINS_VIRUS) {
        file.addError(T_virus_error);
      }

      Text description = upload.addItem().addText("description");
      description.setLabel(T_description);
      description.setHelp(T_description_help);

      Button uploadSubmit = upload.addItem().addButton("submit_upload");
      uploadSubmit.setValue(T_submit_upload);
    }

    make_sherpaRomeo_submission(item, div);

    // Part B:
    //  If the user has already uploaded files provide a list for the user.
    if (bitstreams.length > 0 || disableFileEditing) {
      Table summary = div.addTable("submit-upload-summary", (bitstreams.length * 2) + 2, 7);
      summary.setHead(T_head2);

      Row header = summary.addRow(Row.ROLE_HEADER);
      header.addCellContent(T_column0); // primary bitstream
      header.addCellContent(T_column1); // select checkbox
      header.addCellContent(T_column2); // file name
      header.addCellContent(T_column3); // size
      header.addCellContent(T_column4); // description
      header.addCellContent(T_column5); // format
      header.addCellContent(T_column6); // edit button

      for (Bitstream bitstream : bitstreams) {
        int id = bitstream.getID();
        String name = bitstream.getName();
        String url = makeBitstreamLink(item, bitstream);
        long bytes = bitstream.getSize();
        String desc = bitstream.getDescription();
        String algorithm = bitstream.getChecksumAlgorithm();
        String checksum = bitstream.getChecksum();

        Row row = summary.addRow();

        // Add radio-button to select this as the primary bitstream
        Radio primary = row.addCell().addRadio("primary_bitstream_id");
        primary.addOption(String.valueOf(id));

        // If this bitstream is already marked as the primary bitstream
        // mark it as such.
        if (bundles[0].getPrimaryBitstreamID() == id) {
          primary.setOptionSelected(String.valueOf(id));
        }

        if (!disableFileEditing) {
          // Workflow users can not remove files.
          CheckBox remove = row.addCell().addCheckBox("remove");
          remove.setLabel("remove");
          remove.addOption(id);
        } else {
          row.addCell();
        }

        row.addCell().addXref(url, name);
        row.addCellContent(bytes + " bytes");
        if (desc == null || desc.length() == 0) {
          row.addCellContent(T_unknown_name);
        } else {
          row.addCellContent(desc);
        }

        BitstreamFormat format = bitstream.getFormat();
        if (format == null) {
          row.addCellContent(T_unknown_format);
        } else {
          int support = format.getSupportLevel();
          Cell cell = row.addCell();
          cell.addContent(format.getMIMEType());
          cell.addContent(" ");
          switch (support) {
            case 1:
              cell.addContent(T_supported);
              break;
            case 2:
              cell.addContent(T_known);
              break;
            case 3:
              cell.addContent(T_unsupported);
              break;
          }
        }

        Button edit = row.addCell().addButton("submit_edit_" + id);
        edit.setValue(T_submit_edit);

        Row checksumRow = summary.addRow();
        checksumRow.addCell();
        Cell checksumCell = checksumRow.addCell(null, null, 0, 6, null);
        checksumCell.addHighlight("bold").addContent(T_checksum);
        checksumCell.addContent(" ");
        checksumCell.addContent(algorithm + ":" + checksum);
      }

      if (!disableFileEditing) {
        // Workflow users can not remove files.
        Row actionRow = summary.addRow();
        actionRow.addCell();
        Button removeSeleceted =
            actionRow.addCell(null, null, 0, 6, null).addButton("submit_remove_selected");
        removeSeleceted.setValue(T_submit_remove);
      }

      upload = div.addList("submit-upload-new-part2", List.TYPE_FORM);
    }

    // Part C:
    // add standard control/paging buttons
    addControlButtons(upload);
  }

  /** Sherpa romeo submission support */
  public void make_sherpaRomeo_submission(Item item, Division divIn) throws WingException {

    if (ConfigurationManager.getBooleanProperty(
        "webui.submission.sherparomeo-policy-enabled", true)) {

      SHERPASubmitService sherpaSubmitService =
          new DSpace().getSingletonService(SHERPASubmitService.class);

      if (sherpaSubmitService.hasISSNs(context, item)) {
        List div = divIn.addList("submit-upload-new", List.TYPE_FORM);
        div.setHead(T_sherpa_title);

        // Since sherpa web service doesn't work reliable with more than 1 issn, perform the service
        // for each issn
        Set<String> issns = sherpaSubmitService.getISSNs(context, item);
        Iterator<String> issnsIterator = issns.iterator();

        int i = 0;
        while (issnsIterator.hasNext()) {
          SHERPAResponse shresp =
              sherpaSubmitService.searchRelatedJournalsByISSN(issnsIterator.next());
          java.util.List<SHERPAJournal> journals = shresp.getJournals();
          java.util.List<SHERPAPublisher> publishers = shresp.getPublishers();

          if (CollectionUtils.isNotEmpty(journals)) {
            for (SHERPAJournal journ : journals) {
              SHERPAPublisher pub = publishers.get(0);

              List sherpaList = div.addList("sherpaList" + (i + 1), "simple", "sherpaList");
              sherpaList
                  .addItem()
                  .addFigure(
                      contextPath + "/static/images/" + (i == 0 ? "romeosmall" : "clear") + ".gif",
                      "http://www.sherpa.ac.uk/romeo/",
                      "sherpaLogo");

              sherpaList.addItem().addHighlight("sherpaBold").addContent(T_sherpa_journal);
              sherpaList.addItem(journ.getTitle() + " (" + journ.getIssn() + ")");

              sherpaList.addItem().addHighlight("sherpaBold").addContent(T_sherpa_publisher);
              sherpaList.addItemXref(pub.getHomeurl(), pub.getName());

              sherpaList.addItem().addHighlight("sherpaBold").addContent(T_sherpa_colour);
              sherpaList
                  .addItem()
                  .addHighlight("sherpaStyle " + pub.getRomeocolour())
                  .addContent(message("xmlui.aspect.sherpa.submission." + pub.getRomeocolour()));
              sherpaList
                  .addItem()
                  .addXref(
                      "http://www.sherpa.ac.uk/romeo/search.php?issn=" + journ.getIssn(),
                      T_sherpa_more,
                      "sherpaMoreInfo");

              i = i + 1;
            }
          }
        }

        List sherpaList = div.addList("sherpaListEnd", "simple", "sherpaList");
        sherpaList.addItem(T_sherpa_consult);
      }
    }
  }

  /**
   * Each submission step must define its own information to be reviewed during the final
   * Review/Verify Step in the submission process.
   *
   * <p>The information to review should be tacked onto the passed in List object.
   *
   * <p>NOTE: To remain consistent across all Steps, you should first add a sub-List object (with
   * this step's name as the heading), by using a call to reviewList.addList(). This sublist is the
   * list you return from this method!
   *
   * @param reviewList The List to which all reviewable information should be added
   * @return The new sub-List object created by this step, which contains all the reviewable
   *     information. If this step has nothing to review, then return null!
   */
  public List addReviewSection(List reviewList)
      throws SAXException, WingException, UIException, SQLException, IOException,
          AuthorizeException {
    // Create a new list section for this step (and set its heading)
    List uploadSection = reviewList.addList("submit-review-" + this.stepAndPage, List.TYPE_FORM);
    uploadSection.setHead(T_head);

    // Review all uploaded files
    Item item = submission.getItem();
    Bundle[] bundles = item.getBundles("ORIGINAL");
    Bitstream[] bitstreams = new Bitstream[0];
    if (bundles.length > 0) {
      bitstreams = bundles[0].getBitstreams();
    }

    for (Bitstream bitstream : bitstreams) {
      BitstreamFormat bitstreamFormat = bitstream.getFormat();

      String name = bitstream.getName();
      String url = makeBitstreamLink(item, bitstream);
      String format = bitstreamFormat.getShortDescription();
      Message support = ReviewStep.T_unknown;
      if (bitstreamFormat.getSupportLevel() == BitstreamFormat.KNOWN) {
        support = T_known;
      } else if (bitstreamFormat.getSupportLevel() == BitstreamFormat.SUPPORTED) {
        support = T_supported;
      }

      org.dspace.app.xmlui.wing.element.Item file = uploadSection.addItem();
      file.addXref(url, name);
      file.addContent(" - " + format + " ");
      file.addContent(support);
    }

    // return this new "upload" section
    return uploadSection;
  }

  /**
   * Returns canonical link to a bitstream in the item.
   *
   * @param item The DSpace Item that the bitstream is part of
   * @param bitstream The bitstream to link to
   * @returns a String link to the bitstream
   */
  private String makeBitstreamLink(Item item, Bitstream bitstream) {
    String name = bitstream.getName();
    StringBuilder result = new StringBuilder(contextPath);
    result.append("/bitstream/item/").append(String.valueOf(item.getID()));
    // append name although it isn't strictly necessary
    try {
      if (name != null) {
        result.append("/").append(Util.encodeBitstreamName(name, "UTF-8"));
      }
    } catch (UnsupportedEncodingException uee) {
      // just ignore it, we don't have to have a pretty
      // name on the end of the url because the sequence id will
      // locate it. However it means that links in this file might
      // not work....
    }
    result.append("?sequence=").append(String.valueOf(bitstream.getSequenceID()));
    return result.toString();
  }

  public void addRioxxVersionSection(List upload, Item item) throws WingException {
    String version = item.getMetadata("rioxxterms.version");

    if (StringUtils.isNotBlank(version) && !"NA".equals(version)) {
      try {
        DCInputsReader a = new DCInputsReader();
        java.util.List<String> pairs = a.getPairs("rioxxterms_version");
        int humanReadable = pairs.indexOf(version) - 1;
        version = pairs.get(humanReadable);
      } catch (DCInputsReaderException e) {
        log.error(e.getMessage(), e);
      }
      upload
          .addItem("upload-rioxx-version-warning", "upload-rioxx-version-warning")
          .addContent(T_rioxx_version.parameterize(version));
    }
  }
}
Exemplo n.º 2
0
// SingleThreadModel causes servlet instances to be assigned to only a
// single thread (request) at a time.
public abstract class LockssServlet extends HttpServlet implements SingleThreadModel {
  protected static Logger log = Logger.getLogger("LockssServlet");

  // Constants
  static final String PARAM_LOCAL_IP = Configuration.PREFIX + "localIPAddress";

  static final String PARAM_PLATFORM_VERSION = Configuration.PREFIX + "platform.version";

  /** Inactive HTTP session (cookie) timeout */
  static final String PARAM_UI_SESSION_TIMEOUT = Configuration.PREFIX + "ui.sessionTimeout";

  static final long DEFAULT_UI_SESSION_TIMEOUT = 2 * Constants.DAY;

  /** Maximum size of uploaded file accepted */
  static final String PARAM_MAX_UPLOAD_FILE_SIZE = Configuration.PREFIX + "ui.maxUploadFileSize";

  static final int DEFAULT_MAX_UPLOAD_FILE_SIZE = 500000;

  /** The warning string to display when the UI is disabled. */
  static final String PARAM_UI_WARNING = Configuration.PREFIX + "ui.warning";

  // session keys
  static final String SESSION_KEY_OBJECT_ID = "obj_id";
  static final String SESSION_KEY_OBJ_MAP = "obj_map";
  public static final String SESSION_KEY_RUNNING_SERVLET = "running_servlet";
  public static final String SESSION_KEY_REQUEST_HOST = "request_host";

  // Name given to form element whose value is the action that should be
  // performed when the form is submitted.  (Not always the submit button.)
  public static final String ACTION_TAG = "lockssAction";

  public static final String JAVASCRIPT_RESOURCE = "org/lockss/htdocs/admin.js";

  public static final String ATTR_INCLUDE_SCRIPT = "IncludeScript";
  public static final String ATTR_ALLOW_ROLES = "AllowRoles";

  /** User may configure admin access (add/delete/modify users, set admin access list) */
  public static final String ROLE_USER_ADMIN = "userAdminRole";

  /** User may configure content access (set content access list) */
  public static final String ROLE_CONTENT_ADMIN = "contentAdminRole";

  /** User may change AU configuration (add/delete content) */
  public static final String ROLE_AU_ADMIN = "auAdminRole";

  public static final String ROLE_DEBUG = "debugRole";

  protected ServletContext context;

  private LockssApp theApp = null;
  private ServletManager servletMgr;
  private AccountManager acctMgr;

  // Request-local storage.  Convenient, but requires servlet instances
  // to be single threaded, and must ensure reset them to avoid carrying
  // over state between requests.
  protected HttpServletRequest req;
  protected HttpServletResponse resp;
  protected URL reqURL;
  protected HttpSession session;
  private String adminDir = null;
  protected String clientAddr; // client addr, even if no param
  protected String localAddr;
  protected MultiPartRequest multiReq;

  private Vector footnotes;
  private int footNumber;
  private int tabindex;
  ServletDescr _myServletDescr = null;
  private String myName = null;

  // number submit buttons sequentially so unit tests can find them
  protected int submitButtonNumber = 0;

  /** Run once when servlet loaded. */
  public void init(ServletConfig config) throws ServletException {
    super.init(config);
    context = config.getServletContext();
    theApp = (LockssApp) context.getAttribute(ServletManager.CONTEXT_ATTR_LOCKSS_APP);
    servletMgr = (ServletManager) context.getAttribute(ServletManager.CONTEXT_ATTR_SERVLET_MGR);
    if (theApp instanceof LockssDaemon) {
      acctMgr = getLockssDaemon().getAccountManager();
    }
  }

  public ServletManager getServletManager() {
    return servletMgr;
  }

  protected ServletDescr[] getServletDescrs() {
    return servletMgr.getServletDescrs();
  }

  /** Servlets must implement this method. */
  protected abstract void lockssHandleRequest() throws ServletException, IOException;

  /** Common request handling. */
  public void service(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException {
    resetState();
    boolean success = false;
    HttpSession session = req.getSession(false);
    try {
      this.req = req;
      this.resp = resp;
      if (log.isDebug()) {
        logParams();
      }
      resp.setContentType("text/html");

      if (!mayPageBeCached()) {
        resp.setHeader("pragma", "no-cache");
        resp.setHeader("Cache-control", "no-cache");
      }

      reqURL = new URL(UrlUtil.getRequestURL(req));
      clientAddr = getLocalIPAddr();

      // check that current user has permission to run this servlet
      if (!isServletAllowed(myServletDescr())) {
        displayWarningInLieuOfPage("You are not authorized to use " + myServletDescr().heading);
        return;
      }

      // check whether servlet is disabled
      String reason = ServletUtil.servletDisabledReason(myServletDescr().getServletName());
      if (reason != null) {
        displayWarningInLieuOfPage("This function is disabled. " + reason);
        return;
      }
      if (session != null) {
        session.setAttribute(SESSION_KEY_RUNNING_SERVLET, getHeading());
        String reqHost = req.getRemoteHost();
        String forw = req.getHeader(HttpFields.__XForwardedFor);
        if (!StringUtil.isNullString(forw)) {
          reqHost += " (proxies for " + forw + ")";
        }
        session.setAttribute(SESSION_KEY_REQUEST_HOST, reqHost);
      }
      lockssHandleRequest();
      success = (errMsg == null);
    } catch (ServletException e) {
      log.error("Servlet threw", e);
      throw e;
    } catch (IOException e) {
      log.error("Servlet threw", e);
      throw e;
    } catch (RuntimeException e) {
      log.error("Servlet threw", e);
      throw e;
    } finally {
      if (session != null) {
        session.setAttribute(SESSION_KEY_RUNNING_SERVLET, null);
        session.setAttribute(LockssFormAuthenticator.__J_AUTH_ACTIVITY, TimeBase.nowMs());
      }
      if ("please".equalsIgnoreCase(req.getHeader("X-Lockss-Result"))) {
        log.debug3("X-Lockss-Result: " + (success ? "Ok" : "Fail"));
        resp.setHeader("X-Lockss-Result", success ? "Ok" : "Fail");
      }
      resetMyLocals();
      resetLocals();
    }
  }

  protected void resetState() {
    multiReq = null;
    footNumber = 0;
    submitButtonNumber = 0;
    tabindex = 1;
    statusMsg = null;
    errMsg = null;
    isFramed = false;
  }

  protected void resetLocals() {}

  protected void resetMyLocals() {
    // Don't hold on to stuff forever
    req = null;
    resp = null;
    session = null;
    reqURL = null;
    adminDir = null;
    localAddr = null;
    footnotes = null;
    _myServletDescr = null;
    myName = null;
    multiReq = null;
  }

  /**
   * Return true if generated page may be cached (e.g., by browser). Default is false as most
   * servlets generate dynamic results
   */
  protected boolean mayPageBeCached() {
    return false;
  }

  /** Set the session timeout to the configured value */
  protected void setSessionTimeout(HttpSession session) {
    Configuration config = CurrentConfig.getCurrentConfig();
    setSessionTimeout(
        session, config.getTimeInterval(PARAM_UI_SESSION_TIMEOUT, DEFAULT_UI_SESSION_TIMEOUT));
  }

  /** Set the session timeout */
  protected void setSessionTimeout(HttpSession session, long time) {
    session.setMaxInactiveInterval((int) (time / Constants.SECOND));
  }

  /** Get the current session, creating it if necessary (and set the timeout if so) */
  protected HttpSession getSession() {
    if (session == null) {
      session = req.getSession(true);
      if (session.isNew()) {
        setSessionTimeout(session);
      }
    }
    return session;
  }

  /** Return true iff a session has already been established */
  protected boolean hasSession() {
    return req.getSession(false) != null;
  }

  /** Get an unused ID string for storing an object in the session */
  protected String getNewSessionObjectId() {
    HttpSession session = getSession();
    synchronized (session) {
      Integer id = (Integer) getSession().getAttribute(SESSION_KEY_OBJECT_ID);
      if (id == null) {
        id = new Integer(1);
      }
      session.setAttribute(SESSION_KEY_OBJECT_ID, new Integer(id.intValue() + 1));
      return id.toString();
    }
  }

  /** Get the object associated with the ID in the session */
  protected Object getSessionIdObject(String id) {
    HttpSession session = getSession();
    synchronized (session) {
      BidiMap map = (BidiMap) session.getAttribute(SESSION_KEY_OBJ_MAP);
      if (map == null) {
        return null;
      }
      return map.getKey(id);
    }
  }

  /** Get the String associated with the ID in the session */
  protected String getSessionIdString(String id) {
    return (String) getSessionIdObject(id);
  }

  /** Get the ID with which the object is associated with the session, if any */
  protected String getSessionObjectId(Object obj) {
    HttpSession session = getSession();
    BidiMap map;
    synchronized (session) {
      map = (BidiMap) session.getAttribute(SESSION_KEY_OBJ_MAP);
      if (map == null) {
        map = new DualHashBidiMap();
        session.setAttribute(SESSION_KEY_OBJ_MAP, map);
      }
    }
    synchronized (map) {
      String id = (String) map.get(obj);
      if (id == null) {
        id = getNewSessionObjectId();
        map.put(obj, id);
      }
      return id;
    }
  }

  // Return descriptor of running servlet
  protected ServletDescr myServletDescr() {
    if (_myServletDescr == null) {
      _myServletDescr = servletMgr.findServletDescr(this);
    }
    return _myServletDescr;
  }

  // By default, servlet heading is in descr.  Override method to
  // compute other heading
  protected String getHeading(ServletDescr d) {
    if (d == null) return "Unknown Servlet";
    return d.heading;
  }

  protected String getHeading() {
    return getHeading(myServletDescr());
  }

  String getLocalIPAddr() {
    if (localAddr == null) {
      try {
        IPAddr localHost = IPAddr.getLocalHost();
        localAddr = localHost.getHostAddress();
      } catch (UnknownHostException e) {
        // shouldn't happen
        log.error("LockssServlet: getLocalHost: " + e.toString());
        return "???";
      }
    }
    return localAddr;
  }

  // Return IP addr used by LCAP.  If specified by (misleadingly named)
  // localIPAddress prop, might not really be our address (if we are
  // behind NAT).
  String getLcapIPAddr() {
    String ip = CurrentConfig.getParam(PARAM_LOCAL_IP);
    if (ip == null || ip.length() <= 0) {
      return getLocalIPAddr();
    }
    return ip;
  }

  String getRequestHost() {
    return reqURL.getHost();
  }

  String getMachineName() {
    return PlatformUtil.getLocalHostname();
  }

  //   String getMachineName0() {
  //     if (myName == null) {
  //       // Return the canonical name of the interface the request was aimed
  //       // at.  (localIPAddress prop isn't necessarily right here, as it
  //       // might be the address of a NAT that we're behind.)
  //       String host = reqURL.getHost();
  //       try {
  // 	IPAddr localHost = IPAddr.getByName(host);
  // 	String ip = localHost.getHostAddress();
  // 	myName = getMachineName(ip);
  //       } catch (UnknownHostException e) {
  // 	// shouldn't happen
  // 	log.error("getMachineName", e);
  // 	return host;
  //       }
  //     }
  //     return myName;
  //   }

  //   String getMachineName(String ip) {
  //     try {
  //       IPAddr inet = IPAddr.getByName(ip);
  //       return inet.getHostName();
  //     } catch (UnknownHostException e) {
  //       log.warning("getMachineName", e);
  //     }
  //     return ip;
  //   }

  // return IP given name or IP
  String getMachineIP(String name) {
    try {
      IPAddr inet = IPAddr.getByName(name);
      return inet.getHostAddress();
    } catch (UnknownHostException e) {
      return null;
    }
  }

  boolean isServletLinkInNav(ServletDescr d) {
    return !isThisServlet(d) || linkMeInNav();
  }

  boolean isThisServlet(ServletDescr d) {
    return d == myServletDescr();
  }

  /** servlets may override this to determine whether they should be a link in nav table */
  protected boolean linkMeInNav() {
    return false;
  }

  boolean isLargeLogo() {
    return myServletDescr().isLargeLogo();
  }

  // user predicates
  String getUsername() {
    Principal user = req.getUserPrincipal();
    return user != null ? user.toString() : null;
  }

  protected UserAccount getUserAccount() {
    if (acctMgr != null) {
      return acctMgr.getUser(getUsername());
    }
    return AccountManager.NOBODY_ACCOUNT;
  }

  protected boolean isDebugUser() {
    return doesUserHaveRole(ROLE_DEBUG);
  }

  protected boolean doesUserHaveRole(String role) {
    if ((req.isUserInRole(role) || req.isUserInRole(ROLE_USER_ADMIN)) && !hasNoRoleParsm(role)) {
      return true;
    }
    return hasTestRole(role);
  }

  static Map<String, String> noRoleParams = new HashMap<String, String>();

  static {
    noRoleParams.put(ROLE_USER_ADMIN, "noadmin");
    noRoleParams.put(ROLE_CONTENT_ADMIN, "nocontent");
    noRoleParams.put(ROLE_AU_ADMIN, "noau");
    noRoleParams.put(ROLE_DEBUG, "nodebug");
  }

  protected boolean hasNoRoleParsm(String roleName) {
    String noRoleParam = noRoleParams.get(roleName);
    return (noRoleParam != null && !StringUtil.isNullString(req.getParameter(noRoleParam)));
  }

  protected boolean hasTestRole(String role) {
    // Servlet test harness puts roles in context
    List roles = (List) context.getAttribute(ATTR_ALLOW_ROLES);
    return roles != null && (roles.contains(role) || roles.contains(ROLE_USER_ADMIN));
  }

  protected boolean isServletAllowed(ServletDescr d) {
    if (d.needsUserAdminRole() && !doesUserHaveRole(ROLE_USER_ADMIN)) return false;
    if (d.needsContentAdminRole() && !doesUserHaveRole(ROLE_CONTENT_ADMIN)) return false;
    if (d.needsAuAdminRole() && !doesUserHaveRole(ROLE_AU_ADMIN)) return false;

    return d.isEnabled(getLockssDaemon());
  }

  protected boolean isServletDisplayed(ServletDescr d) {
    if (!isServletAllowed(d)) return false;
    if (d.needsDebugRole() && !doesUserHaveRole(ROLE_DEBUG)) return false;
    return true;
  }

  protected boolean isServletInNav(ServletDescr d) {
    if (d.cls == ServletDescr.UNAVAILABLE_SERVLET_MARKER) return false;
    return d.isInNav(this) && isServletDisplayed(d);
  }

  // Called when a servlet doesn't get the parameters it expects/needs
  protected void paramError() throws IOException {
    // FIXME: As of 2006-03-15 this method and its only caller checkParam() are not called from
    // anywhere
    PrintWriter wrtr = resp.getWriter();
    Page page = new Page();
    // add referer, params, msg to contact lockss unless from old bookmark
    // or manually entered url
    page.add("Parameter error");
    page.write(wrtr);
  }

  // return true iff error
  protected boolean checkParam(boolean ok, String msg) throws IOException {
    if (ok) return false;
    log.error(myServletDescr().getPath() + ": " + msg);
    paramError();
    return true;
  }

  /** Construct servlet URL */
  String srvURL(ServletDescr d) {
    return srvURL((String) null, d, null);
  }

  /** Construct servlet URL with params */
  String srvURL(ServletDescr d, String params) {
    return srvURL((String) null, d, params);
  }

  /** Construct servlet URL with params */
  String srvURL(ServletDescr d, Properties params) {
    return srvURL(d, concatParams(params));
  }

  /** Construct servlet absolute URL, with params as necessary. */
  String srvAbsURL(ServletDescr d, String params) {
    return srvURL(getRequestHost(), d, params);
  }

  /**
   * Construct servlet URL, with params as necessary. Avoid generating a hostname different from
   * that used in the original request, or browsers will prompt again for login
   */
  String srvURL(String host, ServletDescr d, String params) {
    return srvURLFromStem(srvUrlStem(host), d, params);
  }

  String srvURL(PeerIdentity peer, ServletDescr d, String params) {
    return srvURLFromStem(peer.getUiUrlStem(reqURL.getPort()), d, params);
  }

  /**
   * Construct servlet URL, with params as necessary. Avoid generating a hostname different from
   * that used in the original request, or browsers will prompt again for login
   */
  String srvURLFromStem(String stem, ServletDescr d, String params) {
    if (d.isPathIsUrl()) {
      return d.getPath();
    }
    StringBuilder sb = new StringBuilder(80);
    if (stem != null) {
      sb.append(stem);
      if (stem.charAt(stem.length() - 1) != '/') {
        sb.append('/');
      }
    } else {
      // ensure absolute path even if no scheme/host/port
      sb.append('/');
    }
    sb.append(d.getPath());
    if (params != null) {
      sb.append('?');
      sb.append(params);
    }
    return sb.toString();
  }

  String srvUrlStem(String host) {
    if (host == null) {
      return null;
    }
    StringBuilder sb = new StringBuilder();
    sb.append(reqURL.getProtocol());
    sb.append("://");
    sb.append(host);
    sb.append(':');
    sb.append(reqURL.getPort());
    return sb.toString();
  }

  /** Return a link to a servlet */
  String srvLink(ServletDescr d, String text) {
    return srvLink(d, text, (String) null);
  }

  /** Return a link to a servlet with params */
  String srvLink(ServletDescr d, String text, String params) {
    return new Link(srvURL(d, params), (text != null ? text : d.heading)).toString();
  }

  /** Return a link to a servlet with params */
  String srvLink(ServletDescr d, String text, Properties params) {
    return new Link(srvURL(d, params), text).toString();
  }

  /** Return an absolute link to a servlet with params */
  String srvAbsLink(ServletDescr d, String text, Properties params) {
    return srvAbsLink(d, text, concatParams(params));
  }

  /** Return an absolute link to a servlet with params */
  String srvAbsLink(ServletDescr d, String text, String params) {
    return new Link(srvAbsURL(d, params), (text != null ? text : d.heading)).toString();
  }

  /** Return an absolute link to a servlet with params */
  String srvAbsLink(String host, ServletDescr d, String text, String params) {
    return new Link(srvURL(host, d, params), (text != null ? text : d.heading)).toString();
  }

  /** Return an absolute link to a servlet with params */
  String srvAbsLink(PeerIdentity peer, ServletDescr d, String text, String params) {
    return new Link(srvURL(peer, d, params), (text != null ? text : d.heading)).toString();
  }

  /** Return text as a link iff isLink */
  String conditionalSrvLink(ServletDescr d, String text, String params, boolean isLink) {
    if (isLink) {
      return srvLink(d, text, params);
    } else {
      return text;
    }
  }

  /** Return text as a link iff isLink */
  String conditionalSrvLink(ServletDescr d, String text, boolean isLink) {
    return conditionalSrvLink(d, text, null, isLink);
  }

  /** Concatenate params for URL string */
  static String concatParams(String p1, String p2) {
    if (StringUtil.isNullString(p1)) {
      return p2;
    }
    if (StringUtil.isNullString(p2)) {
      return p1;
    }
    return p1 + "&" + p2;
  }

  /** Concatenate params for URL string */
  String concatParams(Properties props) {
    if (props == null) {
      return null;
    }
    java.util.List list = new ArrayList();
    for (Iterator iter = props.keySet().iterator(); iter.hasNext(); ) {
      String key = (String) iter.next();
      String val = props.getProperty(key);
      if (!StringUtil.isNullString(val)) {
        list.add(key + "=" + urlEncode(val));
      }
    }
    return StringUtil.separatedString(list, "&");
  }

  String modifyParams(String key, String val) {
    Properties props = getParamsAsProps();
    props.setProperty(key, val);
    return concatParams(props);
  }

  /**
   * Return the request parameters as a Properties. Only the first value of multivalued parameters
   * is included.
   */
  Properties getParamsAsProps() {
    Properties props = new Properties();
    for (Enumeration en = req.getParameterNames(); en.hasMoreElements(); ) {
      String name = (String) en.nextElement();
      props.setProperty(name, req.getParameter(name));
    }
    return props;
  }

  /**
   * Return the request parameters as a Map<String,String>. Only the first value of multivalued
   * parameters is included.
   */
  Map<String, String> getParamsAsMap() {
    Map<String, String> map = new HashMap<String, String>();
    for (Enumeration en = req.getParameterNames(); en.hasMoreElements(); ) {
      String name = (String) en.nextElement();
      map.put(name, req.getParameter(name));
    }
    return map;
  }

  protected String urlEncode(String param) {
    return UrlUtil.encodeUrl(param);
  }

  protected String getRequestKey() {
    String key = req.getPathInfo();
    if (key != null && key.startsWith("/")) {
      return key.substring(1);
    }
    return key;
  }

  /** Common page setup. */
  protected Page newPage() {
    // Compute heading
    String heading = getHeading();
    if (heading == null) {
      heading = "Box Administration";
    }

    // Create page and layout header
    Page page = ServletUtil.doNewPage(getPageTitle(), isFramed());
    Iterator inNavIterator;
    if (myServletDescr().hasNoNavTable()) {
      inNavIterator = CollectionUtil.EMPTY_ITERATOR;
    } else {
      inNavIterator =
          new FilterIterator(
              new ObjectArrayIterator(getServletDescrs()),
              new Predicate() {
                public boolean evaluate(Object obj) {
                  return isServletInNav((ServletDescr) obj);
                }
              });
    }
    ServletUtil.layoutHeader(
        this,
        page,
        heading,
        isLargeLogo(),
        getMachineName(),
        getLockssApp().getStartDate(),
        inNavIterator);
    String warnMsg = CurrentConfig.getParam(PARAM_UI_WARNING);
    if (warnMsg != null) {
      Composite warning = new Composite();
      warning.add("<center><font color=red size=+1>");
      warning.add(warnMsg);
      warning.add("</font></center><br>");
      page.add(warning);
    }
    return page;
  }

  protected Page addBarePageHeading(Page page) {
    // FIXME: Move the following fragment elsewhere
    // It causes the doctype statement to appear in the middle,
    // after the <body> tag.
    page.add("<!doctype html public \"-//w3c//dtd html 4.0 transitional//en\">");
    page.addHeader("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\">");
    page.addHeader("<meta http-equiv=\"content-type\" content=\"text/html;charset=ISO-8859-1\">");
    page.addHeader("<link rel=\"shortcut icon\" href=\"/favicon.ico\" type=\"image/x-icon\" />");
    return page;
  }

  private boolean isFramed = false;

  protected String errMsg;

  protected String statusMsg;

  protected boolean isFramed() {
    return isFramed;
  }

  protected void setFramed(boolean v) {
    isFramed = v;
  }

  protected String getPageTitle() {
    String heading = getHeading();
    if (heading != null) {
      return "LOCKSS: " + heading;
    } else {
      return "LOCKSS";
    }
  }

  /** Return a button that invokes the javascript submit routine with the specified action */
  protected Element submitButton(String label, String action) {
    return submitButton(label, action, null, null);
  }

  /** Return a button that invokes javascript when clicked. */
  Input jsButton(String label, String js) {
    Input btn = new Input("button", null);
    btn.attribute("value", label);
    setTabOrder(btn);
    btn.attribute("onClick", js);
    return btn;
  }

  /**
   * Return a button that invokes the javascript submit routine with the specified action, first
   * storing the value in the specified form prop.
   */
  protected Element submitButton(String label, String action, String prop, String value) {
    StringBuilder sb = new StringBuilder(40);
    sb.append("lockssButton(this, '");
    sb.append(action);
    sb.append("'");
    if (prop != null && value != null) {
      sb.append(", '");
      sb.append(prop);
      sb.append("', '");
      sb.append(value);
      sb.append("'");
    }
    sb.append(")");
    Input btn = jsButton(label, sb.toString());
    btn.attribute("id", "lsb." + (++submitButtonNumber));
    return btn;
  }

  /**
   * Return a (possibly labelled) checkbox.
   *
   * @param label appears to right of checkbox if non null
   * @param value value included in result set if box checked
   * @param key form key to which result set is assigned
   * @param checked if true, box is initially checked
   * @return a checkbox Element
   */
  Element checkBox(String label, String value, String key, boolean checked) {
    Input in = new Input(Input.Checkbox, key, value);
    if (checked) {
      in.check();
    }
    setTabOrder(in);
    if (StringUtil.isNullString(label)) {
      return in;
    } else {
      Composite c = new Composite();
      c.add(in);
      c.add(" ");
      c.add(label);
      return c;
    }
  }

  /**
   * Return a labelled rasio button
   *
   * @param label label to right of circle, and form value if checked
   * @param key form key to which value is assigned
   * @param checked if true, is initially checked
   * @return a readio button Element
   */
  protected Element radioButton(String label, String key, boolean checked) {
    return radioButton(label, label, key, checked);
  }

  /**
   * Return a labelled rasio button
   *
   * @param label appears to right of circle if non null
   * @param value value assigned to key if box checked
   * @param key form key to which value is assigned
   * @param checked if true, is initially checked
   * @return a readio button Element
   */
  protected Element radioButton(String label, String value, String key, boolean checked) {
    Composite c = new Composite();
    Input in = new Input(Input.Radio, key, value);
    if (checked) {
      in.check();
    }
    setTabOrder(in);
    c.add(in);
    c.add(label);
    return c;
  }

  /** Add html tags to grey the text if isGrey is true */
  protected String greyText(String txt, boolean isGrey) {
    if (!isGrey) {
      return txt;
    }
    return "<font color=gray>" + txt + "</font>";
  }

  /**
   * Set this element next in the tab order. Returns the element for easier nesting in expressions.
   */
  protected Element setTabOrder(Element ele) {
    ele.attribute("tabindex", tabindex++);
    return ele;
  }

  /**
   * Store a footnote, assign it a number, return html for footnote reference. If footnote in null
   * or empty, no footnote is added and an empty string is returned. Footnote numbers get turned
   * into links; <b>Do not put the result of addFootnote inside a link!</b>.
   */
  protected String addFootnote(String s) {
    if (s == null || s.length() == 0) {
      return "";
    }
    if (footNumber == 0) {
      if (footnotes == null) {
        footnotes = new Vector(10, 10);
      } else {
        footnotes.removeAllElements();
      }
    }
    int n = footnotes.indexOf(s);
    if (n < 0) {
      n = footNumber++;
      footnotes.addElement(s);
    }
    return "<sup><font size=-1><a href=#foottag" + (n + 1) + ">" + (n + 1) + "</a></font></sup>";
  }

  /**
   * Add javascript to page. Normally adds a link to the script file, but can be told to include the
   * script directly in the page, to accomodate unit testing of individual servlets, when other
   * fetches won't work.
   */
  protected void addJavaScript(Composite comp) {
    String include = (String) context.getAttribute(ATTR_INCLUDE_SCRIPT);
    if (StringUtil.isNullString(include)) {
      linkToJavaScript(comp);
    } else {
      includeJavaScript0(comp);
    }
  }

  private void includeJavaScript0(Composite comp) {
    Script script = new Script(getJavascript());
    comp.add(script);
  }

  private void linkToJavaScript(Composite comp) {
    Script script = new Script("");
    script.attribute("src", "admin.js");
    comp.add(script);
  }

  private static String jstext = null;

  private static synchronized String getJavascript() {
    if (jstext == null) {
      InputStream istr = null;
      try {
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        istr = loader.getResourceAsStream(JAVASCRIPT_RESOURCE);
        jstext = StringUtil.fromInputStream(istr);
        istr.close();
      } catch (Exception e) {
        log.error("Can't load javascript", e);
      } finally {
        IOUtil.safeClose(istr);
      }
    }
    return jstext;
  }

  /** Display a message in lieu of the normal page */
  protected void displayMsgInLieuOfPage(String msg) throws IOException {
    // TODO: Look at HTML
    Page page = newPage();
    Composite warning = new Composite();
    warning.add(msg);
    warning.add("<br>");
    page.add(warning);
    layoutFooter(page);
    page.write(resp.getWriter());
  }

  /** Display a warning in red, in lieu of the normal page */
  protected void displayWarningInLieuOfPage(String msg) throws IOException {
    displayMsgInLieuOfPage("<center><font color=red size=+1>" + msg + "</font></center>");
  }

  /** Display "The cache isn't ready yet, come back later" */
  protected void displayNotStarted() throws IOException {
    displayWarningInLieuOfPage(
        "This LOCKSS box is still starting.  Please "
            + srvLink(myServletDescr(), "try again", getParamsAsProps())
            + " in a moment.");
  }

  public MultiPartRequest getMultiPartRequest() throws FormDataTooLongException, IOException {
    int maxUpload =
        CurrentConfig.getIntParam(PARAM_MAX_UPLOAD_FILE_SIZE, DEFAULT_MAX_UPLOAD_FILE_SIZE);
    return getMultiPartRequest(maxUpload);
  }

  public MultiPartRequest getMultiPartRequest(int maxLen)
      throws FormDataTooLongException, IOException {
    if (req.getContentType() == null || !req.getContentType().startsWith("multipart/form-data")) {
      return null;
    }
    if (req.getContentLength() > maxLen) {
      throw new FormDataTooLongException(req.getContentLength() + " bytes, " + maxLen + " allowed");
    }
    MultiPartRequest multi = new MultiPartRequest(req);
    if (log.isDebug2()) {
      String[] parts = multi.getPartNames();
      log.debug3("Multipart request, " + parts.length + " parts");
      if (log.isDebug3()) {
        for (int p = 0; p < parts.length; p++) {
          String name = parts[p];
          String cont = multi.getString(parts[p]);
          log.debug3(name + ": " + cont);
        }
      }
    }
    multiReq = multi;
    return multi;
  }

  public String getParameter(String name) {
    String val = req.getParameter(name);
    if (val == null && multiReq != null) {
      val = multiReq.getString(name);
    }
    if (val == null) {
      return null;
    }
    val = StringUtils.strip(val, " \t");
    //     if (StringUtil.isNullString(val)) {
    if ("".equals(val)) {
      return null;
    }
    return val;
  }

  protected void layoutFooter(Page page) {
    ServletUtil.doLayoutFooter(
        page, (footnotes == null ? null : footnotes.iterator()), getLockssApp().getVersionInfo());
    if (footnotes != null) {
      footnotes.removeAllElements();
    }
  }

  /** Return the app instance. */
  protected LockssApp getLockssApp() {
    return theApp;
  }

  /**
   * Return the daemon instance, assumes that the servlet is running in the daemon.
   *
   * @throws ClassCastException if the servlet is running in an app other than the daemon
   */
  protected LockssDaemon getLockssDaemon() {
    return (LockssDaemon) theApp;
  }

  protected void logParams() {
    Enumeration en = req.getParameterNames();
    while (en.hasMoreElements()) {
      String name = (String) en.nextElement();
      String vals[];
      String dispval;
      if (StringUtil.indexOfIgnoreCase(name, "passw") >= 0) {
        dispval = req.getParameter(name).length() == 0 ? "" : "********";
      } else if (log.isDebug2() && (vals = req.getParameterValues(name)).length > 1) {
        dispval = StringUtil.separatedString(vals, ", ");
      } else {
        dispval = req.getParameter(name);
      }
      log.debug(name + " = " + dispval);
    }
  }

  /** Convenience method */
  protected String encodeText(String s) {
    return HtmlUtil.encode(s, HtmlUtil.ENCODE_TEXT);
  }

  /** Convenience method */
  protected String encodeTextArea(String s) {
    return HtmlUtil.encode(s, HtmlUtil.ENCODE_TEXTAREA);
  }

  /** Convenience method */
  protected String encodeAttr(String s) {
    return HtmlUtil.encode(s, HtmlUtil.ENCODE_ATTR);
  }

  /**
   * Create message and error message block
   *
   * @param composite TODO
   */
  protected void layoutErrorBlock(Composite composite) {
    if (errMsg != null || statusMsg != null) {
      ServletUtil.layoutErrorBlock(composite, errMsg, statusMsg);
    }
  }

  /** Exception thrown if multipart form data is longer than the caller-supplied max */
  public static class FormDataTooLongException extends Exception {
    public FormDataTooLongException(String message) {
      super(message);
    }
  }
}
Exemplo n.º 3
0
public class CIManagerImpl implements CIManager, FrameworkConstants {

  private static final Logger S_LOGGER = Logger.getLogger(CIManagerImpl.class);
  private static Boolean debugEnabled = S_LOGGER.isDebugEnabled();

  private CLI cli = null;

  public BufferedReader setup(
      ProjectInfo projectInfo,
      ActionType action,
      List<String> buildArgCmds,
      String workingDirectory)
      throws PhrescoException {
    try {
      ApplicationManager applicationManager = PhrescoFrameworkFactory.getApplicationManager();
      BufferedReader reader =
          applicationManager.performAction(projectInfo, action, buildArgCmds, workingDirectory);
      return reader;
    } catch (Exception e) {
      throw new PhrescoException(e);
    }
  }

  public BufferedReader start(
      ProjectInfo projectInfo,
      ActionType action,
      List<String> buildArgCmds,
      String workingDirectory)
      throws PhrescoException {
    try {
      ApplicationManager applicationManager = PhrescoFrameworkFactory.getApplicationManager();
      BufferedReader reader =
          applicationManager.performAction(projectInfo, action, buildArgCmds, workingDirectory);
      return reader;
    } catch (Exception e) {
      throw new PhrescoException(e);
    }
  }

  public BufferedReader stop(
      ProjectInfo projectInfo,
      ActionType action,
      List<String> buildArgCmds,
      String workingDirectory)
      throws PhrescoException {
    try {
      ApplicationManager applicationManager = PhrescoFrameworkFactory.getApplicationManager();
      BufferedReader reader =
          applicationManager.performAction(projectInfo, action, buildArgCmds, workingDirectory);
      return reader;
    } catch (Exception e) {
      throw new PhrescoException(e);
    }
  }

  public void createJob(ApplicationInfo appInfo, CIJob job) throws PhrescoException {
    if (debugEnabled) {
      S_LOGGER.debug(
          "Entering Method ProjectAdministratorImpl.createJob(Project project, CIJob job)");
    }
    FileWriter writer = null;
    try {
      CIJobStatus jobStatus = configureJob(job, FrameworkConstants.CI_CREATE_JOB_COMMAND);
      if (jobStatus.getCode() == -1) {
        throw new PhrescoException(jobStatus.getMessage());
      }
      if (debugEnabled) {
        S_LOGGER.debug("ProjectInfo = " + appInfo);
      }
      writeJsonJobs(appInfo, Arrays.asList(job), CI_APPEND_JOBS);
    } catch (ClientHandlerException ex) {
      if (debugEnabled) {
        S_LOGGER.error(ex.getLocalizedMessage());
      }
      throw new PhrescoException(ex);
    } finally {
      if (writer != null) {
        try {
          writer.close();
        } catch (IOException e) {
          S_LOGGER.error(e.getLocalizedMessage());
        }
      }
    }
  }

  public void updateJob(ApplicationInfo appInfo, CIJob job) throws PhrescoException {
    if (debugEnabled) {
      S_LOGGER.debug(
          "Entering Method ProjectAdministratorImpl.updateJob(Project project, CIJob job)");
    }
    FileWriter writer = null;
    try {
      CIJobStatus jobStatus = configureJob(job, FrameworkConstants.CI_UPDATE_JOB_COMMAND);
      if (jobStatus.getCode() == -1) {
        throw new PhrescoException(jobStatus.getMessage());
      }
      if (debugEnabled) {
        S_LOGGER.debug("getCustomModules() ProjectInfo = " + appInfo);
      }
      updateJsonJob(appInfo, job);
    } catch (ClientHandlerException ex) {
      if (debugEnabled) {
        S_LOGGER.error(ex.getLocalizedMessage());
      }
      throw new PhrescoException(ex);
    } finally {
      if (writer != null) {
        try {
          writer.close();
        } catch (IOException e) {
          if (debugEnabled) {
            S_LOGGER.error(e.getLocalizedMessage());
          }
        }
      }
    }
  }

  private CIJobStatus configureJob(CIJob job, String jobType) throws PhrescoException {
    if (debugEnabled) {
      S_LOGGER.debug("Entering Method CIManagerImpl.createJob(CIJob job)");
    }
    try {
      cli = getCLI(job);
      List<String> argList = new ArrayList<String>();
      argList.add(jobType);
      argList.add(job.getName());

      String jenkinsTemplateDir = Utility.getJenkinsTemplateDir();
      String configFilePath = jenkinsTemplateDir + job.getRepoType() + HYPHEN + CONFIG_XML;
      if (debugEnabled) {
        S_LOGGER.debug("configFilePath ...  " + configFilePath);
      }

      File configFile = new File(configFilePath);
      ConfigProcessor processor = new ConfigProcessor(configFile);
      customizeNodes(processor, job);

      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      if (debugEnabled) {
        S_LOGGER.debug("argList " + argList.toString());
      }
      int result = cli.execute(argList, processor.getConfigAsStream(), System.out, baos);

      String message = "Job created successfully";
      if (result == -1) {
        byte[] byteArray = baos.toByteArray();
        message = new String(byteArray);
      }
      if (debugEnabled) {
        S_LOGGER.debug("message " + message);
      }
      // when svn is selected credential value has to set
      if (SVN.equals(job.getRepoType())) {
        setSvnCredential(job);
      }

      setMailCredential(job);
      return new CIJobStatus(result, message);
    } catch (IOException e) {
      throw new PhrescoException(e);
    } catch (JDOMException e) {
      throw new PhrescoException(e);
    } finally {
      if (cli != null) {
        try {
          cli.close();
        } catch (IOException e) {
          if (debugEnabled) {
            S_LOGGER.error(e.getLocalizedMessage());
          }
        } catch (InterruptedException e) {
          if (debugEnabled) {
            S_LOGGER.error(e.getLocalizedMessage());
          }
        }
      }
    }
  }

  private void setSvnCredential(CIJob job) throws JDOMException, IOException {
    S_LOGGER.debug("Entering Method CIManagerImpl.setSvnCredential");
    try {
      String jenkinsTemplateDir = Utility.getJenkinsTemplateDir();
      String credentialFilePath = jenkinsTemplateDir + job.getRepoType() + HYPHEN + CREDENTIAL_XML;
      if (debugEnabled) {
        S_LOGGER.debug("credentialFilePath ... " + credentialFilePath);
      }
      File credentialFile = new File(credentialFilePath);

      SvnProcessor processor = new SvnProcessor(credentialFile);

      //			DataInputStream in = new DataInputStream(new FileInputStream(credentialFile));
      //			while (in.available() != 0) {
      //				System.out.println(in.readLine());
      //			}
      //			in.close();

      processor.changeNodeValue("credentials/entry//userName", job.getUserName());
      processor.changeNodeValue("credentials/entry//password", job.getPassword());
      processor.writeStream(new File(Utility.getJenkinsHome() + File.separator + job.getName()));

      // jenkins home location
      String jenkinsJobHome = System.getenv(JENKINS_HOME);
      StringBuilder builder = new StringBuilder(jenkinsJobHome);
      builder.append(File.separator);

      processor.writeStream(new File(builder.toString() + CI_CREDENTIAL_XML));
    } catch (Exception e) {
      S_LOGGER.error(
          "Entered into the catch block of CIManagerImpl.setSvnCredential "
              + e.getLocalizedMessage());
    }
  }

  private void setMailCredential(CIJob job) {
    if (debugEnabled) {
      S_LOGGER.debug("Entering Method CIManagerImpl.setMailCredential");
    }
    try {
      String jenkinsTemplateDir = Utility.getJenkinsTemplateDir();
      String mailFilePath = jenkinsTemplateDir + MAIL + HYPHEN + CREDENTIAL_XML;
      if (debugEnabled) {
        S_LOGGER.debug("configFilePath ... " + mailFilePath);
      }
      File mailFile = new File(mailFilePath);

      SvnProcessor processor = new SvnProcessor(mailFile);

      //			DataInputStream in = new DataInputStream(new FileInputStream(mailFile));
      //			while (in.available() != 0) {
      //				System.out.println(in.readLine());
      //			}
      //			in.close();

      // Mail have to go with jenkins running email address
      InetAddress ownIP = InetAddress.getLocalHost();
      processor.changeNodeValue(
          CI_HUDSONURL,
          HTTP_PROTOCOL
              + PROTOCOL_POSTFIX
              + ownIP.getHostAddress()
              + COLON
              + job.getJenkinsPort()
              + FORWARD_SLASH
              + CI
              + FORWARD_SLASH);
      processor.changeNodeValue("smtpAuthUsername", job.getSenderEmailId());
      processor.changeNodeValue("smtpAuthPassword", job.getSenderEmailPassword());
      processor.changeNodeValue("adminAddress", job.getSenderEmailId());

      // jenkins home location
      String jenkinsJobHome = System.getenv(JENKINS_HOME);
      StringBuilder builder = new StringBuilder(jenkinsJobHome);
      builder.append(File.separator);

      processor.writeStream(new File(builder.toString() + CI_MAILER_XML));
    } catch (Exception e) {
      S_LOGGER.error(
          "Entered into the catch block of CIManagerImpl.setMailCredential "
              + e.getLocalizedMessage());
    }
  }

  private CIJobStatus buildJob(CIJob job) throws PhrescoException {
    if (debugEnabled) {
      S_LOGGER.debug("Entering Method CIManagerImpl.buildJob(CIJob job)");
    }
    cli = getCLI(job);

    List<String> argList = new ArrayList<String>();
    argList.add(FrameworkConstants.CI_BUILD_JOB_COMMAND);
    argList.add(job.getName());
    try {
      int status = cli.execute(argList);
      String message = FrameworkConstants.CI_BUILD_STARTED;
      if (status == FrameworkConstants.JOB_STATUS_NOTOK) {
        message = FrameworkConstants.CI_BUILD_STARTING_ERROR;
      }
      return new CIJobStatus(status, message);
    } finally {
      if (cli != null) {
        try {
          cli.close();
        } catch (IOException e) {
          if (debugEnabled) {
            S_LOGGER.error(e.getLocalizedMessage());
          }
        } catch (InterruptedException e) {
          if (debugEnabled) {
            S_LOGGER.error(e.getLocalizedMessage());
          }
        }
      }
    }
  }

  private JsonArray getBuildsArray(CIJob job) throws PhrescoException {
    try {
      String jenkinsUrl = "http://" + job.getJenkinsUrl() + ":" + job.getJenkinsPort() + "/ci/";
      String jobNameUtf8 = job.getName().replace(" ", "%20");
      String buildsJsonUrl = jenkinsUrl + "job/" + jobNameUtf8 + "/api/json";
      String jsonResponse = getJsonResponse(buildsJsonUrl);

      JsonParser parser = new JsonParser();
      JsonElement jsonElement = parser.parse(jsonResponse);
      JsonObject jsonObject = jsonElement.getAsJsonObject();
      JsonElement element = jsonObject.get(FrameworkConstants.CI_JOB_JSON_BUILDS);

      JsonArray jsonArray = element.getAsJsonArray();

      return jsonArray;
    } catch (Exception e) {
      throw new PhrescoException(e);
    }
  }

  public List<CIBuild> getBuilds(CIJob job) throws PhrescoException {
    if (debugEnabled) {
      S_LOGGER.debug("Entering Method CIManagerImpl.getCIBuilds(CIJob job)");
    }
    List<CIBuild> ciBuilds = null;
    try {
      if (debugEnabled) {
        S_LOGGER.debug("getCIBuilds()  JobName = " + job.getName());
      }
      JsonArray jsonArray = getBuildsArray(job);
      ciBuilds = new ArrayList<CIBuild>(jsonArray.size());
      Gson gson = new Gson();
      CIBuild ciBuild = null;
      for (int i = 0; i < jsonArray.size(); i++) {
        ciBuild = gson.fromJson(jsonArray.get(i), CIBuild.class);
        setBuildStatus(ciBuild, job);
        String buildUrl = ciBuild.getUrl();
        String jenkinUrl = job.getJenkinsUrl() + ":" + job.getJenkinsPort();
        buildUrl =
            buildUrl.replaceAll(
                "localhost:" + job.getJenkinsPort(),
                jenkinUrl); // when displaying url it should display setup machine ip
        ciBuild.setUrl(buildUrl);
        ciBuilds.add(ciBuild);
      }
    } catch (Exception e) {
      if (debugEnabled) {
        S_LOGGER.debug(
            "Entering Method CIManagerImpl.getCIBuilds(CIJob job) " + e.getLocalizedMessage());
      }
    }
    return ciBuilds;
  }

  private void setBuildStatus(CIBuild ciBuild, CIJob job) throws PhrescoException {
    S_LOGGER.debug("Entering Method CIManagerImpl.setBuildStatus(CIBuild ciBuild)");
    S_LOGGER.debug("setBuildStatus()  url = " + ciBuild.getUrl());
    String buildUrl = ciBuild.getUrl();
    String jenkinsUrl = job.getJenkinsUrl() + ":" + job.getJenkinsPort();
    buildUrl =
        buildUrl.replaceAll(
            "localhost:" + job.getJenkinsPort(),
            jenkinsUrl); // display the jenkins running url in ci list
    String response = getJsonResponse(buildUrl + API_JSON);
    JsonParser parser = new JsonParser();
    JsonElement jsonElement = parser.parse(response);
    JsonObject jsonObject = jsonElement.getAsJsonObject();

    JsonElement resultJson = jsonObject.get(FrameworkConstants.CI_JOB_BUILD_RESULT);
    JsonElement idJson = jsonObject.get(FrameworkConstants.CI_JOB_BUILD_ID);
    JsonElement timeJson = jsonObject.get(FrameworkConstants.CI_JOB_BUILD_TIME_STAMP);
    JsonArray asJsonArray = jsonObject.getAsJsonArray(FrameworkConstants.CI_JOB_BUILD_ARTIFACTS);

    if (jsonObject
        .get(FrameworkConstants.CI_JOB_BUILD_RESULT)
        .toString()
        .equals(STRING_NULL)) { // when build is result is not known
      ciBuild.setStatus(INPROGRESS);
    } else if (resultJson.getAsString().equals(CI_SUCCESS_FLAG)
        && asJsonArray.size()
            < 1) { // when build is success and zip relative path is not added in json
      ciBuild.setStatus(INPROGRESS);
    } else {
      ciBuild.setStatus(resultJson.getAsString());
      // download path
      for (JsonElement jsonArtElement : asJsonArray) {
        String buildDownloadZip =
            jsonArtElement
                .getAsJsonObject()
                .get(FrameworkConstants.CI_JOB_BUILD_DOWNLOAD_PATH)
                .toString();
        if (buildDownloadZip.endsWith(CI_ZIP)) {
          if (debugEnabled) {
            S_LOGGER.debug("download artifact " + buildDownloadZip);
          }
          ciBuild.setDownload(buildDownloadZip);
        }
      }
    }

    ciBuild.setId(idJson.getAsString());
    String dispFormat = DD_MM_YYYY_HH_MM_SS;
    ciBuild.setTimeStamp(getDate(timeJson.getAsString(), dispFormat));
  }

  private String getDate(String timeStampStr, String format) {
    DateFormat formatter = new SimpleDateFormat(format);
    long timeStamp = Long.parseLong(timeStampStr);
    Calendar calendar = Calendar.getInstance();
    calendar.setTimeInMillis(timeStamp);
    return formatter.format(calendar.getTime());
  }

  private String getJsonResponse(String jsonUrl) throws PhrescoException {
    if (debugEnabled) {
      S_LOGGER.debug("Entering Method CIManagerImpl.getJsonResponse(String jsonUrl)");
      S_LOGGER.debug("getJsonResponse() JSonUrl = " + jsonUrl);
    }
    try {
      HttpClient httpClient = new DefaultHttpClient();
      HttpGet httpget = new HttpGet(jsonUrl);
      ResponseHandler<String> responseHandler = new BasicResponseHandler();
      return httpClient.execute(httpget, responseHandler);
    } catch (IOException e) {
      throw new PhrescoException(e);
    }
  }

  private CLI getCLI(CIJob job) throws PhrescoException {
    if (debugEnabled) {
      S_LOGGER.debug("Entering Method CIManagerImpl.getCLI()");
    }
    String jenkinsUrl =
        HTTP_PROTOCOL
            + PROTOCOL_POSTFIX
            + job.getJenkinsUrl()
            + COLON
            + job.getJenkinsPort()
            + FORWARD_SLASH
            + CI
            + FORWARD_SLASH;
    if (debugEnabled) {
      S_LOGGER.debug("jenkinsUrl to get cli object " + jenkinsUrl);
    }
    try {
      return new CLI(new URL(jenkinsUrl));
    } catch (MalformedURLException e) {
      throw new PhrescoException(e);
    } catch (IOException e) {
      throw new PhrescoException(e);
    } catch (InterruptedException e) {
      throw new PhrescoException(e);
    }
  }

  private void customizeNodes(ConfigProcessor processor, CIJob job)
      throws JDOMException, PhrescoException {

    // SVN url customization
    if (SVN.equals(job.getRepoType())) {
      S_LOGGER.debug("This is svn type project!!!!!");
      processor.changeNodeValue(SCM_LOCATIONS_REMOTE, job.getSvnUrl());
    } else if (GIT.equals(job.getRepoType())) {
      S_LOGGER.debug("This is git type project!!!!!");
      processor.changeNodeValue(SCM_USER_REMOTE_CONFIGS_URL, job.getSvnUrl());
      processor.changeNodeValue(SCM_BRANCHES_NAME, job.getBranch());
      // cloned workspace
    } else if (CLONED_WORKSPACE.equals(job.getRepoType())) {
      S_LOGGER.debug("Clonned workspace selected!!!!!!!!!!");
      processor.useClonedScm(job.getUsedClonnedWorkspace(), SUCCESSFUL);
    }

    // Schedule expression customization
    processor.changeNodeValue(TRIGGERS_SPEC, job.getScheduleExpression());

    // Triggers Implementation
    List<String> triggers = job.getTriggers();

    processor.createTriggers(TRIGGERS, triggers, job.getScheduleExpression());

    // if the technology is java stanalone and functional test , goal have to specified in post
    // build step only
    if (job.isEnablePostBuildStep() && FUNCTIONAL_TEST.equals(job.getOperation())) {
      // Maven command customization
      processor.changeNodeValue(GOALS, CI_FUNCTIONAL_ADAPT.trim());
    } else {
      // Maven command customization
      processor.changeNodeValue(GOALS, job.getMvnCommand());
    }

    // Recipients customization
    Map<String, String> email = job.getEmail();

    // Failure Reception list
    processor.changeNodeValue(
        TRIGGER_FAILURE_EMAIL_RECIPIENT_LIST, (String) email.get(FAILURE_EMAILS));

    // Success Reception list
    processor.changeNodeValue(
        TRIGGER_SUCCESS__EMAIL_RECIPIENT_LIST, (String) email.get(SUCCESS_EMAILS));

    // enable collabnet file release plugin integration
    if (job.isEnableBuildRelease()) {
      S_LOGGER.debug("Enablebling collabnet file release plugin ");
      processor.enableCollabNetBuildReleasePlugin(job);
    }

    // use clonned scm
    if (CLONED_WORKSPACE.equals(job.getRepoType())) {
      S_LOGGER.debug("using cloned workspace ");
      processor.useClonedScm(job.getUsedClonnedWorkspace(), SUCCESSFUL);
    }

    // clone workspace for future use
    if (job.isCloneWorkspace()) {
      S_LOGGER.debug("Clonning the workspace ");
      processor.cloneWorkspace(ALL_FILES, SUCCESSFUL, TAR);
    }

    // Build Other projects
    if (StringUtils.isNotEmpty(job.getDownStreamProject())) {
      S_LOGGER.debug("Enabling downstream project!!!!!!");
      processor.buildOtherProjects(job.getDownStreamProject());
    }

    // pom location specifier
    if (StringUtils.isNotEmpty(job.getPomLocation())) {
      S_LOGGER.debug("POM location changing " + job.getPomLocation());
      processor.updatePOMLocation(job.getPomLocation());
    }

    if (job.isEnablePostBuildStep()) {
      System.out.println("java stanalone technology with functional test enabled!!!!!!!");
      String mvnCommand = job.getMvnCommand();
      String[] ciAdapted =
          mvnCommand.split(CI_FUNCTIONAL_ADAPT); // java stanalone functional test alone
      for (String ciCommand : ciAdapted) {
        S_LOGGER.debug("ciCommand...." + ciCommand);
      }
      // iterate over loop
      processor.enablePostBuildStep(job.getPomLocation(), ciAdapted[1]);
    }

    if (job.isEnablePreBuildStep()) {
      System.out.println("java stanalone technology with functional test enabled!!!!!!!");
      // iterate over loop
      List<String> prebuildStepCommands = job.getPrebuildStepCommands();
      for (String prebuildStepCommand : prebuildStepCommands) {
        processor.enablePreBuildStep(job.getPomLocation(), prebuildStepCommand);
      }
    }
  }

  private CIJobStatus deleteCI(CIJob job, List<String> builds) throws PhrescoException {
    S_LOGGER.debug("Entering Method CIManagerImpl.deleteCI(CIJob job)");
    S_LOGGER.debug("Job name " + job.getName());
    cli = getCLI(job);
    String deleteType = null;
    List<String> argList = new ArrayList<String>();
    S_LOGGER.debug("job name " + job.getName());
    S_LOGGER.debug("Builds " + builds);
    if (CollectionUtils.isEmpty(builds)) { // delete job
      S_LOGGER.debug("Job deletion started");
      S_LOGGER.debug("Command " + FrameworkConstants.CI_JOB_DELETE_COMMAND);
      deleteType = DELETE_TYPE_JOB;
      argList.add(FrameworkConstants.CI_JOB_DELETE_COMMAND);
      argList.add(job.getName());
    } else { // delete Build
      S_LOGGER.debug("Build deletion started");
      deleteType = DELETE_TYPE_BUILD;
      argList.add(FrameworkConstants.CI_BUILD_DELETE_COMMAND);
      argList.add(job.getName());
      StringBuilder result = new StringBuilder();
      for (String string : builds) {
        result.append(string);
        result.append(",");
      }
      String buildNos = result.substring(0, result.length() - 1);
      argList.add(buildNos);
      S_LOGGER.debug("Command " + FrameworkConstants.CI_BUILD_DELETE_COMMAND);
      S_LOGGER.debug("Build numbers " + buildNos);
    }
    try {
      int status = cli.execute(argList);
      String message = deleteType + " deletion started in jenkins";
      if (status == FrameworkConstants.JOB_STATUS_NOTOK) {
        deleteType = deleteType.substring(0, 1).toLowerCase() + deleteType.substring(1);
        message = "Error while deleting " + deleteType + " in jenkins";
      }
      S_LOGGER.debug("Delete CI Status " + status);
      S_LOGGER.debug("Delete CI Message " + message);
      return new CIJobStatus(status, message);
    } finally {
      if (cli != null) {
        try {
          cli.close();
        } catch (IOException e) {
          if (debugEnabled) {
            S_LOGGER.error(
                "Entered into catch block of CIManagerImpl.deleteCI(CIJob job) "
                    + e.getLocalizedMessage());
          }
        } catch (InterruptedException e) {
          if (debugEnabled) {
            S_LOGGER.error(
                "Entered into catch block of CIManagerImpl.deleteCI(CIJob job) "
                    + e.getLocalizedMessage());
          }
        }
      }
    }
  }

  private CIJob getJob(ApplicationInfo appInfo) throws PhrescoException {
    Gson gson = new Gson();
    try {
      BufferedReader br = new BufferedReader(new FileReader(getCIJobPath(appInfo)));
      CIJob job = gson.fromJson(br, CIJob.class);
      br.close();
      return job;
    } catch (FileNotFoundException e) {
      S_LOGGER.debug(e.getLocalizedMessage());
      return null;
    } catch (com.google.gson.JsonParseException e) {
      S_LOGGER.debug("it is already adpted project !!!!! " + e.getLocalizedMessage());
      return null;
    } catch (IOException e) {
      S_LOGGER.debug(e.getLocalizedMessage());
      return null;
    }
  }

  private boolean adaptExistingJobs(ApplicationInfo appInfo) {
    try {
      CIJob existJob = getJob(appInfo);
      S_LOGGER.debug("Going to get existing jobs to relocate!!!!!");
      if (existJob != null) {
        S_LOGGER.debug("Existing job found " + existJob.getName());
        boolean deleteExistJob = deleteCIJobFile(appInfo);
        Gson gson = new Gson();
        List<CIJob> existingJobs = new ArrayList<CIJob>();
        existingJobs.addAll(Arrays.asList(existJob));
        FileWriter writer = null;
        File ciJobFile = new File(getCIJobPath(appInfo));
        String jobJson = gson.toJson(existingJobs);
        writer = new FileWriter(ciJobFile);
        writer.write(jobJson);
        writer.flush();
        S_LOGGER.debug("Existing job moved to new type of project!!");
      }
      return true;
    } catch (Exception e) {
      S_LOGGER.debug("It is already adapted !!!!! ");
    }
    return false;
  }

  public List<CIJob> getJobs(ApplicationInfo appInfo) throws PhrescoException {
    S_LOGGER.debug("GetJobs Called!");
    try {
      boolean adaptedProject = adaptExistingJobs(appInfo);
      S_LOGGER.debug("Project adapted for new feature => " + adaptedProject);
      Gson gson = new Gson();
      BufferedReader br = new BufferedReader(new FileReader(getCIJobPath(appInfo)));
      Type type = new TypeToken<List<CIJob>>() {}.getType();
      List<CIJob> jobs = gson.fromJson(br, type);
      br.close();
      return jobs;
    } catch (FileNotFoundException e) {
      S_LOGGER.debug("FileNotFoundException");
      return null;
    } catch (IOException e) {
      S_LOGGER.debug("IOException");
      throw new PhrescoException(e);
    }
  }

  public CIJob getJob(ApplicationInfo appInfo, String jobName) throws PhrescoException {
    try {
      S_LOGGER.debug("Search for jobName => " + jobName);
      if (StringUtils.isEmpty(jobName)) {
        return null;
      }
      List<CIJob> jobs = getJobs(appInfo);
      if (CollectionUtils.isEmpty(jobs)) {
        S_LOGGER.debug("job list is empty!!!!!!!!");
        return null;
      }
      S_LOGGER.debug("Job list found!!!!!");
      for (CIJob job : jobs) {
        S_LOGGER.debug("job list job Names => " + job.getName());
        if (job.getName().equals(jobName)) {
          return job;
        }
      }
    } catch (Exception e) {
      throw new PhrescoException(e);
    }
    return null;
  }

  private void writeJsonJobs(ApplicationInfo appInfo, List<CIJob> jobs, String status)
      throws PhrescoException {
    try {
      if (jobs == null) {
        return;
      }
      Gson gson = new Gson();
      List<CIJob> existingJobs = getJobs(appInfo);
      if (CI_CREATE_NEW_JOBS.equals(status) || existingJobs == null) {
        existingJobs = new ArrayList<CIJob>();
      }
      existingJobs.addAll(jobs);
      FileWriter writer = null;
      File ciJobFile = new File(getCIJobPath(appInfo));
      String jobJson = gson.toJson(existingJobs);
      writer = new FileWriter(ciJobFile);
      writer.write(jobJson);
      writer.flush();
    } catch (Exception e) {
      throw new PhrescoException(e);
    }
  }

  private void deleteJsonJobs(ApplicationInfo appInfo, List<CIJob> selectedJobs)
      throws PhrescoException {
    try {
      if (CollectionUtils.isEmpty(selectedJobs)) {
        return;
      }
      Gson gson = new Gson();
      List<CIJob> jobs = getJobs(appInfo);
      if (CollectionUtils.isEmpty(jobs)) {
        return;
      }
      // all values
      Iterator<CIJob> iterator = jobs.iterator();
      // deletable values
      for (CIJob selectedInfo : selectedJobs) {
        while (iterator.hasNext()) {
          CIJob itrCiJob = iterator.next();
          if (itrCiJob.getName().equals(selectedInfo.getName())) {
            iterator.remove();
            break;
          }
        }
      }
      writeJsonJobs(appInfo, jobs, CI_CREATE_NEW_JOBS);
    } catch (Exception e) {
      throw new PhrescoException(e);
    }
  }

  private void updateJsonJob(ApplicationInfo appInfo, CIJob job) throws PhrescoException {
    try {
      deleteJsonJobs(appInfo, Arrays.asList(job));
      writeJsonJobs(appInfo, Arrays.asList(job), CI_APPEND_JOBS);
    } catch (Exception e) {
      throw new PhrescoException(e);
    }
  }

  private String getCIJobPath(ApplicationInfo appInfo) {
    StringBuilder builder = new StringBuilder(Utility.getProjectHome());
    builder.append(appInfo.getAppDirName());
    builder.append(File.separator);
    builder.append(FOLDER_DOT_PHRESCO);
    builder.append(File.separator);
    builder.append(CI_JOB_INFO_NAME);
    return builder.toString();
  }

  public CIJobStatus buildJobs(ApplicationInfo appInfo, List<String> jobsName)
      throws PhrescoException {
    try {
      CIJobStatus jobStatus = null;
      for (String jobName : jobsName) {
        CIJob ciJob = getJob(appInfo, jobName);
        jobStatus = buildJob(ciJob);
      }
      return jobStatus;
    } catch (ClientHandlerException ex) {
      S_LOGGER.error(ex.getLocalizedMessage());
      throw new PhrescoException(ex);
    }
  }

  public CIJobStatus deleteBuilds(ApplicationInfo appInfo, Map<String, List<String>> builds)
      throws PhrescoException {
    S_LOGGER.debug("Entering Method ProjectAdministratorImpl.deleteCI()");
    try {
      CIJobStatus deleteCI = null;
      Iterator iterator = builds.keySet().iterator();
      while (iterator.hasNext()) {
        String jobName = iterator.next().toString();
        List<String> deleteBuilds = builds.get(jobName);
        S_LOGGER.debug("jobName " + jobName + " builds " + deleteBuilds);
        CIJob ciJob = getJob(appInfo, jobName);
        // job and build numbers
        deleteCI = deleteCI(ciJob, deleteBuilds);
      }
      return deleteCI;
    } catch (ClientHandlerException ex) {
      S_LOGGER.error(
          "Entered into catch block of ProjectAdministratorImpl.deleteCI()"
              + ex.getLocalizedMessage());
      throw new PhrescoException(ex);
    }
  }

  public CIJobStatus deleteJobs(ApplicationInfo appInfo, List<String> jobNames)
      throws PhrescoException {
    S_LOGGER.debug("Entering Method ProjectAdministratorImpl.deleteCI()");
    try {
      CIJobStatus deleteCI = null;
      for (String jobName : jobNames) {
        S_LOGGER.debug(" Deleteable job name " + jobName);
        CIJob ciJob = getJob(appInfo, jobName);
        // job and build numbers
        deleteCI = deleteCI(ciJob, null);
        S_LOGGER.debug("write back json data after job deletion successfull");
        deleteJsonJobs(appInfo, Arrays.asList(ciJob));
      }
      return deleteCI;
    } catch (ClientHandlerException ex) {
      S_LOGGER.error(
          "Entered into catch block of ProjectAdministratorImpl.deleteCI()"
              + ex.getLocalizedMessage());
      throw new PhrescoException(ex);
    }
  }

  // When already existing adapted project is created , need to move to new adapted project
  private boolean deleteCIJobFile(ApplicationInfo appInfo) throws PhrescoException {
    S_LOGGER.debug("Entering Method ProjectAdministratorImpl.deleteCI()");
    try {
      File ciJobInfo = new File(getCIJobPath(appInfo));
      return ciJobInfo.delete();
    } catch (ClientHandlerException ex) {
      S_LOGGER.error(
          "Entered into catch block of ProjectAdministratorImpl.deleteCI()"
              + ex.getLocalizedMessage());
      throw new PhrescoException(ex);
    }
  }

  public boolean isJobCreatingBuild(CIJob ciJob) throws PhrescoException {
    S_LOGGER.debug("Entering Method ProjectAdministratorImpl.isBuilding()");
    try {
      int isBuilding = getProgressInBuild(ciJob);
      if (isBuilding > 0) {
        return true;
      } else {
        return false;
      }
    } catch (Exception ex) {
      return false;
    }
  }

  private int getProgressInBuild(CIJob job) throws PhrescoException {
    S_LOGGER.debug("Entering Method CIManagerImpl.isBuilding(CIJob job)");
    String jenkinsUrl =
        HTTP_PROTOCOL
            + PROTOCOL_POSTFIX
            + job.getJenkinsUrl()
            + COLON
            + job.getJenkinsPort()
            + FORWARD_SLASH
            + CI
            + FORWARD_SLASH;
    String isBuildingUrlUrl = BUSY_EXECUTORS;
    String jsonResponse = getJsonResponse(jenkinsUrl + isBuildingUrlUrl);
    int buidInProgress = Integer.parseInt(jsonResponse);
    S_LOGGER.debug("buidInProgress " + buidInProgress);
    return buidInProgress;
  }

  public int getTotalBuilds(ApplicationInfo appInfo) throws PhrescoException {
    try {
      CIJob ciJob = getJob(appInfo);
      return getTotalBuilds(ciJob);
    } catch (ClientHandlerException ex) {
      S_LOGGER.error(ex.getLocalizedMessage());
      throw new PhrescoException(ex);
    }
  }

  private int getTotalBuilds(CIJob job) throws PhrescoException {
    try {
      S_LOGGER.debug("Entering Method CIManagerImpl.getTotalBuilds(CIJob job)");
      S_LOGGER.debug("getCIBuilds()  JobName = " + job.getName());
      JsonArray jsonArray = getBuildsArray(job);
      Gson gson = new Gson();
      CIBuild ciBuild = null;
      if (jsonArray.size() > 0) {
        ciBuild = gson.fromJson(jsonArray.get(0), CIBuild.class);
        String buildUrl = ciBuild.getUrl();
        String jenkinsUrl = job.getJenkinsUrl() + ":" + job.getJenkinsPort();
        // display the jenkins running url in ci
        buildUrl = buildUrl.replaceAll("localhost:" + job.getJenkinsPort(), jenkinsUrl);
        // list
        String response = getJsonResponse(buildUrl + API_JSON);
        JsonParser parser = new JsonParser();
        JsonElement jsonElement = parser.parse(response);
        JsonObject jsonObject = jsonElement.getAsJsonObject();
        JsonElement resultJson = jsonObject.get(FrameworkConstants.CI_JOB_BUILD_RESULT);
        JsonArray asJsonArray =
            jsonObject.getAsJsonArray(FrameworkConstants.CI_JOB_BUILD_ARTIFACTS);
        // when build result is not known
        if (jsonObject.get(FrameworkConstants.CI_JOB_BUILD_RESULT).toString().equals(STRING_NULL)) {
          // it indicates the job is in progress and not yet completed
          return -1;
          // when build is success and build zip relative path is unknown
        } else if (resultJson.getAsString().equals(CI_SUCCESS_FLAG) && asJsonArray.size() < 1) {
          return -1;
        } else {
          return jsonArray.size();
        }
      } else {
        return -1; // When the project is build first time,
      }
    } catch (ClientHandlerException ex) {
      S_LOGGER.error(ex.getLocalizedMessage());
      throw new PhrescoException(ex);
    }
  }
}