Example #1
0
  public void doIndex(StaplerRequest req, StaplerResponse rsp)
      throws IOException, ServletException {
    List<Ancestor> l = req.getAncestors();
    for (int i = l.size() - 1; i >= 0; i--) {
      Ancestor a = l.get(i);
      if (a.getObject() instanceof SearchableModelObject) {
        SearchableModelObject smo = (SearchableModelObject) a.getObject();

        SearchIndex index = smo.getSearchIndex();
        String query = req.getParameter("q");
        if (query != null) {
          SuggestedItem target = find(index, query);
          if (target != null) {
            // found
            rsp.sendRedirect2(a.getUrl() + target.getUrl());
            return;
          }
        }
      }
    }

    // no exact match. show the suggestions
    rsp.setStatus(SC_NOT_FOUND);
    req.getView(this, "search-failed.jelly").forward(req, rsp);
  }
Example #2
0
  public static View create(StaplerRequest req, StaplerResponse rsp, ViewGroup owner)
      throws FormException, IOException, ServletException {
    String requestContentType = req.getContentType();
    if (requestContentType == null) throw new Failure("No Content-Type header set");

    boolean isXmlSubmission =
        requestContentType.startsWith("application/xml")
            || requestContentType.startsWith("text/xml");

    String name = req.getParameter("name");
    checkGoodName(name);
    if (owner.getView(name) != null)
      throw new FormException(Messages.Hudson_ViewAlreadyExists(name), "name");

    String mode = req.getParameter("mode");
    if (mode == null || mode.length() == 0) {
      if (isXmlSubmission) {
        View v;
        v = createViewFromXML(name, req.getInputStream());
        v.owner = owner;
        rsp.setStatus(HttpServletResponse.SC_OK);
        return v;
      } else throw new FormException(Messages.View_MissingMode(), "mode");
    }

    // create a view
    View v = all().findByName(mode).newInstance(req, req.getSubmittedForm());
    v.owner = owner;

    // redirect to the config screen
    rsp.sendRedirect2(req.getContextPath() + '/' + v.getUrl() + v.getPostConstructLandingPage());

    return v;
  }
  /**
   * Implements the progressive text handling. This method is used as a "web method" with
   * progressiveText.jelly.
   */
  public void doProgressText(StaplerRequest req, StaplerResponse rsp) throws IOException {
    setContentType(rsp);
    rsp.setStatus(HttpServletResponse.SC_OK);

    if (!source.exists()) {
      // file doesn't exist yet
      rsp.addHeader("X-Text-Size", "0");
      rsp.addHeader("X-More-Data", "true");
      return;
    }

    long start = 0;
    String s = req.getParameter("start");
    if (s != null) start = Long.parseLong(s);

    if (source.length() < start) start = 0; // text rolled over

    CharSpool spool = new CharSpool();
    long r = writeLogTo(start, spool);

    rsp.addHeader("X-Text-Size", String.valueOf(r));
    if (!completed) rsp.addHeader("X-More-Data", "true");

    Writer w = createWriter(req, rsp, r - start);
    spool.writeTo(new LineEndNormalizingWriter(w));
    w.close();
  }
