| package org.apache.continuum.builder.distributed.executor; |
| |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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. |
| */ |
| |
| import java.net.MalformedURLException; |
| import java.net.URL; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.apache.continuum.builder.utils.ContinuumBuildConstant; |
| import org.apache.continuum.dao.BuildDefinitionDao; |
| import org.apache.continuum.dao.BuildResultDao; |
| import org.apache.continuum.dao.ProjectDao; |
| import org.apache.continuum.dao.ProjectScmRootDao; |
| import org.apache.continuum.distributed.transport.slave.SlaveBuildAgentTransportClient; |
| import org.apache.continuum.model.project.ProjectScmRoot; |
| import org.apache.continuum.model.repository.LocalRepository; |
| import org.apache.continuum.taskqueue.PrepareBuildProjectsTask; |
| import org.apache.continuum.utils.ContinuumUtils; |
| import org.apache.continuum.utils.ProjectSorter; |
| import org.apache.maven.continuum.ContinuumException; |
| import org.apache.maven.continuum.model.project.BuildDefinition; |
| import org.apache.maven.continuum.model.project.BuildResult; |
| import org.apache.maven.continuum.model.project.Project; |
| import org.apache.maven.continuum.project.ContinuumProjectState; |
| import org.apache.maven.continuum.store.ContinuumStoreException; |
| import org.codehaus.plexus.taskqueue.Task; |
| import org.codehaus.plexus.taskqueue.execution.TaskExecutionException; |
| import org.codehaus.plexus.util.dag.CycleDetectedException; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| public class DistributedBuildProjectTaskExecutor |
| implements DistributedBuildTaskExecutor |
| { |
| private Logger log = LoggerFactory.getLogger( this.getClass() ); |
| |
| private String buildAgentUrl; |
| |
| private long startTime; |
| |
| private long endTime; |
| |
| /** |
| * @plexus.requirement |
| */ |
| private ProjectDao projectDao; |
| |
| /** |
| * @plexus.requirement |
| */ |
| private ProjectScmRootDao projectScmRootDao; |
| |
| /** |
| * @plexus.requirement |
| */ |
| private BuildDefinitionDao buildDefinitionDao; |
| |
| /** |
| * @plexus.requirement |
| */ |
| private BuildResultDao buildResultDao; |
| |
| public void setBuildAgentUrl( String buildAgentUrl ) |
| { |
| this.buildAgentUrl = buildAgentUrl; |
| } |
| |
| public String getBuildAgentUrl() |
| { |
| return buildAgentUrl; |
| } |
| |
| public void executeTask( Task task ) |
| throws TaskExecutionException |
| { |
| PrepareBuildProjectsTask prepareBuildTask = (PrepareBuildProjectsTask) task; |
| |
| try |
| { |
| SlaveBuildAgentTransportClient client = new SlaveBuildAgentTransportClient( new URL( buildAgentUrl ) ); |
| |
| log.info( "initializing buildContext" ); |
| List buildContext = initializeBuildContext( prepareBuildTask.getProjectsBuildDefinitionsMap(), |
| prepareBuildTask.getTrigger(), |
| prepareBuildTask.getScmRootAddress() ); |
| |
| startTime = System.currentTimeMillis(); |
| client.buildProjects( buildContext ); |
| |
| endTime = System.currentTimeMillis(); |
| } |
| catch ( MalformedURLException e ) |
| { |
| log.error( "Invalid URL " + buildAgentUrl + ", not building" ); |
| throw new TaskExecutionException( "Invalid URL " + buildAgentUrl, e ); |
| } |
| catch ( Exception e ) |
| { |
| log.error( "Error occurred while building task", e ); |
| endTime = System.currentTimeMillis(); |
| createResult( prepareBuildTask, ContinuumUtils.throwableToString( e ) ); |
| } |
| } |
| |
| private List initializeBuildContext( Map<Integer, Integer> projectsAndBuildDefinitions, |
| int trigger, String scmRootAddress ) |
| throws ContinuumException |
| { |
| List buildContext = new ArrayList(); |
| List<Project> projects = new ArrayList<Project>(); |
| |
| try |
| { |
| for ( Integer projectId : projectsAndBuildDefinitions.keySet() ) |
| { |
| Project project = projectDao.getProjectWithDependencies( projectId ); |
| projects.add( project ); |
| } |
| |
| try |
| { |
| projects = ProjectSorter.getSortedProjects( projects, null ); |
| } |
| catch ( CycleDetectedException e ) |
| { |
| log.info( "Cycle Detected" ); |
| } |
| |
| for ( Project project : projects ) |
| { |
| int buildDefinitionId = projectsAndBuildDefinitions.get( project.getId() ); |
| BuildDefinition buildDef = buildDefinitionDao.getBuildDefinition( buildDefinitionId ); |
| BuildResult oldBuildResult = |
| buildResultDao.getLatestBuildResultForBuildDefinition( project.getId(), buildDefinitionId ); |
| |
| Map context = new HashMap(); |
| |
| context.put( ContinuumBuildConstant.KEY_PROJECT_GROUP_ID, new Integer( project.getProjectGroup().getId() ) ); |
| context.put( ContinuumBuildConstant.KEY_SCM_ROOT_ADDRESS, scmRootAddress ); |
| context.put( ContinuumBuildConstant.KEY_PROJECT_ID, new Integer( project.getId() ) ); |
| context.put( ContinuumBuildConstant.KEY_PROJECT_NAME, project.getName() ); |
| context.put( ContinuumBuildConstant.KEY_EXECUTOR_ID, project.getExecutorId() ); |
| context.put( ContinuumBuildConstant.KEY_SCM_URL, project.getScmUrl() ); |
| context.put( ContinuumBuildConstant.KEY_PROJECT_STATE, new Integer( project.getState() ) ); |
| |
| LocalRepository localRepo = project.getProjectGroup().getLocalRepository(); |
| |
| if ( localRepo != null ) |
| { |
| context.put( ContinuumBuildConstant.KEY_LOCAL_REPOSITORY, localRepo.getLocation() ); |
| } |
| else |
| { |
| context.put( ContinuumBuildConstant.KEY_LOCAL_REPOSITORY, "" ); |
| } |
| |
| if ( project.getScmUsername() == null ) |
| { |
| context.put( ContinuumBuildConstant.KEY_SCM_USERNAME, "" ); |
| } |
| else |
| { |
| context.put( ContinuumBuildConstant.KEY_SCM_USERNAME, project.getScmUsername() ); |
| } |
| |
| if ( project.getScmPassword() == null ) |
| { |
| context.put( ContinuumBuildConstant.KEY_SCM_PASSWORD, "" ); |
| } |
| else |
| { |
| context.put( ContinuumBuildConstant.KEY_SCM_PASSWORD, project.getScmPassword() ); |
| } |
| |
| context.put( ContinuumBuildConstant.KEY_BUILD_DEFINITION_ID, new Integer( buildDefinitionId ) ); |
| context.put( ContinuumBuildConstant.KEY_BUILD_FILE, buildDef.getBuildFile() ); |
| context.put( ContinuumBuildConstant.KEY_GOALS, buildDef.getGoals() ); |
| |
| if ( buildDef.getArguments() == null ) |
| { |
| context.put( ContinuumBuildConstant.KEY_ARGUMENTS, "" ); |
| } |
| else |
| { |
| context.put( ContinuumBuildConstant.KEY_ARGUMENTS, buildDef.getArguments() ); |
| } |
| context.put( ContinuumBuildConstant.KEY_TRIGGER, new Integer( trigger ) ); |
| context.put( ContinuumBuildConstant.KEY_BUILD_FRESH, new Boolean( buildDef.isBuildFresh() ) ); |
| |
| buildContext.add( context ); |
| } |
| |
| return buildContext; |
| } |
| catch ( ContinuumStoreException e ) |
| { |
| throw new ContinuumException( "Error while initializing build context", e ); |
| } |
| } |
| |
| private void createResult( PrepareBuildProjectsTask task, String error ) |
| throws TaskExecutionException |
| { |
| try |
| { |
| ProjectScmRoot scmRoot = projectScmRootDao.getProjectScmRootByProjectGroupAndScmRootAddress( task.getProjectGroupId(), task.getScmRootAddress() ); |
| |
| if ( scmRoot.getState() == ContinuumProjectState.UPDATING ) |
| { |
| scmRoot.setState( ContinuumProjectState.ERROR ); |
| scmRoot.setError( error ); |
| projectScmRootDao.updateProjectScmRoot( scmRoot ); |
| } |
| else |
| { |
| Map<Integer, Integer> map = task.getProjectsBuildDefinitionsMap(); |
| for ( Integer projectId : map.keySet() ) |
| { |
| int buildDefinitionId = map.get( projectId ); |
| Project project = projectDao.getProject( projectId ); |
| BuildDefinition buildDef = buildDefinitionDao.getBuildDefinition( buildDefinitionId ); |
| BuildResult latestBuildResult = buildResultDao. |
| getLatestBuildResultForBuildDefinition( projectId, buildDefinitionId ); |
| if ( latestBuildResult == null || ( latestBuildResult.getStartTime() >= startTime && latestBuildResult.getEndTime() > 0 && |
| latestBuildResult.getEndTime() < endTime ) || latestBuildResult.getStartTime() < startTime ) |
| { |
| BuildResult buildResult = new BuildResult(); |
| buildResult.setBuildDefinition( buildDef ); |
| buildResult.setError( error ); |
| buildResult.setState( ContinuumProjectState.ERROR ); |
| buildResult.setTrigger( task.getTrigger() ); |
| buildResult.setStartTime( startTime ); |
| buildResult.setEndTime( endTime ); |
| |
| buildResultDao.addBuildResult( project, buildResult ); |
| } |
| } |
| |
| } |
| } |
| catch ( ContinuumStoreException e ) |
| { |
| throw new TaskExecutionException( "Error while creating result", e ); |
| } |
| } |
| } |