Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for programmatically generating OrganizationFolders #145

Merged
merged 8 commits into from May 7, 2019
121 changes: 80 additions & 41 deletions src/main/java/jenkins/branch/OrganizationFolder.java
Expand Up @@ -24,7 +24,43 @@

package jenkins.branch;

import antlr.ANTLRException;
import static jenkins.scm.api.SCMEvent.Type.CREATED;
import static jenkins.scm.api.SCMEvent.Type.UPDATED;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static after non static


import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

bitwiseman marked this conversation as resolved.
Show resolved Hide resolved
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import javax.servlet.ServletException;

import org.acegisecurity.AccessDeniedException;
import org.acegisecurity.Authentication;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My IDE alphabetized imports.

org.acegisecurity.Authentication is an addition.

import org.apache.commons.io.Charsets;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.jenkins.ui.icon.Icon;
import org.jenkins.ui.icon.IconSet;
import org.jenkins.ui.icon.IconSpec;
import org.jvnet.localizer.LocaleProvider;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;

import com.cloudbees.hudson.plugins.folder.AbstractFolderDescriptor;
import com.cloudbees.hudson.plugins.folder.AbstractFolderProperty;
import com.cloudbees.hudson.plugins.folder.ChildNameGenerator;
Expand All @@ -36,7 +72,10 @@
import com.cloudbees.hudson.plugins.folder.computed.FolderComputation;
import com.cloudbees.hudson.plugins.folder.computed.PeriodicFolderTrigger;
import com.cloudbees.hudson.plugins.folder.views.AbstractFolderViewHolder;
import com.google.common.collect.ImmutableSet;
bitwiseman marked this conversation as resolved.
Show resolved Hide resolved
import com.thoughtworks.xstream.XStreamException;

import antlr.ANTLRException;
import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.BulkChange;
import hudson.Extension;
Expand All @@ -57,26 +96,10 @@
import hudson.model.TopLevelItem;
import hudson.model.View;
import hudson.model.listeners.SaveableListener;
import hudson.security.ACL;
import hudson.security.Permission;
bitwiseman marked this conversation as resolved.
Show resolved Hide resolved
import hudson.util.DescribableList;
import hudson.util.StreamTaskListener;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import javax.servlet.ServletException;
import jenkins.model.Jenkins;
import jenkins.model.TransientActionFactory;
import jenkins.scm.api.SCMEvent;
Expand All @@ -95,21 +118,6 @@
import jenkins.scm.api.metadata.ObjectMetadataAction;
import jenkins.scm.impl.SingleSCMNavigator;
import jenkins.scm.impl.UncategorizedSCMSourceCategory;
import org.acegisecurity.AccessDeniedException;
import org.apache.commons.io.Charsets;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.jenkins.ui.icon.Icon;
import org.jenkins.ui.icon.IconSet;
import org.jenkins.ui.icon.IconSpec;
import org.jvnet.localizer.LocaleProvider;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;

import static jenkins.scm.api.SCMEvent.Type.CREATED;
import static jenkins.scm.api.SCMEvent.Type.UPDATED;

/**
* A folder-like collection of {@link MultiBranchProject}s, one per repository.
Expand Down Expand Up @@ -178,12 +186,16 @@ public OrganizationFolder(ItemGroup parent, String name) {
@Override
public void onCreatedFromScratch() {
super.onCreatedFromScratch();
for (MultiBranchProjectFactoryDescriptor d : ExtensionList.lookup(MultiBranchProjectFactoryDescriptor.class)) {
MultiBranchProjectFactory f = d.newInstance();
if (f != null) {
projectFactories.add(f);

if( projectFactories.isEmpty() ) {
for (MultiBranchProjectFactoryDescriptor d : ExtensionList.lookup(MultiBranchProjectFactoryDescriptor.class)) {
bitwiseman marked this conversation as resolved.
Show resolved Hide resolved
MultiBranchProjectFactory f = d.newInstance();
if (f != null) {
projectFactories.add(f);
}
}
}

try {
addTrigger(new PeriodicFolderTrigger("1d"));
} catch (ANTLRException x) {
Expand Down Expand Up @@ -649,6 +661,33 @@ public String getDisplayName() {
return super.getDisplayName();
}

/**
* {@inheritDoc}
*/
@Override
public ACL getACL() {
final ACL acl = super.getACL();
if (getParent() instanceof ComputedFolder<?>) {
bitwiseman marked this conversation as resolved.
Show resolved Hide resolved
return new ACL() {
@Override
public boolean hasPermission(Authentication a, Permission permission) {
if (ACL.SYSTEM.equals(a)) {
return true;
} else if (SUPPRESSED_PERMISSIONS.contains(permission)) {
return false;
} else {
return acl.hasPermission(a, permission);
}
}
};
} else {
return acl;
}
}

private static final Set<Permission> SUPPRESSED_PERMISSIONS =
ImmutableSet.of(Item.CONFIGURE, Item.DELETE, View.CONFIGURE, View.CREATE, View.DELETE);

/**
* Our descriptor
*/
Expand Down Expand Up @@ -686,7 +725,7 @@ public TopLevelItem newInstance(ItemGroup parent, String name) {
*
* @return A string with the category identifier. {@code TopLevelItemDescriptor#getCategoryId()}
*/
//@Override TODO once baseline is 2.x
@Override
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This appears to have happened, so I did the TODO.

@NonNull
public String getCategoryId() {
return "nested-projects";
Expand All @@ -697,7 +736,7 @@ public String getCategoryId() {
*
* @return A string with the description. {@code TopLevelItemDescriptor#getDescription()}.
*/
//@Override TODO once baseline is 2.x
@Override
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This appears to have happened, so I did the TODO.

@NonNull
public String getDescription() {
if (Jenkins.getActiveInstance().getInitLevel().compareTo(InitMilestone.EXTENSIONS_AUGMENTED) > 0) {
Expand All @@ -716,7 +755,7 @@ public String getDescription() {
);
}

//@Override TODO once baseline is 2.x
@Override
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This appears to have happened, so I did the TODO.

public String getIconFilePathPattern() {
List<SCMNavigatorDescriptor> descriptors =
remove(ExtensionList.lookup(SCMNavigatorDescriptor.class),
Expand Down