001    /* 
002     * Copyright 2005 Stephen J. McConnell
003     *
004     * Licensed  under the  Apache License,  Version 2.0  (the "License");
005     * you may not use  this file  except in  compliance with the License.
006     * You may obtain a copy of the License at 
007     * 
008     *   http://www.apache.org/licenses/LICENSE-2.0
009     * 
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed  under the  License is distributed on an "AS IS" BASIS,
012     * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
013     * implied.
014     * 
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    
019    package net.dpml.tools.checkstyle;
020    
021    import java.io.File;
022    import java.net.URI;
023    import java.net.URL;
024    
025    import com.puppycrawl.tools.checkstyle.CheckStyleTask;
026    
027    import net.dpml.library.Resource;
028    import net.dpml.library.Module;
029    
030    import net.dpml.tools.Context;
031    
032    import org.apache.tools.ant.Project;
033    import org.apache.tools.ant.BuildException;
034    import org.apache.tools.ant.types.FileSet;
035    
036    /**
037     * The checkstyle task handes the establishment of a classic checkstyle task 
038     * with automatic resolution of source directories.  Typical usage is within 
039     * a build file that aggregates results for a module.
040     *
041     * @author <a href="http://www.dpml.net">Digital Product Meta Library</a>
042     * @version 1.2.0
043     */
044    public class CheckstyleTask extends CheckStyleTask
045    {
046       /**
047        * The format property key.
048        */
049        public static final String FORMAT_KEY = "project.checkstyle.format";
050        
051       /**
052        * The default format value.
053        */
054        public static final String FORMAT_VALUE = "local:format:dpml/tools/dpml";
055        
056        private boolean m_init = false;
057        private Context m_context;
058        private boolean m_implicit = true;
059        
060       /**
061        * Set the implicit inclusion of the current resource (and potentially
062        * the resources children if the resource is a module).  If implicit
063        * file inclusion is disabled then resources must be declared using an 
064        * explicit fileset.
065        *
066        * @param flag false if implicit inclusion is to be disabled
067        */
068        public void setImplicit( boolean flag )
069        {
070            m_implicit = flag;
071        }
072    
073       /**
074        * Task initialization.
075        */
076        public void init()
077        {
078            super.init();
079            if( !m_init )
080            {
081                m_init = true;
082                m_context = (Context) getProject().getReference( "project.context" );
083                if( null == m_context )
084                {
085                    final String error = 
086                      "Missing 'project.context' reference.";
087                    throw new IllegalStateException( error );
088                }
089    
090                String defaultFormat = "local:format:dpml/tools/dpml";
091                String spec = m_context.getProperty( FORMAT_KEY, FORMAT_VALUE );
092                if( !spec.startsWith( "local:" ) )
093                {
094                    final String error = 
095                      "Invalid checkstyle format uri ["
096                      + spec
097                      + ". The value must be a 'local:' artifact reference (e.g. "
098                      + FORMAT_VALUE 
099                      + ").";
100                    throw new BuildException( error, getLocation() );
101                }
102                
103                try
104                {
105                    URL url = new URI( spec ).toURL();
106                    File format = (File) url.getContent( new Class[]{File.class} );
107                    setConfig( format );
108                }
109                catch( Throwable e )
110                {
111                    final String error = 
112                      "Internal error while attempting to resolve the checkstyle format property value ["
113                      + spec
114                      + "] to a local file.";
115                    throw new BuildException( error, e, getLocation() );
116                }
117            }
118            m_init = true;
119        }
120        
121       /**
122        * Execute the checkstyle check.
123        */
124        public void execute() 
125        {
126            Resource resource = m_context.getResource();
127            if( m_implicit )
128            {
129                addTargetToFileset( resource );
130            }
131            super.execute();
132        }
133        
134        private void addTargetToFileset( Resource resource )
135        {
136            try
137            {
138                File file = resource.getBaseDir();
139                Project project = getProject();
140                //File main = new File( file, "target/build/main" );
141                File main = new File( file, "src/main" );
142                if( main.exists() )
143                {
144                    FileSet fileset = new FileSet();
145                    fileset.setDir( main );
146                    fileset.setIncludes( "**/*.java" );
147                    super.addFileset( fileset );
148                }
149                //File test = new File( file, "target/build/test" );
150                File test = new File( file, "src/test" );
151                if( test.exists() )
152                {
153                    FileSet fileset = new FileSet();
154                    fileset.setDir( test );
155                    fileset.setIncludes( "**/*.java" );
156                    super.addFileset( fileset );
157                }
158                if( resource instanceof Module )
159                {
160                    Module module = (Module) resource;
161                    Resource[] children = module.getResources();
162                    for( int i=0; i < children.length; i++ )
163                    {
164                        Resource child = children[i];
165                        addTargetToFileset( child );
166                    }
167                }
168            }
169            catch( Exception e )
170            {
171                final String error = 
172                  "Internal error while attempting to construct implicit fileset for the resource: " + resource;
173                throw new BuildException( error, e, getLocation() );
174            }
175        }
176    
177        private Context getContext()
178        {
179            return m_context;
180        }
181    }