Package org.guvnor.common.services.project.backend.server

Source Code of org.guvnor.common.services.project.backend.server.ProjectServiceImpl

/*
* Copyright 2012 JBoss Inc
*
* 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.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.ContextNotActiveException;
import javax.enterprise.event.Event;
import javax.inject.Inject;
import javax.inject.Named;

import org.apache.commons.lang.StringUtils;
import org.drools.workbench.models.datamodel.imports.Import;
import org.guvnor.common.services.backend.config.SafeSessionInfo;
import org.guvnor.common.services.backend.exceptions.ExceptionUtilities;
import org.guvnor.common.services.backend.file.LinkedMetaInfFolderFilter;
import org.guvnor.common.services.project.backend.server.utils.IdentifierUtils;
import org.guvnor.common.services.project.builder.events.InvalidateDMOProjectCacheEvent;
import org.guvnor.common.services.project.events.DeleteProjectEvent;
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.model.ProjectImports;
import org.guvnor.common.services.project.service.KModuleService;
import org.guvnor.common.services.project.service.POMService;
import org.guvnor.common.services.project.service.PackageAlreadyExistsException;
import org.guvnor.common.services.project.service.ProjectService;
import org.guvnor.common.services.shared.metadata.MetadataService;
import org.guvnor.common.services.shared.metadata.model.Metadata;
import org.guvnor.common.services.workingset.client.model.WorkingSetSettings;
import org.jboss.errai.bus.server.annotations.Service;
import org.uberfire.backend.repositories.Repository;
import org.uberfire.backend.server.config.ConfigGroup;
import org.uberfire.backend.server.config.ConfigItem;
import org.uberfire.backend.server.config.ConfigType;
import org.uberfire.backend.server.config.ConfigurationFactory;
import org.uberfire.backend.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.base.options.CommentedOption;
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.Identity;
import org.uberfire.security.impl.IdentityImpl;

@Service
@ApplicationScoped
public class ProjectServiceImpl
        implements ProjectService {

    private static final String SOURCE_FILENAME = "src";

    private static final String POM_PATH = "pom.xml";
    private static final String PROJECT_IMPORTS_PATH = "project.imports";
    private static final String KMODULE_PATH = "src/main/resources/META-INF/kmodule.xml";
    private static final String PROJECT_CATEGORIES_PATH = "categories.xml";

    private static final String MAIN_SRC_PATH = "src/main/java";
    private static final String TEST_SRC_PATH = "src/test/java";
    private static final String MAIN_RESOURCES_PATH = "src/main/resources";
    private static final String TEST_RESOURCES_PATH = "src/test/resources";

    private static String[] sourcePaths = { MAIN_SRC_PATH, MAIN_RESOURCES_PATH, TEST_SRC_PATH, TEST_RESOURCES_PATH };

    private IOService ioService;

    private POMService pomService;
    private KModuleService kModuleService;
    private MetadataService metadataService;
    private ProjectConfigurationContentHandler projectConfigurationContentHandler;

    private ConfigurationService configurationService;
    private ConfigurationFactory configurationFactory;

    private Event<NewProjectEvent> newProjectEvent;
    private Event<NewPackageEvent> newPackageEvent;

    private Event<RenameProjectEvent> renameProjectEvent;
    private Event<DeleteProjectEvent> deleteProjectEvent;

    private Event<InvalidateDMOProjectCacheEvent> invalidateDMOCache;

    private Identity identity;
    private SessionInfo sessionInfo;

    public ProjectServiceImpl() {
        // Boilerplate sacrifice for Weld
    }

    @Inject
    public ProjectServiceImpl( final @Named("ioStrategy") IOService ioService,
                               final POMService pomService,
                               final KModuleService kModuleService,
                               final MetadataService metadataService,
                               final ProjectConfigurationContentHandler projectConfigurationContentHandler,
                               final ConfigurationService configurationService,
                               final ConfigurationFactory configurationFactory,
                               final Event<NewProjectEvent> newProjectEvent,
                               final Event<NewPackageEvent> newPackageEvent,
                               final Event<RenameProjectEvent> renameProjectEvent,
                               final Event<DeleteProjectEvent> deleteProjectEvent,
                               final Event<InvalidateDMOProjectCacheEvent> invalidateDMOCache,
                               final Identity identity,
                               final SessionInfo sessionInfo ) {
        this.ioService = ioService;
        this.pomService = pomService;
        this.kModuleService = kModuleService;
        this.metadataService = metadataService;
        this.projectConfigurationContentHandler = projectConfigurationContentHandler;
        this.configurationService = configurationService;
        this.configurationFactory = configurationFactory;
        this.newProjectEvent = newProjectEvent;
        this.newPackageEvent = newPackageEvent;
        this.renameProjectEvent = renameProjectEvent;
        this.deleteProjectEvent = deleteProjectEvent;
        this.invalidateDMOCache = invalidateDMOCache;
        this.identity = identity;
        this.sessionInfo = new SafeSessionInfo(sessionInfo);
    }

    @Override
    public WorkingSetSettings loadWorkingSetConfig( final Path project ) {
        //TODO {porcelli}
        return new WorkingSetSettings();
    }

    @Override
    public Project resolveProject( final Path resource ) {
        try {
            //Null resource paths cannot resolve to a Project
            if ( resource == null ) {
                return null;
            }

            //Check if resource is the project root
            org.uberfire.java.nio.file.Path path = Paths.convert( resource ).normalize();

            //A project root is the folder containing the pom.xml file. This will be the parent of the "src" folder
            if ( Files.isRegularFile( path ) ) {
                path = path.getParent();
            }
            if ( hasPom( path ) && hasKModule( path ) ) {
                return makeProject( path );
            }
            while ( path.getNameCount() > 0 && !path.getFileName().toString().equals( SOURCE_FILENAME ) ) {
                path = path.getParent();
            }
            if ( path.getNameCount() == 0 ) {
                return null;
            }
            path = path.getParent();
            if ( path.getNameCount() == 0 || path == null ) {
                return null;
            }
            if ( !hasPom( path ) ) {
                return null;
            }
            if ( !hasKModule( path ) ) {
                return null;
            }
            return makeProject( path );

        } catch ( Exception e ) {
            throw ExceptionUtilities.handleException( e );
        }
    }

    private Project makeProject( final org.uberfire.java.nio.file.Path nioProjectRootPath ) {
        final Path projectRootPath = Paths.convert( nioProjectRootPath );
        final Project project = simpleProjectInstance( nioProjectRootPath );

        //Copy in Security Roles required to access this resource
        final ConfigGroup projectConfiguration = findProjectConfig( projectRootPath );
        if ( projectConfiguration != null ) {
            ConfigItem<List<String>> roles = projectConfiguration.getConfigItem( "security:roles" );
            if ( roles != null ) {
                for ( String role : roles.getValue() ) {
                    project.getRoles().add( role );
                }
            }
        }
        return project;
    }

    public Project simpleProjectInstance( final org.uberfire.java.nio.file.Path nioProjectRootPath ) {
        final Path projectRootPath = Paths.convert( nioProjectRootPath );

        return new Project( projectRootPath,
                            Paths.convert( nioProjectRootPath.resolve( POM_PATH ) ),
                            Paths.convert( nioProjectRootPath.resolve( KMODULE_PATH ) ),
                            Paths.convert( nioProjectRootPath.resolve( PROJECT_IMPORTS_PATH ) ),
                            projectRootPath.getFileName() );
    }

    @Override
    public Package resolvePackage( final Path resource ) {
        try {
            //Null resource paths cannot resolve to a Project
            if ( resource == null ) {
                return null;
            }

            //If Path is not within a Project we cannot resolve a package
            final Project project = resolveProject( resource );
            if ( project == null ) {
                return null;
            }

            //pom.xml and kmodule.xml are not inside packages
            if ( isPom( resource ) || isKModule( resource ) ) {
                return null;
            }

            return makePackage( project,
                                resource );

        } catch ( Exception e ) {
            throw ExceptionUtilities.handleException( e );
        }
    }

    @Override
    public Set<Package> resolvePackages( final Project project ) {
        final Set<Package> packages = new HashSet<Package>();
        final Set<String> packageNames = new HashSet<String>();
        if ( project == null ) {
            return packages;
        }
        //Build a set of all package names across /src/main/java, /src/main/resources, /src/test/java and /src/test/resources paths
        //It is possible (if the project was not created within the workbench that some packages only exist in certain paths)
        final Path projectRoot = project.getRootPath();
        final org.uberfire.java.nio.file.Path nioProjectRootPath = Paths.convert( projectRoot );
        for ( String src : sourcePaths ) {
            final org.uberfire.java.nio.file.Path nioPackageRootSrcPath = nioProjectRootPath.resolve( src );
            packageNames.addAll( getPackageNames( nioProjectRootPath,
                                                  nioPackageRootSrcPath,
                                                  true,
                                                  true,
                                                  true ) );
        }

        //Construct Package objects for each package name
        final java.util.Set<String> resolvedPackages = new java.util.HashSet<String>();
        for ( String packagePathSuffix : packageNames ) {
            for ( String src : sourcePaths ) {
                final org.uberfire.java.nio.file.Path nioPackagePath = nioProjectRootPath.resolve( src ).resolve( packagePathSuffix );
                if ( Files.exists( nioPackagePath ) && !resolvedPackages.contains( packagePathSuffix ) ) {
                    packages.add( resolvePackage( Paths.convert( nioPackagePath ) ) );
                    resolvedPackages.add( packagePathSuffix );
                }
            }
        }

        return packages;
    }

    @Override
    public Set<Package> resolvePackages( final Package pkg ) {
        final Set<Package> packages = new HashSet<Package>();
        final Set<String> packageNames = new HashSet<String>();
        if ( pkg == null ) {
            return packages;
        }

        //Build a set of all package names across /src/main/java, /src/main/resources, /src/test/java and /src/test/resources paths
        //It is possible (if the project was not created within the workbench that some packages only exist in certain paths)

        final Path projectRoot = pkg.getProjectRootPath();
        final org.uberfire.java.nio.file.Path nioProjectRootPath = Paths.convert( projectRoot );

        for ( String src : sourcePaths ) {
            final org.uberfire.java.nio.file.Path nioPackageRootSrcPath = nioProjectRootPath.resolve( src ).resolve( resolvePkgName( pkg.getCaption() ) );
            packageNames.addAll( getPackageNames( nioProjectRootPath,
                                                  nioPackageRootSrcPath,
                                                  false,
                                                  true,
                                                  false ) );
        }

        //Construct Package objects for each package name
        final java.util.Set<String> resolvedPackages = new java.util.HashSet<String>();
        for ( String packagePathSuffix : packageNames ) {
            for ( String src : sourcePaths ) {
                final org.uberfire.java.nio.file.Path nioPackagePath = nioProjectRootPath.resolve( src ).resolve( packagePathSuffix );
                if ( Files.exists( nioPackagePath ) && !resolvedPackages.contains( packagePathSuffix ) ) {
                    packages.add( resolvePackage( Paths.convert( nioPackagePath ) ) );
                    resolvedPackages.add( packagePathSuffix );
                }
            }
        }

        return packages;
    }

    @Override
    public Package resolveDefaultPackage( final Project project ) {
        final Set<String> packageNames = new HashSet<String>();
        if ( project == null ) {
            return null;
        }
        //Build a set of all package names across /src/main/java, /src/main/resources, /src/test/java and /src/test/resources paths
        //It is possible (if the project was not created within the workbench that some packages only exist in certain paths)
        final Path projectRoot = project.getRootPath();
        final org.uberfire.java.nio.file.Path nioProjectRootPath = Paths.convert( projectRoot );
        for ( String src : sourcePaths ) {
            final org.uberfire.java.nio.file.Path nioPackageRootSrcPath = nioProjectRootPath.resolve( src );
            packageNames.addAll( getPackageNames( nioProjectRootPath,
                                                  nioPackageRootSrcPath,
                                                  true,
                                                  true,
                                                  false ) );
        }

        //Construct Package objects for each package name
        final java.util.Set<String> resolvedPackages = new java.util.HashSet<String>();
        for ( String packagePathSuffix : packageNames ) {
            for ( String src : sourcePaths ) {
                final org.uberfire.java.nio.file.Path nioPackagePath = nioProjectRootPath.resolve( src ).resolve( packagePathSuffix );
                if ( Files.exists( nioPackagePath ) && !resolvedPackages.contains( packagePathSuffix ) ) {
                    return resolvePackage( Paths.convert( nioPackagePath ) );
                }
            }
        }

        return null;
    }

    @Override
    public Package resolveParentPackage( final Package pkg ) {
        final Set<String> packageNames = new HashSet<String>();

        final org.uberfire.java.nio.file.Path nioProjectRootPath = Paths.convert( pkg.getProjectRootPath() );
        packageNames.addAll( getPackageNames( nioProjectRootPath, Paths.convert( pkg.getPackageMainSrcPath() ).getParent(), true, false, false ) );

        //Construct Package objects for each package name
        for ( String packagePathSuffix : packageNames ) {
            for ( String src : sourcePaths ) {
                if ( packagePathSuffix == null ) {
                    return null;
                }
                final org.uberfire.java.nio.file.Path nioPackagePath = nioProjectRootPath.resolve( src ).resolve( packagePathSuffix );
                if ( Files.exists( nioPackagePath ) ) {
                    return resolvePackage( Paths.convert( nioPackagePath ) );
                }
            }
        }

        return null;
    }

    private String resolvePkgName( final String caption ) {
        if ( caption.equals( "<default>" ) ) {
            return "";
        }
        return caption.replaceAll( "\\.", "/" );
    }

    private Set<String> getPackageNames( final org.uberfire.java.nio.file.Path nioProjectRootPath,
                                         final org.uberfire.java.nio.file.Path nioPackageSrcPath,
                                         final boolean includeDefault,
                                         final boolean includeChild,
                                         final boolean recursive ) {
        final Set<String> packageNames = new HashSet<String>();
        if ( !Files.exists( nioPackageSrcPath ) ) {
            return packageNames;
        }
        if ( includeDefault || recursive ) {
            packageNames.add( getPackagePathSuffix( nioProjectRootPath,
                                                    nioPackageSrcPath ) );

        }

        if ( !includeChild ) {
            return packageNames;
        }

        final LinkedMetaInfFolderFilter metaDataFileFilter = new LinkedMetaInfFolderFilter();
        final DirectoryStream<org.uberfire.java.nio.file.Path> nioChildPackageSrcPaths = ioService.newDirectoryStream( nioPackageSrcPath,
                                                                                                                       metaDataFileFilter );
        for ( org.uberfire.java.nio.file.Path nioChildPackageSrcPath : nioChildPackageSrcPaths ) {
            if ( Files.isDirectory( nioChildPackageSrcPath ) ) {
                if ( recursive ) {
                    packageNames.addAll( getPackageNames( nioProjectRootPath,
                                                          nioChildPackageSrcPath,
                                                          includeDefault,
                                                          includeChild,
                                                          recursive ) );
                } else {
                    packageNames.add( getPackagePathSuffix( nioProjectRootPath,
                                                            nioChildPackageSrcPath ) );
                }

            }
        }

        return packageNames;
    }

    private String getPackagePathSuffix( final org.uberfire.java.nio.file.Path nioProjectRootPath,
                                         final org.uberfire.java.nio.file.Path nioPackagePath ) {
        final org.uberfire.java.nio.file.Path nioMainSrcPath = nioProjectRootPath.resolve( MAIN_SRC_PATH );
        final org.uberfire.java.nio.file.Path nioTestSrcPath = nioProjectRootPath.resolve( TEST_SRC_PATH );
        final org.uberfire.java.nio.file.Path nioMainResourcesPath = nioProjectRootPath.resolve( MAIN_RESOURCES_PATH );
        final org.uberfire.java.nio.file.Path nioTestResourcesPath = nioProjectRootPath.resolve( TEST_RESOURCES_PATH );

        String packageName = null;
        org.uberfire.java.nio.file.Path packagePath = null;
        if ( nioPackagePath.startsWith( nioMainSrcPath ) ) {
            packagePath = nioMainSrcPath.relativize( nioPackagePath );
            packageName = packagePath.toString();
        } else if ( nioPackagePath.startsWith( nioTestSrcPath ) ) {
            packagePath = nioTestSrcPath.relativize( nioPackagePath );
            packageName = packagePath.toString();
        } else if ( nioPackagePath.startsWith( nioMainResourcesPath ) ) {
            packagePath = nioMainResourcesPath.relativize( nioPackagePath );
            packageName = packagePath.toString();
        } else if ( nioPackagePath.startsWith( nioTestResourcesPath ) ) {
            packagePath = nioTestResourcesPath.relativize( nioPackagePath );
            packageName = packagePath.toString();
        }

        return packageName;
    }

    private Package makePackage( final Project project,
                                 final Path resource ) {
        final Path projectRoot = project.getRootPath();
        final org.uberfire.java.nio.file.Path nioProjectRoot = Paths.convert( projectRoot );
        final org.uberfire.java.nio.file.Path nioMainSrcPath = nioProjectRoot.resolve( MAIN_SRC_PATH );
        final org.uberfire.java.nio.file.Path nioTestSrcPath = nioProjectRoot.resolve( TEST_SRC_PATH );
        final org.uberfire.java.nio.file.Path nioMainResourcesPath = nioProjectRoot.resolve( MAIN_RESOURCES_PATH );
        final org.uberfire.java.nio.file.Path nioTestResourcesPath = nioProjectRoot.resolve( TEST_RESOURCES_PATH );

        org.uberfire.java.nio.file.Path nioResource = Paths.convert( resource );

        if ( Files.isRegularFile( nioResource ) ) {
            nioResource = nioResource.getParent();
        }

        String packageName = null;
        org.uberfire.java.nio.file.Path packagePath = null;
        if ( nioResource.startsWith( nioMainSrcPath ) ) {
            packagePath = nioMainSrcPath.relativize( nioResource );
            packageName = packagePath.toString().replaceAll( "/",
                                                             "." );
        } else if ( nioResource.startsWith( nioTestSrcPath ) ) {
            packagePath = nioTestSrcPath.relativize( nioResource );
            packageName = packagePath.toString().replaceAll( "/",
                                                             "." );
        } else if ( nioResource.startsWith( nioMainResourcesPath ) ) {
            packagePath = nioMainResourcesPath.relativize( nioResource );
            packageName = packagePath.toString().replaceAll( "/",
                                                             "." );
        } else if ( nioResource.startsWith( nioTestResourcesPath ) ) {
            packagePath = nioTestResourcesPath.relativize( nioResource );
            packageName = packagePath.toString().replaceAll( "/",
                                                             "." );
        }

        //Resource was not inside a package
        if ( packageName == null ) {
            return null;
        }

        final Path mainSrcPath = Paths.convert( nioMainSrcPath.resolve( packagePath ) );
        final Path testSrcPath = Paths.convert( nioTestSrcPath.resolve( packagePath ) );
        final Path mainResourcesPath = Paths.convert( nioMainResourcesPath.resolve( packagePath ) );
        final Path testResourcesPath = Paths.convert( nioTestResourcesPath.resolve( packagePath ) );

        final String displayName = getPackageDisplayName( packageName );

        final Package pkg = new Package( project.getRootPath(),
                                         mainSrcPath,
                                         testSrcPath,
                                         mainResourcesPath,
                                         testResourcesPath,
                                         packageName,
                                         displayName,
                                         getPackageRelativeCaption( displayName, resource.getFileName() ) );
        return pkg;
    }

    private String getPackageDisplayName( final String packageName ) {
        return packageName.isEmpty() ? "<default>" : packageName;
    }

    private String getPackageRelativeCaption( final String displayName,
                                              final String relativeName ) {
        return displayName.equals( "<default>" ) ? "<default>" : relativeName;
    }

    @Override
    public boolean isPom( final Path resource ) {
        try {
            //Null resource paths cannot resolve to a Project
            if ( resource == null ) {
                return false;
            }

            //Check if path equals pom.xml
            final Project project = resolveProject( resource );

            //It's possible that the Incremental Build attempts to act on a Project file before the project has been fully created.
            //This should be a short-term issue that will be resolved when saving a project batches pom.xml, kmodule.xml and project.imports
            //etc into a single git-batch. At present they are saved individually leading to multiple Incremental Build requests.
            if ( project == null ) {
                return false;
            }

            final org.uberfire.java.nio.file.Path path = Paths.convert( resource ).normalize();
            final org.uberfire.java.nio.file.Path pomFilePath = Paths.convert( project.getPomXMLPath() );
            return path.startsWith( pomFilePath );

        } catch ( Exception e ) {
            throw ExceptionUtilities.handleException( e );
        }
    }

    @Override
    public boolean isKModule( final Path resource ) {
        try {
            //Null resource paths cannot resolve to a Project
            if ( resource == null ) {
                return false;
            }

            //Check if path equals kmodule.xml
            final Project project = resolveProject( resource );
            //It's possible that the Incremental Build attempts to act on a Project file before the project has been fully created.
            //This should be a short-term issue that will be resolved when saving a project batches pom.xml, kmodule.xml and project.imports
            //etc into a single git-batch. At present they are saved individually leading to multiple Incremental Build requests.
            if ( project == null ) {
                return false;
            }

            final org.uberfire.java.nio.file.Path path = Paths.convert( resource ).normalize();
            final org.uberfire.java.nio.file.Path kmoduleFilePath = Paths.convert( project.getKModuleXMLPath() );
            return path.startsWith( kmoduleFilePath );

        } catch ( Exception e ) {
            throw ExceptionUtilities.handleException( e );
        }
    }

    @Override
    public Project newProject( final Repository repository,
                               final String projectName,
                               final POM pom,
                               final String baseUrl ) {
        try {
            //Projects are always created in the FS root
            final Path fsRoot = repository.getRoot();
            final Path projectRootPath = Paths.convert( Paths.convert( fsRoot ).resolve( projectName ) );

            ioService.startBatch( makeCommentedOption( "New project [" + projectName + "]" ) );

            //Set-up project structure and KModule.xml
            kModuleService.setUpKModuleStructure( projectRootPath );

            //Create POM.xml
            pomService.create( projectRootPath,
                               baseUrl,
                               pom );

            //Create Project configuration
            final Path projectConfigPath = Paths.convert( Paths.convert( projectRootPath ).resolve( PROJECT_IMPORTS_PATH ) );

            if ( ioService.exists( Paths.convert( projectConfigPath ) ) ) {
                throw new FileAlreadyExistsException( projectConfigPath.toString() );
            }
            ioService.write( Paths.convert( projectConfigPath ),
                             projectConfigurationContentHandler.toString( createProjectImports() ) );

            //Raise an event for the new project
            final Project project = resolveProject( projectRootPath );
            newProjectEvent.fire( new NewProjectEvent( project, sessionInfo ) );

            //Create a default workspace based on the GAV
            final String legalJavaGroupId[] = IdentifierUtils.convertMavenIdentifierToJavaIdentifier( pom.getGav().getGroupId().split( "\\.",
                                                                                                                                       -1 ) );
            final String legalJavaArtifactId[] = IdentifierUtils.convertMavenIdentifierToJavaIdentifier( pom.getGav().getArtifactId().split( "\\.",
                                                                                                                                             -1 ) );
            final String defaultWorkspacePath = StringUtils.join( legalJavaGroupId,
                                                                  "/" ) + "/" + StringUtils.join( legalJavaArtifactId,
                                                                                                  "/" );
            final Path defaultPackagePath = Paths.convert( Paths.convert( projectRootPath ).resolve( MAIN_RESOURCES_PATH ) );
            final Package defaultPackage = resolvePackage( defaultPackagePath );
            final Package defaultWorkspacePackage = doNewPackage( defaultPackage,
                                                                  defaultWorkspacePath,
                                                                  false );

            //Raise an event for the new project's default workspace
            newPackageEvent.fire( new NewPackageEvent( defaultWorkspacePackage ) );

            //Return new project
            return project;

        } catch ( Exception e ) {
            throw ExceptionUtilities.handleException( e );
        } finally {
            ioService.endBatch();
        }
    }

    private ProjectImports createProjectImports() {
        ProjectImports imports = new ProjectImports();
        imports.getImports().addImport( new Import( "java.lang.Number" ) );
        return imports;
    }

    @Override
    public Package newPackage( final Package parentPackage,
                               final String packageName ) {
        try {
            //Make new Package
            final Package newPackage = doNewPackage( 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 );
        }
    }

    private Package doNewPackage( final Package parentPackage,
                                  final String packageName,
                                  final boolean startBatch ) {
        //If the package name contains separators, create sub-folders
        String newPackageName = packageName.toLowerCase();
        if ( newPackageName.contains( "." ) ) {
            newPackageName = newPackageName.replace( ".",
                                                     "/" );
        }

        //Return new package
        final Path mainSrcPath = parentPackage.getPackageMainSrcPath();
        final Path testSrcPath = parentPackage.getPackageTestSrcPath();
        final Path mainResourcesPath = parentPackage.getPackageMainResourcesPath();
        final Path testResourcesPath = parentPackage.getPackageTestResourcesPath();

        Path pkgPath = null;

        try {

            if ( startBatch ) {
                ioService.startBatch( makeCommentedOption( "New package [" + packageName + "]" ) );
            }

            final org.uberfire.java.nio.file.Path nioMainSrcPackagePath = Paths.convert( mainSrcPath ).resolve( newPackageName );
            if ( !Files.exists( nioMainSrcPackagePath ) ) {
                pkgPath = Paths.convert( ioService.createDirectory( nioMainSrcPackagePath ) );
            }
            final org.uberfire.java.nio.file.Path nioTestSrcPackagePath = Paths.convert( testSrcPath ).resolve( newPackageName );
            if ( !Files.exists( nioTestSrcPackagePath ) ) {
                pkgPath = Paths.convert( ioService.createDirectory( nioTestSrcPackagePath ) );
            }
            final org.uberfire.java.nio.file.Path nioMainResourcesPackagePath = Paths.convert( mainResourcesPath ).resolve( newPackageName );
            if ( !Files.exists( nioMainResourcesPackagePath ) ) {
                pkgPath = Paths.convert( ioService.createDirectory( nioMainResourcesPackagePath ) );
            }
            final org.uberfire.java.nio.file.Path nioTestResourcesPackagePath = Paths.convert( testResourcesPath ).resolve( newPackageName );
            if ( !Files.exists( nioTestResourcesPackagePath ) ) {
                pkgPath = Paths.convert( ioService.createDirectory( nioTestResourcesPackagePath ) );
            }

            //If pkgPath is null the package already existed in src/main/java, scr/main/resources, src/test/java and src/test/resources
            if ( pkgPath == null ) {
                throw new PackageAlreadyExistsException( packageName );
            }

            //Return new package
            final Package newPackage = resolvePackage( pkgPath );
            return newPackage;

        } catch ( Exception e ) {
            throw ExceptionUtilities.handleException( e );
        } finally {
            if ( startBatch ) {
                ioService.endBatch();
            }
        }
    }

    private boolean hasPom( final org.uberfire.java.nio.file.Path path ) {
        final org.uberfire.java.nio.file.Path pomPath = path.resolve( POM_PATH );
        return Files.exists( pomPath );
    }

    private boolean hasKModule( final org.uberfire.java.nio.file.Path path ) {
        final org.uberfire.java.nio.file.Path kmodulePath = path.resolve( KMODULE_PATH );
        return Files.exists( kmodulePath );
    }

    @Override
    public ProjectImports load( final Path path ) {
        final String content = ioService.readAllString( Paths.convert( path ) );
        return projectConfigurationContentHandler.toModel( content );
    }

    @Override
    public Path save( final Path resource,
                      final ProjectImports projectImports,
                      final Metadata metadata,
                      final String comment ) {
        try {
            ioService.write( Paths.convert( resource ),
                             projectConfigurationContentHandler.toString( projectImports ),
                             metadataService.setUpAttributes( resource,
                                                              metadata ) );

            //The pom.xml, kmodule.xml and project.imports are all saved from ProjectScreenPresenter
            //We only raise InvalidateDMOProjectCacheEvent and ResourceUpdatedEvent(pom.xml) events once
            //in POMService.save to avoid duplicating events (and re-construction of DMO).

            return resource;

        } catch ( Exception e ) {
            throw ExceptionUtilities.handleException( e );
        }
    }

    private CommentedOption makeCommentedOption( final String commitMessage ) {
        final String name = getIdentityName();
        final Date when = new Date();
        final CommentedOption co = new CommentedOption( getSessionId(),
                                                        name,
                                                        null,
                                                        commitMessage,
                                                        when );
        return co;
    }

    protected String getIdentityName() {
        try {
            return identity.getName();
        } catch ( ContextNotActiveException e ) {
            return "unknown";
        }
    }

    protected String getSessionId() {
        try {
            return sessionInfo.getId();
        } catch ( ContextNotActiveException e ) {
            return "--";
        catch ( Exception e ) {
            return "--";
        }
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public void addRole( final Project project,
                         final String role ) {
        ConfigGroup thisProjectConfig = findProjectConfig( project.getRootPath() );

        if ( thisProjectConfig == null ) {
            thisProjectConfig = configurationFactory.newConfigGroup( ConfigType.PROJECT,
                                                                     project.getRootPath().toURI(),
                                                                     "Project '" + project.getProjectName() + "' configuration" );
            thisProjectConfig.addConfigItem( configurationFactory.newConfigItem( "security:roles",
                                                                                 new ArrayList<String>() ) );
            configurationService.addConfiguration( thisProjectConfig );
        }

        if ( thisProjectConfig != null ) {
            final ConfigItem<List> roles = thisProjectConfig.getConfigItem( "security:roles" );
            roles.getValue().add( role );

            configurationService.updateConfiguration( thisProjectConfig );

        } else {
            throw new IllegalArgumentException( "Project " + project.getProjectName() + " not found" );
        }
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public void removeRole( final Project project,
                            final String role ) {
        final ConfigGroup thisProjectConfig = findProjectConfig( project.getRootPath() );

        if ( thisProjectConfig != null ) {
            final ConfigItem<List> roles = thisProjectConfig.getConfigItem( "security:roles" );
            roles.getValue().remove( role );

            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 = resolveProject( oldProjectDir );

            content.setName( newName );
            final Path newPathToPomXML = Paths.convert( newProjectPath.resolve( "pom.xml" ) );
            try {
                ioService.startBatch();
                ioService.move( projectDirectory, newProjectPath, makeCommentedOption( comment ) );
                pomService.save( newPathToPomXML, content, null, comment );
            } catch ( final Exception e ) {
                throw e;
            } finally {
                ioService.endBatch();
            }
            final Project newProject = resolveProject( Paths.convert( newProjectPath ) );
            invalidateDMOCache.fire( new InvalidateDMOProjectCacheEvent( sessionInfo, oldProject, oldProjectDir ) );
            renameProjectEvent.fire( new RenameProjectEvent( oldProject, newProject ) );

            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 = resolveProject( Paths.convert( projectDirectory ) );

            ioService.delete( projectDirectory, StandardDeleteOption.NON_EMPTY_DIRECTORIES, new CommentedOption( getSessionId(), getIdentityName(), null, comment ) );
            deleteProjectEvent.fire( new DeleteProjectEvent( project2Delete ) );
        } 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.xml" ) );
            try {
                ioService.startBatch();
                ioService.copy( projectDirectory, newProjectPath, makeCommentedOption( comment ) );
                pomService.save( newPathToPomXML, content, null, comment );
            } catch ( final Exception e ) {
                throw e;
            } finally {
                ioService.endBatch();
            }
            final Project newProject = resolveProject( Paths.convert( newProjectPath ) );
            newProjectEvent.fire( new NewProjectEvent( newProject, sessionInfo ) );

        } catch ( final Exception e ) {
            throw ExceptionUtilities.handleException( e );
        }
    }

    protected ConfigGroup findProjectConfig( final Path projectRoot ) {
        final Collection<ConfigGroup> groups = configurationService.getConfiguration( ConfigType.PROJECT );
        if ( groups != null ) {
            for ( ConfigGroup groupConfig : groups ) {
                if ( groupConfig.getName().equals( projectRoot.toURI() ) ) {
                    return groupConfig;
                }
            }
        }
        return null;
    }
}
TOP

Related Classes of org.guvnor.common.services.project.backend.server.ProjectServiceImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.