/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jetbrains.buildServer.server.rest.request;
import com.intellij.openapi.diagnostic.Logger;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.UriInfo;
import jetbrains.buildServer.ServiceLocator;
import jetbrains.buildServer.server.rest.ApiUrlBuilder;
import jetbrains.buildServer.server.rest.data.*;
import jetbrains.buildServer.server.rest.errors.BadRequestException;
import jetbrains.buildServer.server.rest.errors.InvalidStateException;
import jetbrains.buildServer.server.rest.model.Fields;
import jetbrains.buildServer.server.rest.model.Properties;
import jetbrains.buildServer.server.rest.model.Property;
import jetbrains.buildServer.server.rest.model.agent.AgentPool;
import jetbrains.buildServer.server.rest.model.agent.AgentPools;
import jetbrains.buildServer.server.rest.model.build.Build;
import jetbrains.buildServer.server.rest.model.build.Builds;
import jetbrains.buildServer.server.rest.model.buildType.BuildType;
import jetbrains.buildServer.server.rest.model.buildType.BuildTypeUtil;
import jetbrains.buildServer.server.rest.model.buildType.BuildTypes;
import jetbrains.buildServer.server.rest.model.buildType.NewBuildTypeDescription;
import jetbrains.buildServer.server.rest.model.project.NewProjectDescription;
import jetbrains.buildServer.server.rest.model.project.Project;
import jetbrains.buildServer.server.rest.model.project.Projects;
import jetbrains.buildServer.server.rest.util.BeanContext;
import jetbrains.buildServer.server.rest.util.BeanFactory;
import jetbrains.buildServer.server.rest.util.BuildTypeOrTemplate;
import jetbrains.buildServer.serverSide.*;
import jetbrains.buildServer.serverSide.agentPools.AgentPoolManager;
import jetbrains.buildServer.serverSide.agentPools.NoSuchAgentPoolException;
import jetbrains.buildServer.serverSide.identifiers.DuplicateExternalIdException;
import jetbrains.buildServer.util.StringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/*
* User: Yegor Yarko
* Date: 11.04.2009
*/
@Path(ProjectRequest.API_PROJECTS_URL)
public class ProjectRequest {
private static final Logger LOG = Logger.getInstance(ProjectRequest.class.getName());
public static final boolean ID_GENERATION_FLAG = true;
@Context @NotNull private DataProvider myDataProvider;
@Context @NotNull private BuildFinder myBuildFinder;
@Context @NotNull private BuildTypeFinder myBuildTypeFinder;
@Context @NotNull private ProjectFinder myProjectFinder;
@Context @NotNull private AgentPoolsFinder myAgentPoolsFinder;
@Context @NotNull private ApiUrlBuilder myApiUrlBuilder;
@Context @NotNull private ServiceLocator myServiceLocator;
@Context @NotNull private BeanFactory myFactory;
@Context @NotNull private BeanContext myBeanContext;
public static final String API_PROJECTS_URL = Constants.API_URL + "/projects";
protected static final String PARAMETERS = "/parameters";
@NotNull
public static String getProjectHref(SProject project) {
return API_PROJECTS_URL + "/" + ProjectFinder.getLocator(project);
}
@NotNull
public static String getParametersHref(final SProject project) {
return getProjectHref(project) + PARAMETERS;
}
@GET
@Produces({"application/xml", "application/json"})
public Projects serveProjects(@QueryParam("fields") String fields) {
return new Projects(myDataProvider.getServer().getProjectManager().getProjects(), new Fields(fields),
new BeanContext(myFactory, myServiceLocator, myApiUrlBuilder));
}
@POST
@Consumes({"text/plain"})
@Produces({"application/xml", "application/json"})
public Project createEmptyProject(String name) {
if (StringUtil.isEmpty(name)) {
throw new BadRequestException("Project name cannot be empty.");
}
final SProject project = myDataProvider.getServer().getProjectManager().createProject(name);
project.persist();
return new Project(project, Fields.LONG, new BeanContext(myFactory, myServiceLocator, myApiUrlBuilder));
}
@POST
@Consumes({"application/xml", "application/json"})
@Produces({"application/xml", "application/json"})
public Project createProject(NewProjectDescription descriptor) {
if (StringUtil.isEmpty(descriptor.name)) {
throw new BadRequestException("Project name cannot be empty.");
}
SProject resultingProject;
@Nullable SProject sourceProject = descriptor.getSourceProject(myServiceLocator);
final ProjectManager projectManager = myDataProvider.getServer().getProjectManager();
final SProject parentProject = descriptor.getParentProject(myServiceLocator);
if (sourceProject == null) {
resultingProject = parentProject.createProject(descriptor.getId(myServiceLocator), descriptor.name);
} else {
final CopyOptions copyOptions = descriptor.getCopyOptions();
//see also getExampleNewProjectDescription which prepares NewProjectDescription
copyOptions.addProjectExternalIdMapping(Collections.singletonMap(sourceProject.getExternalId(), descriptor.getId(myServiceLocator)));
copyOptions.setGenerateExternalIdsBasedOnOriginalExternalIds(ID_GENERATION_FLAG);
if (descriptor.name != null) copyOptions.setNewProjectName(descriptor.name);
try {
resultingProject = projectManager.copyProject(sourceProject, parentProject, copyOptions);
} catch (MaxNumberOfBuildTypesReachedException e) {
throw new BadRequestException("Build configurations number limit is reached", e);
} catch (NotAllIdentifiersMappedException e) {
throw new BadRequestException("Not all ids are mapped", e);
} catch (InvalidNameException e) {
throw new BadRequestException("Invalid name", e);
} catch (DuplicateExternalIdException e) {
throw new BadRequestException("Duplicate id", e);
}
try {
if (descriptor.name != null) resultingProject.setName(descriptor.name);
//todo: TeamCity api: is this necessary? http://youtrack.jetbrains.com/issue/TW-28495
resultingProject.setExternalId(descriptor.getId(myServiceLocator));
} catch (InvalidIdentifierException e) {
processCreatiedProjectFinalizationError(resultingProject, projectManager, e);
} catch (DuplicateExternalIdException e) {
processCreatiedProjectFinalizationError(resultingProject, projectManager, e);
}
}
try {
resultingProject.persist();
} catch (PersistFailedException e) {
processCreatiedProjectFinalizationError(resultingProject, projectManager, e);
}
return new Project(resultingProject, Fields.LONG, new BeanContext(myFactory, myServiceLocator, myApiUrlBuilder));
}
private void processCreatiedProjectFinalizationError(final SProject resultingProject, final ProjectManager projectManager, final Exception e) {
try {
projectManager.removeProject(resultingProject.getProjectId());
} catch (ProjectRemoveFailedException e1) {
LOG.warn("Rallback of project creation failed", e1);
//ignore
}
throw new InvalidStateException("Error during project creation finalization", e);
}
@GET
@Path("/{projectLocator}")
@Produces({"application/xml", "application/json"})
public Project serveProject(@PathParam("projectLocator") String projectLocator, @QueryParam("fields") String fields) {
return new Project(myProjectFinder.getProject(projectLocator), new Fields(fields), new BeanContext(myFactory, myServiceLocator, myApiUrlBuilder));
}
@DELETE
@Path("/{projectLocator}")
public void deleteProject(@PathParam("projectLocator") String projectLocator) {
final SProject project = myProjectFinder.getProject(projectLocator);
myDataProvider.getServer().getProjectManager().removeProject(project.getProjectId());
}
@GET
@Path("/{projectLocator}/{field}")
@Produces("text/plain")
public String serveProjectField(@PathParam("projectLocator") String projectLocator, @PathParam("field") String fieldName) {
return Project.getFieldValue(myProjectFinder.getProject(projectLocator), fieldName);
}
@PUT
@Path("/{projectLocator}/{field}")
@Consumes("text/plain")
@Produces("text/plain")
public String setProjectFiled(@PathParam("projectLocator") String projectLocator, @PathParam("field") String fieldName, String newValue) {
final SProject project = myProjectFinder.getProject(projectLocator);
Project.setFieldValueAndPersist(project, fieldName, newValue, myDataProvider);
return Project.getFieldValue(project, fieldName);
}
@GET
@Path("/{projectLocator}/buildTypes")
@Produces({"application/xml", "application/json"})
public BuildTypes serveBuildTypesInProject(@PathParam("projectLocator") String projectLocator, @QueryParam("fields") String fields) {
SProject project = myProjectFinder.getProject(projectLocator);
return new BuildTypes(BuildTypes.fromBuildTypes(project.getOwnBuildTypes()), new Fields(fields), myBeanContext);
}
@POST
@Path("/{projectLocator}/buildTypes")
@Produces({"application/xml", "application/json"})
@Consumes({"text/plain"})
public BuildType createEmptyBuildType(@PathParam("projectLocator") String projectLocator, String name, @QueryParam("fields") String fields) {
SProject project = myProjectFinder.getProject(projectLocator);
if (StringUtil.isEmpty(name)) {
throw new BadRequestException("Build type name cannot be empty.");
}
final SBuildType buildType = project.createBuildType(name);
buildType.persist();
return new BuildType(new BuildTypeOrTemplate(buildType), new Fields(fields), myBeanContext);
}
/**
* Creates a new build configuration by copying existing one.
*
* @param projectLocator
* @param descriptor reference to the build configuration to copy and copy options.
* e.g.
* @return the build configuration created
*/
@POST
@Path("/{projectLocator}/buildTypes")
@Produces({"application/xml", "application/json"})
@Consumes({"application/xml", "application/json"})
public BuildType createBuildType(@PathParam("projectLocator") String projectLocator, NewBuildTypeDescription descriptor, @QueryParam("fields") String fields) {
@NotNull SProject project = myProjectFinder.getProject(projectLocator);
SBuildType resultingBuildType;
@Nullable final BuildTypeOrTemplate sourceBuildType = descriptor.getSourceBuildTypeOrTemplate(myServiceLocator);
if (sourceBuildType == null) {
resultingBuildType = project.createBuildType(descriptor.getId(myServiceLocator, project), descriptor.getName());
} else {
if (sourceBuildType.isBuildType()) {
resultingBuildType =
project.copyBuildType(sourceBuildType.getBuildType(), descriptor.getId(myServiceLocator, project), descriptor.getName(), descriptor.getCopyOptions());
} else {
throw new BadRequestException("Could not create build type as a copy of a template.");
}
}
resultingBuildType.persist();
return new BuildType(new BuildTypeOrTemplate(resultingBuildType), new Fields(fields), myBeanContext);
}
@GET
@Path("/{projectLocator}/buildTypes/{btLocator}")
@Produces({"application/xml", "application/json"})
public BuildType serveBuildType(@PathParam("projectLocator") String projectLocator, @PathParam("btLocator") String buildTypeLocator, @QueryParam("fields") String fields) {
SBuildType buildType = myBuildTypeFinder.getBuildType(myProjectFinder.getItem(projectLocator, false), buildTypeLocator, false);
return new BuildType(new BuildTypeOrTemplate(buildType), new Fields(fields), myBeanContext);
}
@GET
@Path("/{projectLocator}/templates")
@Produces({"application/xml", "application/json"})
public BuildTypes serveTemplatesInProject(@PathParam("projectLocator") String projectLocator, @QueryParam("fields") String fields) {
SProject project = myProjectFinder.getItem(projectLocator, true);
return new BuildTypes(BuildTypes.fromTemplates(project.getOwnBuildTypeTemplates()), new Fields(fields),
new BeanContext(myFactory, myServiceLocator, myApiUrlBuilder));
}
@POST
@Path("/{projectLocator}/templates")
@Produces({"application/xml", "application/json"})
@Consumes({"text/plain"})
public BuildType createEmptyBuildTypeTemplate(@PathParam("projectLocator") String projectLocator, String name, @QueryParam("fields") String fields) {
SProject project = myProjectFinder.getItem(projectLocator, true);
if (StringUtil.isEmpty(name)) {
throw new BadRequestException("Build type template name cannot be empty.");
}
final BuildTypeTemplate buildType = project.createBuildTypeTemplate(name);
buildType.persist();
return new BuildType(new BuildTypeOrTemplate(buildType), new Fields(fields), myBeanContext);
}
/**
* Creates a new build configuration template by copying existing one.
*
* @param projectLocator
* @param descriptor reference to the build configuration template to copy and copy options.
* e.g.
* @return the build configuration created
*/
@POST
@Path("/{projectLocator}/templates")
@Produces({"application/xml", "application/json"})
@Consumes({"application/xml", "application/json"})
public BuildType createBuildTypeTemplate(@PathParam("projectLocator") String projectLocator, NewBuildTypeDescription descriptor, @QueryParam("fields") String fields) {
@NotNull SProject project = myProjectFinder.getItem(projectLocator, true);
BuildTypeTemplate resultingBuildType;
@Nullable final BuildTypeOrTemplate sourceBuildType = descriptor.getSourceBuildTypeOrTemplate(myServiceLocator);
if (sourceBuildType == null) {
resultingBuildType = project.createBuildTypeTemplate(descriptor.getId(myServiceLocator, project), descriptor.getName());
} else {
if (sourceBuildType.isBuildType()) {
resultingBuildType =
project.extractBuildTypeTemplate(sourceBuildType.getBuildType(), descriptor.getId(myServiceLocator, project), descriptor.getName());
} else {
resultingBuildType =
project.copyBuildTypeTemplate(sourceBuildType.getTemplate(), descriptor.getId(myServiceLocator, project), descriptor.getName());
}
}
resultingBuildType.persist();
return new BuildType(new BuildTypeOrTemplate(resultingBuildType), new Fields(fields), myBeanContext);
}
@GET
@Path("/{projectLocator}/templates/{btLocator}")
@Produces({"application/xml", "application/json"})
public BuildType serveBuildTypeTemplates(@PathParam("projectLocator") String projectLocator, @PathParam("btLocator") String buildTypeLocator, @QueryParam("fields") String fields) {
BuildTypeTemplate buildType = myBuildTypeFinder.getBuildTemplate(myProjectFinder.getItem(projectLocator, true), buildTypeLocator, true);
return new BuildType(new BuildTypeOrTemplate(buildType), new Fields(fields), myBeanContext);
}
@GET
@Path("/{projectLocator}" + PARAMETERS)
@Produces({"application/xml", "application/json"})
public Properties serveParameters(@PathParam("projectLocator") String projectLocator, @QueryParam("fields") String fields) {
SProject project = myProjectFinder.getItem(projectLocator, true);
return new Properties(project.getParametersCollection(), project.getOwnParametersCollection(), getParametersHref(project),
new Fields(fields), myServiceLocator);
}
@PUT
@Path("/{projectLocator}" + PARAMETERS)
@Consumes({"application/xml", "application/json"})
@Produces({"application/xml", "application/json"})
public Properties changeAllParameters(@PathParam("projectLocator") String projectLocator, Properties properties, @QueryParam("fields") String fields) {
SProject project = myProjectFinder.getItem(projectLocator, true);
BuildTypeUtil.removeAllParameters(project);
for (Parameter p : properties.getFromPosted(myServiceLocator)) {
project.addParameter(p);
}
project.persist();
return new Properties(project.getParametersCollection(), project.getOwnParametersCollection(), getParametersHref(project),
new Fields(fields), myServiceLocator);
}
@POST
@Path("/{projectLocator}" + PARAMETERS)
@Consumes({"application/xml", "application/json"})
@Produces({"application/xml", "application/json"})
public Property setParameter(@PathParam("projectLocator") String projectLocator, Property parameter) {
SProject project = myProjectFinder.getItem(projectLocator, true);
project.addParameter(parameter.getFromPosted(myServiceLocator));
project.persist();
return Property.createFrom(parameter.name, project, Fields.LONG, myServiceLocator);
}
@DELETE
@Path("/{projectLocator}" + PARAMETERS)
public void deleteAllParameters(@PathParam("projectLocator") String projectLocator) {
SProject project = myProjectFinder.getItem(projectLocator, true);
BuildTypeUtil.removeAllParameters(project);
project.persist();
}
@GET
@Path("/{projectLocator}" + PARAMETERS + "/{name}")
@Produces("text/plain")
public String getParameterValue(@PathParam("projectLocator") String projectLocator, @PathParam("name") String parameterName) {
SProject project = myProjectFinder.getItem(projectLocator, true);
return BuildTypeUtil.getParameter(parameterName, project, true, false);
}
@GET
@Path("/{projectLocator}" + PARAMETERS + "/{name}")
@Produces({"application/xml", "application/json"})
public Property getParameter(@PathParam("projectLocator") String projectLocator, @PathParam("name") String parameterName) {
SProject project = myProjectFinder.getItem(projectLocator, true);
return Property.createFrom(parameterName, project, Fields.LONG, myServiceLocator);
}
@PUT
@Path("/{projectLocator}" + PARAMETERS + "/{name}")
@Consumes("text/plain")
@Produces("text/plain")
public String putParameter(@PathParam("projectLocator") String projectLocator, @PathParam("name") String parameterName, String newValue) {
SProject project = myProjectFinder.getItem(projectLocator, true);
BuildTypeUtil.changeParameter(parameterName, newValue, project, myServiceLocator);
project.persist();
return BuildTypeUtil.getParameter(parameterName, project, false, false);
}
@DELETE
@Path("/{projectLocator}" + PARAMETERS + "/{name}")
public void deleteParameter(@PathParam("projectLocator") String projectLocator, @PathParam("name") String parameterName) {
SProject project = myProjectFinder.getItem(projectLocator, true);
BuildTypeUtil.deleteParameter(parameterName, project);
project.persist();
}
@GET
@Path("/{projectLocator}/buildTypes/{btLocator}/{field}")
@Produces("text/plain")
public String serveBuildTypeFieldWithProject(@PathParam("projectLocator") String projectLocator,
@PathParam("btLocator") String buildTypeLocator,
@PathParam("field") String fieldName) {
BuildTypeOrTemplate buildType = myBuildTypeFinder.getBuildTypeOrTemplate(myProjectFinder.getItem(projectLocator, false), buildTypeLocator, false);
return buildType.getFieldValue(fieldName);
}
//todo: separate methods to serve running builds
/**
* Serves builds matching supplied condition.
*
* @param locator Build locator to filter builds
* @param buildTypeLocator Deprecated, use "locator" parameter instead
* @param status Deprecated, use "locator" parameter instead
* @param userLocator Deprecated, use "locator" parameter instead
* @param includePersonal Deprecated, use "locator" parameter instead
* @param includeCanceled Deprecated, use "locator" parameter instead
* @param onlyPinned Deprecated, use "locator" parameter instead
* @param tags Deprecated, use "locator" parameter instead
* @param agentName Deprecated, use "locator" parameter instead
* @param sinceBuildLocator Deprecated, use "locator" parameter instead
* @param sinceDate Deprecated, use "locator" parameter instead
* @param start Deprecated, use "locator" parameter instead
* @param count Deprecated, use "locator" parameter instead, defaults to 100
* @return
*/
@GET
@Path("/{projectLocator}/buildTypes/{btLocator}/builds")
@Produces({"application/xml", "application/json"})
public Builds serveBuilds(@PathParam("projectLocator") String projectLocator,
@PathParam("btLocator") String buildTypeLocator,
@QueryParam("status") String status,
@QueryParam("triggeredByUser") String userLocator,
@QueryParam("includePersonal") boolean includePersonal,
@QueryParam("includeCanceled") boolean includeCanceled,
@QueryParam("onlyPinned") boolean onlyPinned,
@QueryParam("tag") List tags,
@QueryParam("agentName") String agentName,
@QueryParam("sinceBuild") String sinceBuildLocator,
@QueryParam("sinceDate") String sinceDate,
@QueryParam("start") Long start,
@QueryParam("count") Integer count,
@QueryParam("locator") String locator,
@QueryParam("fields") String fields,
@Context UriInfo uriInfo, @Context HttpServletRequest request) {
SBuildType buildType = myBuildTypeFinder.getBuildType(myProjectFinder.getItem(projectLocator, false), buildTypeLocator, false);
return myBuildFinder.getBuildsForRequest(buildType, status, userLocator, includePersonal, includeCanceled, onlyPinned, tags, agentName,
sinceBuildLocator, sinceDate, start, count, locator, "locator", uriInfo, request, new Fields(fields), myBeanContext);
}
@GET
@Path("/{projectLocator}/buildTypes/{btLocator}/builds/{buildLocator}")
@Produces({"application/xml", "application/json"})
public Build serveBuildWithProject(@PathParam("projectLocator") String projectLocator,
@PathParam("btLocator") String buildTypeLocator,
@PathParam("buildLocator") String buildLocator,
@QueryParam("fields") String fields) {
SBuildType buildType = myBuildTypeFinder.getBuildType(myProjectFinder.getItem(projectLocator, false), buildTypeLocator, false);
SBuild build = myBuildFinder.getBuild(buildType, buildLocator);
return new Build(build, new Fields(fields), myBeanContext);
}
@GET
@Path("/{projectLocator}/buildTypes/{btLocator}/builds/{buildLocator}/{field}")
@Produces("text/plain")
public String serveBuildFieldWithProject(@PathParam("projectLocator") String projectLocator,
@PathParam("btLocator") String buildTypeLocator,
@PathParam("buildLocator") String buildLocator,
@PathParam("field") String field) {
SBuildType buildType = myBuildTypeFinder.getBuildType(myProjectFinder.getItem(projectLocator, false), buildTypeLocator, false);
SBuild build = myBuildFinder.getBuild(buildType, buildLocator);
return Build.getFieldValue(build.getBuildPromotion(), field, new BeanContext(myFactory, myServiceLocator, myApiUrlBuilder));
}
@GET
@Path("/{projectLocator}/parentProject")
@Produces({"application/xml", "application/json"})
public Project getParentProject(@PathParam("projectLocator") String projectLocator, @QueryParam("fields") String fields) {
SProject project = myProjectFinder.getProject(projectLocator);
final SProject actulParentProject = project.getParentProject();
return actulParentProject == null
? null
: new Project(actulParentProject, new Fields(fields), new BeanContext(myFactory, myServiceLocator, myApiUrlBuilder));
}
@PUT
@Path("/{projectLocator}/parentProject")
@Produces({"application/xml", "application/json"})
@Consumes({"application/xml", "application/json"})
public Project setParentProject(@PathParam("projectLocator") String projectLocator, Project parentProject) {
SProject project = myProjectFinder.getProject(projectLocator);
project.moveToProject(parentProject.getProjectFromPosted(myProjectFinder));
project.persist();
return new Project(project, Fields.LONG, new BeanContext(myFactory, myServiceLocator, myApiUrlBuilder));
}
@GET
@Path("/{projectLocator}/agentPools")
@Produces({"application/xml", "application/json"})
public AgentPools getProjectAgentPools(@PathParam("projectLocator") String projectLocator) {
SProject project = myProjectFinder.getProject(projectLocator);
return new AgentPools(myAgentPoolsFinder.getPoolsForProject(project), myApiUrlBuilder);
}
@DELETE
@Path("/{projectLocator}/agentPools/{agentPoolLocator}")
public void getProjectAgentPools(@PathParam("projectLocator") String projectLocator, @PathParam("agentPoolLocator") String agentPoolLocator) {
SProject project = myProjectFinder.getProject(projectLocator);
final jetbrains.buildServer.serverSide.agentPools.AgentPool agentPool = myAgentPoolsFinder.getAgentPool(agentPoolLocator);
final AgentPoolManager agentPoolManager = myServiceLocator.getSingletonService(AgentPoolManager.class);
final int agentPoolId = agentPool.getAgentPoolId();
try {
agentPoolManager.dissociateProjectsFromPool(agentPoolId, Collections.singleton(project.getProjectId()));
} catch (NoSuchAgentPoolException e) {
throw new IllegalStateException("Agent pool with id \'" + agentPoolId + "' is not found.");
}
}
@PUT
@Path("/{projectLocator}/agentPools")
@Produces({"application/xml", "application/json"})
@Consumes({"application/xml", "application/json"})
public AgentPools setProjectAgentPools(@PathParam("projectLocator") String projectLocator, AgentPools pools) {
SProject project = myProjectFinder.getProject(projectLocator);
myDataProvider.setProjectPools(project, pools.getPoolsFromPosted(myAgentPoolsFinder));
return new AgentPools(myAgentPoolsFinder.getPoolsForProject(project), myApiUrlBuilder);
}
@POST
@Path("/{projectLocator}/agentPools")
@Produces({"application/xml", "application/json"})
@Consumes({"application/xml", "application/json"})
public AgentPool setProjectAgentPools(@PathParam("projectLocator") String projectLocator, AgentPool pool) {
SProject project = myProjectFinder.getProject(projectLocator);
final AgentPoolManager agentPoolManager = myServiceLocator.getSingletonService(AgentPoolManager.class);
final jetbrains.buildServer.serverSide.agentPools.AgentPool agentPoolFromPosted = pool.getAgentPoolFromPosted(myAgentPoolsFinder);
final int agentPoolId = agentPoolFromPosted.getAgentPoolId();
try {
agentPoolManager.associateProjectsWithPool(agentPoolId, Collections.singleton(project.getProjectId()));
} catch (NoSuchAgentPoolException e) {
throw new IllegalStateException("Agent pool with id \'" + agentPoolId + "' is not found.");
}
return new AgentPool(agentPoolFromPosted, Fields.LONG, new BeanContext(myDataProvider.getBeanFactory(), myServiceLocator, myApiUrlBuilder));
}
/**
* For compatibility with experimental feature of 8.0
*/
@GET
@Path("/{projectLocator}/newProjectDescription")
@Produces({"application/xml", "application/json"})
public NewProjectDescription getExampleNewProjectDescriptionCompatibilityVersion1(@PathParam("projectLocator") String projectLocator, @QueryParam("id") String newId) {
return getExampleNewProjectDescription(projectLocator, newId);
}
/**
* Experimental support only.
* Use this to get an example of the bean to be posted to the /projects request to create a new project
*
* @param projectLocator
* @return
*/
@GET
@Path("/{projectLocator}/example/newProjectDescription")
@Produces({"application/xml", "application/json"})
public NewProjectDescription getExampleNewProjectDescription(@PathParam("projectLocator") String projectLocator, @QueryParam("id") String newId) {
final SProject project = myProjectFinder.getProject(projectLocator);
final SProject parentProject = project.getParentProject();
final Project parentProjectRef =
parentProject != null ? new Project(parentProject, Fields.SHORT, new BeanContext(myFactory, myServiceLocator, myApiUrlBuilder)) : null;
@NotNull final String newNotEmptyId = StringUtil.isEmpty(newId) ? project.getExternalId() : newId;
final ProjectManagerEx.IdsMaps idsMaps =
((ProjectManagerEx)myDataProvider.getServer().getProjectManager()).generateDefaultExternalIds(project, newNotEmptyId, ID_GENERATION_FLAG, true);
final Map projectIdsMap = idsMaps.getProjectIdsMap();
projectIdsMap.remove(project.getExternalId()); // remove ptoject's own id to make the object more clean
return new NewProjectDescription(project.getName(), newNotEmptyId, new Project(project, Fields.SHORT, new BeanContext(myFactory, myServiceLocator, myApiUrlBuilder)),
parentProjectRef, true,
getNullOrCollection(projectIdsMap),
getNullOrCollection(idsMaps.getBuildTypeIdsMap()),
getNullOrCollection(idsMaps.getVcsRootIdsMap()));
}
@Nullable
private Map getNullOrCollection(final @NotNull Map map) {
return map.size() > 0 ? map : null;
}
}