PR: MPLINKCHECK-10, MPLINKCHECK-24, MAVEN-1739, MPLINKCHECK-25
- "Moved Permanently" sites are reported as a warning and not as an error. - Speed and stability enhancement [better usage of httpClient]. - Upgrade to HttpClient 3.0. - Display for each file the number of links and the number of errors. - New counters to report how many files and links are checked and how many errors are found. - Display a more verbose message than the "NOT FOUND" error. git-svn-id: https://svn.apache.org/repos/asf/maven/maven-1/plugins/trunk@368935 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
@@ -23,28 +23,35 @@
|
||||
xmlns:define="jelly:define"
|
||||
xmlns:linkcheck="linkcheck"
|
||||
xmlns:maven="jelly:maven"
|
||||
xmlns:ant="jelly:ant"
|
||||
xmlns:x="jelly:xml"
|
||||
xmlns:util="jelly:util"
|
||||
xmlns:log="jelly:log"
|
||||
xmlns:doc="doc">
|
||||
|
||||
<j:set var="loggerName">org.apache.maven.plugin.linkcheck.Jelly</j:set>
|
||||
|
||||
<goal name="maven-linkcheck-plugin:register">
|
||||
<doc:registerReport
|
||||
name="Link Check Report"
|
||||
pluginName="maven-linkcheck-plugin"
|
||||
link="linkcheck"
|
||||
description="Report on the validity of all links in the documentation."/>
|
||||
<log:debug name="${loggerName}">LinkCheck report registred.</log:debug>
|
||||
</goal>
|
||||
|
||||
<goal name="maven-linkcheck-plugin:deregister">
|
||||
<doc:deregisterReport name="Link Check Report"/>
|
||||
<log:debug name="${loggerName}">LinkCheck report unregistred.</log:debug>
|
||||
</goal>
|
||||
|
||||
<define:taglib uri="linkcheck">
|
||||
<define:jellybean
|
||||
name="linkcheck"
|
||||
className="org.apache.maven.linkcheck.LinkCheck"
|
||||
className="org.apache.maven.plugin.linkcheck.LinkCheck"
|
||||
method="doExecute"
|
||||
/>
|
||||
<log:debug name="${loggerName}">LinkCheck taglib defined.</log:debug>
|
||||
</define:taglib>
|
||||
|
||||
<!-- ================================================================== -->
|
||||
@@ -56,28 +63,22 @@
|
||||
-->
|
||||
|
||||
<goal name="maven-linkcheck-plugin:report">
|
||||
<copy file="${plugin.resources}/linkcheck-temp.xml"
|
||||
toFile="${maven.gen.docs}/linkcheck.xml"/>
|
||||
<copy file="${plugin.resources}/linkcheck-temp.xml"
|
||||
toFile="${maven.gen.docs}/linkcheck.xml"/>
|
||||
<log:debug name="${loggerName}">Fake LinkCheck report copied.</log:debug>
|
||||
<postGoal name="xdoc:jelly-transform">
|
||||
<!-- The linkcheck plugin must be called after any other one.-->
|
||||
<j:set var="online">${maven.mode.online}</j:set>
|
||||
<j:if test="${online.trim().length() > 0}">
|
||||
<attainGoal name="maven-linkcheck-plugin:report-real"/>
|
||||
</j:if>
|
||||
</postGoal>
|
||||
</goal>
|
||||
|
||||
<postGoal name="xdoc:jelly-transform">
|
||||
<maven:pluginVar var="reports" plugin="maven-xdoc-plugin" property="reports" />
|
||||
|
||||
<j:set var="online">${maven.mode.online}</j:set>
|
||||
|
||||
<j:if test="${online.trim().length() > 0}">
|
||||
<j:forEach var="report" items="${reports}">
|
||||
<!-- FIXME: Why special case linkcheck - fix it! -->
|
||||
<j:if test="${report.get('pluginName').equals('maven-linkcheck-plugin')}">
|
||||
<attainGoal name="maven-linkcheck-plugin:report-real"/>
|
||||
</j:if>
|
||||
</j:forEach>
|
||||
</j:if>
|
||||
</postGoal>
|
||||
|
||||
<goal
|
||||
name="maven-linkcheck-plugin:report-real"
|
||||
description="Generate link check results and then transform to HTML">
|
||||
<log:debug name="${loggerName}">Begin to generate the linkcheck report.</log:debug>
|
||||
<mkdir dir="${maven.build.dir}/linkcheck"/>
|
||||
<mkdir dir="${maven.build.dir}/linkcheck/docs"/>
|
||||
|
||||
@@ -108,15 +109,21 @@
|
||||
outputMode="xml"
|
||||
prettyPrint="true"
|
||||
/>
|
||||
|
||||
|
||||
<doc:jslToSite srcdir="${maven.build.dir}/linkcheck/docs"/>
|
||||
|
||||
<!-- copy images used in the report -->
|
||||
<mkdir dir="${maven.docs.dest}/images"/>
|
||||
<copy todir="${maven.docs.dest}/images">
|
||||
<fileset dir="${plugin.resources}/images"/>
|
||||
</copy>
|
||||
|
||||
</goal>
|
||||
|
||||
<goal name="maven-linkcheck-plugin:clearcache"
|
||||
description="Removes the cache file">
|
||||
<delete file="${maven.linkcheck.cache}"/>
|
||||
<log:info name="${loggerName}">Cache cleared.</log:info>
|
||||
</goal>
|
||||
|
||||
|
||||
</project>
|
||||
|
||||
@@ -20,3 +20,4 @@
|
||||
maven.linkcheck.cache=${maven.build.dir}/linkcheck/linkcheck.cache
|
||||
maven.linkcheck.failonerror=false
|
||||
maven.linkcheck.exclude=${pom.repository.url}
|
||||
maven.linkcheck.timeout=30000
|
||||
|
||||
@@ -18,6 +18,15 @@
|
||||
# P R O J E C T P R O P E R T I E S
|
||||
# -------------------------------------------------------------------
|
||||
maven.junit.fork=yes
|
||||
# Properties required for the unit tests
|
||||
maven.junit.sysproperties = \
|
||||
maven.proxy.host \
|
||||
maven.proxy.port \
|
||||
maven.proxy.username \
|
||||
maven.proxy.password \
|
||||
maven.mode.online
|
||||
|
||||
maven.jar.override = on
|
||||
maven.jar.maven = ${maven.home}/lib/maven.jar
|
||||
|
||||
log4j.logger.org.apache.maven.plugin.linkcheck=INFO
|
||||
@@ -1,5 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!--
|
||||
/*
|
||||
* Copyright 2001-2005 The Apache Software Foundation.
|
||||
@@ -17,9 +16,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/3.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/3.0.0 http://maven.apache.org/maven-v3_0_0.xsd">
|
||||
<project xmlns="http://maven.apache.org/POM/3.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/3.0.0 http://maven.apache.org/maven-v3_0_0.xsd">
|
||||
<extend>../plugin-parent/project.xml</extend>
|
||||
<pomVersion>3</pomVersion>
|
||||
<id>maven-linkcheck-plugin</id>
|
||||
@@ -77,6 +74,15 @@
|
||||
<role>Java Developer</role>
|
||||
</roles>
|
||||
</developer>
|
||||
<developer>
|
||||
<name>Arnaud Heritier</name>
|
||||
<id>aheritier</id>
|
||||
<email>aheritier@apache.org</email>
|
||||
<organization>Octo Technology</organization>
|
||||
<roles>
|
||||
<role>Java Developer</role>
|
||||
</roles>
|
||||
</developer>
|
||||
<developer>
|
||||
<name>Carlos Sanchez</name>
|
||||
<id>carlos</id>
|
||||
@@ -111,7 +117,16 @@
|
||||
<dependency>
|
||||
<groupId>commons-httpclient</groupId>
|
||||
<artifactId>commons-httpclient</artifactId>
|
||||
<version>2.0.2</version>
|
||||
<version>3.0</version>
|
||||
<properties>
|
||||
<comment>This library is already loaded by maven's core. Be careful to use the same version number as in the core.</comment>
|
||||
</properties>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
<version>1.2</version>
|
||||
<url>http://jakarta.apache.org/commons/codec/</url>
|
||||
<properties>
|
||||
<comment>This library is already loaded by maven's core. Be careful to use the same version number as in the core.</comment>
|
||||
</properties>
|
||||
@@ -137,6 +152,11 @@
|
||||
<artifactId>commons-jelly-tags-jsl</artifactId>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-jelly</groupId>
|
||||
<artifactId>commons-jelly-tags-log</artifactId>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-jelly</groupId>
|
||||
<artifactId>commons-jelly-tags-xml</artifactId>
|
||||
|
||||
@@ -1,317 +0,0 @@
|
||||
package org.apache.maven.linkcheck;
|
||||
|
||||
/* ====================================================================
|
||||
* Copyright 2001-2004 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.maven.linkcheck.validation.LinkValidationItem;
|
||||
import org.apache.maven.linkcheck.validation.LinkValidationResult;
|
||||
import org.apache.maven.linkcheck.validation.LinkValidatorManager;
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.Node;
|
||||
import org.dom4j.io.DOMReader;
|
||||
import org.w3c.tidy.Tidy;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bwalding@apache.org">Ben Walding</a>
|
||||
* @version $Id$
|
||||
*/
|
||||
public class FileToCheck
|
||||
{
|
||||
/**
|
||||
* Log for debug output
|
||||
*/
|
||||
private static Log LOG = LogFactory.getLog(FileToCheck.class);
|
||||
|
||||
private String base;
|
||||
private File fileToCheck;
|
||||
private String status = STATUS_OK;
|
||||
private String message = "";
|
||||
private int successful;
|
||||
private int unsuccessful;
|
||||
private List links = new LinkedList();
|
||||
|
||||
public static final String STATUS_UNKNOWN = null;
|
||||
public static final String STATUS_JTIDY_FAILURE = "Unable to tidy source";
|
||||
public static final String STATUS_OK = "OK";
|
||||
|
||||
public FileToCheck(File baseFile, File fileToCheck)
|
||||
{
|
||||
this.base = baseFile.getAbsolutePath();
|
||||
this.fileToCheck = fileToCheck;
|
||||
|
||||
}
|
||||
|
||||
private void addResult(LinkCheckResult lcr)
|
||||
{
|
||||
this.links.add(lcr);
|
||||
}
|
||||
|
||||
public void check(LinkValidatorManager lvm) throws Exception
|
||||
{
|
||||
successful = 0;
|
||||
unsuccessful = 0;
|
||||
status = STATUS_OK;
|
||||
message = "";
|
||||
|
||||
try
|
||||
{
|
||||
final Set hrefs;
|
||||
try
|
||||
{
|
||||
hrefs = getLinks();
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
//We catch Throwable, because there is a chance that the domReader will throw
|
||||
//a stack overflow exception for some files
|
||||
LOG.info("Caught " + e.toString() + " processing " + getName());
|
||||
LOG.info("Exception Message: " + e.getLocalizedMessage());
|
||||
LinkCheckResult lcr = new LinkCheckResult();
|
||||
lcr.setStatus("PARSE FAILURE");
|
||||
lcr.setTarget("N/A");
|
||||
addResult(lcr);
|
||||
return;
|
||||
}
|
||||
|
||||
for (Iterator iter = hrefs.iterator(); iter.hasNext(); )
|
||||
{
|
||||
String href = (String) iter.next();
|
||||
|
||||
LOG.debug("Link Found: " + href);
|
||||
|
||||
LinkCheckResult lcr = new LinkCheckResult();
|
||||
|
||||
LinkValidationItem lvi = new LinkValidationItem(fileToCheck, href);
|
||||
LinkValidationResult result = lvm.validateLink(lvi);
|
||||
lcr.setTarget(href);
|
||||
|
||||
switch (result.getStatus())
|
||||
{
|
||||
case LinkValidationResult.VALID :
|
||||
successful++;
|
||||
lcr.setStatus("OK");
|
||||
addResult(lcr); //At some point we won't want to store valid links. The tests require that we do at present
|
||||
break;
|
||||
case LinkValidationResult.UNKNOWN :
|
||||
unsuccessful++;
|
||||
lcr.setStatus("UNKNOWN REF");
|
||||
addResult(lcr);
|
||||
break;
|
||||
case LinkValidationResult.INVALID :
|
||||
unsuccessful++;
|
||||
lcr.setStatus("NOT FOUND");
|
||||
addResult(lcr);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.err.println(message);
|
||||
throw (e);
|
||||
}
|
||||
}
|
||||
|
||||
private Set getLinks() throws FileNotFoundException
|
||||
{
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
PrintWriter errOut = new PrintWriter(baos);
|
||||
BufferedInputStream bin = new BufferedInputStream(new FileInputStream(fileToCheck));
|
||||
try
|
||||
{
|
||||
Tidy tidy = getTidy();
|
||||
tidy.setErrout(errOut);
|
||||
LOG.debug("Processing:" + fileToCheck);
|
||||
org.w3c.dom.Document domDocument = tidy.parseDOM(bin, null);
|
||||
|
||||
// now read a dom4j document from
|
||||
// JTidy's W3C DOM object
|
||||
final DOMReader domReader = new DOMReader();
|
||||
final Document doc = domReader.read(domDocument);
|
||||
|
||||
LOG.debug(baos.toString());
|
||||
|
||||
return findUniqueLinks(doc);
|
||||
}
|
||||
finally
|
||||
{
|
||||
close(bin);
|
||||
close(baos);
|
||||
}
|
||||
}
|
||||
|
||||
private void close(InputStream is)
|
||||
{
|
||||
try
|
||||
{
|
||||
is.close();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
//Don't really care.
|
||||
}
|
||||
}
|
||||
|
||||
private void close(OutputStream os)
|
||||
{
|
||||
try
|
||||
{
|
||||
os.close();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
//Don't really care.
|
||||
}
|
||||
}
|
||||
|
||||
private Set findUniqueLinks(Document doc)
|
||||
{
|
||||
List xpathResults = new LinkedList();
|
||||
|
||||
xpathResults.addAll(doc.selectNodes("//a/@href"));
|
||||
xpathResults.addAll(doc.selectNodes("//img/@src"));
|
||||
|
||||
//<link rel="stylesheet" href="...">
|
||||
xpathResults.addAll(doc.selectNodes("//link/@href"));
|
||||
|
||||
//<script src="http://ar.atwola.com/file/adsWrapper.js">
|
||||
xpathResults.addAll(doc.selectNodes("//script/@src"));
|
||||
|
||||
Set results = new TreeSet();
|
||||
Iterator linkIter = xpathResults.iterator();
|
||||
while (linkIter.hasNext())
|
||||
{
|
||||
Node node = (Node) linkIter.next();
|
||||
String href = node.getText();
|
||||
results.add(href);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private Tidy getTidy()
|
||||
{
|
||||
Tidy tidy = new Tidy();
|
||||
tidy.setMakeClean(true);
|
||||
tidy.setXmlTags(true);
|
||||
tidy.setXmlOut(true);
|
||||
tidy.setXHTML(true);
|
||||
tidy.setQuiet(true);
|
||||
tidy.setShowWarnings(false);
|
||||
return tidy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the message.
|
||||
* @return String
|
||||
*/
|
||||
public String getMessage()
|
||||
{
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the status.
|
||||
* @return int
|
||||
*/
|
||||
public String getStatus()
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the message.
|
||||
* @param message The message to set
|
||||
*/
|
||||
public void setMessage(String message)
|
||||
{
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public List getResults()
|
||||
{
|
||||
return links;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the successful.
|
||||
* @return int
|
||||
*/
|
||||
public int getSuccessful()
|
||||
{
|
||||
return successful;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unsuccessful.
|
||||
* @return int
|
||||
*/
|
||||
public int getUnsuccessful()
|
||||
{
|
||||
return unsuccessful;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
String fileName = fileToCheck.getAbsolutePath();
|
||||
if (fileName.startsWith(base)) {
|
||||
fileName = fileName.substring(base.length() + 1);
|
||||
}
|
||||
|
||||
fileName = fileName.replace('\\', '/');
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public String toXML()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
|
||||
buf.append(" <file>\n");
|
||||
buf.append(" <name><![CDATA[" + getName() + "]]></name>\n");
|
||||
buf.append(" <successful>" + getSuccessful() + "</successful>\n");
|
||||
buf.append(" <unsuccessful>" + getUnsuccessful() + "</unsuccessful>\n");
|
||||
|
||||
Iterator iter = getResults().iterator();
|
||||
while (iter.hasNext())
|
||||
{
|
||||
LinkCheckResult result = (LinkCheckResult) iter.next();
|
||||
buf.append(result.toXML());
|
||||
}
|
||||
|
||||
buf.append(" </file>\n");
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,329 +0,0 @@
|
||||
package org.apache.maven.linkcheck;
|
||||
|
||||
/* ====================================================================
|
||||
* Copyright 2001-2004 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.maven.jelly.MavenJellyContext;
|
||||
import org.apache.maven.linkcheck.validation.FileLinkValidator;
|
||||
import org.apache.maven.linkcheck.validation.HTTPLinkValidator;
|
||||
import org.apache.maven.linkcheck.validation.LinkValidatorManager;
|
||||
import org.apache.maven.linkcheck.validation.MailtoLinkValidator;
|
||||
import org.apache.maven.project.Project;
|
||||
|
||||
/**
|
||||
* The main bean to be called whenever a set of documents should have
|
||||
* their links checked.
|
||||
*
|
||||
* @author <a href="mailto:bwalding@apache.org">Ben Walding</a>
|
||||
* @author <a href="mailto:carlos@apache.org">Carlos Sanchez</a>
|
||||
* @version $Id$
|
||||
*/
|
||||
public class LinkCheck
|
||||
{
|
||||
/** Log */
|
||||
private static final Log LOG = LogFactory.getLog(LinkCheck.class);
|
||||
|
||||
/** Output file for xml document */
|
||||
private File output;
|
||||
|
||||
/** Output encoding for the xml document */
|
||||
private String outputEncoding;
|
||||
|
||||
private File baseDir;
|
||||
private String cache;
|
||||
private String exclude;
|
||||
private Project project;
|
||||
|
||||
/**
|
||||
* Set the base directory for the change log generator.
|
||||
* @param base the base directory
|
||||
*/
|
||||
public void setBasedir(File base)
|
||||
{
|
||||
this.baseDir = base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the base directory for the change log generator.
|
||||
*
|
||||
* @return the base directory
|
||||
*/
|
||||
public File getBasedir()
|
||||
{
|
||||
return baseDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the output file for the log.
|
||||
* @param output the output file
|
||||
*/
|
||||
public void setOutput(File output)
|
||||
{
|
||||
this.output = output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute task.
|
||||
* @throws FileNotFoundException if {@link ChangeLog#base} doesn't exist
|
||||
* @throws IOException if there are problems running CVS
|
||||
* @throws UnsupportedEncodingException if the underlying platform doesn't
|
||||
* support ISO-8859-1 encoding
|
||||
*/
|
||||
private List filesToCheck = null; //of FileToCheck
|
||||
public void doExecute() throws Exception
|
||||
{
|
||||
if (output == null)
|
||||
{
|
||||
throw new NullPointerException("output must be set");
|
||||
}
|
||||
LinkValidatorManager validator = getLinkValidatorManager();
|
||||
|
||||
filesToCheck = new LinkedList();
|
||||
validator.loadCache(cache);
|
||||
List files = new LinkedList();
|
||||
LOG.debug("Locating all files to be checked...");
|
||||
findFiles(files, baseDir);
|
||||
LOG.debug("Located all files to be checked.");
|
||||
Iterator fileIter = files.iterator();
|
||||
while (fileIter.hasNext())
|
||||
{
|
||||
FileToCheck flc = (FileToCheck) fileIter.next();
|
||||
try
|
||||
{
|
||||
filesToCheck.add(flc);
|
||||
LOG.info("Validating " + flc.getName());
|
||||
flc.check(validator);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
createDocument(files);
|
||||
validator.saveCache(cache);
|
||||
}
|
||||
|
||||
public List getFiles()
|
||||
{
|
||||
return filesToCheck;
|
||||
}
|
||||
|
||||
public void findFiles(List allFiles, File base)
|
||||
{
|
||||
FilenameFilter ff = new FilenameFilter()
|
||||
{
|
||||
/**
|
||||
* @see java.io.FilenameFilter#accept(java.io.File, java.lang.String)
|
||||
*/
|
||||
public boolean accept(File dir, String name)
|
||||
{
|
||||
File n = new File(dir, name);
|
||||
if (n.isDirectory())
|
||||
return true;
|
||||
|
||||
if (name.endsWith(".html"))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
File[] f = base.listFiles(ff);
|
||||
|
||||
if (f != null)
|
||||
{
|
||||
for (int i = 0; i < f.length; i++)
|
||||
{
|
||||
File file = f[i];
|
||||
if (file.isDirectory())
|
||||
{
|
||||
findFiles(allFiles, file);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (allFiles.size() % 1000 == 0) {
|
||||
LOG.info("Found " + allFiles.size() + " files so far.");
|
||||
final long MEG = 1024 * 1024;
|
||||
Runtime r = Runtime.getRuntime();
|
||||
LOG.info( " Memory: " + ((r.totalMemory() - r.freeMemory()) / MEG) + "M/" + (r.totalMemory() / MEG) + "M");
|
||||
}
|
||||
//LOG.info(" File - " + file);
|
||||
allFiles.add(new FileToCheck(baseDir, file));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the XML document from the currently available details
|
||||
* @throws FileNotFoundException when the output file previously provided
|
||||
* does not exist
|
||||
* @throws UnsupportedEncodingException when the platform doesn't support
|
||||
* ISO-8859-1 encoding
|
||||
*/
|
||||
private void createDocument(List files) throws Exception
|
||||
{
|
||||
File dir = output.getParentFile();
|
||||
if (dir != null)
|
||||
{
|
||||
dir.mkdirs();
|
||||
}
|
||||
PrintWriter out = new PrintWriter(new OutputStreamWriter(new FileOutputStream(output), getOutputEncoding()));
|
||||
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append("<?xml version=\"1.0\" encoding=\"").append(getOutputEncoding()).append("\" ?>\n");
|
||||
|
||||
out.write(buffer.toString());
|
||||
|
||||
out.write(toXML());
|
||||
out.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the outputEncoding.
|
||||
* @return String
|
||||
*/
|
||||
public String getOutputEncoding()
|
||||
{
|
||||
return outputEncoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the outputEncoding.
|
||||
* @param outputEncoding The outputEncoding to set
|
||||
*/
|
||||
public void setOutputEncoding(String outputEncoding)
|
||||
{
|
||||
this.outputEncoding = outputEncoding;
|
||||
}
|
||||
|
||||
LinkValidatorManager lvm = null;
|
||||
public LinkValidatorManager getLinkValidatorManager()
|
||||
{
|
||||
if (lvm == null)
|
||||
{
|
||||
lvm = new LinkValidatorManager();
|
||||
if (exclude != null) {
|
||||
StringTokenizer st = new StringTokenizer(exclude, " ,\t\n\r\f");
|
||||
String[] tokens = new String[st.countTokens()];
|
||||
for (int i = 0; i < tokens.length; i++) {
|
||||
tokens[i] = st.nextToken();
|
||||
}
|
||||
lvm.setExcludes(tokens);
|
||||
}
|
||||
lvm.addLinkValidator(new FileLinkValidator());
|
||||
// Project is only null in test cases
|
||||
if (getProject() != null) {
|
||||
MavenJellyContext ctx = ((Project) getProject()).getContext();
|
||||
lvm.addLinkValidator(new HTTPLinkValidator(ctx.getProxyHost(), ctx.getProxyPort(), ctx.getProxyUserName(), ctx.getProxyPassword()));
|
||||
}
|
||||
|
||||
lvm.addLinkValidator(new MailtoLinkValidator());
|
||||
lvm.loadCache(cache);
|
||||
}
|
||||
return lvm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cacheFile.
|
||||
* @return String
|
||||
*/
|
||||
public String getCache()
|
||||
{
|
||||
return cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cacheFile.
|
||||
* @param cacheFile The cacheFile to set
|
||||
*/
|
||||
public void setCache(String cache)
|
||||
{
|
||||
this.cache = cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the exclude.
|
||||
* @return String
|
||||
*/
|
||||
public String getExclude()
|
||||
{
|
||||
return exclude;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the exclude, a string with exclude locations delimited by the space
|
||||
* character, the comma character, the tab character, the newline character,
|
||||
* the carriage-return character, and the form-feed character.
|
||||
*
|
||||
* @param exclude
|
||||
* The exclude to set
|
||||
*/
|
||||
public void setExclude(String exclude)
|
||||
{
|
||||
this.exclude = exclude;
|
||||
}
|
||||
|
||||
public String toXML()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
|
||||
buf.append("<linkcheck>\n");
|
||||
|
||||
//buf.append(" <files>\n");
|
||||
for (Iterator iter = getFiles().iterator(); iter.hasNext();)
|
||||
{
|
||||
FileToCheck ftc = (FileToCheck) iter.next();
|
||||
buf.append(ftc.toXML());
|
||||
}
|
||||
//buf.append(" </files>\n");
|
||||
buf.append("</linkcheck>\n");
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Project
|
||||
*/
|
||||
public Object getProject()
|
||||
{
|
||||
return project;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the project.
|
||||
* @param project The project to set
|
||||
*/
|
||||
public void setProject(Object project)
|
||||
{
|
||||
//System.out.println("Setting project: " + project);
|
||||
this.project = (Project) project;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package org.apache.maven.linkcheck;
|
||||
|
||||
/* ====================================================================
|
||||
* Copyright 2001-2004 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.apache.maven.jelly.MavenJellyContext;
|
||||
import org.apache.maven.project.Project;
|
||||
|
||||
/**
|
||||
* @author <a href="bwalding@apache.org">Ben Walding</a>
|
||||
* @version $Id$
|
||||
*/
|
||||
public class LinkCheckCli
|
||||
{
|
||||
public static void main(String args[]) throws Exception
|
||||
{
|
||||
LinkCheckCli lcc = new LinkCheckCli();
|
||||
lcc.doMain(args);
|
||||
}
|
||||
|
||||
private void doMain(String args[]) throws Exception
|
||||
{
|
||||
Project p = new Project();
|
||||
MavenJellyContext ctx = new MavenJellyContext();
|
||||
ctx.setProxyHost(null);
|
||||
p.setContext(ctx);
|
||||
|
||||
LinkCheck lc = new LinkCheck();
|
||||
lc.setBasedir(new File("d:/data"));
|
||||
lc.setOutput(new File("target/linkcheck.xml"));
|
||||
lc.setCache("target/linkcheck.cache");
|
||||
lc.setOutputEncoding("ISO-8859");
|
||||
lc.setExclude("");
|
||||
lc.setProject(p);
|
||||
lc.doExecute();
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
package org.apache.maven.linkcheck;
|
||||
|
||||
/* ====================================================================
|
||||
* Copyright 2001-2004 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
import org.apache.commons.lang.StringEscapeUtils;
|
||||
|
||||
/**
|
||||
* An class containing the results of a single check of a link.
|
||||
* @author <a href="mailto:bwalding@apache.org">Ben Walding</a>
|
||||
* @version $Id$
|
||||
*/
|
||||
public class LinkCheckResult
|
||||
{
|
||||
private String status;
|
||||
private String target;
|
||||
|
||||
/**
|
||||
* Returns the status.
|
||||
* @return String
|
||||
*/
|
||||
public String getStatus()
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the status.
|
||||
* @param status The status to set
|
||||
*/
|
||||
public void setStatus(String status)
|
||||
{
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the target.
|
||||
* @return String
|
||||
*/
|
||||
public String getTarget()
|
||||
{
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the target.
|
||||
* @param target The target to set
|
||||
*/
|
||||
public void setTarget(String target)
|
||||
{
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an XML representation of this link check result
|
||||
* @return xml fragment representation of this result
|
||||
*/
|
||||
public String toXML()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
|
||||
buf.append(" <result>\n");
|
||||
buf.append(" <target>" + StringEscapeUtils.escapeXml(getTarget()) + "</target>\n");
|
||||
buf.append(" <status>" + getStatus() + "</status>\n");
|
||||
buf.append(" </result>\n");
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
package org.apache.maven.linkcheck.validation;
|
||||
|
||||
/* ====================================================================
|
||||
* Copyright 2001-2004 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* A link validator solely for files on the local filesystem.
|
||||
*
|
||||
* @author <a href="mailto:bwalding@apache.org">Ben Walding</a>
|
||||
* @version $Id$
|
||||
*/
|
||||
public class FileLinkValidator implements LinkValidator {
|
||||
private final static LinkValidationResult LVR_INVALID =
|
||||
new LinkValidationResult(LinkValidationResult.INVALID, false);
|
||||
|
||||
private final static LinkValidationResult LVR_VALID =
|
||||
new LinkValidationResult(LinkValidationResult.VALID, false);
|
||||
|
||||
/**
|
||||
* @see org.apache.maven.linkcheck.LinkValidator#validateLink(org.apache.maven.linkcheck.LinkValidationItem)
|
||||
*/
|
||||
public LinkValidationResult validateLink(LinkValidationItem lvi) {
|
||||
File f = getFile(lvi);
|
||||
|
||||
if (f.exists())
|
||||
return LVR_VALID;
|
||||
else
|
||||
return LVR_INVALID;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param lvi
|
||||
* @return File
|
||||
*/
|
||||
protected File getFile(LinkValidationItem lvi) {
|
||||
String link = lvi.getLink();
|
||||
if (link.indexOf('#') != -1) {
|
||||
link = link.substring(0, link.indexOf('#'));
|
||||
|
||||
//If the link was just #fred or similar, then the file is the file it came from
|
||||
//XXX: Theoretically we could even validate the anchor tag?
|
||||
if (link.trim().length() == 0)
|
||||
return lvi.getSource();
|
||||
}
|
||||
|
||||
File f = new File(lvi.getSource().getParentFile(), link);
|
||||
return f;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.maven.linkcheck.LinkValidator#getResourceKey(org.apache.maven.linkcheck.LinkValidationItem)
|
||||
*/
|
||||
public Object getResourceKey(LinkValidationItem lvi) {
|
||||
String link = lvi.getLink();
|
||||
|
||||
if (link.indexOf(':') != -1)
|
||||
return null;
|
||||
|
||||
return getFile(lvi).getAbsolutePath();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,183 +0,0 @@
|
||||
package org.apache.maven.linkcheck.validation;
|
||||
|
||||
/* ====================================================================
|
||||
* Copyright 2001-2004 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
import org.apache.commons.httpclient.Header;
|
||||
import org.apache.commons.httpclient.HostConfiguration;
|
||||
import org.apache.commons.httpclient.HttpClient;
|
||||
import org.apache.commons.httpclient.HttpState;
|
||||
import org.apache.commons.httpclient.StatusLine;
|
||||
import org.apache.commons.httpclient.UsernamePasswordCredentials;
|
||||
import org.apache.commons.httpclient.methods.HeadMethod;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Checks links which are normal URLs
|
||||
* @author <a href="mailto:bwalding@apache.org">Ben Walding</a>
|
||||
* @version $Id$
|
||||
*/
|
||||
public class HTTPLinkValidator implements LinkValidator
|
||||
{
|
||||
/**
|
||||
* Log for debug output
|
||||
*/
|
||||
private static Log LOG = LogFactory.getLog(HTTPLinkValidator.class);
|
||||
|
||||
private static final LinkValidationResult LVR_INVALID =
|
||||
new LinkValidationResult(LinkValidationResult.INVALID, true);
|
||||
|
||||
private static final LinkValidationResult LVR_VALID = new LinkValidationResult(LinkValidationResult.VALID, true);
|
||||
|
||||
private String proxyHost;
|
||||
private int proxyPort;
|
||||
private String proxyUser;
|
||||
private String proxyPass;
|
||||
|
||||
public HTTPLinkValidator(String proxyHost, String proxyPort, String proxyUser, String proxyPass)
|
||||
{
|
||||
if (proxyHost == null || proxyHost.trim().equals(""))
|
||||
{
|
||||
LOG.info("maven-linkcheck-plugin: Not using a proxy");
|
||||
this.proxyHost = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.proxyHost = proxyHost;
|
||||
try{
|
||||
this.proxyPort = Integer.parseInt(proxyPort);
|
||||
}catch(NumberFormatException e){
|
||||
LOG.warn("maven-linkcheck-plugin: Invalid number for Proxy Port:" + proxyPort);
|
||||
LOG.warn("maven-linkcheck-plugin: Proxy Port won't be used.");
|
||||
this.proxyPort = 0;
|
||||
}
|
||||
this.proxyUser = proxyUser;
|
||||
this.proxyPass = proxyPass;
|
||||
LOG.info("maven-linkcheck-plugin: Proxy Host:" + proxyHost);
|
||||
LOG.info("maven-linkcheck-plugin: Proxy Port:" + proxyPort);
|
||||
LOG.info("maven-linkcheck-plugin: Proxy User:" + proxyUser);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.maven.linkcheck.LinkValidator#validateLink(org.apache.maven.linkcheck.LinkValidationItem)
|
||||
*/
|
||||
public LinkValidationResult validateLink(LinkValidationItem lvi)
|
||||
{
|
||||
try
|
||||
{
|
||||
String link = lvi.getLink();
|
||||
LOG.debug("Checking web link:" + link);
|
||||
|
||||
HttpClient cl = new HttpClient();
|
||||
HostConfiguration hc = new HostConfiguration();
|
||||
|
||||
if (proxyHost != null)
|
||||
{
|
||||
hc.setProxy(proxyHost, proxyPort);
|
||||
}
|
||||
HttpState state = new HttpState();
|
||||
|
||||
if (proxyUser != null && proxyPass != null)
|
||||
{
|
||||
state.setProxyCredentials(null, null, new UsernamePasswordCredentials(proxyUser, proxyPass));
|
||||
}
|
||||
|
||||
cl.setHostConfiguration(hc);
|
||||
cl.setState(state);
|
||||
|
||||
// execute the GET
|
||||
HeadMethod hm = checkLink(cl, link);
|
||||
StatusLine sl = hm.getStatusLine();
|
||||
|
||||
if (sl == null) {
|
||||
LOG.info("Unknown error validating link : " + link);
|
||||
return LVR_INVALID;
|
||||
}
|
||||
|
||||
if (hm.getStatusCode() == 302)
|
||||
{
|
||||
Header locationHeader = hm.getResponseHeader("Location");
|
||||
if (locationHeader == null) {
|
||||
LOG.info("Site sent redirect, but did not set Location header");
|
||||
} else {
|
||||
String newLink = locationHeader.getValue();
|
||||
LOG.debug("Following 1 redirect to " + newLink);
|
||||
hm = checkLink(cl, newLink);
|
||||
}
|
||||
}
|
||||
|
||||
//FIXME: This constant is defined somewhere, but I can't remember where...
|
||||
if (hm.getStatusCode() == 200)
|
||||
{
|
||||
return LVR_VALID;
|
||||
}
|
||||
else
|
||||
{
|
||||
String msg = "Received: [" + hm.getStatusCode() + "] for " + link;
|
||||
LOG.info(msg);
|
||||
System.out.println(msg);
|
||||
return LVR_INVALID;
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOG.warn("Error accessing " + lvi.getLink(), e);
|
||||
e.printStackTrace();
|
||||
return LVR_INVALID;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private HeadMethod checkLink(HttpClient cl, String link)
|
||||
{
|
||||
HeadMethod hm = new HeadMethod(link);
|
||||
try
|
||||
{
|
||||
LOG.info("Checking link " + link);
|
||||
hm.setFollowRedirects(true);
|
||||
cl.executeMethod(hm);
|
||||
LOG.debug("Checked link " + link);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOG.warn("Error validating " + link + ": " + e);
|
||||
LOG.debug("Exception was", e);
|
||||
}
|
||||
return hm;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.maven.linkcheck.LinkValidator#getResourceKey(org.apache.maven.linkcheck.LinkValidationItem)
|
||||
*/
|
||||
public Object getResourceKey(LinkValidationItem lvi)
|
||||
{
|
||||
String link = lvi.getLink();
|
||||
|
||||
if (!link.startsWith("http://"))
|
||||
return null;
|
||||
|
||||
int hashPos = link.indexOf("#");
|
||||
if (hashPos != -1)
|
||||
link = link.substring(0, hashPos);
|
||||
|
||||
return link;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
package org.apache.maven.linkcheck.validation;
|
||||
|
||||
/* ====================================================================
|
||||
* Copyright 2001-2004 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bwalding@apache.org">Ben Walding</a>
|
||||
* @version $Id$
|
||||
*/
|
||||
public class LinkValidatorCache {
|
||||
private LinkValidatorManager lvm;
|
||||
private final Map cache = new HashMap();
|
||||
|
||||
public LinkValidatorCache(LinkValidatorManager lvm) {
|
||||
this.lvm = lvm;
|
||||
}
|
||||
public void setCachedResult(Object resourceKey, LinkValidationResult lvr) {
|
||||
cache.put(resourceKey, lvr);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param lvi
|
||||
* @return int Will return a status level, VALID, INVALID, UNKNOWN
|
||||
*/
|
||||
public LinkValidationResult getCachedResult(LinkValidationItem lvi) {
|
||||
Iterator iter = lvm.getValidators().iterator();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
LinkValidator lv = (LinkValidator) iter.next();
|
||||
|
||||
Object resourceKey = lv.getResourceKey(lvi);
|
||||
|
||||
if (resourceKey != null) {
|
||||
return (LinkValidationResult) cache.get(resourceKey);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
public void load(InputStream is) {
|
||||
final LinkValidationResult LVR_VALID =
|
||||
new LinkValidationResult(LinkValidationResult.VALID, true);
|
||||
final LinkValidationResult LVR_INVALID =
|
||||
new LinkValidationResult(LinkValidationResult.INVALID, true);
|
||||
try {
|
||||
Properties p = new Properties();
|
||||
p.load(is);
|
||||
|
||||
Iterator iter = p.keySet().iterator();
|
||||
while (iter.hasNext()) {
|
||||
String key = (String) iter.next();
|
||||
String value = (String) p.getProperty(key);
|
||||
|
||||
if (value.equals("VALID"))
|
||||
cache.put(key, LVR_VALID);
|
||||
|
||||
if (value.equals("INVALID"))
|
||||
cache.put(key, LVR_INVALID);
|
||||
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void save(OutputStream os) {
|
||||
|
||||
try {
|
||||
Properties p = new Properties();
|
||||
Iterator iter = cache.keySet().iterator();
|
||||
while (iter.hasNext()) {
|
||||
String key = (String) iter.next();
|
||||
LinkValidationResult lvr =
|
||||
(LinkValidationResult) cache.get(key);
|
||||
if (lvr.isPersistent()) {
|
||||
if (lvr.getStatus() == LinkValidationResult.VALID) {
|
||||
p.setProperty(key, "VALID");
|
||||
}
|
||||
|
||||
if (lvr.getStatus() == LinkValidationResult.INVALID) {
|
||||
p.setProperty(key, "INVALID");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p.store(os, "LinkCheck Cache");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,173 +0,0 @@
|
||||
package org.apache.maven.linkcheck.validation;
|
||||
|
||||
/* ====================================================================
|
||||
* Copyright 2001-2004 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bwalding@apache.org">Ben Walding</a>
|
||||
* @author <a href="mailto:carlos@apache.org">Carlos Sanchez</a>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
public class LinkValidatorManager {
|
||||
/**
|
||||
* Log for debug output
|
||||
*/
|
||||
private static Log LOG = LogFactory.getLog(LinkValidatorManager.class);
|
||||
|
||||
private List validators = new LinkedList();
|
||||
private LinkValidatorCache cache = new LinkValidatorCache(this);
|
||||
private String[] excludes = new String[0];
|
||||
|
||||
public LinkValidatorManager() {
|
||||
|
||||
}
|
||||
|
||||
public void addLinkValidator(LinkValidator lv) {
|
||||
validators.add(lv);
|
||||
}
|
||||
|
||||
public List getValidators() {
|
||||
return validators;
|
||||
}
|
||||
|
||||
public LinkValidationResult validateLink(LinkValidationItem lvi)
|
||||
throws Exception {
|
||||
{
|
||||
LinkValidationResult status = cache.getCachedResult(lvi);
|
||||
if (status != null) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < excludes.length; i++) {
|
||||
if (excludes[i] != null && lvi.getLink().startsWith(excludes[i])) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Excluded " + lvi.getLink());
|
||||
}
|
||||
return new LinkValidationResult(LinkValidationResult.VALID, false);
|
||||
}
|
||||
}
|
||||
|
||||
Iterator iter = validators.iterator();
|
||||
while (iter.hasNext()) {
|
||||
LinkValidator lv = (LinkValidator) iter.next();
|
||||
|
||||
Object resourceKey = lv.getResourceKey(lvi);
|
||||
|
||||
if (resourceKey != null) {
|
||||
|
||||
LinkValidationResult lvr = lv.validateLink(lvi);
|
||||
|
||||
if (lvr.getStatus() == LinkValidationResult.NOTMINE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cache.setCachedResult(resourceKey, lvr);
|
||||
return lvr;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
LOG.info("Unable to validate link : " + lvi.getLink());
|
||||
return new LinkValidationResult(LinkValidationResult.UNKNOWN, false);
|
||||
}
|
||||
|
||||
public void loadCache(String cacheFilename) {
|
||||
try {
|
||||
File f = new File(cacheFilename);
|
||||
if (f.exists()) {
|
||||
BufferedInputStream is = new BufferedInputStream(
|
||||
new FileInputStream(cacheFilename));
|
||||
this.cache.load(is);
|
||||
is.close();
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void saveCache(String cacheFilename) {
|
||||
try {
|
||||
File cacheFile = new File(cacheFilename);
|
||||
File dir = cacheFile.getParentFile();
|
||||
if (dir != null) {
|
||||
dir.mkdirs();
|
||||
}
|
||||
BufferedOutputStream os = new BufferedOutputStream(
|
||||
new FileOutputStream(cacheFilename));
|
||||
this.cache.save(os);
|
||||
os.close();
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the exclude.
|
||||
* @return String
|
||||
* @deprecated use getExcludes()
|
||||
*/
|
||||
public String getExclude() {
|
||||
return excludes[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the exclude.
|
||||
* @param exclude The exclude to set
|
||||
* @deprecated use setExcludes()
|
||||
*/
|
||||
public void setExclude(String exclude) {
|
||||
this.excludes = new String[] {exclude};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the excludes.
|
||||
* @return String[]
|
||||
*/
|
||||
public String[] getExcludes() {
|
||||
return excludes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the excludes.
|
||||
* @param excludes The excludes to set
|
||||
*/
|
||||
public void setExcludes(String[] excludes) {
|
||||
this.excludes = excludes;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,327 @@
|
||||
package org.apache.maven.plugin.linkcheck;
|
||||
|
||||
/* ====================================================================
|
||||
* Copyright 2001-2005 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.maven.plugin.linkcheck.validation.LinkValidationItem;
|
||||
import org.apache.maven.plugin.linkcheck.validation.LinkValidationResult;
|
||||
import org.apache.maven.plugin.linkcheck.validation.LinkValidatorManager;
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.Node;
|
||||
import org.dom4j.io.DOMReader;
|
||||
import org.w3c.tidy.Tidy;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bwalding@apache.org">Ben Walding</a>
|
||||
* @author <a href="mailto:aheritier@apache.org">Arnaud Heritier</a>
|
||||
* @version $Id$
|
||||
*/
|
||||
public final class FileToCheck
|
||||
{
|
||||
/**
|
||||
* Log for debug output
|
||||
*/
|
||||
private static final Log LOG = LogFactory.getLog( FileToCheck.class );
|
||||
|
||||
public static final String STATUS_UNKNOWN = null;
|
||||
|
||||
public static final String STATUS_JTIDY_FAILURE = "Unable to tidy source";
|
||||
|
||||
public static final String STATUS_OK = "OK";
|
||||
|
||||
private String base;
|
||||
|
||||
private File fileToCheck;
|
||||
|
||||
private List links = new LinkedList();
|
||||
|
||||
private String message = "";
|
||||
|
||||
private String status = STATUS_OK;
|
||||
|
||||
private int successful;
|
||||
|
||||
private int unsuccessful;
|
||||
|
||||
private Set getLinks()
|
||||
throws FileNotFoundException
|
||||
{
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
PrintWriter errOut = new PrintWriter( baos );
|
||||
BufferedInputStream bin = new BufferedInputStream( new FileInputStream( fileToCheck ) );
|
||||
try
|
||||
{
|
||||
Tidy tidy = getTidy();
|
||||
tidy.setErrout( errOut );
|
||||
org.w3c.dom.Document domDocument = tidy.parseDOM( bin, null );
|
||||
// now read a dom4j document from
|
||||
// JTidy's W3C DOM object
|
||||
final DOMReader domReader = new DOMReader();
|
||||
final Document doc = domReader.read( domDocument );
|
||||
return findUniqueLinks( doc );
|
||||
}
|
||||
finally
|
||||
{
|
||||
close( bin );
|
||||
close( baos );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the message.
|
||||
* @return String
|
||||
*/
|
||||
public String getMessage()
|
||||
{
|
||||
return message;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
String fileName = fileToCheck.getAbsolutePath();
|
||||
if ( fileName.startsWith( base ) )
|
||||
{
|
||||
fileName = fileName.substring( base.length() + 1 );
|
||||
}
|
||||
|
||||
fileName = fileName.replace( '\\', '/' );
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public List getResults()
|
||||
{
|
||||
return links;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the status.
|
||||
* @return int
|
||||
*/
|
||||
public String getStatus()
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the successful.
|
||||
* @return int
|
||||
*/
|
||||
public int getSuccessful()
|
||||
{
|
||||
return successful;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unsuccessful.
|
||||
* @return int
|
||||
*/
|
||||
public int getUnsuccessful()
|
||||
{
|
||||
return unsuccessful;
|
||||
}
|
||||
|
||||
public FileToCheck( File baseFile, File fileToCheck )
|
||||
{
|
||||
this.base = baseFile.getAbsolutePath();
|
||||
this.fileToCheck = fileToCheck;
|
||||
}
|
||||
|
||||
public void check( LinkValidatorManager lvm )
|
||||
throws Exception
|
||||
{
|
||||
successful = 0;
|
||||
unsuccessful = 0;
|
||||
status = STATUS_OK;
|
||||
message = "";
|
||||
if ( LOG.isDebugEnabled() )
|
||||
{
|
||||
LOG.debug( "Validating " + getName() );
|
||||
}
|
||||
try
|
||||
{
|
||||
final Set hrefs;
|
||||
try
|
||||
{
|
||||
hrefs = getLinks();
|
||||
}
|
||||
catch ( Throwable t )
|
||||
{
|
||||
//We catch Throwable, because there is a chance that the domReader will throw
|
||||
//a stack overflow exception for some files
|
||||
if ( LOG.isDebugEnabled() )
|
||||
LOG.error( "Received: [" + t + "] in page [" + getName() + "]", t );
|
||||
else
|
||||
LOG.error( "Received: [" + t + "] in page [" + getName() + "]" );
|
||||
LinkCheckResult lcr = new LinkCheckResult();
|
||||
lcr.setStatus( "PARSE FAILURE" );
|
||||
lcr.setTarget( "N/A" );
|
||||
addResult( lcr );
|
||||
return;
|
||||
}
|
||||
String href;
|
||||
LinkCheckResult lcr;
|
||||
LinkValidationItem lvi;
|
||||
LinkValidationResult result;
|
||||
for ( Iterator iter = hrefs.iterator(); iter.hasNext(); )
|
||||
{
|
||||
href = (String) iter.next();
|
||||
lcr = new LinkCheckResult();
|
||||
lvi = new LinkValidationItem( fileToCheck, href );
|
||||
result = lvm.validateLink( lvi );
|
||||
lcr.setTarget( href );
|
||||
lcr.setErrorMessage( result.getErrorMessage() );
|
||||
switch ( result.getStatus() )
|
||||
{
|
||||
case LinkValidationResult.VALID:
|
||||
successful++;
|
||||
lcr.setStatus( "valid" );
|
||||
addResult( lcr ); //At some point we won't want to store valid links. The tests require that we do at present
|
||||
break;
|
||||
case LinkValidationResult.UNKNOWN:
|
||||
unsuccessful++;
|
||||
lcr.setStatus( "unknown" );
|
||||
addResult( lcr );
|
||||
break;
|
||||
case LinkValidationResult.ERROR:
|
||||
unsuccessful++;
|
||||
lcr.setStatus( "error" );
|
||||
addResult( lcr );
|
||||
break;
|
||||
case LinkValidationResult.WARNING:
|
||||
unsuccessful++;
|
||||
lcr.setStatus( "warning" );
|
||||
addResult( lcr );
|
||||
break;
|
||||
}
|
||||
}
|
||||
href = null;
|
||||
lcr = null;
|
||||
lvi = null;
|
||||
result = null;
|
||||
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
LOG.error( message );
|
||||
throw ( e );
|
||||
}
|
||||
}
|
||||
|
||||
public String toXML()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append( " <file>\n" );
|
||||
buf.append( " <name><![CDATA[" + getName() + "]]></name>\n" );
|
||||
buf.append( " <successful>" + getSuccessful() + "</successful>\n" );
|
||||
buf.append( " <unsuccessful>" + getUnsuccessful() + "</unsuccessful>\n" );
|
||||
Iterator iter = getResults().iterator();
|
||||
LinkCheckResult result;
|
||||
while ( iter.hasNext() )
|
||||
{
|
||||
result = (LinkCheckResult) iter.next();
|
||||
buf.append( result.toXML() );
|
||||
}
|
||||
buf.append( " </file>\n" );
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private void addResult( LinkCheckResult lcr )
|
||||
{
|
||||
this.links.add( lcr );
|
||||
}
|
||||
|
||||
private void close( InputStream is )
|
||||
{
|
||||
try
|
||||
{
|
||||
is.close();
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
//Don't really care.
|
||||
}
|
||||
}
|
||||
|
||||
private void close( OutputStream os )
|
||||
{
|
||||
try
|
||||
{
|
||||
os.close();
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
//Don't really care.
|
||||
}
|
||||
}
|
||||
|
||||
private Set findUniqueLinks( Document doc )
|
||||
{
|
||||
List xpathResults = new LinkedList();
|
||||
|
||||
xpathResults.addAll( doc.selectNodes( "//a/@href" ) );
|
||||
xpathResults.addAll( doc.selectNodes( "//img/@src" ) );
|
||||
|
||||
xpathResults.addAll( doc.selectNodes( "//link/@href" ) );
|
||||
|
||||
xpathResults.addAll( doc.selectNodes( "//script/@src" ) );
|
||||
|
||||
Set results = new TreeSet();
|
||||
Iterator linkIter = xpathResults.iterator();
|
||||
Node node = null;
|
||||
String href = null;
|
||||
while ( linkIter.hasNext() )
|
||||
{
|
||||
node = (Node) linkIter.next();
|
||||
href = node.getText();
|
||||
results.add( href );
|
||||
}
|
||||
xpathResults = null;
|
||||
linkIter = null;
|
||||
node = null;
|
||||
href = null;
|
||||
return results;
|
||||
}
|
||||
|
||||
private Tidy getTidy()
|
||||
{
|
||||
Tidy tidy = new Tidy();
|
||||
tidy.setMakeClean( true );
|
||||
tidy.setXmlTags( true );
|
||||
tidy.setXmlOut( true );
|
||||
tidy.setXHTML( true );
|
||||
tidy.setQuiet( true );
|
||||
tidy.setShowWarnings( false );
|
||||
return tidy;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,385 @@
|
||||
package org.apache.maven.plugin.linkcheck;
|
||||
|
||||
/* ====================================================================
|
||||
* Copyright 2001-2005 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.maven.jelly.MavenJellyContext;
|
||||
import org.apache.maven.plugin.linkcheck.validation.FileLinkValidator;
|
||||
import org.apache.maven.plugin.linkcheck.validation.LinkValidatorManager;
|
||||
import org.apache.maven.plugin.linkcheck.validation.MailtoLinkValidator;
|
||||
import org.apache.maven.plugin.linkcheck.validation.OfflineHTTPLinkValidator;
|
||||
import org.apache.maven.plugin.linkcheck.validation.OnlineHTTPLinkValidator;
|
||||
import org.apache.maven.project.Project;
|
||||
|
||||
/**
|
||||
* The main bean to be called whenever a set of documents should have
|
||||
* their links checked.
|
||||
*
|
||||
* @author <a href="mailto:bwalding@apache.org">Ben Walding</a>
|
||||
* @author <a href="mailto:carlos@apache.org">Carlos Sanchez</a>
|
||||
* @author <a href="mailto:aheritier@apache.org">Arnaud Heritier</a>
|
||||
* @version $Id$
|
||||
*/
|
||||
public final class LinkCheck
|
||||
{
|
||||
/** Log */
|
||||
private static final Log LOG = LogFactory.getLog( LinkCheck.class );
|
||||
|
||||
private static final FilenameFilter CUSTOM_FF = new LinkCheck.CustomFilenameFilter();
|
||||
|
||||
private static final long MEG = 1024 * 1024;
|
||||
|
||||
private File basedir;
|
||||
|
||||
private String cache;
|
||||
|
||||
private String exclude;
|
||||
|
||||
private List filesToCheck = null;
|
||||
|
||||
private LinkValidatorManager lvm = null;
|
||||
|
||||
/**
|
||||
* Output file for xml document
|
||||
*/
|
||||
private File output;
|
||||
|
||||
/**
|
||||
* Output encoding for the xml document
|
||||
*/
|
||||
private String outputEncoding;
|
||||
|
||||
private Project project;
|
||||
|
||||
/**
|
||||
* Get the base directory for the change log generator.
|
||||
*
|
||||
* @return the base directory
|
||||
*/
|
||||
public File getBasedir()
|
||||
{
|
||||
return basedir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the base directory for the change log generator.
|
||||
* @param base the base directory
|
||||
*/
|
||||
public void setBasedir( File base )
|
||||
{
|
||||
this.basedir = base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cacheFile.
|
||||
* @return String
|
||||
*/
|
||||
public String getCache()
|
||||
{
|
||||
return cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cacheFile.
|
||||
* @param cacheFile The cacheFile to set
|
||||
*/
|
||||
public void setCache( String cache )
|
||||
{
|
||||
this.cache = cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the exclude.
|
||||
* @return String
|
||||
*/
|
||||
public String getExclude()
|
||||
{
|
||||
return exclude;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the exclude, a string with exclude locations delimited by the space
|
||||
* character, the comma character, the tab character, the newline character,
|
||||
* the carriage-return character, and the form-feed character.
|
||||
*
|
||||
* @param exclude
|
||||
* The exclude to set
|
||||
*/
|
||||
public void setExclude( String exclude )
|
||||
{
|
||||
this.exclude = exclude;
|
||||
}
|
||||
|
||||
public List getFiles()
|
||||
{
|
||||
return filesToCheck;
|
||||
}
|
||||
|
||||
public LinkValidatorManager getLinkValidatorManager()
|
||||
{
|
||||
if ( lvm == null )
|
||||
{
|
||||
lvm = new LinkValidatorManager();
|
||||
if ( exclude != null )
|
||||
{
|
||||
StringTokenizer st = new StringTokenizer( exclude, " ,\t\n\r\f" );
|
||||
String[] tokens = new String[st.countTokens()];
|
||||
for ( int i = 0; i < tokens.length; i++ )
|
||||
{
|
||||
tokens[i] = st.nextToken();
|
||||
}
|
||||
lvm.setExcludes( tokens );
|
||||
tokens = null;
|
||||
st = null;
|
||||
}
|
||||
lvm.addLinkValidator( new FileLinkValidator() );
|
||||
// Project is only null in test cases
|
||||
if ( getProject() != null )
|
||||
{
|
||||
MavenJellyContext ctx = ( (Project) getProject() ).getContext();
|
||||
if ( ctx.getOnline().booleanValue() )
|
||||
{
|
||||
lvm.addLinkValidator( new OnlineHTTPLinkValidator( ctx.getProxyHost(), ctx.getProxyPort(), ctx
|
||||
.getProxyUserName(), ctx.getProxyPassword() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
lvm.addLinkValidator( new OfflineHTTPLinkValidator() );
|
||||
|
||||
}
|
||||
ctx = null;
|
||||
}
|
||||
lvm.addLinkValidator( new MailtoLinkValidator() );
|
||||
}
|
||||
return lvm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the output file for the log.
|
||||
* @param output the output file
|
||||
*/
|
||||
public void setOutput( File output )
|
||||
{
|
||||
this.output = output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the outputEncoding.
|
||||
* @return String
|
||||
*/
|
||||
public String getOutputEncoding()
|
||||
{
|
||||
return outputEncoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the outputEncoding.
|
||||
* @param outputEncoding The outputEncoding to set
|
||||
*/
|
||||
public void setOutputEncoding( String outputEncoding )
|
||||
{
|
||||
this.outputEncoding = outputEncoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Project
|
||||
*/
|
||||
public Object getProject()
|
||||
{
|
||||
return project;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the project.
|
||||
* @param project The project to set
|
||||
*/
|
||||
public void setProject( Object project )
|
||||
{
|
||||
this.project = (Project) project;
|
||||
}
|
||||
|
||||
public void findFiles( List allFiles, File base )
|
||||
{
|
||||
File[] f = base.listFiles( CUSTOM_FF );
|
||||
if ( f != null )
|
||||
{
|
||||
File file;
|
||||
for ( int i = 0; i < f.length; i++ )
|
||||
{
|
||||
file = f[i];
|
||||
if ( file.isDirectory() )
|
||||
{
|
||||
findFiles( allFiles, file );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( LOG.isDebugEnabled() )
|
||||
{
|
||||
LOG.debug( " File - " + file );
|
||||
}
|
||||
allFiles.add( new FileToCheck( basedir, file ) );
|
||||
if ( allFiles.size() % 100 == 0 )
|
||||
{
|
||||
LOG.info( "Found " + allFiles.size() + " files so far." );
|
||||
}
|
||||
}
|
||||
}
|
||||
file = null;
|
||||
}
|
||||
f = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute task.
|
||||
* @throws FileNotFoundException if {@link ChangeLog#base} doesn't exist
|
||||
* @throws IOException if there are problems running CVS
|
||||
* @throws UnsupportedEncodingException if the underlying platform doesn't
|
||||
* support ISO-8859-1 encoding
|
||||
*/
|
||||
|
||||
public void doExecute()
|
||||
throws FileNotFoundException, IOException, UnsupportedEncodingException
|
||||
{
|
||||
if ( output == null )
|
||||
{
|
||||
throw new NullPointerException( "output must be set" );
|
||||
}
|
||||
if ( LOG.isDebugEnabled() )
|
||||
{
|
||||
displayMemoryConsumption();
|
||||
}
|
||||
LinkValidatorManager validator = getLinkValidatorManager();
|
||||
filesToCheck = new LinkedList();
|
||||
validator.loadCache( cache );
|
||||
List files = new LinkedList();
|
||||
LOG.debug( "Locating all files to be checked..." );
|
||||
findFiles( files, basedir );
|
||||
LOG.debug( "Located all files to be checked." );
|
||||
LOG.info( "Found " + files.size() + " files to check." );
|
||||
displayMemoryConsumption();
|
||||
LOG.info( "Begin to check links in files..." );
|
||||
Iterator fileIter = files.iterator();
|
||||
FileToCheck flc;
|
||||
while ( fileIter.hasNext() )
|
||||
{
|
||||
flc = (FileToCheck) fileIter.next();
|
||||
try
|
||||
{
|
||||
filesToCheck.add( flc );
|
||||
flc.check( validator );
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
LOG.error( "Error while checking : " + flc.getName(), e );
|
||||
}
|
||||
}
|
||||
flc = null;
|
||||
LOG.info( "Links checked." );
|
||||
displayMemoryConsumption();
|
||||
createDocument( files );
|
||||
validator.saveCache( cache );
|
||||
displayMemoryConsumption();
|
||||
}
|
||||
|
||||
public String toXML()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append( "<linkcheck>\n" );
|
||||
FileToCheck ftc;
|
||||
for ( Iterator iter = getFiles().iterator(); iter.hasNext(); )
|
||||
{
|
||||
ftc = (FileToCheck) iter.next();
|
||||
buf.append( ftc.toXML() );
|
||||
}
|
||||
ftc = null;
|
||||
buf.append( "</linkcheck>\n" );
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private void displayMemoryConsumption()
|
||||
{
|
||||
if ( LOG.isDebugEnabled() )
|
||||
{
|
||||
Runtime r = Runtime.getRuntime();
|
||||
LOG.debug( "Memory: " + ( ( r.totalMemory() - r.freeMemory() ) / MEG ) + "M/" + ( r.totalMemory() / MEG )
|
||||
+ "M" );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the XML document from the currently available details
|
||||
* @throws FileNotFoundException when the output file previously provided
|
||||
* does not exist
|
||||
* @throws UnsupportedEncodingException when the platform doesn't support
|
||||
* ISO-8859-1 encoding
|
||||
*/
|
||||
private void createDocument( List files )
|
||||
throws FileNotFoundException, UnsupportedEncodingException
|
||||
|
||||
{
|
||||
File dir = output.getParentFile();
|
||||
if ( dir != null )
|
||||
{
|
||||
dir.mkdirs();
|
||||
}
|
||||
PrintWriter out = new PrintWriter( new OutputStreamWriter( new FileOutputStream( output ), getOutputEncoding() ) );
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append( "<?xml version=\"1.0\" encoding=\"" ).append( getOutputEncoding() ).append( "\" ?>\n" );
|
||||
out.write( buffer.toString() );
|
||||
out.write( toXML() );
|
||||
out.close();
|
||||
out = null;
|
||||
buffer = null;
|
||||
dir = null;
|
||||
}
|
||||
|
||||
/** Custom FilenameFilter used to search html files */
|
||||
static class CustomFilenameFilter
|
||||
implements FilenameFilter
|
||||
{
|
||||
/**
|
||||
* @see java.io.FilenameFilter#accept(java.io.File, java.lang.String)
|
||||
*/
|
||||
public boolean accept( File dir, String name )
|
||||
{
|
||||
File n = new File( dir, name );
|
||||
if ( n.isDirectory() )
|
||||
return true;
|
||||
if ( name.endsWith( ".html" ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package org.apache.maven.plugin.linkcheck;
|
||||
|
||||
/* ====================================================================
|
||||
* Copyright 2001-2006 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
import org.apache.commons.lang.StringEscapeUtils;
|
||||
|
||||
/**
|
||||
* An class containing the results of a single check of a link.
|
||||
* @author <a href="mailto:bwalding@apache.org">Ben Walding</a>
|
||||
* @author <a href="mailto:aheritier@apache.org">Arnaud Heritier</a>
|
||||
* @version $Id$
|
||||
*/
|
||||
public final class LinkCheckResult
|
||||
{
|
||||
private String status;
|
||||
|
||||
private String target;
|
||||
|
||||
private String errorMessage;
|
||||
|
||||
/**
|
||||
* Returns the status.
|
||||
* @return String
|
||||
*/
|
||||
public String getStatus()
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the status.
|
||||
* @param status The status to set
|
||||
*/
|
||||
public void setStatus( String status )
|
||||
{
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the target.
|
||||
* @return String
|
||||
*/
|
||||
public String getTarget()
|
||||
{
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the target.
|
||||
* @param target The target to set
|
||||
*/
|
||||
public void setTarget( String target )
|
||||
{
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the errorMessage.
|
||||
*/
|
||||
public String getErrorMessage()
|
||||
{
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param errorMessage The errorMessage to set.
|
||||
*/
|
||||
public void setErrorMessage( String errorMessage )
|
||||
{
|
||||
this.errorMessage = errorMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an XML representation of this link check result
|
||||
* @return xml fragment representation of this result
|
||||
*/
|
||||
public String toXML()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append( " <result>\n" );
|
||||
buf.append( " <target>" + StringEscapeUtils.escapeXml( getTarget() ) + "</target>\n" );
|
||||
buf.append( " <status>" + getStatus() + "</status>\n" );
|
||||
buf.append( " <errorMessage>" + StringEscapeUtils.escapeXml( getErrorMessage() ) + "</errorMessage>\n" );
|
||||
buf.append( " </result>\n" );
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package org.apache.maven.plugin.linkcheck.validation;
|
||||
|
||||
/* ====================================================================
|
||||
* Copyright 2001-2006 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* A link validator solely for files on the local filesystem.
|
||||
*
|
||||
* @author <a href="mailto:bwalding@apache.org">Ben Walding</a>
|
||||
* @author <a href="mailto:aheritier@apache.org">Arnaud Heritier</a>
|
||||
* @version $Id$
|
||||
*/
|
||||
public final class FileLinkValidator
|
||||
implements LinkValidator
|
||||
{
|
||||
/**
|
||||
* @see org.apache.maven.plugin.linkcheck.LinkValidator#validateLink(org.apache.maven.plugin.linkcheck.LinkValidationItem)
|
||||
*/
|
||||
public LinkValidationResult validateLink( LinkValidationItem lvi )
|
||||
{
|
||||
File f = getFile( lvi );
|
||||
if ( f.exists() )
|
||||
return new LinkValidationResult( LinkValidationResult.VALID, false, "" );
|
||||
else
|
||||
return new LinkValidationResult( LinkValidationResult.ERROR, false, "doesn't exist." );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.maven.plugin.linkcheck.LinkValidator#getResourceKey(org.apache.maven.plugin.linkcheck.LinkValidationItem)
|
||||
*/
|
||||
public Object getResourceKey( LinkValidationItem lvi )
|
||||
{
|
||||
String link = lvi.getLink();
|
||||
// If we find an http(s) link or a mail link, it's not good
|
||||
if ( link.startsWith( "http://" ) || link.startsWith( "https://" ) || link.indexOf( '@' ) != -1 )
|
||||
return null;
|
||||
return getFile( lvi ).getAbsolutePath();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param lvi
|
||||
* @return File
|
||||
*/
|
||||
protected File getFile( LinkValidationItem lvi )
|
||||
{
|
||||
String link = lvi.getLink();
|
||||
if ( link.indexOf( '#' ) != -1 )
|
||||
{
|
||||
link = link.substring( 0, link.indexOf( '#' ) );
|
||||
|
||||
//If the link was just #fred or similar, then the file is the file it came from
|
||||
//XXX: Theoretically we could even validate the anchor tag?
|
||||
if ( link.trim().length() == 0 )
|
||||
return lvi.getSource();
|
||||
}
|
||||
File f = new File( lvi.getSource().getParentFile(), link );
|
||||
return f;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package org.apache.maven.linkcheck.validation;
|
||||
package org.apache.maven.plugin.linkcheck.validation;
|
||||
|
||||
/* ====================================================================
|
||||
* Copyright 2001-2004 The Apache Software Foundation.
|
||||
* Copyright 2001-2006 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,27 +17,28 @@ package org.apache.maven.linkcheck.validation;
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Checks links which are normal URLs
|
||||
* @author <a href="mailto:bwalding@apache.org">Ben Walding</a>
|
||||
* @author <a href="mailto:aheritier@apache.org">Arnaud Heritier</a>
|
||||
* @version $Id$
|
||||
*
|
||||
* Validates mailto links
|
||||
*/
|
||||
public class MailtoLinkValidator implements LinkValidator {
|
||||
private static final LinkValidationResult LVR =
|
||||
new LinkValidationResult(LinkValidationResult.VALID, false);
|
||||
public abstract class HTTPLinkValidator
|
||||
implements LinkValidator
|
||||
{
|
||||
/**
|
||||
* @see org.apache.maven.linkcheck.validation.LinkValidator#validateLink(org.apache.maven.linkcheck.validation.LinkValidationItem)
|
||||
* @see org.apache.maven.plugin.linkcheck.LinkValidator#getResourceKey(org.apache.maven.plugin.linkcheck.LinkValidationItem)
|
||||
*/
|
||||
public LinkValidationResult validateLink(LinkValidationItem lvi)
|
||||
throws Exception {
|
||||
return LVR;
|
||||
}
|
||||
/**
|
||||
* @see org.apache.maven.linkcheck.validation.LinkValidator#getResourceKey(org.apache.maven.linkcheck.validation.LinkValidationItem)
|
||||
*/
|
||||
public Object getResourceKey(LinkValidationItem lvi) {
|
||||
return lvi.getLink();
|
||||
public Object getResourceKey( LinkValidationItem lvi )
|
||||
{
|
||||
String link = lvi.getLink();
|
||||
if ( !link.startsWith( "http://" ) && !link.startsWith( "https://" ) )
|
||||
return null;
|
||||
int hashPos = link.indexOf( "#" );
|
||||
if ( hashPos != -1 )
|
||||
link = link.substring( 0, hashPos );
|
||||
return link;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package org.apache.maven.linkcheck.validation;
|
||||
package org.apache.maven.plugin.linkcheck.validation;
|
||||
|
||||
/* ====================================================================
|
||||
* Copyright 2001-2004 The Apache Software Foundation.
|
||||
* Copyright 2001-2005 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,6 +21,7 @@ import java.io.File;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bwalding@apache.org">Ben Walding</a>
|
||||
* @author <a href="mailto:aheritier@apache.org">Arnaud Heritier</a>
|
||||
* @version $Id$
|
||||
*/
|
||||
public class LinkValidationItem {
|
||||
@@ -40,6 +41,22 @@ public class LinkValidationItem {
|
||||
this.link = link;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the link.
|
||||
* @return String
|
||||
*/
|
||||
public String getLink() {
|
||||
return link;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the source.
|
||||
* @return File
|
||||
*/
|
||||
public File getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@@ -61,22 +78,5 @@ public class LinkValidationItem {
|
||||
public int hashCode() {
|
||||
return source.hashCode() ^ link.hashCode();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the link.
|
||||
* @return String
|
||||
*/
|
||||
public String getLink() {
|
||||
return link;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the source.
|
||||
* @return File
|
||||
*/
|
||||
public File getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
package org.apache.maven.linkcheck.validation;
|
||||
package org.apache.maven.plugin.linkcheck.validation;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/* ====================================================================
|
||||
* Copyright 2001-2004 The Apache Software Foundation.
|
||||
* Copyright 2001-2005 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,42 +20,69 @@ package org.apache.maven.linkcheck.validation;
|
||||
*/
|
||||
|
||||
/**
|
||||
* <b>This is an immutable class.</b><br/>
|
||||
* <p>
|
||||
* This class is used to return status responses from the
|
||||
* validation handlers. A persistent result means that it
|
||||
* can be stored in the persistent cache and used across runs.
|
||||
* </p>
|
||||
* @author <a href="mailto:bwalding@apache.org">Ben Walding</a>
|
||||
* @author <a href="mailto:aheritier@apache.org">Arnaud Heritier</a>
|
||||
* @version $Id$
|
||||
*/
|
||||
public class LinkValidationResult {
|
||||
public class LinkValidationResult
|
||||
implements Serializable
|
||||
{
|
||||
public static final int NOTMINE = 0;
|
||||
public static final int INVALID = 1;
|
||||
public static final int VALID = 2;
|
||||
|
||||
public static final int ERROR = 1;
|
||||
|
||||
public static final int VALID = 2;
|
||||
|
||||
public static final int UNKNOWN = 3;
|
||||
|
||||
|
||||
public static final int WARNING = 4;
|
||||
|
||||
private final boolean persistent;
|
||||
|
||||
private final int status;
|
||||
|
||||
public LinkValidationResult(int status, boolean persistent) {
|
||||
this.status = status;
|
||||
this.persistent = persistent;
|
||||
}
|
||||
|
||||
public boolean isPersistent() {
|
||||
|
||||
private final String errorMessage;
|
||||
|
||||
public boolean isPersistent()
|
||||
{
|
||||
return persistent;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the status.
|
||||
* @return int
|
||||
*/
|
||||
public int getStatus() {
|
||||
public int getStatus()
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Returns the errorMessage.
|
||||
*/
|
||||
public String getErrorMessage()
|
||||
{
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
public LinkValidationResult( int status, boolean persistent, String errorMessage )
|
||||
{
|
||||
this.status = status;
|
||||
this.persistent = persistent;
|
||||
this.errorMessage = errorMessage;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
return persistent + "/" + status + "/" + errorMessage;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package org.apache.maven.linkcheck.validation;
|
||||
package org.apache.maven.plugin.linkcheck.validation;
|
||||
|
||||
/* ====================================================================
|
||||
* Copyright 2001-2004 The Apache Software Foundation.
|
||||
* Copyright 2001-2005 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,19 +19,21 @@ package org.apache.maven.linkcheck.validation;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bwalding@apache.org">Ben Walding</a>
|
||||
* @author <a href="mailto:aheritier@apache.org">Arnaud Heritier</a>
|
||||
* @version $Id$
|
||||
*/
|
||||
public interface LinkValidator {
|
||||
|
||||
public interface LinkValidator
|
||||
{
|
||||
|
||||
/**
|
||||
* If getResource(lvi) returned null, this will NOT be called.
|
||||
* @param lvi
|
||||
* @return int
|
||||
* @throws Exception
|
||||
*/
|
||||
public LinkValidationResult validateLink(LinkValidationItem lvi) throws Exception;
|
||||
|
||||
|
||||
public LinkValidationResult validateLink( LinkValidationItem lvi )
|
||||
throws Exception;
|
||||
|
||||
/**
|
||||
* The resource key is used by the cache to determine if it really needs to
|
||||
* validate the link. No actual validation should be done at this point.
|
||||
@@ -39,5 +41,5 @@ public interface LinkValidator {
|
||||
* @return Object null if this validator should not be doing this work.
|
||||
* @throws Exception
|
||||
*/
|
||||
public Object getResourceKey(LinkValidationItem lvi);
|
||||
public Object getResourceKey( LinkValidationItem lvi );
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
package org.apache.maven.plugin.linkcheck.validation;
|
||||
|
||||
/* ====================================================================
|
||||
* Copyright 2001-2005 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InvalidClassException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bwalding@apache.org">Ben Walding</a>
|
||||
* @author <a href="mailto:carlos@apache.org">Carlos Sanchez</a>
|
||||
* @author <a href="mailto:aheritier@apache.org">Arnaud Heritier</a>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
public class LinkValidatorManager
|
||||
implements Serializable
|
||||
{
|
||||
/**
|
||||
* Log for debug output
|
||||
*/
|
||||
private static Log LOG = LogFactory.getLog( LinkValidatorManager.class );
|
||||
|
||||
private List validators = new LinkedList();
|
||||
|
||||
private String[] excludes = new String[0];
|
||||
|
||||
private Map cache = new HashMap();
|
||||
|
||||
public LinkValidatorManager()
|
||||
{
|
||||
}
|
||||
|
||||
public List getValidators()
|
||||
{
|
||||
return validators;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the exclude.
|
||||
* @return String
|
||||
* @deprecated use getExcludes()
|
||||
*/
|
||||
public String getExclude()
|
||||
{
|
||||
return excludes[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the exclude.
|
||||
* @param exclude The exclude to set
|
||||
* @deprecated use setExcludes()
|
||||
*/
|
||||
public void setExclude( String exclude )
|
||||
{
|
||||
this.excludes = new String[] { exclude };
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the excludes.
|
||||
* @return String[]
|
||||
*/
|
||||
public String[] getExcludes()
|
||||
{
|
||||
return excludes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the excludes.
|
||||
* @param excludes The excludes to set
|
||||
*/
|
||||
public void setExcludes( String[] excludes )
|
||||
{
|
||||
this.excludes = excludes;
|
||||
}
|
||||
|
||||
public void addLinkValidator( LinkValidator lv )
|
||||
{
|
||||
validators.add( lv );
|
||||
}
|
||||
|
||||
public LinkValidationResult validateLink( LinkValidationItem lvi )
|
||||
throws Exception
|
||||
{
|
||||
{
|
||||
LinkValidationResult status = getCachedResult( lvi );
|
||||
if ( status != null )
|
||||
{
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
for ( int i = 0; i < excludes.length; i++ )
|
||||
{
|
||||
if ( excludes[i] != null && lvi.getLink().startsWith( excludes[i] ) )
|
||||
{
|
||||
if ( LOG.isDebugEnabled() )
|
||||
{
|
||||
LOG.debug( "Excluded " + lvi.getLink() );
|
||||
}
|
||||
return new LinkValidationResult( LinkValidationResult.VALID, false, "" );
|
||||
}
|
||||
}
|
||||
Iterator iter = validators.iterator();
|
||||
LinkValidator lv;
|
||||
Object resourceKey;
|
||||
LinkValidationResult lvr;
|
||||
while ( iter.hasNext() )
|
||||
{
|
||||
lv = (LinkValidator) iter.next();
|
||||
resourceKey = lv.getResourceKey( lvi );
|
||||
if ( resourceKey != null )
|
||||
{
|
||||
if ( LOG.isDebugEnabled() )
|
||||
LOG.debug( lv.getClass().getName() + " - Checking link " + lvi.getLink() );
|
||||
lvr = lv.validateLink( lvi );
|
||||
if ( lvr.getStatus() == LinkValidationResult.NOTMINE )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
setCachedResult( resourceKey, lvr );
|
||||
return lvr;
|
||||
}
|
||||
}
|
||||
lv = null;
|
||||
resourceKey = null;
|
||||
lvr = null;
|
||||
LOG.error( "Unable to validate link : " + lvi.getLink() );
|
||||
return new LinkValidationResult( LinkValidationResult.UNKNOWN, false, "No validator found for this link" );
|
||||
}
|
||||
|
||||
public void loadCache( String cacheFilename )
|
||||
{
|
||||
try
|
||||
{
|
||||
File f = new File( cacheFilename );
|
||||
if ( f.exists() )
|
||||
{
|
||||
ObjectInputStream is = new ObjectInputStream( new FileInputStream( cacheFilename ) );
|
||||
this.cache = (Map) is.readObject();
|
||||
is.close();
|
||||
}
|
||||
}
|
||||
catch ( InvalidClassException e )
|
||||
{
|
||||
LOG.warn( "Your cache is incompatible with this new release of the plugin. It will be recreated." );
|
||||
}
|
||||
catch ( Throwable t )
|
||||
{
|
||||
LOG.error( "Unable to load the cache", t );
|
||||
}
|
||||
}
|
||||
|
||||
public void saveCache( String cacheFilename )
|
||||
{
|
||||
try
|
||||
{
|
||||
// Remove non-persistent items from cache
|
||||
Map persistentCache = new HashMap();
|
||||
Iterator iter = this.cache.keySet().iterator();
|
||||
Object resourceKey;
|
||||
while ( iter.hasNext() )
|
||||
{
|
||||
resourceKey = iter.next();
|
||||
if ( ( (LinkValidationResult) cache.get( resourceKey ) ).isPersistent() )
|
||||
{
|
||||
persistentCache.put( resourceKey, cache.get( resourceKey ) );
|
||||
if ( LOG.isDebugEnabled() )
|
||||
LOG.debug( "[" + resourceKey + "] with result [" + cache.get( resourceKey )
|
||||
+ "] is stored in the cache." );
|
||||
}
|
||||
}
|
||||
File cacheFile = new File( cacheFilename );
|
||||
File dir = cacheFile.getParentFile();
|
||||
if ( dir != null )
|
||||
{
|
||||
dir.mkdirs();
|
||||
}
|
||||
ObjectOutputStream os = new ObjectOutputStream( new FileOutputStream( cacheFilename ) );
|
||||
os.writeObject( persistentCache );
|
||||
os.close();
|
||||
persistentCache = null;
|
||||
iter = null;
|
||||
resourceKey = null;
|
||||
cacheFile = null;
|
||||
dir = null;
|
||||
os = null;
|
||||
}
|
||||
catch ( Throwable t )
|
||||
{
|
||||
LOG.error( "Unable to save the cache", t );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param lvi
|
||||
* @return int Will return a status level, VALID, ERROR, UNKNOWN, WARNING
|
||||
*/
|
||||
public LinkValidationResult getCachedResult( LinkValidationItem lvi )
|
||||
{
|
||||
Iterator iter = getValidators().iterator();
|
||||
LinkValidator lv;
|
||||
Object resourceKey;
|
||||
while ( iter.hasNext() )
|
||||
{
|
||||
lv = (LinkValidator) iter.next();
|
||||
resourceKey = lv.getResourceKey( lvi );
|
||||
if ( resourceKey != null && cache.containsKey( resourceKey ) )
|
||||
{
|
||||
if ( LOG.isDebugEnabled() )
|
||||
LOG.debug( "The cache returns for [" + resourceKey + "] the result [" + cache.get( resourceKey )
|
||||
+ "]." );
|
||||
return (LinkValidationResult) cache.get( resourceKey );
|
||||
}
|
||||
}
|
||||
lv = null;
|
||||
resourceKey = null;
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setCachedResult( Object resourceKey, LinkValidationResult lvr )
|
||||
{
|
||||
cache.put( resourceKey, lvr );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package org.apache.maven.plugin.linkcheck.validation;
|
||||
|
||||
/* ====================================================================
|
||||
* Copyright 2001-2006 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bwalding@apache.org">Ben Walding</a>
|
||||
* @author <a href="mailto:aheritier@apache.org">Arnaud Heritier</a>
|
||||
* @version $Id$
|
||||
*
|
||||
* Validates mailto links
|
||||
*/
|
||||
public final class MailtoLinkValidator
|
||||
implements LinkValidator
|
||||
{
|
||||
private static final LinkValidationResult LVR = new LinkValidationResult( LinkValidationResult.VALID, false, "" );
|
||||
|
||||
/**
|
||||
* @see org.apache.maven.plugin.linkcheck.validation.LinkValidator#validateLink(org.apache.maven.plugin.linkcheck.validation.LinkValidationItem)
|
||||
*/
|
||||
public LinkValidationResult validateLink( LinkValidationItem lvi )
|
||||
throws Exception
|
||||
{
|
||||
return LVR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.maven.plugin.linkcheck.validation.LinkValidator#getResourceKey(org.apache.maven.plugin.linkcheck.validation.LinkValidationItem)
|
||||
*/
|
||||
public Object getResourceKey( LinkValidationItem lvi )
|
||||
{
|
||||
if ( lvi.getLink().indexOf( '@' ) != -1 )
|
||||
return lvi.getLink();
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package org.apache.maven.plugin.linkcheck.validation;
|
||||
|
||||
/* ====================================================================
|
||||
* Copyright 2001-2006 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fake links check when maven is offline
|
||||
* @author <a href="mailto:aheritier@apache.org">Arnaud Heritier</a>
|
||||
* @version $Id: HTTPLinkValidator.java 155277 2005-02-24 23:23:29Z aheritier $
|
||||
*/
|
||||
public final class OfflineHTTPLinkValidator
|
||||
extends HTTPLinkValidator
|
||||
implements LinkValidator
|
||||
{
|
||||
|
||||
/**
|
||||
* @see org.apache.maven.plugin.linkcheck.LinkValidator#validateLink(org.apache.maven.plugin.linkcheck.LinkValidationItem)
|
||||
*/
|
||||
public LinkValidationResult validateLink( LinkValidationItem lvi )
|
||||
{
|
||||
return new LinkValidationResult( LinkValidationResult.WARNING, false, "Maven is offline. Link not checked." );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,243 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package org.apache.maven.plugin.linkcheck.validation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
|
||||
import org.apache.commons.httpclient.Header;
|
||||
import org.apache.commons.httpclient.HostConfiguration;
|
||||
import org.apache.commons.httpclient.HttpClient;
|
||||
import org.apache.commons.httpclient.HttpException;
|
||||
import org.apache.commons.httpclient.HttpMethod;
|
||||
import org.apache.commons.httpclient.HttpState;
|
||||
import org.apache.commons.httpclient.HttpStatus;
|
||||
import org.apache.commons.httpclient.StatusLine;
|
||||
import org.apache.commons.httpclient.UsernamePasswordCredentials;
|
||||
import org.apache.commons.httpclient.methods.HeadMethod;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Checks links which are normal URLs
|
||||
* @author <a href="mailto:bwalding@apache.org">Ben Walding</a>
|
||||
* @author <a href="mailto:aheritier@apache.org">Arnaud Heritier</a>
|
||||
* @version $Id: HTTPLinkValidator.java 155277 2005-02-24 23:23:29Z aheritier $
|
||||
*/
|
||||
public final class OnlineHTTPLinkValidator
|
||||
extends HTTPLinkValidator
|
||||
{
|
||||
/**
|
||||
* Log for debug output
|
||||
*/
|
||||
private final static Log LOG = LogFactory.getLog( OnlineHTTPLinkValidator.class );
|
||||
|
||||
private String proxyHost;
|
||||
|
||||
private int proxyPort;
|
||||
|
||||
private String proxyUser;
|
||||
|
||||
private String proxyPass;
|
||||
|
||||
private transient HttpClient cl;
|
||||
|
||||
public OnlineHTTPLinkValidator( String proxyHost, String proxyPort, String proxyUser, String proxyPass )
|
||||
{
|
||||
if ( proxyHost == null || proxyHost.trim().equals( "" ) )
|
||||
{
|
||||
this.proxyHost = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.proxyHost = proxyHost;
|
||||
if ( proxyPort != null )
|
||||
{
|
||||
try
|
||||
{
|
||||
this.proxyPort = Integer.parseInt( proxyPort );
|
||||
}
|
||||
catch ( NumberFormatException e )
|
||||
{
|
||||
LOG.warn( "Invalid number for Proxy Port:" + proxyPort );
|
||||
LOG.warn( "Proxy Port won't be used." );
|
||||
this.proxyPort = -1;
|
||||
}
|
||||
}
|
||||
this.proxyUser = proxyUser;
|
||||
this.proxyPass = proxyPass;
|
||||
}
|
||||
initHttpClient();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.maven.plugin.linkcheck.LinkValidator#validateLink(org.apache.maven.plugin.linkcheck.LinkValidationItem)
|
||||
*/
|
||||
public LinkValidationResult validateLink( LinkValidationItem lvi )
|
||||
{
|
||||
if ( cl == null )
|
||||
initHttpClient();
|
||||
try
|
||||
{
|
||||
String link = lvi.getLink();
|
||||
HttpMethod hm = null;
|
||||
try
|
||||
{
|
||||
hm = checkLink( cl, link );
|
||||
}
|
||||
catch ( Throwable t )
|
||||
{
|
||||
if ( LOG.isDebugEnabled() )
|
||||
{
|
||||
LOG
|
||||
.error( "Received: [" + t + "] for [" + lvi.getLink() + "] in page [" + lvi.getSource() + "]",
|
||||
t );
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG.error( "Received: [" + t + "] for [" + lvi.getLink() + "] in page [" + lvi.getSource() + "]" );
|
||||
}
|
||||
return new LinkValidationResult( LinkValidationResult.ERROR, false, t.getClass().getName() + " : "
|
||||
+ t.getMessage() );
|
||||
}
|
||||
if ( hm == null )
|
||||
return new LinkValidationResult( LinkValidationResult.ERROR, false, "Cannot retreive HTTP Status" );
|
||||
if ( hm.getStatusCode() == HttpStatus.SC_OK )
|
||||
{
|
||||
return new LinkValidationResult( LinkValidationResult.VALID, true, hm.getStatusCode() + " "
|
||||
+ hm.getStatusText() );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( hm.getStatusCode() == HttpStatus.SC_MOVED_PERMANENTLY )
|
||||
{
|
||||
LOG.warn( "Received: [" + hm.getStatusCode() + "] for [" + lvi.getLink() + "] in page ["
|
||||
+ lvi.getSource() + "]" );
|
||||
return new LinkValidationResult( LinkValidationResult.WARNING, true, hm.getStatusCode() + " "
|
||||
+ hm.getStatusText() );
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG.error( "Received: [" + hm.getStatusCode() + "] for [" + lvi.getLink() + "] in page ["
|
||||
+ lvi.getSource() + "]" );
|
||||
return new LinkValidationResult( LinkValidationResult.ERROR, false, hm.getStatusCode() + " "
|
||||
+ hm.getStatusText() );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch ( Throwable t )
|
||||
{
|
||||
if ( LOG.isDebugEnabled() )
|
||||
LOG.error( "Received: [" + t + "] for [" + lvi.getLink() + "] in page [" + lvi.getSource() + "]", t );
|
||||
else
|
||||
LOG.error( "Received: [" + t + "] for [" + lvi.getLink() + "] in page [" + lvi.getSource() + "]" );
|
||||
return new LinkValidationResult( LinkValidationResult.ERROR, false, t.getMessage() );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void initHttpClient()
|
||||
{
|
||||
LOG.debug( "A new HttpClient instance is needed ..." );
|
||||
// Some web servers doesn't allow the default user-agent sent by httpClient
|
||||
System.setProperty( "httpclient.useragent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)" );
|
||||
//cl = new HttpClient( new MultiThreadedHttpConnectionManager() );
|
||||
cl = new HttpClient();
|
||||
HostConfiguration hc = new HostConfiguration();
|
||||
HttpState state = new HttpState();
|
||||
if ( this.proxyHost != null )
|
||||
{
|
||||
hc.setProxy( this.proxyHost, this.proxyPort );
|
||||
if ( LOG.isDebugEnabled() )
|
||||
{
|
||||
LOG.debug( "Proxy Host:" + proxyHost );
|
||||
LOG.debug( "Proxy Port:" + proxyPort );
|
||||
}
|
||||
if ( this.proxyUser != null && this.proxyPass != null )
|
||||
{
|
||||
if ( LOG.isDebugEnabled() )
|
||||
LOG.debug( "Proxy User:" + proxyUser );
|
||||
state
|
||||
.setProxyCredentials( null, null, new UsernamePasswordCredentials( this.proxyUser, this.proxyPass ) );
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG.debug( "Not using a proxy" );
|
||||
}
|
||||
cl.setHostConfiguration( hc );
|
||||
cl.setState( state );
|
||||
LOG.debug( "New HttpClient instance created." );
|
||||
}
|
||||
|
||||
private HttpMethod checkLink( HttpClient cl, String link )
|
||||
throws HttpException, IOException
|
||||
{
|
||||
// execute the HEAD (a GET without the body returned)
|
||||
HttpMethod hm = new HeadMethod( link );
|
||||
try
|
||||
{
|
||||
// We want to do it manually
|
||||
hm.setFollowRedirects( false );
|
||||
URL url = new URL( link );
|
||||
cl.getHostConfiguration().setHost( url.getHost(), url.getPort(), url.getProtocol() );
|
||||
cl.executeMethod( hm );
|
||||
StatusLine sl = hm.getStatusLine();
|
||||
|
||||
if ( sl == null )
|
||||
{
|
||||
LOG.error( "Unknown error validating link : " + link );
|
||||
return null;
|
||||
}
|
||||
|
||||
if ( hm.getStatusCode() == HttpStatus.SC_MOVED_PERMANENTLY
|
||||
|| hm.getStatusCode() == HttpStatus.SC_MOVED_TEMPORARILY
|
||||
|| hm.getStatusCode() == HttpStatus.SC_TEMPORARY_REDIRECT )
|
||||
{
|
||||
Header locationHeader = hm.getResponseHeader( "location" );
|
||||
if ( locationHeader == null )
|
||||
{
|
||||
LOG.error( "Site sent redirect, but did not set Location header" );
|
||||
return hm;
|
||||
}
|
||||
else
|
||||
{
|
||||
String newLink = locationHeader.getValue();
|
||||
// Be careful to absolute/relative links
|
||||
if ( !newLink.startsWith( "http://" ) && !newLink.startsWith( "https://" ) )
|
||||
{
|
||||
if ( newLink.startsWith( "/" ) )
|
||||
{
|
||||
URL oldUrl = new URL( link );
|
||||
newLink = oldUrl.getProtocol() + "://" + oldUrl.getHost()
|
||||
+ ( oldUrl.getPort() > 0 ? ":" + oldUrl.getPort() : "" ) + newLink;
|
||||
}
|
||||
else
|
||||
{
|
||||
newLink = link + newLink;
|
||||
}
|
||||
}
|
||||
HttpMethod oldHm = hm;
|
||||
LOG.info( "[" + link + "] is redirected to [" + newLink + "]" );
|
||||
hm = checkLink( cl, newLink );
|
||||
// Restore the hm to "Moved permanently" if the new location is found to allow us to report it
|
||||
if ( oldHm.getStatusCode() == HttpStatus.SC_MOVED_PERMANENTLY
|
||||
&& hm.getStatusCode() == HttpStatus.SC_OK )
|
||||
{
|
||||
return oldHm;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
hm.releaseConnection();
|
||||
}
|
||||
return hm;
|
||||
}
|
||||
|
||||
}
|
||||
BIN
linkcheck/src/plugin-resources/images/icon_error_sml.gif
Normal file
BIN
linkcheck/src/plugin-resources/images/icon_error_sml.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1010 B |
BIN
linkcheck/src/plugin-resources/images/icon_unknown_sml.gif
Normal file
BIN
linkcheck/src/plugin-resources/images/icon_unknown_sml.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1019 B |
BIN
linkcheck/src/plugin-resources/images/icon_valid_sml.gif
Normal file
BIN
linkcheck/src/plugin-resources/images/icon_valid_sml.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 990 B |
BIN
linkcheck/src/plugin-resources/images/icon_warning_sml.gif
Normal file
BIN
linkcheck/src/plugin-resources/images/icon_warning_sml.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 576 B |
BIN
linkcheck/src/plugin-resources/images/trans.gif
Normal file
BIN
linkcheck/src/plugin-resources/images/trans.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 43 B |
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
/*
|
||||
* Copyright 2001-2004 The Apache Software Foundation.
|
||||
* Copyright 2001-2005 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,14 +20,10 @@
|
||||
<document>
|
||||
<properties>
|
||||
<title>Maven LinkCheck Plug-in</title>
|
||||
<author email="ben@walding.com">Ben Walding</author>
|
||||
</properties>
|
||||
|
||||
<body>
|
||||
<section name="Maven LinkCheck Temporary File">
|
||||
<p>
|
||||
This file is used as a placeholder until the final link check can occur.
|
||||
</p>
|
||||
<p>This file is used as a placeholder until the final link check can occur.</p>
|
||||
</section>
|
||||
</body>
|
||||
</document>
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<!--
|
||||
* ========================================================================
|
||||
*
|
||||
* Copyright 2004 The Apache Software Foundation.
|
||||
* Copyright 2005 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,7 +18,6 @@
|
||||
*
|
||||
* ========================================================================
|
||||
-->
|
||||
|
||||
<jsl:stylesheet
|
||||
select="$doc"
|
||||
xmlns:j="jelly:core"
|
||||
@@ -31,38 +29,48 @@
|
||||
|
||||
<jsl:template match="linkcheck">
|
||||
<document>
|
||||
|
||||
<properties>
|
||||
<title>Link Check Report</title>
|
||||
</properties>
|
||||
<body>
|
||||
<section name="Link Check Report">
|
||||
<p><b><span style="color:#00AA00;text-align:right"><x:expr select="count(file)"/> </span></b> file(s) and <b><span style="color:#00AA00;text-align:right"><x:expr select="sum(file/unsuccessful)+sum(file/successful)"/> </span></b> link(s) checked. <b><span style="color:#FF0000;text-align:right"><x:expr select="count(file/result[status='error'])"/></span></b> error(s) and <b><span style="color:#FFA916;text-align:right"><x:expr select="count(file/result[status='warning'])"/></span></b> warning(s) reported in <b><span style="color:#00AA00;text-align:right"><x:expr select="count(file[unsuccessful!=0])"/> </span></b> file(s).</p>
|
||||
<table summary="Link Check summary">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>URL</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th rowspan="2">Document</th>
|
||||
<th colspan="4">links</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th width="50">total</th>
|
||||
<th width="50"><img align="right" src="images/icon_valid_sml.gif" alt="success"/></th>
|
||||
<th width="50"><img align="right" src="images/icon_warning_sml.gif" alt="warning"/></th>
|
||||
<th width="50"><img align="right" src="images/icon_error_sml.gif" alt="error"/></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<x:forEach var="file" select="file[unsuccessful != 0]">
|
||||
<util:replace var="name" oldChar="\\" newChar="/">
|
||||
<x:expr select="$file/name"/>
|
||||
</util:replace>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<util:replace var="name" oldChar="\\" newChar="/">
|
||||
<x:expr select="$file/name"/>
|
||||
</util:replace>
|
||||
<a href="${name}">${name}</a>
|
||||
</td>
|
||||
<td><a href="${name.trim()}">${name.trim()}</a></td>
|
||||
<td width="50" style="text-align:right" nowrap="nowrap"><b><x:expr select="$file/successful + $file/unsuccessful"/></b></td>
|
||||
<td width="50" style="text-align:right"><b><span style="color:#00AA00;text-align:right"><x:expr select="$file/successful"/></span></b></td>
|
||||
<td width="50" style="text-align:right"><b><span style="color:#FFA916;text-align:right"><x:expr select="count($file/result[status='warning'])"/></span></b></td>
|
||||
<td width="50" style="text-align:right"><b><span style="color:#FF0000;text-align:right"><x:expr select="count($file/result[status='error'])"/></span></b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<x:forEach var="result" select="$file/result">
|
||||
<j:set var="status"><x:expr select="$result/status"/></j:set>
|
||||
<j:set var="target"><x:expr select="$result/target"/></j:set>
|
||||
<j:if test="${status != 'OK'}">
|
||||
<p>${status} - ${target}</p>
|
||||
</j:if>
|
||||
</x:forEach>
|
||||
</td>
|
||||
<td colspan="5">
|
||||
<x:forEach var="result" select="$file/result">
|
||||
<j:set var="status"><x:expr select="$result/status"/></j:set>
|
||||
<j:set var="target"><x:expr select="$result/target"/></j:set>
|
||||
<j:set var="errorMessage"><x:expr select="$result/errorMessage"/></j:set>
|
||||
<j:if test="${status != 'valid'}">
|
||||
<img src="images/trans.gif" alt="trans" width="20" height="5" border="0"/><img src="images/icon_${status}_sml.gif" alt="${status}"/><img src="images/trans.gif" alt="trans" width="5" height="5" border="0"/> ${target} - <j:if test="${errorMessage != ''}"><span style="font-style:italic">${errorMessage}</span></j:if><br/>
|
||||
</j:if>
|
||||
</x:forEach>
|
||||
</td>
|
||||
</tr>
|
||||
</x:forEach>
|
||||
</tbody>
|
||||
@@ -71,4 +79,4 @@
|
||||
</body>
|
||||
</document>
|
||||
</jsl:template>
|
||||
</jsl:stylesheet>
|
||||
</jsl:stylesheet>
|
||||
@@ -21,8 +21,8 @@
|
||||
</goal>
|
||||
|
||||
<goal name="test-linkcheck">
|
||||
<attainGoal name="site"/>
|
||||
<attainGoal name="clean"/>
|
||||
<attainGoal name="site"/>
|
||||
</goal>
|
||||
|
||||
</project>
|
||||
@@ -16,8 +16,15 @@
|
||||
*/
|
||||
-->
|
||||
<html>
|
||||
<body>
|
||||
<a href="#bumpkin">test2</a>
|
||||
</body>
|
||||
|
||||
<head>
|
||||
<title>test</title>
|
||||
</head>
|
||||
<body>
|
||||
<a href="#bumpkin">test2</a><br/>
|
||||
<a href="http://www.seoconsultants.com/w3c/status-codes/301.asp">301 Moved Permanently</a><br/>
|
||||
<a href="http://www.seoconsultants.com/w3c/status-codes/302.asp">302 Found</a><br/>
|
||||
<a href="http://www.seoconsultants.com/w3c/status-codes/307.asp">307 Temporary Redirect</a><br/>
|
||||
<a href="http://www.seoconsultants.com/w3c/status-codes/404.asp">404 Not Found</a><br/>
|
||||
<a href="http://www.seoconsultants.com/w3c/status-codes/410.asp">410 Gone</a><br/>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,97 +0,0 @@
|
||||
package org.apache.maven.linkcheck;
|
||||
|
||||
/* ====================================================================
|
||||
* Copyright 2001-2004 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* @author Ben Walding
|
||||
* @author <a href="mailto:carlos@apache.org">Carlos Sanchez</a>
|
||||
*/
|
||||
public class LinkCheckTest extends TestCase
|
||||
{
|
||||
String baseDir;
|
||||
|
||||
public void setUp()
|
||||
{
|
||||
baseDir = System.getProperty("basedir");
|
||||
}
|
||||
|
||||
public void testScan() throws Exception
|
||||
{
|
||||
File f = new File(baseDir + "/src/test-resources");
|
||||
LinkCheck lc = new LinkCheck();
|
||||
lc.setBasedir(f);
|
||||
lc.setOutput(new File(baseDir + "/target/linkcheck.xml"));
|
||||
lc.setOutputEncoding("ISO8859-1");
|
||||
lc.setCache(baseDir + "/target/linkcheck-cache.xml");
|
||||
lc.setExclude("http://cvs.apache.org/viewcvs.cgi/maven-pluginszz/,"
|
||||
+ "http://cvs.apache.org/viewcvs.cgi/mavenzz/");
|
||||
lc.doExecute();
|
||||
|
||||
Iterator iter = lc.getFiles().iterator();
|
||||
Map map = new HashMap();
|
||||
while (iter.hasNext())
|
||||
{
|
||||
FileToCheck ftc = (FileToCheck) iter.next();
|
||||
map.put(ftc.getName(), ftc);
|
||||
}
|
||||
|
||||
assertEquals("files.size()", 8, lc.getFiles().size());
|
||||
|
||||
check(map, "nolink.html", 0);
|
||||
check(map, "test-resources/nolink.html", 0);
|
||||
check(map, "test-resources/test1/test1.html", 2);
|
||||
check(map, "test-resources/test1/test2.html", 0);
|
||||
check(map, "test1/test1.html", 1);
|
||||
check(map, "testA.html", 3);
|
||||
|
||||
/* test excludes */
|
||||
String fileName = "testExcludes.html";
|
||||
check(map, fileName, 2);
|
||||
|
||||
FileToCheck ftc = (FileToCheck) map.get(fileName);
|
||||
assertEquals("Excluded links", 2, ftc.getSuccessful());
|
||||
|
||||
//index-all.html should get parsed, but is currently having problems.
|
||||
//check(map, "index-all.html", 1);
|
||||
|
||||
}
|
||||
|
||||
private void check(Map map, String name, int linkCount)
|
||||
{
|
||||
FileToCheck ftc;
|
||||
|
||||
ftc = (FileToCheck) map.get(name);
|
||||
assertNotNull(name, ftc);
|
||||
|
||||
/*if (ftc.getResults().size() != linkCount) {
|
||||
|
||||
}*/
|
||||
|
||||
assertEquals(name + ".getLinks().size()", linkCount, ftc.getResults().size());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package org.apache.maven.linkcheck.validation;
|
||||
|
||||
/* ====================================================================
|
||||
* Copyright 2001-2004 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* @author <a href="bwalding@apache.org">Ben Walding</a>
|
||||
* @version $Id$
|
||||
*/
|
||||
public class HTTPLinkValidatorTest extends TestCase
|
||||
{
|
||||
|
||||
public void testValidateLink()
|
||||
{
|
||||
//I've disabled these as they require access to the net. Ultimately
|
||||
//I'd like to setup a temporary internal webserver during testing.
|
||||
//Probably a test repository so it can be used for a variety of things.
|
||||
//checkLink("http://www.example.com");
|
||||
//checkLink("http://www.example.com>);");
|
||||
}
|
||||
|
||||
protected LinkValidationResult checkLink(String link)
|
||||
{
|
||||
HTTPLinkValidator hlv = new HTTPLinkValidator(null, null, null, null);
|
||||
LinkValidationItem lvi = new LinkValidationItem(new File("."), link);
|
||||
return hlv.validateLink(lvi);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package org.apache.maven.plugin.linkcheck;
|
||||
|
||||
/* ====================================================================
|
||||
* Copyright 2001-2004 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* @author Ben Walding
|
||||
* @author <a href="mailto:carlos@apache.org">Carlos Sanchez</a>
|
||||
*/
|
||||
public class LinkCheckTest
|
||||
extends TestCase
|
||||
{
|
||||
String baseDir;
|
||||
|
||||
public void setUp()
|
||||
{
|
||||
baseDir = System.getProperty( "basedir" );
|
||||
}
|
||||
|
||||
public void testScan()
|
||||
throws Exception
|
||||
{
|
||||
File f = new File( baseDir + "/src/test-resources" );
|
||||
LinkCheck lc = new LinkCheck();
|
||||
lc.setBasedir( f );
|
||||
lc.setOutput( new File( baseDir + "/target/linkcheck.xml" ) );
|
||||
lc.setOutputEncoding( "ISO8859-1" );
|
||||
lc.setCache( baseDir + "/target/linkcheck-cache.xml" );
|
||||
lc.setExclude( "http://cvs.apache.org/viewcvs.cgi/maven-pluginszz/,"
|
||||
+ "http://cvs.apache.org/viewcvs.cgi/mavenzz/" );
|
||||
lc.doExecute();
|
||||
|
||||
Iterator iter = lc.getFiles().iterator();
|
||||
Map map = new HashMap();
|
||||
while ( iter.hasNext() )
|
||||
{
|
||||
FileToCheck ftc = (FileToCheck) iter.next();
|
||||
map.put( ftc.getName(), ftc );
|
||||
}
|
||||
|
||||
assertEquals( "files.size()", 8, lc.getFiles().size() );
|
||||
|
||||
check( map, "nolink.html", 0 );
|
||||
check( map, "test-resources/nolink.html", 0 );
|
||||
check( map, "test-resources/test1/test1.html", 2 );
|
||||
check( map, "test-resources/test1/test2.html", 0 );
|
||||
check( map, "test1/test1.html", 1 );
|
||||
check( map, "testA.html", 3 );
|
||||
|
||||
/* test excludes */
|
||||
String fileName = "testExcludes.html";
|
||||
check( map, fileName, 2 );
|
||||
|
||||
FileToCheck ftc = (FileToCheck) map.get( fileName );
|
||||
assertEquals( "Excluded links", 2, ftc.getSuccessful() );
|
||||
|
||||
//index-all.html should get parsed, but is currently having problems.
|
||||
//check(map, "index-all.html", 1);
|
||||
|
||||
}
|
||||
|
||||
private void check( Map map, String name, int linkCount )
|
||||
{
|
||||
FileToCheck ftc;
|
||||
|
||||
ftc = (FileToCheck) map.get( name );
|
||||
assertNotNull( name, ftc );
|
||||
|
||||
/*if (ftc.getResults().size() != linkCount) {
|
||||
|
||||
}*/
|
||||
|
||||
assertEquals( name + ".getLinks().size()", linkCount, ftc.getResults().size() );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package org.apache.maven.plugin.linkcheck.validation;
|
||||
|
||||
/* ====================================================================
|
||||
* Copyright 2001-2006 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* @author <a href="bwalding@apache.org">Ben Walding</a>
|
||||
* @author <a href="aheritier@apache.org">Arnaud Heritier</a>
|
||||
* @version $Id$
|
||||
*/
|
||||
public class HTTPLinkValidatorTest
|
||||
extends TestCase
|
||||
{
|
||||
private LinkValidator hlv;
|
||||
|
||||
private boolean mavenOnline = Boolean.getBoolean( "maven.mode.online" );
|
||||
|
||||
public void testValidateLink()
|
||||
throws Exception
|
||||
{
|
||||
System.err.println( "maven.mode.online : " + mavenOnline );
|
||||
if ( mavenOnline )
|
||||
{
|
||||
hlv = new OnlineHTTPLinkValidator( System.getProperty( "maven.proxy.host" ), System
|
||||
.getProperty( "maven.proxy.port" ), System.getProperty( "maven.proxy.username" ), System
|
||||
.getProperty( "maven.proxy.password" ) );
|
||||
|
||||
assertEquals( LinkValidationResult.VALID, checkLink( "http://www.apache.org" ).getStatus() );
|
||||
assertEquals( LinkValidationResult.ERROR, checkLink( "http://www.example.com>);" ).getStatus() );
|
||||
}
|
||||
else
|
||||
{
|
||||
hlv = new OfflineHTTPLinkValidator();
|
||||
|
||||
assertEquals( LinkValidationResult.WARNING, checkLink( "http://www.apache.org" ).getStatus() );
|
||||
assertEquals( LinkValidationResult.WARNING, checkLink( "http://www.example.com>);" ).getStatus() );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
protected LinkValidationResult checkLink( String link )
|
||||
throws Exception
|
||||
{
|
||||
|
||||
LinkValidationItem lvi = new LinkValidationItem( new File( "." ), link );
|
||||
return hlv.validateLink( lvi );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -26,6 +26,12 @@
|
||||
</properties>
|
||||
<body>
|
||||
<release version="1.4-SNAPSHOT" date="in SVN">
|
||||
<action dev="aheritier" type="update" issue="MPLINKCHECK-10">"Moved Permanently" sites are reported as a warning and not as an error.</action>
|
||||
<action dev="aheritier" type="update" issue="MPLINKCHECK-24">Speed and stability enhancement [better usage of httpClient].</action>
|
||||
<action dev="aheritier" type="update" issue="MPLINKCHECK-24,MAVEN-1739">Upgrade to HttpClient 3.0.</action>
|
||||
<action dev="aheritier" type="add" issue="MPLINKCHECK-25">Display for each file the number of links and the number of errors.</action>
|
||||
<action dev="aheritier" type="add" issue="MPLINKCHECK-25">New counters to report how many files and links are checked and how many errors are found.</action>
|
||||
<action dev="aheritier" type="update" issue="MPLINKCHECK-25">Display a more verbose message than the "NOT FOUND" error.</action>
|
||||
<action dev="aheritier" type="update" issue="MAVEN-1712">Update dependencies to match ones in maven 1.1 core and to unify them between plugins. The following dependencies are updated :
|
||||
<ul>
|
||||
<li>commons-collections v2.1 -> v3.0</li>
|
||||
|
||||
Reference in New Issue
Block a user