Example #4
0
  /** Accepts submission from the configuration page. */
  @RequirePOST
  public synchronized void doConfigSubmit(StaplerRequest req, StaplerResponse rsp)
      throws IOException, ServletException, FormException {
    checkPermission(CONFIGURE);

    description = req.getParameter("description");

    keepDependencies = req.getParameter("keepDependencies") != null;

    try {
      JSONObject json = req.getSubmittedForm();

      setDisplayName(json.optString("displayNameOrNull"));

      if (req.getParameter("logrotate") != null)
        logRotator = LogRotator.DESCRIPTOR.newInstance(req, json.getJSONObject("logrotate"));
      else logRotator = null;

      DescribableList<JobProperty<?>, JobPropertyDescriptor> t =
          new DescribableList<JobProperty<?>, JobPropertyDescriptor>(NOOP, getAllProperties());
      t.rebuild(
          req,
          json.optJSONObject("properties"),
          JobPropertyDescriptor.getPropertyDescriptors(Job.this.getClass()));
      properties.clear();
      for (JobProperty p : t) {
        p.setOwner(this);
        properties.add(p);
      }

      submit(req, rsp);

      save();
      ItemListener.fireOnUpdated(this);

      String newName = req.getParameter("name");
      final ProjectNamingStrategy namingStrategy = Jenkins.getInstance().getProjectNamingStrategy();
      if (newName != null && !newName.equals(name)) {
        // check this error early to avoid HTTP response splitting.
        Jenkins.checkGoodName(newName);
        namingStrategy.checkName(newName);
        rsp.sendRedirect("rename?newName=" + URLEncoder.encode(newName, "UTF-8"));
      } else {
        if (namingStrategy.isForceExistingJobs()) {
          namingStrategy.checkName(name);
        }
        FormApply.success(".").generateResponse(req, rsp, null);
      }
    } catch (JSONException e) {
      StringWriter sw = new StringWriter();
      PrintWriter pw = new PrintWriter(sw);
      pw.println("Failed to parse form data. Please report this problem as a bug");
      pw.println("JSON=" + req.getSubmittedForm());
      pw.println();
      e.printStackTrace(pw);

      rsp.setStatus(SC_BAD_REQUEST);
      sendError(sw.toString(), req, rsp, true);
    }
  }
Example #5
0
 /** Handles incremental log output. */
 public void doProgressiveHtml(StaplerRequest req, StaplerResponse rsp) throws IOException {
   AnnotatedLargeText text = obtainLog();
   if (text != null) {
     text.doProgressiveHtml(req, rsp);
     return;
   }
   rsp.setStatus(HttpServletResponse.SC_OK);
 }
Example #6
0
  /**
   * Creates a {@link TopLevelItem} from the submission of the '/lib/hudson/newFromList/formList' or
   * throws an exception if it fails.
   */
  public synchronized TopLevelItem createTopLevelItem(StaplerRequest req, StaplerResponse rsp)
      throws IOException, ServletException {
    acl.checkPermission(Job.CREATE);

    TopLevelItem result;

    String requestContentType = req.getContentType();
    if (requestContentType == null) throw new Failure("No Content-Type header set");

    boolean isXmlSubmission =
        requestContentType.startsWith("application/xml")
            || requestContentType.startsWith("text/xml");

    String name = req.getParameter("name");
    if (name == null) throw new Failure("Query parameter 'name' is required");

    { // check if the name looks good
      Jenkins.checkGoodName(name);
      name = name.trim();
      if (parent.getItem(name) != null) throw new Failure(Messages.Hudson_JobAlreadyExists(name));
    }

    String mode = req.getParameter("mode");
    if (mode != null && mode.equals("copy")) {
      String from = req.getParameter("from");

      // resolve a name to Item
      Item src = null;
      if (!from.startsWith("/")) src = parent.getItem(from);
      if (src == null) src = Jenkins.getInstance().getItemByFullName(from);

      if (src == null) {
        if (Util.fixEmpty(from) == null) throw new Failure("Specify which job to copy");
        else throw new Failure("No such job: " + from);
      }
      if (!(src instanceof TopLevelItem)) throw new Failure(from + " cannot be copied");

      result = copy((TopLevelItem) src, name);
    } else {
      if (isXmlSubmission) {
        result = createProjectFromXML(name, req.getInputStream());
        rsp.setStatus(HttpServletResponse.SC_OK);
        return result;
      } else {
        if (mode == null) throw new Failure("No mode given");

        // create empty job and redirect to the project config screen
        result = createProject(Items.all().findByName(mode), name, true);
      }
    }

    rsp.sendRedirect2(redirectAfterCreateItem(req, result));
    return result;
  }
