Skip to content

Commit

Permalink
Merge pull request #1234 from olivergondza/directly-modifiable-view
Browse files Browse the repository at this point in the history
[FIXED JENKINS-22967] Introduce directly modifiable views
  • Loading branch information
olivergondza committed May 21, 2014
2 parents 6302c50 + 5f443a7 commit c6a492a
Show file tree
Hide file tree
Showing 3 changed files with 323 additions and 7 deletions.
79 changes: 79 additions & 0 deletions core/src/main/java/hudson/model/DirectlyModifiableView.java
@@ -0,0 +1,79 @@
/*
* The MIT License
*
* Copyright (c) 2014 Red Hat, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.model;

import hudson.util.HttpResponses;

import java.io.IOException;

import javax.annotation.Nonnull;
import javax.servlet.ServletException;

import org.kohsuke.stapler.HttpResponse;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.interceptor.RequirePOST;

/**
* Marker interface for {@link View} its items can be modified.
*
* @author ogondza
* @since TODO
*/
public interface DirectlyModifiableView {

/**
* Remove item from this view.
*
* @return false if item not present in view, true if removed.
* @throws IOException Removal failed.
* @throws IllegalArgumentException View rejected to remove an item.
*/
boolean remove(@Nonnull TopLevelItem item) throws IOException, IllegalArgumentException;

/**
* Add item to this view.
*
* @throws IOException Adding failed.
* @throws IllegalArgumentException View rejected to add an item.
*/
void add(@Nonnull TopLevelItem item) throws IOException, IllegalArgumentException;

/**
* Handle addJobToView web method.
*
* This method should {@link RequirePOST}.
*
* @param name Item name. This can be either full name relative to owner item group or full item name prefixed with '/'.
*/
HttpResponse doAddJobToView(@QueryParameter String name) throws IOException, ServletException;

/**
* Handle removeJobFromView web method.
*
* This method should {@link RequirePOST}.
*
* @param name Item name. This can be either full name relative to owner item group or full item name prefixed with '/'.
*/
HttpResponse doRemoveJobFromView(@QueryParameter String name) throws IOException, ServletException;
}
48 changes: 41 additions & 7 deletions core/src/main/java/hudson/model/ListView.java
Expand Up @@ -63,7 +63,7 @@
*
* @author Kohsuke Kawaguchi
*/
public class ListView extends View implements Saveable {
public class ListView extends View implements DirectlyModifiableView {

/**
* List of job names. This is what gets serialized.
Expand Down Expand Up @@ -146,6 +146,7 @@ public DescribableList<ViewJobFilter, Descriptor<ViewJobFilter>> getJobFilters()
return jobFilters;
}

@Override
public DescribableList<ListViewColumn, Descriptor<ListViewColumn>> getColumns() {
return columns;
}
Expand All @@ -157,6 +158,7 @@ public DescribableList<ListViewColumn, Descriptor<ListViewColumn>> getColumns()
* This method returns a separate copy each time to avoid
* concurrent modification issue.
*/
@Override
public List<TopLevelItem> getItems() {
SortedSet<String> names;
List<TopLevelItem> items = new ArrayList<TopLevelItem>();
Expand Down Expand Up @@ -235,20 +237,34 @@ public synchronized boolean jobNamesContains(TopLevelItem item) {
return jobNames.contains(item.getRelativeNameFrom(getOwnerItemGroup()));
}



/**
* Adds the given item to this view.
*
* @since 1.389
*/
@Override
public void add(TopLevelItem item) throws IOException {
synchronized (this) {
jobNames.add(item.getRelativeNameFrom(getOwnerItemGroup()));
}
save();
}

/**
* Removes given item from this view.
*
* @since TODO
*/
@Override
public boolean remove(TopLevelItem item) throws IOException {
synchronized (this) {
String name = item.getRelativeNameFrom(getOwnerItemGroup());
if (!jobNames.remove(name)) return false;
}
save();
return true;
}

public String getIncludeRegex() {
return includeRegex;
}
Expand All @@ -272,6 +288,7 @@ public Boolean getStatusFilter() {
return statusFilter;
}

@Override
@RequirePOST
public Item doCreateItem(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
ItemGroup<? extends TopLevelItem> ig = getOwnerItemGroup();
Expand All @@ -288,33 +305,48 @@ public Item doCreateItem(StaplerRequest req, StaplerResponse rsp) throws IOExcep
return null;
}

@Override
@RequirePOST
public HttpResponse doAddJobToView(@QueryParameter String name) throws IOException, ServletException {
checkPermission(View.CONFIGURE);
if(name==null)
throw new Failure("Query parameter 'name' is required");

if (getOwnerItemGroup().getItem(name) == null)
TopLevelItem item = resolveName(name);
if (item == null)
throw new Failure("Query parameter 'name' does not correspond to a known item");

if (jobNames.add(name))
owner.save();
if (contains(item)) return HttpResponses.ok();

add(item);
owner.save();

return HttpResponses.ok();
}

@Override
@RequirePOST
public HttpResponse doRemoveJobFromView(@QueryParameter String name) throws IOException, ServletException {
checkPermission(View.CONFIGURE);
if(name==null)
throw new Failure("Query parameter 'name' is required");

if (jobNames.remove(name))
TopLevelItem item = resolveName(name);
if (remove(item))
owner.save();

return HttpResponses.ok();
}

private TopLevelItem resolveName(String name) {
TopLevelItem item = getOwnerItemGroup().getItem(name);
if (item == null) {
name = Items.getCanonicalName(getOwnerItemGroup(), name);
item = Jenkins.getInstance().getItemByFullName(name, TopLevelItem.class);
}
return item;
}

/**
* Handles the configuration submission.
*
Expand Down Expand Up @@ -367,6 +399,7 @@ public void setIncludeRegex(String includeRegex) {

@Extension
public static class DescriptorImpl extends ViewDescriptor {
@Override
public String getDisplayName() {
return Messages.ListView_DisplayName();
}
Expand All @@ -391,6 +424,7 @@ public FormValidation doCheckIncludeRegex( @QueryParameter String value ) throws
* @deprecated as of 1.391
* Use {@link ListViewColumn#createDefaultInitialColumnList()}
*/
@Deprecated
public static List<ListViewColumn> getDefaultColumns() {
return ListViewColumn.createDefaultInitialColumnList();
}
Expand Down

0 comments on commit c6a492a

Please sign in to comment.