/* * Copyright 2014 Red Hat, Inc. and/or its affiliates. * * 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 org.guvnor.common.services.project.backend.server; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.enterprise.event.Event; import org.guvnor.common.services.backend.config.SafeSessionInfo; import org.guvnor.common.services.backend.exceptions.ExceptionUtilities; import org.guvnor.common.services.backend.util.CommentedOptionFactory; import org.guvnor.common.services.project.builder.events.InvalidateDMOProjectCacheEvent; import org.guvnor.common.services.project.events.NewPackageEvent; import org.guvnor.common.services.project.events.NewProjectEvent; import org.guvnor.common.services.project.events.RenameProjectEvent; import org.guvnor.common.services.project.model.POM; import org.guvnor.common.services.project.model.Package; import org.guvnor.common.services.project.model.Project; import org.guvnor.common.services.project.project.ProjectFactory; import org.guvnor.common.services.project.service.POMService; import org.guvnor.common.services.project.service.ProjectServiceCore; import org.guvnor.common.services.workingset.client.model.WorkingSetSettings; import org.guvnor.structure.backend.backcompat.BackwardCompatibleUtil; import org.guvnor.structure.repositories.Repository; import org.guvnor.structure.server.config.ConfigGroup; import org.guvnor.structure.server.config.ConfigItem; import org.guvnor.structure.server.config.ConfigType; import org.guvnor.structure.server.config.ConfigurationFactory; import org.guvnor.structure.server.config.ConfigurationService; import org.uberfire.backend.server.util.Paths; import org.uberfire.backend.vfs.Path; import org.uberfire.io.IOService; import org.uberfire.java.nio.file.DirectoryStream; import org.uberfire.java.nio.file.FileAlreadyExistsException; import org.uberfire.java.nio.file.Files; import org.uberfire.java.nio.file.StandardDeleteOption; import org.uberfire.rpc.SessionInfo; import org.uberfire.security.authz.AuthorizationManager; import static org.guvnor.common.services.project.utils.ProjectResourcePaths.POM_PATH; public abstract class AbstractProjectService<T extends Project> implements ProjectServiceCore<T>, ProjectFactory<T> { protected IOService ioService; protected POMService pomService; private ConfigurationService configurationService; private ConfigurationFactory configurationFactory; protected Event<NewProjectEvent> newProjectEvent; protected Event<NewPackageEvent> newPackageEvent; private Event<RenameProjectEvent> renameProjectEvent; private Event<InvalidateDMOProjectCacheEvent> invalidateDMOCache; private AuthorizationManager authorizationManager; private BackwardCompatibleUtil backward; protected CommentedOptionFactory commentedOptionFactory; protected ResourceResolver resourceResolver; protected SessionInfo sessionInfo; protected AbstractProjectService() { } public AbstractProjectService(final IOService ioService, final POMService pomService, final ConfigurationService configurationService, final ConfigurationFactory configurationFactory, final Event<NewProjectEvent> newProjectEvent, final Event<NewPackageEvent> newPackageEvent, final Event<RenameProjectEvent> renameProjectEvent, final Event<InvalidateDMOProjectCacheEvent> invalidateDMOCache, final SessionInfo sessionInfo, final AuthorizationManager authorizationManager, final BackwardCompatibleUtil backward, final CommentedOptionFactory commentedOptionFactory, final ResourceResolver resourceResolver) { this.ioService = ioService; this.pomService = pomService; this.configurationService = configurationService; this.configurationFactory = configurationFactory; this.newProjectEvent = newProjectEvent; this.newPackageEvent = newPackageEvent; this.renameProjectEvent = renameProjectEvent; this.invalidateDMOCache = invalidateDMOCache; this.authorizationManager = authorizationManager; this.backward = backward; this.commentedOptionFactory = commentedOptionFactory; this.resourceResolver = resourceResolver; this.sessionInfo = new SafeSessionInfo(sessionInfo); } @Override public WorkingSetSettings loadWorkingSetConfig(final Path project) { //TODO {porcelli} return new WorkingSetSettings(); } @Override public Set<Project> getAllProjects(Repository repository, String branch) { return getProjects(repository, branch, false); } @Override public Set<Project> getProjects(final Repository repository, String branch) { return getProjects(repository, branch, true); } public Set<Project> getProjects(final Repository repository, String branch, boolean secure) { final Set<Project> authorizedProjects = new HashSet<Project>(); if (repository == null) { return authorizedProjects; } final Path repositoryRoot = repository.getBranchRoot(branch); final DirectoryStream<org.uberfire.java.nio.file.Path> nioRepositoryPaths = ioService.newDirectoryStream(Paths.convert(repositoryRoot)); try { for (org.uberfire.java.nio.file.Path nioRepositoryPath : nioRepositoryPaths) { if (Files.isDirectory(nioRepositoryPath)) { final org.uberfire.backend.vfs.Path projectPath = Paths.convert(nioRepositoryPath); final Project project = resourceResolver.resolveProject(projectPath); if (project != null) { if (!secure || authorizationManager.authorize(project, sessionInfo.getIdentity())) { POM projectPom = pomService.load(project.getPomXMLPath()); project.setPom(projectPom); authorizedProjects.add(project); } } } } } finally { nioRepositoryPaths.close(); } return authorizedProjects; } @Override public Package newPackage(final Package parentPackage, final String packageName) { try { //Make new Package final Package newPackage = resourceResolver.newPackage(parentPackage, packageName, true); //Raise an event for the new package newPackageEvent.fire(new NewPackageEvent(newPackage)); //Return the new package return newPackage; } catch (Exception e) { throw ExceptionUtilities.handleException(e); } } @SuppressWarnings({"rawtypes"}) @Override public void addGroup(final Project project, final String group) { ConfigGroup thisProjectConfig = resourceResolver.findProjectConfig(project.getRootPath()); if (thisProjectConfig == null) { thisProjectConfig = configurationFactory.newConfigGroup(ConfigType.PROJECT, project.getRootPath().toURI(), "Project '" + project.getProjectName() + "' configuration"); thisProjectConfig.addConfigItem(configurationFactory.newConfigItem("security:groups", new ArrayList<String>())); configurationService.addConfiguration(thisProjectConfig); } if (thisProjectConfig != null) { final ConfigItem<List> groups = backward.compat(thisProjectConfig).getConfigItem("security:groups"); groups.getValue().add(group); configurationService.updateConfiguration(thisProjectConfig); } else { throw new IllegalArgumentException("Project " + project.getProjectName() + " not found"); } } @SuppressWarnings({"unchecked", "rawtypes"}) @Override public void removeGroup(final Project project, final String group) { final ConfigGroup thisProjectConfig = resourceResolver.findProjectConfig(project.getRootPath()); if (thisProjectConfig != null) { final ConfigItem<List> groups = backward.compat(thisProjectConfig).getConfigItem("security:groups"); groups.getValue().remove(group); configurationService.updateConfiguration(thisProjectConfig); } else { throw new IllegalArgumentException("Project " + project.getProjectName() + " not found"); } } @Override public Path rename(final Path pathToPomXML, final String newName, final String comment) { try { final org.uberfire.java.nio.file.Path projectDirectory = Paths.convert(pathToPomXML).getParent(); final org.uberfire.java.nio.file.Path newProjectPath = projectDirectory.resolveSibling(newName); final POM content = pomService.load(pathToPomXML); if (newProjectPath.equals(projectDirectory)) { return pathToPomXML; } if (ioService.exists(newProjectPath)) { throw new FileAlreadyExistsException(newProjectPath.toString()); } final Path oldProjectDir = Paths.convert(projectDirectory); final Project oldProject = resourceResolver.resolveProject(oldProjectDir); content.setName(newName); final Path newPathToPomXML = Paths.convert(newProjectPath.resolve(POM_PATH)); try { ioService.startBatch(newProjectPath.getFileSystem()); ioService.move(projectDirectory, newProjectPath, commentedOptionFactory.makeCommentedOption(comment)); pomService.save(newPathToPomXML, content, null, comment); } catch (final Exception e) { throw e; } finally { final Project newProject = resourceResolver.resolveProject(Paths.convert(newProjectPath)); renameProjectEvent.fire(new RenameProjectEvent(oldProject, newProject)); ioService.endBatch(); } invalidateDMOCache.fire(new InvalidateDMOProjectCacheEvent(sessionInfo, oldProject, oldProjectDir)); return newPathToPomXML; } catch (final Exception e) { throw ExceptionUtilities.handleException(e); } } @Override public void delete(final Path pathToPomXML, final String comment) { try { final org.uberfire.java.nio.file.Path projectDirectory = Paths.convert(pathToPomXML).getParent(); final Project project2Delete = resourceResolver.resolveProject(Paths.convert(projectDirectory)); final org.uberfire.java.nio.file.Path parentPom = projectDirectory.getParent().resolve(POM_PATH); POM parent = null; if (ioService.exists(parentPom)) { parent = pomService.load(Paths.convert(parentPom)); } ioService.delete(projectDirectory, StandardDeleteOption.NON_EMPTY_DIRECTORIES, commentedOptionFactory.makeCommentedOption(comment)); //Note we do *not* raise a DeleteProjectEvent here, as that is handled by DeleteProjectObserverBridge if (parent != null) { parent.setPackaging("pom"); parent.getModules().remove(project2Delete.getProjectName()); pomService.save(Paths.convert(parentPom), parent, null, "Removing child module " + project2Delete.getProjectName()); } } catch (final Exception e) { throw ExceptionUtilities.handleException(e); } } @Override public void copy(final Path pathToPomXML, final String newName, final String comment) { try { final org.uberfire.java.nio.file.Path projectDirectory = Paths.convert(pathToPomXML).getParent(); final org.uberfire.java.nio.file.Path newProjectPath = projectDirectory.resolveSibling(newName); final POM content = pomService.load(pathToPomXML); if (newProjectPath.equals(projectDirectory)) { return; } if (ioService.exists(newProjectPath)) { throw new FileAlreadyExistsException(newProjectPath.toString()); } content.setName(newName); final Path newPathToPomXML = Paths.convert(newProjectPath.resolve(POM_PATH)); try { ioService.startBatch(newProjectPath.getFileSystem()); ioService.copy(projectDirectory, newProjectPath, commentedOptionFactory.makeCommentedOption(comment)); pomService.save(newPathToPomXML, content, null, comment); } catch (final Exception e) { throw e; } finally { ioService.endBatch(); } final Project newProject = resourceResolver.resolveProject(Paths.convert(newProjectPath)); newProjectEvent.fire(new NewProjectEvent(newProject, commentedOptionFactory.getSafeSessionId(), commentedOptionFactory.getSafeIdentityName())); } catch (final Exception e) { throw ExceptionUtilities.handleException(e); } } @Override public void reImport(final Path pathToPomXML) { try { final org.uberfire.java.nio.file.Path projectDirectory = Paths.convert(pathToPomXML).getParent(); final Path path = Paths.convert(projectDirectory); final Project project = resourceResolver.resolveProject(path); invalidateDMOCache.fire(new InvalidateDMOProjectCacheEvent(sessionInfo, project, path)); } catch (final Exception e) { throw ExceptionUtilities.handleException(e); } } }