@Override
 /**
  * Called after the user has changed the project name of a job and then clicked on submit.
  *
  * @param item The item that has been renamed. The new project name is already in item.getName()
  * @param oldName the old name
  * @param newName the new name
  */
 public void onRenamed(Item item, String oldName, String newName) {
   // bug 5077308 - Display name field should be cleared when you rename a job.
   if (item instanceof AbstractItem) {
     AbstractItem abstractItem = (AbstractItem) item;
     if (oldName.equals(abstractItem.getDisplayName())) {
       // the user renamed the job, but the old project name which is shown as the
       // displayname if no displayname was set, has been set into the displayname field.
       // This means that the displayname was never set, so we want to set it
       // to null as it was before
       try {
         LOGGER.info(
             String.format(
                 "onRenamed():Setting displayname to null for item.name=%s", item.getName()));
         abstractItem.setDisplayName(null);
       } catch (IOException ioe) {
         LOGGER.log(
             Level.WARNING,
             String.format(
                 "onRenamed():Exception while trying to clear the displayName for Item.name:%s",
                 item.getName()),
             ioe);
       }
     }
   }
 }
 @Override
 public List<? extends ItemGroup<?>> validDestinations(Item item) {
   List<DirectlyModifiableTopLevelItemGroup> result =
       new ArrayList<DirectlyModifiableTopLevelItemGroup>();
   Jenkins instance = Jenkins.getActiveInstance();
   if (permitted(item, instance)) {
     result.add(instance);
   }
   ITEM:
   for (Item g : instance.getAllItems()) {
     if (g instanceof DirectlyModifiableTopLevelItemGroup) {
       DirectlyModifiableTopLevelItemGroup itemGroup = (DirectlyModifiableTopLevelItemGroup) g;
       if (!permitted(item, itemGroup)) {
         continue;
       }
       ItemGroup<?> p = itemGroup;
       while (p instanceof Item) {
         Item i = (Item) p;
         if (i == item) {
           // Cannot move a folder into itself or a descendant.
           continue ITEM;
         }
         p = i.getParent();
       }
       result.add(itemGroup);
     }
   }
   return result;
 }
Beispiel #3
0
 @Override
 protected void compute() throws Exception {
   int itemCount = 0;
   for (Item item : items) {
     for (Job<?, ?> job : item.getAllJobs()) {
       if (job instanceof AbstractProject) {
         AbstractProject<?, ?> p = (AbstractProject) job;
         RunList<? extends AbstractBuild<?, ?>> builds = p.getBuilds();
         int buildCount = 0;
         for (AbstractBuild<?, ?> build : builds) {
           if (canceled()) {
             return;
           }
           for (ChangeLogSet.Entry entry : build.getChangeSet()) {
             User user = entry.getAuthor();
             UserInfo info = users.get(user);
             if (info == null) {
               UserInfo userInfo = new UserInfo(user, p, build.getTimestamp());
               userInfo.avatar = UserAvatarResolver.resolveOrNull(user, iconSize);
               synchronized (this) {
                 users.put(user, userInfo);
                 modified.add(user);
               }
             } else if (info.getLastChange().before(build.getTimestamp())) {
               synchronized (this) {
                 info.project = p;
                 info.lastChange = build.getTimestamp();
                 modified.add(user);
               }
             }
           }
           // TODO consider also adding the user of the UserCause when applicable
           buildCount++;
           progress((itemCount + 1.0 * buildCount / builds.size()) / (items.size() + 1));
         }
       }
     }
     itemCount++;
     progress(1.0 * itemCount / (items.size() + /* handling User.getAll */ 1));
   }
   if (unknown != null) {
     if (canceled()) {
       return;
     }
     for (User u : User.getAll()) { // TODO nice to have a method to iterate these lazily
       if (u == unknown) {
         continue;
       }
       if (!users.containsKey(u)) {
         UserInfo userInfo = new UserInfo(u, null, null);
         userInfo.avatar = UserAvatarResolver.resolveOrNull(u, iconSize);
         synchronized (this) {
           users.put(u, userInfo);
           modified.add(u);
         }
       }
     }
   }
 }
