public synchronized TopLevelItem createProjectFromXML(String name, InputStream xml) throws IOException { acl.checkPermission(Job.CREATE); Jenkins.getInstance().getProjectNamingStrategy().checkName(name); // place it as config.xml File configXml = Items.getConfigFile(getRootDirFor(name)).getFile(); configXml.getParentFile().mkdirs(); try { IOUtils.copy(xml, configXml); // load it TopLevelItem result; Items.updatingByXml.set(true); try { result = (TopLevelItem) Items.load(parent, configXml.getParentFile()); } finally { Items.updatingByXml.set(false); } add(result); ItemListener.fireOnCreated(result); Jenkins.getInstance().rebuildDependencyGraph(); return result; } catch (IOException e) { // if anything fails, delete the config file to avoid further confusion Util.deleteRecursive(configXml.getParentFile()); throw e; } }
/** * Updates Job by its XML definition. * @since 1.473 */ public void updateByXml(Source source) throws IOException { checkPermission(CONFIGURE); XmlFile configXmlFile = 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 IOException("Failed to persist config.xml", e); } // try to reflect the changes by reloading new XmlFile(Items.XSTREAM, out.getTemporaryFile()).unmarshal(this); Items.whileUpdatingByXml(new Callable<Void,IOException>() { @Override public Void call() throws IOException { onLoad(getParent(), getRootDir().getName()); return null; } }); Jenkins.getInstance().rebuildDependencyGraphAsync(); // if everything went well, commit this new version out.commit(); SaveableListener.fireOnChange(this, getConfigFile()); } finally { out.abort(); // don't leave anything behind } }
/** * 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; }
/** * Copies an existing {@link TopLevelItem} to a new name. * * <p>The caller is responsible for calling {@link ItemListener#fireOnCopied(Item, Item)}. This * method cannot do that because it doesn't know how to make the newly added item reachable from * the parent. */ @SuppressWarnings({"unchecked"}) public synchronized <T extends TopLevelItem> T copy(T src, String name) throws IOException { acl.checkPermission(Job.CREATE); T result = (T) createProject(src.getDescriptor(), name, false); // copy config Util.copyFile(Items.getConfigFile(src).getFile(), Items.getConfigFile(result).getFile()); // reload from the new config Items.updatingByXml.set(true); try { result = (T) Items.load(parent, result.getRootDir()); } finally { Items.updatingByXml.set(false); } result.onCopiedFrom(src); add(result); ItemListener.fireOnCopied(src, result); Hudson.getInstance().rebuildDependencyGraph(); return result; }
/** @param env Environment variables from which to expand project names; Might be {@code null}. */ public List<AbstractProject> getProjectList(EnvVars env) { if (projectList == null) { projectList = new ArrayList<AbstractProject>(); // 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(projectNames.toString(), AbstractProject.class)); } return projectList; }
public synchronized void checkPendingDownstream( AbstractBuild<?, ?> owner, TaskListener listener) { if (pendingDownstreamProjects.isEmpty()) { listener.getLogger().println("All downstream projects complete!"); Result threshold = this.evenIfDownstreamUnstable ? Result.UNSTABLE : Result.SUCCESS; if (this.overallResult.isWorseThan(threshold)) { listener.getLogger().println("Minimum result threshold not met for join project"); } else { // Construct a launcher since CopyArchiver wants to get the // channel from it. We use the channel of the node where the // splitProject was built on. final Launcher launcher = new NoopLauncher(listener, owner); for (Publisher pub : this.joinPublishers) { try { pub.perform(owner, launcher, (BuildListener) listener); } catch (InterruptedException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } if (!JoinTrigger.canDeclare(owner.getProject())) { List<AbstractProject> projects = Items.fromNameList(joinProjects, AbstractProject.class); for (AbstractProject project : projects) { listener.getLogger().println("Scheduling join project: " + project.getName()); project.scheduleBuild(new JoinCause(owner)); } } } } else { listener .getLogger() .println( "Project " + owner.getProject().getName() + " still waiting for " + pendingDownstreamProjects.size() + " builds to complete"); } }
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(); } }
/** * Loads all the child {@link Item}s. * * @param modulesDir Directory that contains sub-directories for each child item. */ public static <K, V extends Item> Map<K, V> loadChildren( ItemGroup parent, File modulesDir, Function1<? extends K, ? super V> key) { modulesDir.mkdirs(); // make sure it exists File[] subdirs = modulesDir.listFiles( new FileFilter() { public boolean accept(File child) { return child.isDirectory(); } }); CopyOnWriteMap.Tree<K, V> configurations = new CopyOnWriteMap.Tree<K, V>(); for (File subdir : subdirs) { try { V item = (V) Items.load(parent, subdir); configurations.put(key.call(item), item); } catch (IOException e) { e.printStackTrace(); // TODO: logging } } return configurations; }
/** Gets the encrypted usage stat data to be sent to the Hudson server. */ public String getStatData() throws IOException { Jenkins j = Jenkins.getInstance(); JSONObject o = new JSONObject(); o.put("stat", 1); o.put("install", j.getLegacyInstanceId()); o.put("servletContainer", j.servletContext.getServerInfo()); o.put("version", Jenkins.VERSION); List<JSONObject> nodes = new ArrayList<JSONObject>(); for (Computer c : j.getComputers()) { JSONObject n = new JSONObject(); if (c.getNode() == j) { n.put("master", true); n.put("jvm-vendor", System.getProperty("java.vm.vendor")); n.put("jvm-name", System.getProperty("java.vm.name")); n.put("jvm-version", System.getProperty("java.version")); } n.put("executors", c.getNumExecutors()); DescriptorImpl descriptor = j.getDescriptorByType(DescriptorImpl.class); n.put("os", descriptor.get(c)); nodes.add(n); } o.put("nodes", nodes); List<JSONObject> plugins = new ArrayList<JSONObject>(); for (PluginWrapper pw : j.getPluginManager().getPlugins()) { if (!pw.isActive()) continue; // treat disabled plugins as if they are uninstalled JSONObject p = new JSONObject(); p.put("name", pw.getShortName()); p.put("version", pw.getVersion()); plugins.add(p); } o.put("plugins", plugins); JSONObject jobs = new JSONObject(); List<TopLevelItem> items = j.getAllItems(TopLevelItem.class); for (TopLevelItemDescriptor d : Items.all()) { int cnt = 0; for (TopLevelItem item : items) { if (item.getDescriptor() == d) cnt++; } jobs.put(d.getJsonSafeClassName(), cnt); } o.put("jobs", jobs); try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); // json -> UTF-8 encode -> gzip -> encrypt -> base64 -> string OutputStreamWriter w = new OutputStreamWriter( new GZIPOutputStream(new CombinedCipherOutputStream(baos, getKey(), "AES")), "UTF-8"); try { o.write(w); } finally { IOUtils.closeQuietly(w); } return new String(Base64.encode(baos.toByteArray())); } catch (GeneralSecurityException e) { throw new Error(e); // impossible } }
@SuppressWarnings("unchecked") private static <I extends AbstractItem & TopLevelItem> I doMove( Item item, DirectlyModifiableTopLevelItemGroup destination) throws IOException { return Items.move((I) item, destination); }
public List<AbstractProject> getChildProjects() { return Items.fromNameList(childProjects, AbstractProject.class); }
public List<AbstractProject> getProjectList() { return Items.fromNameList(projects, AbstractProject.class); }
public final XmlFile getConfigFile() { return Items.getConfigFile(this); }
public static String getProjectListString(List<Project> projects) { return Items.toNameList(projects); }