Example #7
0
  public static void adminCheck(
      StaplerRequest req, StaplerResponse rsp, Object required, Permission permission)
      throws IOException, ServletException {
    // this is legacy --- all views should be eventually converted to
    // the permission based model.
    if (required != null && !Hudson.adminCheck(req, rsp)) {
      // check failed. commit the FORBIDDEN response, then abort.
      rsp.setStatus(HttpServletResponse.SC_FORBIDDEN);
      rsp.getOutputStream().close();
      throw new ServletException("Unauthorized access");
    }

    // make sure the user owns the necessary permission to access this page.
    if (permission != null) checkPermission(permission);
  }
Example #8
0
 public void doDynamic(StaplerRequest req, StaplerResponse rsp)
     throws IOException, ServletException, InterruptedException {
   rsp.setStatus(SC_SERVICE_UNAVAILABLE);
   req.getView(this, "index.jelly").forward(req, rsp);
 }
Example #9
0
 @Override
 public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object node)
     throws IOException, ServletException {
   rsp.setStatus(200);
   rsp.addHeader(X_BLUEOCEAN_JWT, sign());
 }
  /**
   * Notify the commit to this repository.
   *
   * <p>Because this URL is not guarded, we can't really trust the data that's sent to us. But we
   * intentionally don't protect this URL to simplify <tt>post-commit</tt> script set up.
   */
  public void doNotifyCommit(StaplerRequest req, StaplerResponse rsp)
      throws ServletException, IOException {
    requirePOST();

    // compute the affected paths
    Set<String> affectedPath = new HashSet<String>();
    String line;
    BufferedReader r = new BufferedReader(req.getReader());

    try {
      while ((line = r.readLine()) != null) {
        if (LOGGER.isLoggable(FINER)) {
          LOGGER.finer("Reading line: " + line);
        }
        affectedPath.add(line.substring(4));
        if (line.startsWith("svnlook changed --revision ")) {
          String msg =
              "Expecting the output from the svnlook command but instead you just sent me the svnlook invocation command line: "
                  + line;
          LOGGER.warning(msg);
          throw new IllegalArgumentException(msg);
        }
      }
    } finally {
      IOUtils.closeQuietly(r);
    }

    if (LOGGER.isLoggable(FINE))
      LOGGER.fine("Change reported to Subversion repository " + uuid + " on " + affectedPath);
    boolean scmFound = false, triggerFound = false, uuidFound = false, pathFound = false;

    // we can't reliably use req.getParameter() as it can try to parse the payload, which we've
    // already consumed above.
    // servlet container relies on Content-type to decide if it wants to parse the payload or not,
    // and at least
    // in case of Jetty, it doesn't check if the payload is
    QueryParameterMap query = new QueryParameterMap(req);
    String revParam = query.get("rev");
    long rev = -1;
    if (revParam != null) {
      rev = Long.parseLong(revParam);
    } else {
      revParam = req.getHeader("X-Hudson-Subversion-Revision");
      if (revParam != null) {
        rev = Long.parseLong(revParam);
      }
    }

    OUTER:
    for (AbstractProject<?, ?> p : Hudson.getInstance().getItems(AbstractProject.class)) {
      try {
        SCM scm = p.getScm();
        if (scm instanceof SubversionSCM) scmFound = true;
        else continue;

        SCMTrigger trigger = p.getTrigger(SCMTrigger.class);
        if (trigger != null) triggerFound = true;
        else continue;

        SubversionSCM sscm = (SubversionSCM) scm;
        for (ModuleLocation loc : sscm.getLocations()) {
          if (loc.getUUID(p).equals(uuid)) uuidFound = true;
          else continue;

          String m = loc.getSVNURL().getPath();
          String n = loc.getRepositoryRoot(p).getPath();
          if (!m.startsWith(n))
            continue; // repository root should be a subpath of the module path, but be defensive

          String remaining = m.substring(n.length());
          if (remaining.startsWith("/")) remaining = remaining.substring(1);
          String remainingSlash = remaining + '/';

          final RevisionParameterAction[] actions;
          if (rev != -1) {
            SvnInfo info[] = {new SvnInfo(loc.getURL(), rev)};
            RevisionParameterAction action = new RevisionParameterAction(info);
            actions = new RevisionParameterAction[] {action};

          } else {
            actions = new RevisionParameterAction[0];
          }

          for (String path : affectedPath) {
            if (path.equals(remaining) /*for files*/
                || path.startsWith(remainingSlash) /*for dirs*/) {
              // this project is possibly changed. poll now.
              // if any of the data we used was bogus, the trigger will not detect a change
              LOGGER.fine("Scheduling the immediate polling of " + p);
              trigger.run(actions);
              pathFound = true;

              continue OUTER;
            }
          }
        }
      } catch (SVNException e) {
        LOGGER.log(WARNING, "Failed to handle Subversion commit notification", e);
      }
    }

    if (!scmFound) LOGGER.warning("No subversion jobs found");
    else if (!triggerFound) LOGGER.warning("No subversion jobs using SCM polling");
    else if (!uuidFound) LOGGER.warning("No subversion jobs using repository: " + uuid);
    else if (!pathFound) LOGGER.fine("No jobs found matching the modified files");

    rsp.setStatus(SC_OK);
  }
  /*
   * Path: /auto/scheduleBuild
   *
   * POST to create automation requests to schedule builds.
   */
  public void doScheduleBuild(StaplerRequest request, StaplerResponse response) throws Exception {
    requirePOST();

    OSLC4JUnmarshaller unmarshaller = OSLC4JContext.newInstance().createUnmarshaller();

    String contentType = request.getContentType();
    if (contentType == null) {
      throw HttpResponses.status(HttpServletResponse.SC_BAD_REQUEST);
    }
    unmarshaller.setMediaType(MediaType.valueOf(contentType));

    final AutomationRequest autoRequest =
        unmarshaller.unmarshal(request.getInputStream(), AutomationRequest.class);
    if (autoRequest == null) {
      throw HttpResponses.status(HttpServletResponse.SC_BAD_REQUEST);
    }

    Link planLink = autoRequest.getExecutesAutomationPlan();
    if (planLink == null) {
      throw HttpResponses.status(HttpServletResponse.SC_BAD_REQUEST);
    }

    URI planURI = planLink.getValue();
    String jobName = getJobNameFromURI(planURI);
    if (jobName == null) {
      throw HttpResponses.status(HttpServletResponse.SC_BAD_REQUEST);
    }

    Job<?, ?> job = getJob(jobName);
    if (job == null) {
      throw HttpResponses.status(HttpServletResponse.SC_BAD_REQUEST);
    }

    if (!job.isBuildable()) {
      throw HttpResponses.status(HttpServletResponse.SC_BAD_REQUEST);
    }

    if (!(job instanceof AbstractProject)) {
      LOG.log(
          Level.WARNING,
          "Cannot schedule builds for jobs that don't extend AbstractProject: " + jobName);
      throw HttpResponses.status(HttpServletResponse.SC_BAD_REQUEST);
    }

    AbstractProject<?, ?> project = (AbstractProject<?, ?>) job;
    int nextBuildNumber = project.getNextBuildNumber();
    Cause cause =
        new Cause() {
          @Override
          public String getShortDescription() {
            String description = autoRequest.getDescription();
            return description != null ? description : "OSLC Automation Request";
          }
        };

    ParameterInstance[] parameters = autoRequest.getInputParameters();
    boolean suceeded;
    if (parameters.length == 0) {
      suceeded = project.scheduleBuild(cause);
    } else {
      List<ParameterValue> values = getParameterValues(project, parameters);
      suceeded =
          project.scheduleBuild2(project.getQuietPeriod(), cause, new ParametersAction(values))
              != null;
    }

    if (!suceeded) {
      // Build already queued.
      LOG.log(
          Level.WARNING,
          "Automation request rejected (409 conflict) since build is already queued: " + jobName);
      throw HttpResponses.status(HttpServletResponse.SC_CONFLICT);
    }

    URI requestURI = getAutoRequestURI(job, nextBuildNumber);
    response.setStatus(HttpServletResponse.SC_CREATED);
    response.setHeader("Location", requestURI.toString());
  }
