001package org.apache.maven.plugins.enforcer;
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 java.io.File;
023import java.util.ArrayList;
024import java.util.List;
025
026import org.apache.maven.enforcer.rule.api.EnforcerRule;
027import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
028import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
029
030/**
031 * Contains the common code to compare an array of files against a requirement.
032 *
033 * @author <a href="mailto:brianf@apache.org">Brian Fox</a>
034 */
035public abstract class AbstractRequireFiles
036    extends AbstractStandardEnforcerRule
037{
038
039    /** Array of files to check. */
040    private File[] files;
041
042    /** if null file handles should be allowed. If they are allowed, it means treat it as a success. */
043    private boolean allowNulls = false;
044
045    // check the file for the specific condition
046    /**
047     * Check one file.
048     *
049     * @param file the file
050     * @return <code>true</code> if successful
051     */
052    abstract boolean checkFile( File file );
053
054    // return standard error message
055    /**
056     * Gets the error msg.
057     *
058     * @return the error msg
059     */
060    abstract String getErrorMsg();
061
062    /*
063     * (non-Javadoc)
064     *
065     * @see org.apache.maven.enforcer.rule.api.EnforcerRule#execute(org.apache.maven.enforcer.rule.api.EnforcerRuleHelper)
066     */
067    public void execute( EnforcerRuleHelper helper )
068        throws EnforcerRuleException
069    {
070
071        if ( !allowNulls && files.length == 0 )
072        {
073            throw new EnforcerRuleException( "The file list is empty and Null files are disabled." );
074        }
075
076        List<File> failures = new ArrayList<File>();
077        for ( File file : files )
078        {
079            if ( !allowNulls && file == null )
080            {
081                failures.add( file );
082            }
083            else if ( !checkFile( file ) )
084            {
085                failures.add( file );
086            }
087        }
088
089        // if anything was found, log it with the optional message.
090        if ( !failures.isEmpty() )
091        {
092            String message = getMessage();
093            
094            StringBuilder buf = new StringBuilder();
095            if ( message != null )
096            {
097                buf.append( message + "\n" );
098            }
099            buf.append( getErrorMsg() );
100
101            for ( File file : failures )
102            {
103                if ( file != null )
104                {
105                    buf.append( file.getAbsolutePath() + "\n" );
106                }
107                else
108                {
109                    buf.append( "(an empty filename was given and allowNulls is false)\n" );
110                }
111            }
112
113            throw new EnforcerRuleException( buf.toString() );
114        }
115    }
116
117    /**
118     * If your rule is cacheable, you must return a unique id when parameters or conditions change that would cause the
119     * result to be different. Multiple cached results are stored based on their id. The easiest way to do this is to
120     * return a hash computed from the values of your parameters. If your rule is not cacheable, then the result here is
121     * not important, you may return anything.
122     *
123     * @return the cache id
124     */
125    public String getCacheId()
126    {
127        return Integer.toString( hashCode( files ) );
128    }
129
130    /**
131     * Calculates a hash code for the specified array as <code>Arrays.hashCode()</code> would do. Unfortunately, the
132     * mentioned method is only available for Java 1.5 and later.
133     *
134     * @param items The array for which to compute the hash code, may be <code>null</code>.
135     * @return The hash code for the array.
136     */
137    private static int hashCode( Object[] items )
138    {
139        int hash = 0;
140        if ( items != null )
141        {
142            hash = 1;
143            for ( int i = 0; i < items.length; i++ )
144            {
145                Object item = items[i];
146                hash = 31 * hash + ( item == null ? 0 : item.hashCode() );
147            }
148        }
149        return hash;
150    }
151
152    /**
153     * This tells the system if the results are cacheable at all. Keep in mind that during forked builds and other
154     * things, a given rule may be executed more than once for the same project. This means that even things that change
155     * from project to project may still be cacheable in certain instances.
156     *
157     * @return <code>true</code> if rule is cacheable
158     */
159    public boolean isCacheable()
160    {
161        return true;
162    }
163
164    /**
165     * If the rule is cacheable and the same id is found in the cache, the stored results are passed to this method to
166     * allow double checking of the results. Most of the time this can be done by generating unique ids, but sometimes
167     * the results of objects returned by the helper need to be queried. You may for example, store certain objects in
168     * your rule and then query them later.
169     *
170     * @param cachedRule the cached rule
171     * @return <code>true</code> if the stored results are valid for the same id.
172     */
173    public boolean isResultValid( EnforcerRule cachedRule )
174    {
175        return true;
176    }
177
178    public File[] getFiles()
179    {
180        return files;
181    }
182
183    public void setFiles( File[] files )
184    {
185        this.files = files;
186    }
187
188    public boolean isAllowNulls()
189    {
190        return allowNulls;
191    }
192
193    public void setAllowNulls( boolean allowNulls )
194    {
195        this.allowNulls = allowNulls;
196    }
197}