001    package org.apache.maven.lifecycle.internal;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one
005     * or more contributor license agreements.  See the NOTICE file
006     * distributed with this work for additional information
007     * regarding copyright ownership.  The ASF licenses this file
008     * to you under the Apache License, Version 2.0 (the
009     * "License"); you may not use this file except in compliance
010     * with the License.  You may obtain a copy of the License at
011     *
012     *  http://www.apache.org/licenses/LICENSE-2.0
013     *
014     * Unless required by applicable law or agreed to in writing,
015     * software distributed under the License is distributed on an
016     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017     * KIND, either express or implied.  See the License for the
018     * specific language governing permissions and limitations
019     * under the License.
020     */
021    
022    import org.apache.maven.project.MavenProject;
023    
024    import java.util.ArrayList;
025    import java.util.Collection;
026    import java.util.Collections;
027    import java.util.HashMap;
028    import java.util.List;
029    import java.util.Map;
030    import java.util.concurrent.ConcurrentHashMap;
031    
032    /**
033     * Handles all concurrency-related logging.
034     * <p/>
035     * The logging/diagnostic needs of a concurrent build are different from a linear build. This
036     * delta required to analyze a concurrent build is located here.
037     * <p/>
038     * NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
039     * 
040     * @since 3.0
041     * @author Kristian Rosenvold
042     */
043    public class ConcurrentBuildLogger
044    {
045        private final long startTime;
046    
047        private final Map<MavenProject, Thread> threadMap = new ConcurrentHashMap<MavenProject, Thread>();
048    
049        public ConcurrentBuildLogger()
050        {
051            startTime = System.currentTimeMillis();
052        }
053    
054    
055        List<BuildLogItem> items = Collections.synchronizedList( new ArrayList<BuildLogItem>() );
056    
057        public BuildLogItem createBuildLogItem( MavenProject project, ExecutionPlanItem current )
058        {
059            threadMap.put( project, Thread.currentThread() );
060            BuildLogItem result = new BuildLogItem( project, current );
061            items.add( result );
062            return result;
063        }
064    
065        public String toString()
066        {
067            StringBuilder result = new StringBuilder();
068            for ( Map.Entry<MavenProject, Thread> mavenProjectThreadEntry : threadMap.entrySet() )
069            {
070                result.append( mavenProjectThreadEntry.getKey().getName() );
071                result.append( " ran on " );
072                result.append( mavenProjectThreadEntry.getValue().getName() );
073                result.append( "\n" );
074            }
075    
076            for ( BuildLogItem builtLogItem : items )
077            {
078                result.append( builtLogItem.toString( startTime ) );
079                result.append( "\n" );
080            }
081            return result.toString();
082        }
083    
084        public String toGraph()
085        {
086            StringBuilder result = new StringBuilder();
087    
088            Map<MavenProject, Collection<BuildLogItem>> multiMap = new HashMap<MavenProject, Collection<BuildLogItem>>();
089            for ( BuildLogItem builtLogItem : items )
090            {
091                MavenProject project = builtLogItem.getProject();
092                Collection<BuildLogItem> bag = multiMap.get( project );
093                if ( bag == null )
094                {
095                    bag = new ArrayList<BuildLogItem>();
096                    multiMap.put( project, bag );
097                }
098                bag.add( builtLogItem );
099            }
100    
101            result.append( "digraph build" );
102            result.append( " {\n " );
103    
104            for ( MavenProject mavenProject : multiMap.keySet() )
105            {
106                final Collection<BuildLogItem> builtLogItems = multiMap.get( mavenProject );
107                result.append( "   subgraph " );
108                result.append( mavenProject.getArtifactId() );
109                result.append( "   {\n" );
110    
111                for ( BuildLogItem builtLogItem : builtLogItems )
112                {
113                    result.append( builtLogItem.toGraph( startTime ) );
114                }
115    
116                result.append( "\n   }\n" );
117            }
118    
119            result.append( "\n}\n " );
120            return result.toString();
121        }
122    
123    }