class ContentExtractor extends Extractor {


    /**
     * Extracts links 
     */
    final protected void extract(CrawlURI uri) {
        boolean finished = innerExtract(uri);
        if (finished) {
            uri.linkExtractorFinished();
        }
    }

    /**
     * Determines if links should be extracted from the given URI. This method
     * performs four checks. It first checks if the URI was processed successfully,
     * i.e. {@link CrawlURI#isSuccess()} returns true. 
     * 
     * <p>
     * The second check runs only if
     * {@link ExtractorParameters#getExtractIndependently()} is false. It checks
     * {@link CrawlURI#hasBeenLinkExtracted()} result. If that result is
     * true, then this method returns false, as some other extractor has claimed
     * that links are already extracted.
     * 
     * <p>
     * Next, this method checks that the content length of the URI is greater
     * than zero (in other words, that there is actually content for links to be
     * extracted from). If the content length of the URI is zero or less, then
     * this method returns false.
     * 
     * <p>
     * Finally, this method delegates to {@link #innerExtract(CrawlURI)} and
     * returns that result.
     * 
     * @param uri
     *            the URI to check
     * @return true if links should be extracted from the URI, false otherwise
     */
    final protected boolean shouldProcess(CrawlURI uri) {<FILL_FUNCTION_BODY>}

    /**
     * Determines if otherwise valid URIs should have links extracted or not.
     * The given URI will have content length greater than zero. Subclasses
     * should implement this method to perform additional checks. For instance,
     * the {@link ExtractorHTML} implementation checks that the content-type of
     * the given URI is text/html.
     * 
     * @param uri
     *            the URI to check
     * @return true if links should be extracted from that URI, false otherwise
     */
    protected abstract boolean shouldExtract(CrawlURI uri);

    
    /**
     * Actually extracts links.  The given URI will have passed the three
     * checks described in {@link #shouldProcess(CrawlURI)}.  Subclasses
     * should implement this method to discover outlinks in the URI's 
     * content stream.  For instance, {@link ExtractorHTML} extracts links
     * from Anchor tags and so on.
     * 
     * <p>This method should only return true if extraction completed 
     * successfully.  If not (for instance, if an IO error occurred), then
     * this method should return false.  Returning false indicates to the
     * pipeline that downstream extractors should attempt to extract links
     * themselves.  Returning true indicates that downstream extractors
     * should be skipped.
     * 
     * @param uri   the URI whose links to extract
     * @return  true if link extraction finished; false if downstream
     * extractors should attempt to extract links
     */
    protected abstract boolean innerExtract(CrawlURI uri);
    
}

    	if (!uri.isSuccess()) {
    		return false;
    	}
        if (!getExtractorParameters().getExtractIndependently()
                && uri.hasBeenLinkExtracted()) {
            return false;
        }
        if (uri.getContentLength() <= 0) {
            return false;
        }
        if (!getExtractorParameters().getExtract404s() 
                && uri.getFetchStatus()==FetchStatusCodes.S_NOT_FOUND) {
            return false; 
        }
        if (!shouldExtract(uri)) {
            return false;
        }
        return true;
    
<methods>public non-sealed void <init>() ,public static void add(org.archive.modules.CrawlURI, int, java.lang.String, org.archive.modules.extractor.LinkContext, org.archive.modules.extractor.Hop) throws URIException,public static org.archive.modules.CrawlURI addRelativeToBase(org.archive.modules.CrawlURI, int, java.lang.CharSequence, org.archive.modules.extractor.LinkContext, org.archive.modules.extractor.Hop) throws URIException,public static org.archive.modules.CrawlURI addRelativeToVia(org.archive.modules.CrawlURI, int, java.lang.String, org.archive.modules.extractor.LinkContext, org.archive.modules.extractor.Hop) throws URIException,public org.archive.modules.extractor.ExtractorParameters getExtractorParameters() ,public org.archive.modules.extractor.UriErrorLoggerModule getLoggerModule() ,public void logUriError(URIException, org.archive.net.UURI, java.lang.CharSequence) ,public java.lang.String report() ,public void setExtractorParameters(org.archive.modules.extractor.ExtractorParameters) ,public void setLoggerModule(org.archive.modules.extractor.UriErrorLoggerModule) <variables>public static final org.archive.modules.extractor.ExtractorParameters DEFAULT_PARAMETERS,private static final java.util.logging.Logger LOGGER,protected transient org.archive.modules.extractor.ExtractorParameters extractorParameters,private static final java.util.logging.Logger logger,protected transient org.archive.modules.extractor.UriErrorLoggerModule loggerModule,protected java.util.concurrent.atomic.AtomicLong numberOfLinksExtracted