/*
* Copyright 2015 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.
*
* 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.asset.management.backend.service;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.inject.Named;
import org.guvnor.asset.management.model.RepositoryStructureModel;
import org.guvnor.asset.management.service.RepositoryStructureService;
import org.guvnor.common.services.backend.exceptions.ExceptionUtilities;
import org.guvnor.common.services.backend.util.CommentedOptionFactory;
import org.guvnor.common.services.project.model.GAV;
import org.guvnor.common.services.project.model.MavenRepositoryMetadata;
import org.guvnor.common.services.project.model.POM;
import org.guvnor.common.services.project.model.Project;
import org.guvnor.common.services.project.service.DeploymentMode;
import org.guvnor.common.services.project.service.GAVAlreadyExistsException;
import org.guvnor.common.services.project.service.POMService;
import org.guvnor.common.services.project.service.ProjectRepositoryResolver;
import org.guvnor.common.services.project.service.ProjectService;
import org.guvnor.m2repo.backend.server.GuvnorM2Repository;
import org.guvnor.structure.repositories.Repository;
import org.jboss.errai.bus.server.annotations.Service;
import org.uberfire.backend.server.util.Paths;
import org.uberfire.backend.vfs.Path;
import org.uberfire.ext.editor.commons.backend.validation.ValidationUtils;
import org.uberfire.io.IOService;
import org.uberfire.java.nio.file.DirectoryStream;
import org.uberfire.java.nio.file.FileSystem;
import org.uberfire.java.nio.file.Files;
@Service
@ApplicationScoped
public class RepositoryStructureServiceImpl
implements RepositoryStructureService {
private IOService ioService;
private POMService pomService;
private ProjectService<? extends Project> projectService;
private GuvnorM2Repository m2service;
private CommentedOptionFactory optionsFactory;
private ProjectRepositoryResolver repositoryResolver;
private RepositoryStructureModelLoader modelLoader;
private ManagedStatusUpdater managedStatusUpdater;
public RepositoryStructureServiceImpl() {
//Zero-parameter constructor for CDI proxies
}
@Inject
public RepositoryStructureServiceImpl( final @Named( "ioStrategy" ) IOService ioService,
final POMService pomService,
final ProjectService<? extends Project> projectService,
final GuvnorM2Repository m2service,
final CommentedOptionFactory optionsFactory,
final ProjectRepositoryResolver repositoryResolver,
final RepositoryStructureModelLoader modelLoader,
final ManagedStatusUpdater managedStatusUpdater ) {
this.ioService = ioService;
this.pomService = pomService;
this.projectService = projectService;
this.m2service = m2service;
this.optionsFactory = optionsFactory;
this.repositoryResolver = repositoryResolver;
this.modelLoader = modelLoader;
this.managedStatusUpdater = managedStatusUpdater;
}
@Override
public Path initRepositoryStructure( final GAV gav,
final Repository repo,
final DeploymentMode mode ) {
final POM pom = new POM( repo.getAlias(),
repo.getAlias(),
gav,
true );
if ( DeploymentMode.VALIDATED.equals( mode ) ) {
checkRepositories( pom );
}
//Creating the parent pom
final Path fsRoot = repo.getRoot();
final Path pathToPom = pomService.create( fsRoot,
"",
pom );
//Deploying the parent pom artifact,
// it needs to be deployed before the first child is created
m2service.deployParentPom( gav );
managedStatusUpdater.updateManagedStatus( repo,
true );
return pathToPom;
}
@Override
public Path initRepositoryStructure( final POM pom,
final String baseUrl,
final Repository repository,
final boolean multiProject,
final DeploymentMode mode ) {
if ( pom == null || baseUrl == null || repository == null ) {
return null;
}
if ( DeploymentMode.VALIDATED.equals( mode ) ) {
checkRepositories( pom );
}
if ( multiProject ) {
pom.setPackaging( "pom" );
//Creating the parent pom
final Path fsRoot = repository.getRoot();
final Path pathToPom = pomService.create( fsRoot,
baseUrl,
pom );
//Deploying the parent pom artifact,
// it needs to be deployed before the first child is created
m2service.deployParentPom( pom.getGav() );
managedStatusUpdater.updateManagedStatus( repository,
true );
return pathToPom;
} else {
final Project project = projectService.newProject( repository.getBranchRoot( repository.getDefaultBranch() ),
pom,
baseUrl,
mode );
return project.getPomXMLPath();
}
}
private void checkRepositories( final POM pom ) {
// Check is the POM's GAV resolves to any pre-existing artifacts. We don't need to filter
// resolved Repositories by those enabled for the Project since this is a new Project.
final Set<MavenRepositoryMetadata> repositories = repositoryResolver.getRepositoriesResolvingArtifact( pom.getGav() );
if ( repositories.size() > 0 ) {
throw new GAVAlreadyExistsException( pom.getGav(),
repositories );
}
}
@Override
public Repository updateManagedStatus( final Repository repo,
final boolean managed ) {
return managedStatusUpdater.updateManagedStatus( repo,
managed );
}
@Override
public Path convertToMultiProjectStructure( final List<Project> projects,
final GAV parentGav,
final Repository repo,
final boolean updateChildrenGav,
final String comment ) {
if ( projects == null || parentGav == null || repo == null ) {
return null;
}
try {
final Path path = initRepositoryStructure( parentGav,
repo,
DeploymentMode.FORCED );
final POM parentPom = pomService.load( path );
if ( parentPom == null ) {
//uncommon case, the pom was just created.
return null;
}
ioService.startBatch( new FileSystem[]{Paths.convert( path ).getFileSystem()},
optionsFactory.makeCommentedOption( comment != null ? comment : "" ) );
boolean saveParentPom = false;
for ( Project project : projects ) {
final POM pom = pomService.load( project.getPomXMLPath() );
pom.setParent( parentGav );
if ( updateChildrenGav ) {
pom.getGav().setGroupId( parentGav.getGroupId() );
pom.getGav().setVersion( parentGav.getVersion() );
}
pomService.save( project.getPomXMLPath(),
pom,
null,
comment );
parentPom.setPackaging( "pom" );
parentPom.getModules().add( pom.getName() != null ? pom.getName() : pom.getGav().getArtifactId() );
saveParentPom = true;
}
if ( saveParentPom ) {
pomService.save( path,
parentPom,
null,
comment );
}
return path;
} catch ( Exception e ) {
throw ExceptionUtilities.handleException( e );
} finally {
ioService.endBatch();
}
}
@Override
public RepositoryStructureModel load( final Repository repository,
final String branch ) {
return modelLoader.load( repository,
branch,
true );
}
@Override
public RepositoryStructureModel load( final Repository repository,
final String branch,
final boolean includeModules ) {
return modelLoader.load( repository,
branch,
includeModules );
}
@Override
@SuppressWarnings("unused")
public void save( final Path pathToPomXML,
final RepositoryStructureModel model,
final String comment ) {
final FileSystem fs = Paths.convert( pathToPomXML ).getFileSystem();
try {
pomService.save( pathToPomXML,
model.getPOM(),
model.getPOMMetaData(),
comment,
true );
} catch ( final Exception e ) {
throw ExceptionUtilities.handleException( e );
}
}
@Override
public boolean isValidProjectName( final String name ) {
return ValidationUtils.isFileName( name );
}
@Override
public boolean isValidGroupId( final String groupId ) {
if ( groupId == null || "".equals( groupId.trim() ) ) {
return false;
}
final String[] groupIdComponents = groupId.split( "\\.", -1 );
for ( String s : groupIdComponents ) {
if ( !ValidationUtils.isArtifactIdentifier( s ) ) {
return false;
}
}
return true;
}
@Override
public boolean isValidArtifactId( final String artifactId ) {
if ( artifactId == null || "".equals( artifactId.trim() ) ) {
return false;
}
final String[] artifactIdComponents = artifactId.split( "\\.", -1 );
for ( String s : artifactIdComponents ) {
if ( !ValidationUtils.isArtifactIdentifier( s ) ) {
return false;
}
}
return true;
}
@Override
public boolean isValidVersion( final String version ) {
if ( version == null || "".equals( version.trim() ) ) {
return false;
}
return version.matches( "^[a-zA-Z0-9\\.\\-_]+$" );
}
@Override
public void delete( final Path pathToPomXML,
final String comment ) {
projectService.delete( pathToPomXML,
comment );
}
private List<Project> getProjects( final Path branchRoot ) {
final List<Project> repositoryProjects = new ArrayList<Project>();
if ( branchRoot == null ) {
return repositoryProjects;
} else {
final DirectoryStream<org.uberfire.java.nio.file.Path> nioRepositoryPaths = ioService.newDirectoryStream( Paths.convert( branchRoot ) );
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 = projectService.resolveProject( projectPath );
if ( project != null ) {
repositoryProjects.add( project );
}
}
}
return repositoryProjects;
}
}
}