Beispiel #4
0
 /**
  * Loads a {@link Item} from a config file.
  *
  * @param dir The directory that contains the config file, not the config file itself.
  * @param loadLazy true if return a LazyTopLevelItem without actually loading; false to actually
  *     load the file and return a real item.
  * @throws IOException
  */
 public static Item load(ItemGroup parent, File dir, boolean loadLazy) throws IOException {
   if (loadLazy) {
     return newLazyTopLevelItem(parent, dir, null);
   } else {
     Item item = (Item) getConfigFile(dir).read();
     item.onLoad(parent, dir.getName());
     return item;
   }
 }
Beispiel #5
0
 public Item doCreateItem(StaplerRequest req, StaplerResponse rsp)
     throws IOException, ServletException {
   Item item = Hudson.getInstance().doCreateItem(req, rsp);
   if (item != null) {
     jobNames.add(item.getName());
     owner.save();
   }
   return item;
 }
Beispiel #6
0
 /** Converts a list of items into a comma-separated list of full names. */
 public static String toNameList(Collection<? extends Item> items) {
   StringBuilder buf = new StringBuilder();
   for (Item item : items) {
     if (buf.length() > 0) {
       buf.append(", ");
     }
     buf.append(item.getFullName());
   }
   return buf.toString();
 }
Beispiel #7
0
 /**
  * Cancels the item in the queue. If the item is scheduled more than once, cancels the first
  * occurrence.
  *
  * @return true if the project was indeed in the queue and was removed. false if this was no-op.
  */
 public synchronized boolean cancel(Task p) {
   LOGGER.fine("Cancelling " + p.getFullDisplayName());
   for (Iterator<WaitingItem> itr = waitingList.iterator(); itr.hasNext(); ) {
     Item item = itr.next();
     if (item.task.equals(p)) {
       itr.remove();
       item.onCancelled();
       return true;
     }
   }
   // use bitwise-OR to make sure that both branches get evaluated all the time
   return blockedProjects.cancel(p) != null | buildables.cancel(p) != null;
 }
Beispiel #8
0
 public static boolean isApplicable(Collection<? extends Item> items) {
   for (Item item : items) {
     for (Job job : item.getAllJobs()) {
       if (job instanceof AbstractProject) {
         AbstractProject<?, ?> p = (AbstractProject) job;
         for (AbstractBuild<?, ?> build : p.getBuilds()) {
           for (Entry entry : build.getChangeSet()) {
             User user = entry.getAuthor();
             if (user != null) return true;
           }
         }
       }
     }
   }
   return false;
 }
Beispiel #9
0
    /**
     * Returns true if {@link BuildPtr} points to the given job or one of its subordinates.
     *
     * <p>This is useful to check if an artifact in MavenModule belongs to MavenModuleSet.
     */
    public boolean belongsTo(Job job) {
      Item p = Jenkins.getInstance().getItemByFullName(name);
      while (p != null) {
        if (p == job) return true;

        // go up the chain while we
        ItemGroup<? extends Item> parent = p.getParent();
        if (!(parent instanceof Item)) {
          return false;
        }

        p = (Item) parent;
      }

      return false;
    }
Beispiel #10
0
    public FormValidation doCheckUrl(
        @AncestorInPath Item project,
        @QueryParameter String credentialsId,
        @QueryParameter String value)
        throws IOException, InterruptedException {

      if (project == null || !project.hasPermission(Item.CONFIGURE)) {
        return FormValidation.ok();
      }

      String url = Util.fixEmptyAndTrim(value);
      if (url == null) return FormValidation.error("Please enter repository url.");

      // get git executable on master
      final EnvVars environment = new EnvVars(EnvVars.masterEnvVars);

      GitClient git =
          Git.with(TaskListener.NULL, environment)
              .using(GitTool.getDefaultInstallation().getGitExe())
              .getClient();
      if (credentialsId != null) {
        StandardCredentials credentials = lookupCredentials(project, credentialsId, url);
        if (credentials != null) git.addDefaultCredentials(credentials);
      }

      // attempt to connect the provided URL
      try {
        git.getHeadRev(url, "HEAD");
      } catch (GitException e) {
        return FormValidation.error(Messages.UserRemoteConfig_FailedToConnect(e.getMessage()));
      }

      return FormValidation.ok();
    }
 public HandlingMode applicability(Item item) {
   if (item instanceof TopLevelItem
       && item instanceof AbstractItem
       && item.getParent() instanceof DirectlyModifiableTopLevelItemGroup) {
     return HandlingMode.HANDLE;
   } else {
     return HandlingMode.SKIP;
   }
 }
 @Override
 public HttpResponse handle(
     Item item,
     ItemGroup<?> destination,
     AtomicReference<Item> newItem,
     List<? extends RelocationHandler> chain)
     throws IOException, InterruptedException {
   if (!(destination instanceof DirectlyModifiableTopLevelItemGroup)) {
     return chain.isEmpty()
         ? null
         : chain.get(0).handle(item, destination, newItem, chain.subList(1, chain.size()));
   }
   Item result = doMove(item, (DirectlyModifiableTopLevelItemGroup) destination);
   newItem.set(result);
   // AbstractItem.getUrl does weird magic here which winds up making it redirect to the old
   // location, so inline the correct part of this method.
   return HttpResponses.redirectViaContextPath(result.getParent().getUrl() + result.getShortUrl());
 }
