/* * 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.data; import com.intellij.openapi.diagnostic.Logger; import java.util.ArrayList; import java.util.List; import jetbrains.buildServer.BuildProject; import jetbrains.buildServer.server.rest.APIController; import jetbrains.buildServer.server.rest.errors.AuthorizationFailedException; import jetbrains.buildServer.server.rest.errors.BadRequestException; import jetbrains.buildServer.server.rest.errors.NotFoundException; import jetbrains.buildServer.server.rest.model.project.Project; import jetbrains.buildServer.serverSide.ProjectManager; import jetbrains.buildServer.serverSide.SProject; import jetbrains.buildServer.serverSide.TeamCityProperties; import jetbrains.buildServer.serverSide.auth.Permission; import jetbrains.buildServer.util.StringUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** * @author Yegor.Yarko * Date: 23.03.13 */ public class ProjectFinder { private static final Logger LOG = Logger.getInstance(ProjectFinder.class.getName()); @NotNull private final ProjectManager myProjectManager; private final DataProvider myPermissionChecker; public ProjectFinder(@NotNull final ProjectManager projectManager, final DataProvider permissionChecker){ myProjectManager = projectManager; myPermissionChecker = permissionChecker; } public static boolean isSameOrParent(@NotNull final BuildProject parent, @NotNull final BuildProject project) { if (parent.getProjectId().equals(project.getProjectId())) return true; if (project.getParentProject() == null) return false; return isSameOrParent(parent, project.getParentProject()); } public static String getLocator(final BuildProject project) { return Locator.createEmptyLocator().setDimension("id", project.getExternalId()).getStringRepresentation(); } @NotNull public SProject getProject(@Nullable String projectLocator) { if (StringUtil.isEmpty(projectLocator)) { throw new BadRequestException("Empty project locator is not supported."); } final Locator locator = new Locator(projectLocator, "id", "name", "parentProject", "internalId", Locator.LOCATOR_SINGLE_VALUE_UNUSED_NAME); if (locator.isSingleValue()) { // no dimensions found, assume it's a name or internal id or external id SProject project = null; @SuppressWarnings("ConstantConditions") @NotNull final String singleValue = locator.getSingleValue(); project = myProjectManager.findProjectByExternalId(singleValue); if (project != null) { return project; } final List projectsByName = findProjectsByName(null, singleValue); if (projectsByName.size() == 1) { project = projectsByName.get(0); if (project != null) { return project; } } project = myProjectManager.findProjectById(singleValue); if (project != null) { return project; } throw new NotFoundException("No project found by name or internal/external id '" + singleValue + "'."); } String id = locator.getSingleDimensionValue("id"); if (id != null) { SProject project = myProjectManager.findProjectByExternalId(id); if (project == null) { if (TeamCityProperties.getBoolean(APIController.REST_COMPATIBILITY_ALLOW_EXTERNAL_ID_AS_INTERNAL)){ project = myProjectManager.findProjectById(id); if (project == null) { throw new NotFoundException("No project found by locator '" + projectLocator + "' in compatibility mode. Project cannot be found by external or internal id '" + id + "'."); } }else{ throw new NotFoundException("No project found by locator '" + projectLocator + "'. Project cannot be found by external id '" + id + "'."); } } if (locator.getDimensionsCount() > 1) { LOG.info("Project locator '" + projectLocator + "' has 'id' dimension and others. Others are ignored."); } locator.checkLocatorFullyProcessed(); return project; } String internalId = locator.getSingleDimensionValue("internalId"); if (internalId != null) { SProject project = myProjectManager.findProjectById(internalId); if (project == null) { throw new NotFoundException("No project found by locator '" + projectLocator + "'. Project cannot be found by internal id '" + internalId + "'."); } if (locator.getDimensionsCount() > 1) { LOG.info("Project locator '" + projectLocator + "' has 'internalId' dimension and others. Others are ignored."); } locator.checkLocatorFullyProcessed(); return project; } String name = locator.getSingleDimensionValue("name"); if (name != null) { final String parentProjectLocator = locator.getSingleDimensionValue("parentProject"); final SProject projectByName = getProjectByName(parentProjectLocator == null ? null : getProject(parentProjectLocator), name); locator.checkLocatorFullyProcessed(); return projectByName; } locator.checkLocatorFullyProcessed(); throw new BadRequestException("Project locator '" + projectLocator + "' is not supported."); } @NotNull public SProject getRootProject() { return myProjectManager.getRootProject(); } @NotNull private SProject getProjectByName(@Nullable final SProject parentProject, @NotNull final String name) { final List projectsByName = findProjectsByName(parentProject, name); if (projectsByName.size() == 0) { throw new NotFoundException("No project can be found by name '" + name + "'" + (parentProject == null ? "" : " in the project " + parentProject.getExtendedFullName()) + "."); } if (projectsByName.size() > 1) { throw new NotFoundException( "Several projects are found by name '" + name + "': " + getPresentable(projectsByName) + ", specify 'parentProject' or 'id' to match exactly one."); } return projectsByName.get(0); } private String getPresentable(final List projects) { final StringBuilder sb = new StringBuilder(); if (projects.size() > 0) { sb.append("["); boolean firstItem = true; for (SProject project : projects) { if (firstItem){ firstItem = false; }else{ sb.append(", "); } sb.append(project.getExtendedFullName()); } sb.append("]"); return sb.toString(); } return ""; } /** * Finds projects with the given name under the project specified * @param parentProject Project under which to search. If 'null' - process all projects including root one. * @param name * @return */ @NotNull private List findProjectsByName(@Nullable SProject parentProject, @NotNull final String name) { final ArrayList result = new ArrayList(); if (parentProject == null) { parentProject = getRootProject(); if (name.equals(parentProject.getName())) { //process root project as well result.add(parentProject); } } for (SProject project : parentProject.getProjects()) { if (name.equals(project.getName())){ result.add(project); } } return result; } @Nullable public SProject getProjectIfNotNull(@Nullable final String projectLocator) { return projectLocator == null ? null : getProject(projectLocator); } @Nullable public BuildProject findProjectByInternalId(final String projectInternalId) { return myProjectManager.findProjectById(projectInternalId); } @NotNull public static SProject getProjectByInternalId(@NotNull final String projectInternalId, @NotNull final ProjectManager projectManager) { final SProject project = projectManager.findProjectById(projectInternalId); if (project == null) { throw new NotFoundException("No project found by internal id '" + projectInternalId + "'."); } return project; } @NotNull public SProject getItem(@Nullable final String locatorText, final boolean checkViewSettingsPermission) { final SProject result = getProject(locatorText); if (checkViewSettingsPermission) { check(result, myPermissionChecker); } return result; } public static void check(@NotNull SProject project, @NotNull final DataProvider permissionChecker) { if (Project.shouldRestrictSettingsViewing(project, permissionChecker)) { throw new AuthorizationFailedException( "User does not have '" + Permission.VIEW_BUILD_CONFIGURATION_SETTINGS.getName() + "' permission in project " + project.describe(false)); } } }