@Initializer(before = InitMilestone.JOB_LOADED) @Restricted(NoExternalUse.class) public static void packageRenameConverting() { for(XStream2 xs : Arrays.asList(Items.XSTREAM2, Run.XSTREAM2, Jenkins.XSTREAM2, getFingerprintXStream())) { xs.addCompatibilityAlias("org.jenkinsci.plugins.dockerhub.notification.DockerHubTrigger", DockerHubTrigger.class); xs.addCompatibilityAlias("org.jenkinsci.plugins.dockerhub.notification.DockerHubWebHookCause", DockerHubWebHookCause.class); xs.addCompatibilityAlias("org.jenkinsci.plugins.dockerhub.notification.DockerPullImageBuilder", DockerPullImageBuilder.class); //TODO no back-compat tests for the column and filter xs.addCompatibilityAlias("org.jenkinsci.plugins.dockerhub.notification.TriggerListViewColumn", TriggerListViewColumn.class); xs.addCompatibilityAlias("org.jenkinsci.plugins.dockerhub.notification.TriggerViewFilter", TriggerViewFilter.class); //The TriggerOption extension point has also changed package name and will not be backwards compatible API xs.addCompatibilityAlias("org.jenkinsci.plugins.dockerhub.notification.opt.impl.TriggerForAllUsedInJob", TriggerForAllUsedInJob.class); xs.addCompatibilityAlias("org.jenkinsci.plugins.dockerhub.notification.opt.impl.TriggerOnSpecifiedImageNames", TriggerOnSpecifiedImageNames.class); xs.addCompatibilityAlias("org.jenkinsci.plugins.dockerhub.notification.TriggerStore$TriggerEntry", TriggerStore.TriggerEntry.class); xs.addCompatibilityAlias("org.jenkinsci.plugins.dockerhub.notification.TriggerStore$TriggerEntry$RunEntry", TriggerStore.TriggerEntry.RunEntry.class); } }
public static List<AbstractProject> getProjectList(String projects, ItemGroup context, EnvVars env) { List<AbstractProject> projectList = new ArrayList<>(); // expand variables if applicable StringBuilder projectNames = new StringBuilder(); StringTokenizer tokens = new StringTokenizer(projects, ","); while (tokens.hasMoreTokens()) { if (projectNames.length() > 0) { projectNames.append(','); } projectNames.append(env != null ? env.expand(tokens.nextToken().trim()) : tokens.nextToken().trim()); } projectList.addAll(Items.fromNameList(context, projectNames.toString(), AbstractProject.class)); return projectList; }
/** * Form validation method. Similar to * {@link hudson.tasks.BuildTrigger.DescriptorImpl#doCheck(AbstractProject, String)}. * * @param folder the folder being configured * @param value the user-entered value * @return validation result */ public FormValidation doCheck(@AncestorInPath AbstractFolder folder, @QueryParameter String value) { // Require CONFIGURE permission on this project if (!folder.hasPermission(Item.CONFIGURE)) { return FormValidation.ok(); } boolean hasJobs = false; StringTokenizer tokens = new StringTokenizer(Util.fixNull(value), ","); while (tokens.hasMoreTokens()) { String jobName = tokens.nextToken().trim(); if (StringUtils.isNotBlank(jobName)) { Item item = Jenkins.getActiveInstance().getItem(jobName, (ItemGroup) folder, Item.class); if (item == null) { Job nearest = Items.findNearest(Job.class, jobName, folder); String alternative = nearest != null ? nearest.getRelativeNameFrom((ItemGroup) folder) : "?"; return FormValidation.error( hudson.tasks.Messages.BuildTrigger_NoSuchProject(jobName, alternative)); } if (!(item instanceof Job)) { return FormValidation.error(hudson.tasks.Messages.BuildTrigger_NotBuildable(jobName)); } hasJobs = true; } } if (!hasJobs) { return FormValidation.error(hudson.tasks.Messages.BuildTrigger_NoProjectSpecified()); } return FormValidation.ok(); }
/** * Common initialization that is invoked when either a new project is created with the constructor * {@link TemplateDrivenMultiBranchProject#TemplateDrivenMultiBranchProject(ItemGroup, String)} or when a project * is loaded from disk with {@link #onLoad(ItemGroup, String)}. */ protected void init3() { if (disabledSubProjects == null) { disabledSubProjects = new PersistedList<>(this); } // Owner doesn't seem to be set when loading from XML disabledSubProjects.setOwner(this); try { XmlFile templateXmlFile = Items.getConfigFile(getTemplateDir()); if (templateXmlFile.getFile().isFile()) { /* * Do not use Items.load here, since it uses getRootDirFor(i) during onLoad, * which returns the wrong location since template would still be unset. * Instead, read the XML directly into template and then invoke onLoad. */ //noinspection unchecked template = (P) templateXmlFile.read(); template.onLoad(this, TEMPLATE); } else { /* * Don't use the factory here because newInstance calls setBranch, attempting * to save the project before template is set. That would invoke * getRootDirFor(i) and get the wrong directory to save into. */ template = newTemplate(); } // Prevent tampering if (!(template.getScm() instanceof NullSCM)) { template.setScm(new NullSCM()); } template.disable(); } catch (IOException e) { LOGGER.log(Level.WARNING, "Failed to load template project " + getTemplateDir(), e); } }
/** * This is a mirror of {@link hudson.model.AbstractItem#updateByXml(Source)} without the * {@link hudson.model.listeners.SaveableListener#fireOnChange(Saveable, XmlFile)} trigger. * * @param project project to update by XML * @param source source of XML * @throws IOException if error performing update */ @SuppressWarnings("ThrowFromFinallyBlock") private void updateByXml(final P project, Source source) throws IOException { project.checkPermission(Item.CONFIGURE); final String projectName = project.getName(); XmlFile configXmlFile = project.getConfigFile(); final AtomicFileWriter out = new AtomicFileWriter(configXmlFile.getFile()); try { try { XMLUtils.safeTransform(source, new StreamResult(out)); out.close(); } catch (SAXException | TransformerException e) { throw new IOException("Failed to persist config.xml", e); } // try to reflect the changes by reloading Object o = new XmlFile(Items.XSTREAM, out.getTemporaryFile()).unmarshal(project); if (o != project) { // ensure that we've got the same job type. extending this code to support updating // to different job type requires destroying & creating a new job type throw new IOException("Expecting " + project.getClass() + " but got " + o.getClass() + " instead"); } Items.whileUpdatingByXml(new NotReallyRoleSensitiveCallable<Void, IOException>() { @SuppressWarnings("unchecked") @Override public Void call() throws IOException { project.onLoad(project.getParent(), projectName); return null; } }); Jenkins.getActiveInstance().rebuildDependencyGraphAsync(); // if everything went well, commit this new version out.commit(); } finally { out.abort(); } }
/** * Get project in Jenkins given its name. * * @since 1.3 * @param projectName project name in Jenkins * @return Project or {@code null} if none with this name * @deprecated The choice is arbitrary if there are multiple matches; use {@link Item#getFullName} and {@link Jenkins#getItemByFullName(String, Class)} instead. */ @SuppressWarnings("rawtypes") public static @CheckForNull Project<?, ?> getProjectByName(@Nonnull String projectName) { Authentication auth = Jenkins.getAuthentication(); for (Project p : Items.allItems(ACL.SYSTEM, Jenkins.getInstance(), Project.class)) { if (p.getName().equals(projectName) && p.getACL().hasPermission(auth, Item.READ)) { return p; } } return null; }
/** * Find the current project give its parameter UUID. * * @author dynamic-parameter-plugin * @since 1.3 * @param parameterUUID parameter UUID * @return {@code null} if the current project cannot be found */ @SuppressWarnings("rawtypes") public static @CheckForNull Project findProjectByParameterUUID(@Nonnull String parameterUUID) { Authentication auth = Jenkins.getAuthentication(); for (Project p : Items.allItems(ACL.SYSTEM, Jenkins.getInstance(), Project.class)) { if (isParameterDefinitionOf(parameterUUID, p) && p.getACL().hasPermission(auth, Item.READ)) { return p; } } return null; }
@Initializer(before=InitMilestone.PLUGINS_STARTED) public static void initializeXStream() { InheritableParameterReferenceConverter conv = new InheritableParameterReferenceConverter(); final XStream2[] xs = { Jenkins.XSTREAM2, Run.XSTREAM2, Items.XSTREAM2 }; for (XStream2 x : xs) { //Add the custom converter to hide some fields x.registerConverter(conv); } }
/** * Copied from {@link AbstractProject#updateByXml(javax.xml.transform.Source)}, removing the save event and * returning the project after the update. */ @SuppressWarnings("unchecked") public static AbstractProject updateProjectWithXmlSource(AbstractProject project, Source source) throws IOException { XmlFile configXmlFile = project.getConfigFile(); AtomicFileWriter out = new AtomicFileWriter(configXmlFile.getFile()); try { try { // this allows us to use UTF-8 for storing data, // plus it checks any well-formedness issue in the submitted // data Transformer t = TransformerFactory.newInstance() .newTransformer(); t.transform(source, new StreamResult(out)); out.close(); } catch (TransformerException e) { throw new IOException2("Failed to persist configuration.xml", e); } // try to reflect the changes by reloading new XmlFile(Items.XSTREAM, out.getTemporaryFile()).unmarshal(project); project.onLoad(project.getParent(), project.getRootDir().getName()); Jenkins.getInstance().rebuildDependencyGraph(); // if everything went well, commit this new version out.commit(); return ProjectUtils.findProject(project.getFullName()); } finally { out.abort(); // don't leave anything behind } }
/** * Gives this class an alias for configuration XML. */ @Initializer(before = InitMilestone.PLUGINS_STARTED) @SuppressWarnings(UNUSED) public static void registerXStream() { Items.XSTREAM.alias("matrix-multi-branch-project", MatrixMultiBranchProject.class); }
/** * Gives this class an alias for configuration XML. */ @SuppressWarnings(UNUSED) @Initializer(before = InitMilestone.PLUGINS_STARTED) public static void registerXStream() { Items.XSTREAM.alias("branch-list-view", BranchListView.class); }
/** * Gives this class an alias for configuration XML. */ @SuppressWarnings(UNUSED) @Initializer(before = InitMilestone.PLUGINS_STARTED) public static void registerXStream() { Items.XSTREAM.alias("ivy-multi-branch-project", IvyMultiBranchProject.class); }
/** * Gives this class an alias for configuration XML. */ @Initializer(before = InitMilestone.PLUGINS_STARTED) @SuppressWarnings("unused") public static void registerXStream() { Items.XSTREAM.alias("freestyle-multi-branch-project", FreeStyleMultiBranchProject.class); }
/** * Gives this class an alias for configuration XML. */ @Initializer(before = InitMilestone.PLUGINS_STARTED) @SuppressWarnings(UNUSED) public static void registerXStream() { Items.XSTREAM.alias("maven-multi-branch-project", MavenMultiBranchProject.class); }
@Override public void start() throws Exception { Items.XSTREAM.registerConverter(new Config.ConverterImpl()); load(); LOG.fine("Loading config: " + config); }
@Initializer(before=InitMilestone.PLUGINS_STARTED) public static void addAlias() { Items.XSTREAM2.addCompatibilityAlias("org.jenkinsci.plugins.awsbeanstalkpublisher.AWSEBDeploymentBuilder", AWSEBBuilder.class); }
@Initializer(before=InitMilestone.PLUGINS_STARTED) public static void addAlias() { Items.XSTREAM2.addCompatibilityAlias("org.jenkinsci.plugins.awsbeanstalkpublisher.AWSEBDeploymentPublisher", AWSEBPublisher.class); }
protected void writeStableConfigDotXml(OutputStream out) throws IOException, HttpStatusException { if (out == null) { return; } //Get the XML for the current project, as it'd be written to disk String selfXml = Items.XSTREAM2.toXML(this); //Then, loading it back, to get a modifiable copy Object obj = Items.XSTREAM2.fromXML(selfXml); if (!(obj instanceof InheritanceProject)) { throw new HttpStatusException( HttpStatus.SC_INTERNAL_SERVER_ERROR, "Error, could not (de-)serialize project" ); } //Casting the project suitably, to access the needed fields InheritanceProject mod = (InheritanceProject) obj; /* Some alterations to the project wish to save it, for this to work, we * need an ephemeral ItemGroup that serves as the container that can be * cleaned, once it is not needed anymore */ MockItemGroup<Job<?,?>> mig = new MockItemGroup<>(); try { //Giving the project a custom name and temporary item-group/directory UUID uuid = UUID.randomUUID(); mod.onLoad(mig, uuid.toString()); //Loaded project start without a VOB, so a blank one is created mod.versionStore = new VersionedObjectStore(); //Replacing all versioned fields in the copy with the currently selected versions //NOTE: Actions can't be modified, since the parent class hides the field :( try { mod.copyVersionedSettingsFrom(this); } catch (IOException ex) { throw new HttpStatusException( HttpStatus.SC_INTERNAL_SERVER_ERROR, "Failed to produce XML for stable version", ex ); } // Turning this modified project into an UTF8 XML and sending it to the client Items.XSTREAM2.toXMLUTF8(mod, out); } finally { //Purge the temporary item group with fire mig.clean(); } }