Beispiel #13
0
 public synchronized boolean cancel(Item item) {
   LOGGER.fine("Cancelling " + item.task.getFullDisplayName() + " item#" + item.id);
   // use bitwise-OR to make sure that all the branches get evaluated all the time
   boolean r =
       (item instanceof WaitingItem && waitingList.remove(item))
           | blockedProjects.remove(item)
           | buildables.remove(item);
   if (r) item.onCancelled();
   return r;
 }
  private void updateGeneratedJobs(
      final AbstractBuild<?, ?> build, BuildListener listener, Set<GeneratedJob> freshJobs)
      throws IOException {
    // Update Project
    Set<GeneratedJob> generatedJobs =
        extractGeneratedObjects(build.getProject(), GeneratedJobsAction.class);
    Set<GeneratedJob> added = Sets.difference(freshJobs, generatedJobs);
    Set<GeneratedJob> existing = Sets.intersection(generatedJobs, freshJobs);
    Set<GeneratedJob> removed = Sets.difference(generatedJobs, freshJobs);

    logItems(listener, "Adding items", added);
    logItems(listener, "Existing items", existing);
    logItems(listener, "Removing items", removed);

    // Update unreferenced jobs
    for (GeneratedJob removedJob : removed) {
      Item removedItem =
          getLookupStrategy().getItem(build.getProject(), removedJob.getJobName(), Item.class);
      if (removedItem != null && removedJobAction != RemovedJobAction.IGNORE) {
        if (removedJobAction == RemovedJobAction.DELETE) {
          try {
            removedItem.delete();
          } catch (InterruptedException e) {
            listener.getLogger().println(String.format("Delete item failed: %s", removedJob));
            if (removedItem instanceof AbstractProject) {
              listener.getLogger().println(String.format("Disabling item instead: %s", removedJob));
              ((AbstractProject) removedItem).disable();
            }
          }
        } else {
          if (removedItem instanceof AbstractProject) {
            ((AbstractProject) removedItem).disable();
          }
        }
      }
    }

    updateGeneratedJobMap(build.getProject(), Sets.union(added, existing), removed);
  }
  @Override
  public OwnershipInfo getOwnershipInfo(AbstractFolder<?> item) {
    if (item == null) { // Handle renames, etc.
      return OwnershipInfo.DISABLED_INFO;
    }

    // Retrieve Ownership from the Folder property
    FolderOwnershipProperty prop = getOwnerProperty(item);
    if (prop != null) {
      OwnershipDescription d = prop.getOwnership();
      if (d.isOwnershipEnabled()) {
        return new OwnershipInfo(prop.getOwnership(), new FolderOwnershipDescriptionSource(item));
      }
    }

    // We go to upper items in order to get the ownership description
    if (!OwnershipPluginConfiguration.get()
        .getInheritanceOptions()
        .isBlockInheritanceFromItemGroups()) {
      ItemGroup parent = item.getParent();
      AbstractOwnershipHelper<ItemGroup> located = OwnershipHelperLocator.locate(parent);
      while (located != null) {
        OwnershipInfo fromParent = located.getOwnershipInfo(parent);
        if (fromParent.getDescription().isOwnershipEnabled()) {
          return fromParent;
        }
        if (parent instanceof Item) {
          Item parentItem = (Item) parent;
          parent = parentItem.getParent();
          located = OwnershipHelperLocator.locate(parent);
        } else {
          located = null;
        }
      }
    }

    return OwnershipInfo.DISABLED_INFO;
  }
