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