001package org.apache.maven.lifecycle;
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
022import org.codehaus.plexus.component.annotations.Component;
023import org.codehaus.plexus.component.annotations.Requirement;
024import org.codehaus.plexus.logging.Logger;
025import org.codehaus.plexus.util.StringUtils;
026
027import com.google.common.base.Preconditions;
028
029import java.util.ArrayList;
030import java.util.Arrays;
031import java.util.HashMap;
032import java.util.LinkedHashMap;
033import java.util.LinkedHashSet;
034import java.util.List;
035import java.util.Map;
036import java.util.Set;
037
038/**
039 * @since 3.0
040 * @author Jason van Zyl
041 * @author Kristian Rosenvold
042 */
043// TODO: The configuration for the lifecycle needs to be externalized so that I can use the annotations properly for the
044// wiring and reference and external source for the lifecycle configuration.
045@Component( role = DefaultLifecycles.class )
046public class DefaultLifecycles
047{
048    public static final String[] STANDARD_LIFECYCLES = { "default", "clean", "site" };
049
050    // @Configuration(source="org/apache/maven/lifecycle/lifecycles.xml")
051
052    @Requirement( role = Lifecycle.class )
053    private Map<String, Lifecycle> lifecycles;
054
055    @Requirement
056    private Logger logger;
057
058    public DefaultLifecycles()
059    {
060    }
061
062    public DefaultLifecycles( Map<String, Lifecycle> lifecycles, Logger logger )
063    {
064        this.lifecycles = new LinkedHashMap<>();
065        this.logger = logger;
066        this.lifecycles = lifecycles;
067    }
068
069    public Lifecycle get( String key )
070    {
071        return getPhaseToLifecycleMap().get( key );
072    }
073
074    /**
075     * We use this to map all phases to the lifecycle that contains it. This is used so that a user can specify the
076     * phase they want to execute and we can easily determine what lifecycle we need to run.
077     *
078     * @return A map of lifecycles, indexed on id
079     */
080    public Map<String, Lifecycle> getPhaseToLifecycleMap()
081    {
082        // If people are going to make their own lifecycles then we need to tell people how to namespace them correctly
083        // so that they don't interfere with internally defined lifecycles.
084
085        HashMap<String, Lifecycle> phaseToLifecycleMap = new HashMap<>();
086
087        for ( Lifecycle lifecycle : getLifeCycles() )
088        {
089            if ( logger.isDebugEnabled() )
090            {
091                logger.debug( "Lifecycle " + lifecycle );
092            }
093
094            for ( String phase : lifecycle.getPhases() )
095            {
096                // The first definition wins.
097                if ( !phaseToLifecycleMap.containsKey( phase ) )
098                {
099                    phaseToLifecycleMap.put( phase, lifecycle );
100                }
101                else
102                {
103                    Lifecycle original = phaseToLifecycleMap.get( phase );
104                    logger.warn( "Duplicated lifecycle phase " + phase + ". Defined in " + original.getId()
105                        + " but also in " + lifecycle.getId() );
106                }
107            }
108        }
109
110        return phaseToLifecycleMap;
111    }
112
113    public List<Lifecycle> getLifeCycles()
114    {
115        // ensure canonical order of standard lifecycles
116        Map<String, Lifecycle> lifecycles = new LinkedHashMap<>( this.lifecycles );
117
118        LinkedHashSet<String> lifecycleNames = new LinkedHashSet<>( Arrays.asList( STANDARD_LIFECYCLES ) );
119        lifecycleNames.addAll( lifecycles.keySet() );
120
121        ArrayList<Lifecycle> result = new ArrayList<>();
122        for ( String name : lifecycleNames )
123        {
124            Lifecycle lifecycle = lifecycles.get( name );
125            Preconditions.checkNotNull( "A lifecycle must have an id.", lifecycle.getId() );
126            result.add( lifecycle );
127        }
128
129        return result;
130    }
131
132    public String getLifecyclePhaseList()
133    {
134        Set<String> phases = new LinkedHashSet<>();
135
136        for ( Lifecycle lifecycle : getLifeCycles() )
137        {
138            phases.addAll( lifecycle.getPhases() );
139        }
140
141        return StringUtils.join( phases.iterator(), ", " );
142    }
143
144}