Beispiel #16
0
    private Map<User, UserInfo> getUserInfo(Collection<? extends Item> items) {
      Map<User, UserInfo> users = new HashMap<User, UserInfo>();
      for (Item item : items) {
        for (Job job : item.getAllJobs()) {
          if (job instanceof AbstractProject) {
            AbstractProject<?, ?> p = (AbstractProject) job;
            for (AbstractBuild<?, ?> build : p.getBuilds()) {
              for (Entry entry : build.getChangeSet()) {
                User user = entry.getAuthor();

                UserInfo info = users.get(user);
                if (info == null) users.put(user, new UserInfo(user, p, build.getTimestamp()));
                else if (info.getLastChange().before(build.getTimestamp())) {
                  info.project = p;
                  info.lastChange = build.getTimestamp();
                }
              }
            }
          }
        }
      }
      return users;
    }
    /** Erase aliases from newly created projects by copying. */
    @Override
    public void onCopied(Item src, Item item) {
      if (!(item instanceof Job)) return;

      Job<?, ?> job = (Job<?, ?>) item;
      PermalinkStorage storage = job.getProperty(PermalinkStorage.class);
      if (storage == null) return;

      try {
        job.removeProperty(storage);
      } catch (IOException ex) {
        LOGGER.log(Level.SEVERE, "Unable to erase aliases when coppying " + item.getFullName(), ex);
      }
    }
Beispiel #18
0
  /** Computes the relative path from the current page to the given item. */
  public static String getRelativeLinkTo(Item p) {
    Map<Object, String> ancestors = new HashMap<Object, String>();
    View view = null;

    StaplerRequest request = Stapler.getCurrentRequest();
    for (Ancestor a : request.getAncestors()) {
      ancestors.put(a.getObject(), a.getRelativePath());
      if (a.getObject() instanceof View) view = (View) a.getObject();
    }

    String path = ancestors.get(p);
    if (path != null) return path;

    Item i = p;
    String url = "";
    while (true) {
      ItemGroup ig = i.getParent();
      url = i.getShortUrl() + url;

      if (ig == Hudson.getInstance()) {
        assert i instanceof TopLevelItem;
        if (view != null && view.contains((TopLevelItem) i)) {
          // if p and the current page belongs to the same view, then return a relative path
          return ancestors.get(view) + '/' + url;
        } else {
          // otherwise return a path from the root Hudson
          return request.getContextPath() + '/' + p.getUrl();
        }
      }

      path = ancestors.get(ig);
      if (path != null) return path + '/' + url;

      assert ig instanceof Item; // if not, ig must have been the Hudson instance
      i = (Item) ig;
    }
  }
Beispiel #19
0
 public ListBoxModel doFillCredentialsIdItems(
     @AncestorInPath Item project, @QueryParameter String url) {
   if (project == null || !project.hasPermission(Item.CONFIGURE)) {
     return new StandardListBoxModel();
   }
   return new StandardListBoxModel()
       .withEmptySelection()
       .withMatching(
           GitClient.CREDENTIALS_MATCHER,
           CredentialsProvider.lookupCredentials(
               StandardCredentials.class,
               project,
               ACL.SYSTEM,
               GitURIRequirementsBuilder.fromUri(url).build()));
 }
 public void observe(Item item) {
   if (item instanceof Folder) {
     // only interested in non-folders in order to prevent double counting
     return;
   }
   HealthReport report = getHealthReport(item);
   if (report != null && (worst == null || report.getScore() < worst.getScore())) {
     worst =
         new HealthReport(
             report.getScore(),
             report.getIconUrl(),
             Messages._Folder_HealthWrap(
                 item.getFullDisplayName(), report.getLocalizableDescription()));
   }
 }
