View Javadoc

1   package org.apache.maven.doxia.linkcheck.validation;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.File;
23  import java.io.IOException;
24  import java.io.Reader;
25  import java.util.Locale;
26  
27  import org.apache.maven.doxia.linkcheck.model.LinkcheckFileResult;
28  import org.codehaus.plexus.util.IOUtil;
29  import org.codehaus.plexus.util.ReaderFactory;
30  import org.codehaus.plexus.util.StringUtils;
31  import org.codehaus.plexus.util.WriterFactory;
32  
33  /**
34   * A link validator solely for files on the local filesystem.
35   *
36   * @author <a href="mailto:bwalding@apache.org">Ben Walding</a>
37   * @author <a href="mailto:aheritier@apache.org">Arnaud Heritier</a>
38   * @version $Id: FileLinkValidator.java 1030039 2010-11-02 13:33:03Z ltheussl $
39   */
40  public final class FileLinkValidator
41      implements LinkValidator
42  {
43      private String encoding;
44  
45      /**
46       * @param encoding the encoding file used. If empty, using UTF-8.
47       */
48      public FileLinkValidator( String encoding )
49      {
50          if ( StringUtils.isEmpty( encoding ) )
51          {
52              encoding = WriterFactory.UTF_8;
53          }
54          this.encoding = encoding;
55      }
56  
57      /** {@inheritDoc} */
58      public LinkValidationResult validateLink( LinkValidationItem lvi )
59      {
60          File f = getFile( lvi );
61  
62          if ( f.exists() )
63          {
64              return new LinkValidationResult( LinkcheckFileResult.VALID_LEVEL, false, "" );
65          }
66  
67          return new LinkValidationResult( LinkcheckFileResult.ERROR_LEVEL, false, "doesn't exist." );
68      }
69  
70      /** {@inheritDoc} */
71      public Object getResourceKey( LinkValidationItem lvi )
72      {
73          String link = lvi.getLink();
74  
75          // If we find an http(s) link or a mail link, it's not good
76          // links starting with "/" should have a base URL pre-pended and be handled by OnlineHTTPLinkValidator.
77          if ( link.toLowerCase( Locale.ENGLISH ).startsWith( "http://" )
78              || link.toLowerCase( Locale.ENGLISH ).startsWith( "https://" ) || link.indexOf( '@' ) != -1
79              || link.startsWith( "/" ) )
80          {
81              return null;
82          }
83  
84          return getFile( lvi ).getAbsolutePath();
85      }
86  
87      // ----------------------------------------------------------------------
88      // Private methods
89      // ----------------------------------------------------------------------
90  
91      /**
92       * Returns the link of the given LinkValidationItem as a File.
93       *
94       * @param lvi The LinkValidationItem.
95       * @return File the link as a File.
96       */
97      private File getFile( LinkValidationItem lvi )
98      {
99          String link = lvi.getLink();
100 
101         if ( link.indexOf( '#' ) != -1 )
102         {
103             String anchor = link.substring( link.indexOf( '#' ) + 1 );
104             link = link.substring( 0, link.indexOf( '#' ) );
105 
106             // If the link was just #fred or similar, then the file is the file it came from
107             if ( link.trim().length() == 0 ) // in the same file
108             {
109                 // the anchor exists?
110                 String content = read( lvi.getSource(), encoding );
111                 if ( Anchors.matchesAnchor( content, anchor ) )
112                 {
113                     return lvi.getSource();
114                 }
115 
116                 // return an invalid file
117                 return new File( lvi.getLink() );
118             }
119 
120             // the anchor exists?
121             String content = read( new File( lvi.getSource().getParentFile(), link ), encoding );
122             if ( Anchors.matchesAnchor( content, anchor ) )
123             {
124                 return new File( lvi.getSource().getParentFile(), link );
125             }
126 
127             // return an invalid file
128             return new File( lvi.getLink() );
129         }
130 
131         if ( link.indexOf( '?' ) != -1 )
132         {
133             link = link.substring( 0, link.indexOf( '?' ) );
134 
135             // If the link was just ?param=something or similar, then the file is the file it came from
136             // XXX: Theoretically we could even validate the anchor tag?
137             if ( link.trim().length() == 0 )
138             {
139                 return lvi.getSource();
140             }
141         }
142 
143         return new File( lvi.getSource().getParentFile(), link );
144     }
145 
146     /**
147      * @param f not null
148      * @param encoding the encoding file used
149      * @return the content of the file or null if an error occurred.
150      */
151     private static String read( File f, String encoding )
152     {
153         Reader reader = null;
154         try
155         {
156             reader = ReaderFactory.newReader( f, encoding );
157             return IOUtil.toString( reader );
158         }
159         catch ( IOException e )
160         {
161             // nop;
162         }
163         finally
164         {
165             IOUtil.close( reader );
166         }
167 
168         return null;
169     }
170 }