ProjectManager { public Project createProject(final String projectName, final String description, final User creator) throws ProjectManagerException { if (projectName == null || projectName.trim().isEmpty()) { throw new ProjectManagerException("Project name cannot be empty."); } else if (description == null || description.trim().isEmpty()) { throw new ProjectManagerException("Description cannot be empty."); } else if (creator == null) { throw new ProjectManagerException("Valid creator user must be set."); } else if (!projectName.matches("[a-zA-Z][a-zA-Z_0-9|-]*")) { throw new ProjectManagerException( "Project names must start with a letter, followed by any number of letters, digits, '-' or '_'."); } final Project newProject; synchronized (this) { if (getProject(projectName) != null) { throw new ProjectManagerException("Project already exists."); } logger.info("Trying to create {} by user {}", projectName, creator.getUserId()); newProject = this.projectLoader.createNewProject(projectName, description, creator); this.cache.putProject(newProject); } if (this.creatorDefaultPermissions) { this.projectLoader.updatePermission(newProject, creator.getUserId(), new Permission(Permission.Type.ADMIN), false); newProject.addProxyUser(creator.getUserId()); try { updateProjectSetting(newProject); } catch (final ProjectManagerException e) { e.printStackTrace(); throw e; } } this.projectLoader.postEvent(newProject, EventType.CREATED, creator.getUserId(), null); return newProject; } @Inject  ProjectManager(final AzkabanProjectLoader azkabanProjectLoader,
      final ProjectLoader loader,
      final ProjectStorageManager projectStorageManager,
      final Props props, final ProjectCache cache); boolean hasFlowTrigger(final Project project, final Flow flow); Props getProps(); List<Project> getUserProjects(final User user); List<Project> getGroupProjects(final User user); List<Project> getUserProjectsByRegex(final User user, final String regexPattern); List<Project> getProjects(); List<Project> getProjectsByRegex(final String regexPattern); Boolean isActiveProject(final int id); Project getProject(final String name); Project getProject(final int id); Project createProject(final String projectName, final String description,
      final User creator); synchronized Project purgeProject(final Project project, final User deleter); synchronized Project removeProject(final Project project, final User deleter); void updateProjectDescription(final Project project, final String description,
      final User modifier); List<ProjectLogEvent> getProjectEventLogs(final Project project,
      final int results, final int skip); Props getPropertiesFromFlowFile(final Flow flow, final String jobName, final String
      flowFileName, final int flowVersion); Props getProperties(final Project project, final Flow flow, final String jobName,
      final String source); Props getJobOverrideProperty(final Project project, final Flow flow, final String jobName,
      final String source); void setJobOverrideProperty(final Project project, final Flow flow, final Props prop,
      final String jobName, final String source, final User modifier); void updateProjectSetting(final Project project); void addProjectProxyUser(final Project project, final String proxyName,
      final User modifier); void removeProjectProxyUser(final Project project, final String proxyName,
      final User modifier); void updateProjectPermission(final Project project, final String name,
      final Permission perm, final boolean group, final User modifier); void removeProjectPermission(final Project project, final String name,
      final boolean group, final User modifier); ProjectFileHandler getProjectFileHandler(final Project project, final int version); Map<String, ValidationReport> uploadProject(final Project project,
      final File archive, final String fileType, final User uploader, final Props additionalProps,
      final String uploaderIPAddr); void updateFlow(final Project project, final Flow flow); void postProjectEvent(final Project project, final EventType type, final String user,
      final String message); boolean loadProjectWhiteList(); void setProjectEventStatus(final String errorMessage, final Map<String, Object> eventData); void postScheduleEvent(final Project project, final azkaban.spi.EventType type, final User user, final Schedule schedule, final String errorMessage);  }
@Test public void testCreateProjectsWithDifferentCases() { final String projectName = "mytestproject"; final String projectDescription = "This is my new project with lower cases."; final User user = new User("testUser1"); when(this.projectLoader.createNewProject(projectName, projectDescription, user)) .thenReturn(new Project(1, projectName)); this.manager.createProject(projectName, projectDescription, user); final String projectName2 = "MYTESTPROJECT"; final String projectDescription2 = "This is my new project with UPPER CASES."; assertThatThrownBy( () -> this.manager.createProject(projectName2, projectDescription2, user)) .isInstanceOf(ProjectManagerException.class) .hasMessageContaining( "Project already exists."); }