Example #12
0
  /** Exposes the bean as XML. */
  public void doXml(
      StaplerRequest req,
      StaplerResponse rsp,
      @QueryParameter String xpath,
      @QueryParameter String wrapper,
      @QueryParameter String tree,
      @QueryParameter int depth)
      throws IOException, ServletException {
    setHeaders(rsp);

    String[] excludes = req.getParameterValues("exclude");

    if (xpath == null && excludes == null) {
      // serve the whole thing
      rsp.serveExposedBean(req, bean, Flavor.XML);
      return;
    }

    StringWriter sw = new StringWriter();

    // first write to String
    Model p = MODEL_BUILDER.get(bean.getClass());
    TreePruner pruner = (tree != null) ? new NamedPathPruner(tree) : new ByDepth(1 - depth);
    p.writeTo(bean, pruner, Flavor.XML.createDataWriter(bean, sw));

    // apply XPath
    Object result;
    try {
      Document dom = new SAXReader().read(new StringReader(sw.toString()));

      // apply exclusions
      if (excludes != null) {
        for (String exclude : excludes) {
          List<org.dom4j.Node> list = (List<org.dom4j.Node>) dom.selectNodes(exclude);
          for (org.dom4j.Node n : list) {
            Element parent = n.getParent();
            if (parent != null) parent.remove(n);
          }
        }
      }

      if (xpath == null) {
        result = dom;
      } else {
        List list = dom.selectNodes(xpath);
        if (wrapper != null) {
          Element root = DocumentFactory.getInstance().createElement(wrapper);
          for (Object o : list) {
            if (o instanceof String) {
              root.addText(o.toString());
            } else {
              root.add(((org.dom4j.Node) o).detach());
            }
          }
          result = root;
        } else if (list.isEmpty()) {
          rsp.setStatus(HttpServletResponse.SC_NOT_FOUND);
          rsp.getWriter().print(Messages.Api_NoXPathMatch(xpath));
          return;
        } else if (list.size() > 1) {
          rsp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
          rsp.getWriter().print(Messages.Api_MultipleMatch(xpath, list.size()));
          return;
        } else {
          result = list.get(0);
        }
      }

    } catch (DocumentException e) {
      LOGGER.log(Level.FINER, "Failed to do XPath/wrapper handling. XML is as follows:" + sw, e);
      throw new IOException2(
          "Failed to do XPath/wrapper handling. Turn on FINER logging to view XML.", e);
    }

    OutputStream o = rsp.getCompressedOutputStream(req);
    try {
      if (result instanceof CharacterData
          || result instanceof String
          || result instanceof Number
          || result instanceof Boolean) {
        if (INSECURE) {
          rsp.setContentType("text/plain;charset=UTF-8");
          String text =
              result instanceof CharacterData
                  ? ((CharacterData) result).getText()
                  : result.toString();
          o.write(text.getBytes("UTF-8"));
        } else {
          rsp.sendError(
              HttpURLConnection.HTTP_FORBIDDEN,
              "primitive XPath result sets forbidden; can use -Dhudson.model.Api.INSECURE=true if you run without security");
        }
        return;
      }

      // otherwise XML
      rsp.setContentType("application/xml;charset=UTF-8");
      new XMLWriter(o).write(result);
    } finally {
      o.close();
    }
  }