001    package org.apache.maven.model.profile.activation;
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 java.io.File;
023    
024    import org.apache.maven.model.Activation;
025    import org.apache.maven.model.ActivationFile;
026    import org.apache.maven.model.Profile;
027    import org.apache.maven.model.building.ModelProblemCollector;
028    import org.apache.maven.model.building.ModelProblem.Severity;
029    import org.apache.maven.model.path.PathTranslator;
030    import org.apache.maven.model.profile.ProfileActivationContext;
031    import org.codehaus.plexus.component.annotations.Component;
032    import org.codehaus.plexus.component.annotations.Requirement;
033    import org.codehaus.plexus.interpolation.AbstractValueSource;
034    import org.codehaus.plexus.interpolation.MapBasedValueSource;
035    import org.codehaus.plexus.interpolation.RegexBasedInterpolator;
036    import org.codehaus.plexus.util.StringUtils;
037    
038    /**
039     * Determines profile activation based on the existence/absence of some file.
040     * 
041     * @author Benjamin Bentmann
042     */
043    @Component( role = ProfileActivator.class, hint = "file" )
044    public class FileProfileActivator
045        implements ProfileActivator
046    {
047    
048        @Requirement
049        private PathTranslator pathTranslator;
050    
051        public FileProfileActivator setPathTranslator( PathTranslator pathTranslator )
052        {
053            this.pathTranslator = pathTranslator;
054            return this;
055        }
056    
057        public boolean isActive( Profile profile, ProfileActivationContext context, ModelProblemCollector problems )
058        {
059            Activation activation = profile.getActivation();
060    
061            if ( activation == null )
062            {
063                return false;
064            }
065    
066            ActivationFile file = activation.getFile();
067    
068            if ( file == null )
069            {
070                return false;
071            }
072    
073            String path;
074            boolean missing;
075    
076            if ( StringUtils.isNotEmpty( file.getExists() ) )
077            {
078                path = file.getExists();
079                missing = false;
080            }
081            else if ( StringUtils.isNotEmpty( file.getMissing() ) )
082            {
083                path = file.getMissing();
084                missing = true;
085            }
086            else
087            {
088                return false;
089            }
090    
091            RegexBasedInterpolator interpolator = new RegexBasedInterpolator();
092    
093            final File basedir = context.getProjectDirectory();
094    
095            if ( basedir != null )
096            {
097                interpolator.addValueSource( new AbstractValueSource( false )
098                {
099                    public Object getValue( String expression )
100                    {
101                        /*
102                         * NOTE: We intentionally only support ${basedir} and not ${project.basedir} as the latter form
103                         * would suggest that other project.* expressions can be used which is however beyond the design.
104                         */
105                        if ( "basedir".equals( expression ) )
106                        {
107                            return basedir.getAbsolutePath();
108                        }
109                        return null;
110                    }
111                } );
112            }
113            else if ( path.indexOf( "${basedir}" ) >= 0 )
114            {
115                return false;
116            }
117    
118            interpolator.addValueSource( new MapBasedValueSource( context.getUserProperties() ) );
119    
120            interpolator.addValueSource( new MapBasedValueSource( context.getSystemProperties() ) );
121    
122            try
123            {
124                path = interpolator.interpolate( path, "" );
125            }
126            catch ( Exception e )
127            {
128                problems.add( Severity.ERROR, "Failed to interpolate file location " + path + " for profile "
129                    + profile.getId() + ": " + e.getMessage(), file.getLocation( missing ? "missing" : "exists" ), e );
130                return false;
131            }
132    
133            path = pathTranslator.alignToBaseDirectory( path, basedir );
134    
135            File f = new File( path );
136    
137            if ( !f.isAbsolute() )
138            {
139                return false;
140            }
141    
142            boolean fileExists = f.exists();
143    
144            return missing ? !fileExists : fileExists;
145        }
146    
147    }