Beispiel #21
0
 @Override
 /**
  * Called after the user has clicked OK in the New Job page when Copy existing job has been
  * selected. The fields in item will be displayed in when the config page is loaded displayed.
  */
 public void onCopied(Item src, Item item) {
   // bug 5056825 - Display name field should be cleared when you copy a job.
   if (item instanceof AbstractItem) {
     AbstractItem dest = (AbstractItem) item;
     try {
       dest.setDisplayName(null);
     } catch (IOException ioe) {
       LOGGER.log(
           Level.WARNING,
           String.format(
               "onCopied():Exception while trying to clear the displayName for Item.name:%s",
               item.getName()),
           ioe);
     }
   }
 }
  private void updateGeneratedJobMap(
      AbstractProject<?, ?> seedJob,
      Set<GeneratedJob> createdOrUpdatedJobs,
      Set<GeneratedJob> removedJobs)
      throws IOException {
    DescriptorImpl descriptor = Jenkins.getInstance().getDescriptorByType(DescriptorImpl.class);
    boolean descriptorMutated = false;
    Map<String, SeedReference> generatedJobMap = descriptor.getGeneratedJobMap();

    for (GeneratedJob generatedJob : createdOrUpdatedJobs) {
      Item item = getLookupStrategy().getItem(seedJob, generatedJob.getJobName(), Item.class);
      if (item != null) {
        SeedReference newSeedReference = new SeedReference(seedJob.getFullName());
        if (generatedJob.getTemplateName() != null) {
          Item template =
              getLookupStrategy().getItem(seedJob, generatedJob.getTemplateName(), Item.class);
          newSeedReference.setTemplateJobName(template.getFullName());
        }
        newSeedReference.setDigest(Util.getDigestOf(Items.getConfigFile(item).getFile()));

        SeedReference oldSeedReference = generatedJobMap.get(item.getFullName());
        if (!newSeedReference.equals(oldSeedReference)) {
          generatedJobMap.put(item.getFullName(), newSeedReference);
          descriptorMutated = true;
        }
      }
    }

    for (GeneratedJob removedJob : removedJobs) {
      Item removedItem = getLookupStrategy().getItem(seedJob, removedJob.getJobName(), Item.class);
      if (removedItem != null) {
        generatedJobMap.remove(removedItem.getFullName());
        descriptorMutated = true;
      }
    }

    if (descriptorMutated) {
      descriptor.save();
    }
  }
 private boolean permitted(Item item, DirectlyModifiableTopLevelItemGroup itemGroup) {
   return itemGroup == item.getParent()
       || itemGroup.canAdd((TopLevelItem) item)
           && ((AccessControlled) itemGroup).hasPermission(Job.CREATE);
 }
Beispiel #24
0
 public String getRelativeNameFrom(Item item) {
     return getRelativeNameFrom(item.getParent());
 }
Beispiel #25
0
  /**
   * Schedules an execution of a task.
   *
   * @since 1.311
   * @return null if this task is already in the queue and therefore the add operation was no-op.
   *     Otherwise indicates the {@link WaitingItem} object added, although the nature of the queue
   *     is that such {@link Item} only captures the state of the item at a particular moment, and
   *     by the time you inspect the object, some of its information can be already stale.
   *     <p>That said, one can still look at {@link WaitingItem#future}, {@link WaitingItem#id},
   *     etc.
   */
  private synchronized WaitingItem scheduleInternal(Task p, int quietPeriod, List<Action> actions) {
    WaitingItem added = null;
    List<Item> items = getItems(p);
    Calendar due = new GregorianCalendar();
    due.add(Calendar.SECOND, quietPeriod);

    List<Item> duplicatesInQueue = new ArrayList<Item>();
    for (Item item : items) {
      boolean shouldScheduleItem = false;
      for (Action action : item.getActions()) {
        if (action instanceof QueueAction)
          shouldScheduleItem |= ((QueueAction) action).shouldSchedule(actions);
      }
      for (Action action : actions) {
        if (action instanceof QueueAction) {
          shouldScheduleItem |= ((QueueAction) action).shouldSchedule(item.getActions());
        }
      }
      if (!shouldScheduleItem) {
        duplicatesInQueue.add(item);
      }
    }
    if (duplicatesInQueue.size() == 0) {
      LOGGER.fine(p.getFullDisplayName() + " added to queue");

      // put the item in the queue
      waitingList.add(added = new WaitingItem(due, p, actions));
    } else {
      // the requested build is already queued, so will not be added
      List<WaitingItem> waitingDuplicates = new ArrayList<WaitingItem>();
      for (Item item : duplicatesInQueue) {
        for (Action a : actions) {
          if (a instanceof FoldableAction) {
            ((FoldableAction) a).foldIntoExisting(item.task, item.getActions());
          }
        }
        if ((item instanceof WaitingItem)) waitingDuplicates.add((WaitingItem) item);
      }
      if (duplicatesInQueue.size() == 0) {
        // all duplicates in the queue are already in the blocked or
        // buildable stage no need to requeue
        return null;
      }
      // TODO: avoid calling scheduleMaintenance() if none of the waiting items
      // actually change
      for (WaitingItem wi : waitingDuplicates) {
        if (quietPeriod <= 0) {
          // the user really wants to build now, and they mean NOW.
          // so let's pull in the timestamp if we can.
          if (wi.timestamp.before(due)) continue;
        } else {
          // otherwise we do the normal quiet period implementation
          if (wi.timestamp.after(due)) continue;
          // quiet period timer reset. start the period over again
        }

        // waitingList is sorted, so when we change a timestamp we need to maintain order
        waitingList.remove(wi);
        wi.timestamp = due;
        waitingList.add(wi);
      }
    }
    scheduleMaintenance(); // let an executor know that a new item is in the queue.
    return added;
  }
Beispiel #26
0
 /** Works like {@link #remove(Object)} but also marks the {@link Item} as cancelled. */
 public boolean cancel(Item t) {
   boolean r = remove(t);
   if (r) t.onCancelled();
   return r;
 }
Beispiel #27
0
 protected Item(Item item) {
   this(item.task, item.getActions(), item.id, item.future);
 }
Beispiel #28
0
 public String call(Item item) {
   return item.getName();
 }
Beispiel #29
0
 @Override
 protected void compute() throws Exception {
   int itemCount = 0;
   for (Item item : items) {
     for (Job<?, ?> job : item.getAllJobs()) {
       if (job instanceof AbstractProject) {
         AbstractProject<?, ?> p = (AbstractProject) job;
         RunList<? extends AbstractBuild<?, ?>> builds = p.getBuilds();
         int buildCount = 0;
         for (AbstractBuild<?, ?> build : builds) {
           if (canceled()) {
             return;
           }
           for (ChangeLogSet.Entry entry : build.getChangeSet()) {
             User user = entry.getAuthor();
             UserInfo info = users.get(user);
             if (info == null) {
               UserInfo userInfo = new UserInfo(user, p, build.getTimestamp());
               userInfo.avatar = UserAvatarResolver.resolveOrNull(user, iconSize);
               synchronized (this) {
                 users.put(user, userInfo);
                 modified.add(user);
               }
             } else if (info.getLastChange().before(build.getTimestamp())) {
               synchronized (this) {
                 info.project = p;
                 info.lastChange = build.getTimestamp();
                 modified.add(user);
               }
             }
           }
           // TODO consider also adding the user of the UserCause when applicable
           buildCount++;
           // TODO this defeats lazy-loading. Should rather do a breadth-first search, as in
           // hudson.plugins.view.dashboard.builds.LatestBuilds
           // (though currently there is no quick implementation of RunMap.size() ~
           // idOnDisk.size(), which would be needed for proper progress)
           progress((itemCount + 1.0 * buildCount / builds.size()) / (items.size() + 1));
         }
       }
     }
     itemCount++;
     progress(1.0 * itemCount / (items.size() + /* handling User.getAll */ 1));
   }
   if (unknown != null) {
     if (canceled()) {
       return;
     }
     for (User u : User.getAll()) { // TODO nice to have a method to iterate these lazily
       if (canceled()) {
         return;
       }
       if (u == unknown) {
         continue;
       }
       if (!users.containsKey(u)) {
         UserInfo userInfo = new UserInfo(u, null, null);
         userInfo.avatar = UserAvatarResolver.resolveOrNull(u, iconSize);
         synchronized (this) {
           users.put(u, userInfo);
           modified.add(u);
         }
       }
     }
   }
 }
Beispiel #30
0
 /** The file we save our configuration. */
 public static XmlFile getConfigFile(Item item) {
   return getConfigFile(item.getRootDir());
 }