<commit_before>/* 
    JSPWiki - a JSP-based WikiWiki clone.

    Copyright (C) 2001 <NAME> (<EMAIL>)

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
package com.ecyrd.jspwiki.providers;

import java.io.File;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.Properties;
import java.util.Collection;
import java.util.ArrayList;
import java.util.Date;
import java.text.SimpleDateFormat;
import org.apache.log4j.Category;
import org.apache.oro.text.*;
import org.apache.oro.text.regex.*;

import com.ecyrd.jspwiki.*;

/**
 *  This class implements a simple RCS file provider.  NOTE: You MUST
 *  have the RCS package installed for this to work.  They must also
 *  be in your path...
 *
 *  <P>
 *  The RCS file provider extends from the FileSystemProvider, which
 *  means that it provides the pages in the same way.  The only difference
 *  is that it implements the version history commands, and also in each
 *  checkin it writes the page to the RCS repository as well.
 *
 *  @author <NAME>
 */
// FIXME: Not all commands read their format from the property file yet.
public class RCSFileProvider
    extends FileSystemProvider
{
    private String m_checkinCommand  = "ci -q -m\"author=%u\" -l -t-none %s";
    private String m_checkoutCommand = "co -l %s";
    private String m_logCommand      = "rlog -zLT -r %s";
    private String m_fullLogCommand  = "rlog -zLT %s";
    private String m_checkoutVersionCommand = "co -p -r1.%v %s";
    
    private static final Category   log = Category.getInstance(RCSFileProvider.class);

    public static final String    PROP_CHECKIN  = "jspwiki.rcsFileProvider.checkinCommand";
    public static final String    PROP_CHECKOUT = "jspwiki.rcsFileProvider.checkoutCommand";
    public static final String    PROP_LOG      = "jspwiki.rcsFileProvider.logCommand";
    public static final String    PROP_FULLLOG  = "jspwiki.rcsFileProvider.fullLogCommand";
    public static final String    PROP_CHECKOUTVERSION = "jspwiki.rcsFileProvider.checkoutVersionCommand";

    private static final String   PATTERN_DATE      = "^date:\\s*(.*)[\\+\\-;]\\d+;";
    private static final String   PATTERN_AUTHOR    = "^\"?author=([\\w\\.\\s\\+\\.\\%]*)\"?";
    private static final String   PATTERN_REVISION  = "^revision \\d+\\.(\\d+)";

    private static final String   RCSFMT_DATE       = "yyyy-MM-dd HH:mm:ss";

    public void initialize( Properties props )
        throws NoRequiredPropertyException,
               IOException
    {
        log.debug("Initing RCS");
        super.initialize( props );

        m_checkinCommand = props.getProperty( PROP_CHECKIN, m_checkinCommand );
        m_checkoutCommand = props.getProperty( PROP_CHECKOUT, m_checkoutCommand );
        m_logCommand     = props.getProperty( PROP_LOG, m_logCommand );
        m_fullLogCommand = props.getProperty( PROP_FULLLOG, m_fullLogCommand );
        m_checkoutVersionCommand = props.getProperty( PROP_CHECKOUTVERSION, m_checkoutVersionCommand );
        
        File rcsdir = new File( getPageDirectory(), "RCS" );

        if( !rcsdir.exists() )
            rcsdir.mkdirs();

        log.debug("checkin="+m_checkinCommand);
        log.debug("checkout="+m_checkoutCommand);
        log.debug("log="+m_logCommand);
        log.debug("fulllog="+m_fullLogCommand);
        log.debug("checkoutversion="+m_checkoutVersionCommand);
    }

    // NB: This is a very slow method.

    public WikiPage getPageInfo( String page, int version )
        throws ProviderException
    {
        PatternMatcher  matcher  = new Perl5Matcher();
        PatternCompiler compiler = new Perl5Compiler();
        PatternMatcherInput input;

        WikiPage info = super.getPageInfo( page, version );

        try
        {
            String   cmd = m_fullLogCommand;

            cmd = TextUtil.replaceString( cmd, "%s", mangleName(page)+FILE_EXT );

            Process process = Runtime.getRuntime().exec( cmd, null, new File(getPageDirectory()) );

            // FIXME: Should this use encoding as well?
            BufferedReader stdout = new BufferedReader( new InputStreamReader(process.getInputStream() ) );

            String line;
            Pattern headpattern = compiler.compile( PATTERN_REVISION );
            // This complicated pattern is required, since on Linux RCS adds
            // quotation marks, but on Windows, it does not.
            Pattern userpattern = compiler.compile( PATTERN_AUTHOR );
            Pattern datepattern = compiler.compile( PATTERN_DATE );
            SimpleDateFormat rcsdatefmt = new SimpleDateFormat( RCSFMT_DATE );
            boolean found = false;

            while( (line = stdout.readLine()) != null )
            {
                if( matcher.contains( line, headpattern ) )
                {                    
                    MatchResult result = matcher.getMatch();
                    int vernum = Integer.parseInt( result.group(1) );

                    if( vernum == version || version == WikiPageProvider.LATEST_VERSION )
                    {
                        info.setVersion( vernum );
                        found = true;
                    }
                }
                else if( matcher.contains( line, datepattern ) && found )
                {
                    MatchResult result = matcher.getMatch();

                    Date d = rcsdatefmt.parse( result.group(1) );

                    if( d != null )
                    {
                        info.setLastModified( d );
                    }
                    else
                    {
                        log.info("WikiPage "+info.getName()+
                                 " has null modification date for version "+
                                 version);
                    }
                }
                else if( matcher.contains( line, userpattern ) && found )
                {
                    MatchResult result = matcher.getMatch();
                    info.setAuthor( TextUtil.urlDecodeUTF8(result.group(1)) );
                }
                else if( found && line.startsWith("----")  )
                {
                    // End of line sign from RCS
                    break;
                }
            }

            //
            //  Especially with certain versions of RCS on Windows,
            //  process.waitFor() hangs unless you read all of the
            //  standard output.  So we make sure it's all emptied.
            //

            while( (line = stdout.readLine()) != null ) 
            { 
            }

            process.waitFor();

        }
        catch( Exception e )
        {
            // This also occurs when 'info' was null.
            log.warn("Failed to read RCS info",e);
        }

        return info;
    }

    public String getPageText( String page, int version )
    {
        String result = null;

        // Let parent handle latest fetches, since the FileSystemProvider
        // can do the file reading just as well.

        if( version == WikiPageProvider.LATEST_VERSION )
            return super.getPageText( page, version );

        log.debug("Fetching specific version "+version+" of page "+page);
        try
        {
            String cmd = m_checkoutVersionCommand;

            cmd = TextUtil.replaceString( cmd, "%s", mangleName(page)+FILE_EXT );
            cmd = TextUtil.replaceString( cmd, "%v", Integer.toString(version ) );

            log.debug("Command = '"+cmd+"'");

            Process process = Runtime.getRuntime().exec( cmd, null, new File(getPageDirectory()) );
            result = FileUtil.readContents( process.getInputStream(),
                                            m_encoding );

            process.waitFor();

            log.debug("Done, returned = "+process.exitValue());
        }
        catch( Exception e )
        {
            log.error("RCS checkout failed",e);
        }
        
        return result;
    }

    /**
     *  Puts the page into RCS and makes sure there is a fresh copy in
     *  the directory as well.
     */
    public void putPageText( WikiPage page, String text )
    {
        String pagename = page.getName();
        // Writes it in the dir.
        super.putPageText( page, text );

        log.debug( "Checking in text..." );

        try
        {
            String cmd = m_checkinCommand;
            
            String author = page.getAuthor();
            if( author == null ) author = "unknown";

            cmd = TextUtil.replaceString( cmd, "%s", mangleName(pagename)+FILE_EXT );
            cmd = TextUtil.replaceString( cmd, "%u", TextUtil.urlEncodeUTF8(author) );

            log.debug("Command = '"+cmd+"'");

            Process process = Runtime.getRuntime().exec( cmd, null, new File(getPageDirectory()) );

            process.waitFor();

            log.debug("Done, returned = "+process.exitValue());
        }
        catch( Exception e )
        {
            log.error("RCS checkin failed",e);
        }
    }

    // FIXME: Put the rcs date formats into properties as well.
    public Collection getVersionHistory( String page )
    {
        PatternMatcher matcher = new Perl5Matcher();
        PatternCompiler compiler = new Perl5Compiler();
        PatternMatcherInput input;

        log.debug("Getting RCS version history");

        ArrayList list = new ArrayList();        

        SimpleDateFormat rcsdatefmt = new SimpleDateFormat( RCSFMT_DATE );

        try
        {
            Pattern revpattern  = compiler.compile( PATTERN_REVISION );
            Pattern datepattern = compiler.compile( PATTERN_DATE );
            // This complicated pattern is required, since on Linux RCS adds
            // quotation marks, but on Windows, it does not.
            Pattern userpattern = compiler.compile( PATTERN_AUTHOR );

            String cmd = TextUtil.replaceString( m_fullLogCommand,
                                                 "%s",
                                                 mangleName(page)+FILE_EXT );
            
            Process process = Runtime.getRuntime().exec( cmd, null, new File(getPageDirectory()) );

            // FIXME: Should this use encoding as well?
            BufferedReader stdout = new BufferedReader( new InputStreamReader(process.getInputStream()) );

            String line;

            WikiPage info = null;

            while( (line = stdout.readLine()) != null )
            { 
                if( matcher.contains( line, revpattern ) )
                {
                    info = new WikiPage( page );

                    MatchResult result = matcher.getMatch();

                    int vernum = Integer.parseInt( result.group(1) );
                    info.setVersion( vernum );
                    list.add( info );
                }

                if( matcher.contains( line, datepattern ) )
                {
                    MatchResult result = matcher.getMatch();

                    Date d = rcsdatefmt.parse( result.group(1) );

                    info.setLastModified( d );
                }

                if( matcher.contains( line, userpattern ) )
                {
                    MatchResult result = matcher.getMatch();

                    info.setAuthor( TextUtil.urlDecodeUTF8(result.group(1)) );
                }
            }

            process.waitFor();

        }
        catch( Exception e )
        {
            log.error( "RCS log failed", e );
        }

        return list;
    }
}
<commit_msg>getPageText() throws ProviderException<commit_after>/* 
    JSPWiki - a JSP-based WikiWiki clone.

    Copyright (C) 2001 <NAME> (<EMAIL>)

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
package com.ecyrd.jspwiki.providers;

import java.io.File;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.Properties;
import java.util.Collection;
import java.util.ArrayList;
import java.util.Date;
import java.text.SimpleDateFormat;
import org.apache.log4j.Category;
import org.apache.oro.text.*;
import org.apache.oro.text.regex.*;

import com.ecyrd.jspwiki.*;

/**
 *  This class implements a simple RCS file provider.  NOTE: You MUST
 *  have the RCS package installed for this to work.  They must also
 *  be in your path...
 *
 *  <P>
 *  The RCS file provider extends from the FileSystemProvider, which
 *  means that it provides the pages in the same way.  The only difference
 *  is that it implements the version history commands, and also in each
 *  checkin it writes the page to the RCS repository as well.
 *
 *  @author <NAME>
 */
// FIXME: Not all commands read their format from the property file yet.
public class RCSFileProvider
    extends FileSystemProvider
{
    private String m_checkinCommand  = "ci -q -m\"author=%u\" -l -t-none %s";
    private String m_checkoutCommand = "co -l %s";
    private String m_logCommand      = "rlog -zLT -r %s";
    private String m_fullLogCommand  = "rlog -zLT %s";
    private String m_checkoutVersionCommand = "co -p -r1.%v %s";
    
    private static final Category   log = Category.getInstance(RCSFileProvider.class);

    public static final String    PROP_CHECKIN  = "jspwiki.rcsFileProvider.checkinCommand";
    public static final String    PROP_CHECKOUT = "jspwiki.rcsFileProvider.checkoutCommand";
    public static final String    PROP_LOG      = "jspwiki.rcsFileProvider.logCommand";
    public static final String    PROP_FULLLOG  = "jspwiki.rcsFileProvider.fullLogCommand";
    public static final String    PROP_CHECKOUTVERSION = "jspwiki.rcsFileProvider.checkoutVersionCommand";

    private static final String   PATTERN_DATE      = "^date:\\s*(.*)[\\+\\-;]\\d+;";
    private static final String   PATTERN_AUTHOR    = "^\"?author=([\\w\\.\\s\\+\\.\\%]*)\"?";
    private static final String   PATTERN_REVISION  = "^revision \\d+\\.(\\d+)";

    private static final String   RCSFMT_DATE       = "yyyy-MM-dd HH:mm:ss";

    public void initialize( Properties props )
        throws NoRequiredPropertyException,
               IOException
    {
        log.debug("Initing RCS");
        super.initialize( props );

        m_checkinCommand = props.getProperty( PROP_CHECKIN, m_checkinCommand );
        m_checkoutCommand = props.getProperty( PROP_CHECKOUT, m_checkoutCommand );
        m_logCommand     = props.getProperty( PROP_LOG, m_logCommand );
        m_fullLogCommand = props.getProperty( PROP_FULLLOG, m_fullLogCommand );
        m_checkoutVersionCommand = props.getProperty( PROP_CHECKOUTVERSION, m_checkoutVersionCommand );
        
        File rcsdir = new File( getPageDirectory(), "RCS" );

        if( !rcsdir.exists() )
            rcsdir.mkdirs();

        log.debug("checkin="+m_checkinCommand);
        log.debug("checkout="+m_checkoutCommand);
        log.debug("log="+m_logCommand);
        log.debug("fulllog="+m_fullLogCommand);
        log.debug("checkoutversion="+m_checkoutVersionCommand);
    }

    // NB: This is a very slow method.

    public WikiPage getPageInfo( String page, int version )
        throws ProviderException
    {
        PatternMatcher  matcher  = new Perl5Matcher();
        PatternCompiler compiler = new Perl5Compiler();
        PatternMatcherInput input;

        WikiPage info = super.getPageInfo( page, version );

        try
        {
            String   cmd = m_fullLogCommand;

            cmd = TextUtil.replaceString( cmd, "%s", mangleName(page)+FILE_EXT );

            Process process = Runtime.getRuntime().exec( cmd, null, new File(getPageDirectory()) );

            // FIXME: Should this use encoding as well?
            BufferedReader stdout = new BufferedReader( new InputStreamReader(process.getInputStream() ) );

            String line;
            Pattern headpattern = compiler.compile( PATTERN_REVISION );
            // This complicated pattern is required, since on Linux RCS adds
            // quotation marks, but on Windows, it does not.
            Pattern userpattern = compiler.compile( PATTERN_AUTHOR );
            Pattern datepattern = compiler.compile( PATTERN_DATE );
            SimpleDateFormat rcsdatefmt = new SimpleDateFormat( RCSFMT_DATE );
            boolean found = false;

            while( (line = stdout.readLine()) != null )
            {
                if( matcher.contains( line, headpattern ) )
                {                    
                    MatchResult result = matcher.getMatch();
                    int vernum = Integer.parseInt( result.group(1) );

                    if( vernum == version || version == WikiPageProvider.LATEST_VERSION )
                    {
                        info.setVersion( vernum );
                        found = true;
                    }
                }
                else if( matcher.contains( line, datepattern ) && found )
                {
                    MatchResult result = matcher.getMatch();

                    Date d = rcsdatefmt.parse( result.group(1) );

                    if( d != null )
                    {
                        info.setLastModified( d );
                    }
                    else
                    {
                        log.info("WikiPage "+info.getName()+
                                 " has null modification date for version "+
                                 version);
                    }
                }
                else if( matcher.contains( line, userpattern ) && found )
                {
                    MatchResult result = matcher.getMatch();
                    info.setAuthor( TextUtil.urlDecodeUTF8(result.group(1)) );
                }
                else if( found && line.startsWith("----")  )
                {
                    // End of line sign from RCS
                    break;
                }
            }

            //
            //  Especially with certain versions of RCS on Windows,
            //  process.waitFor() hangs unless you read all of the
            //  standard output.  So we make sure it's all emptied.
            //

            while( (line = stdout.readLine()) != null ) 
            { 
            }

            process.waitFor();

        }
        catch( Exception e )
        {
            // This also occurs when 'info' was null.
            log.warn("Failed to read RCS info",e);
        }

        return info;
    }

    public String getPageText( String page, int version )
        throws ProviderException
    {
        String result = null;

        // Let parent handle latest fetches, since the FileSystemProvider
        // can do the file reading just as well.

        if( version == WikiPageProvider.LATEST_VERSION )
            return super.getPageText( page, version );

        log.debug("Fetching specific version "+version+" of page "+page);
        try
        {
            String cmd = m_checkoutVersionCommand;

            cmd = TextUtil.replaceString( cmd, "%s", mangleName(page)+FILE_EXT );
            cmd = TextUtil.replaceString( cmd, "%v", Integer.toString(version ) );

            log.debug("Command = '"+cmd+"'");

            Process process = Runtime.getRuntime().exec( cmd, null, new File(getPageDirectory()) );
            result = FileUtil.readContents( process.getInputStream(),
                                            m_encoding );

            process.waitFor();

            log.debug("Done, returned = "+process.exitValue());
        }
        catch( Exception e )
        {
            log.error("RCS checkout failed",e);
        }
        
        return result;
    }

    /**
     *  Puts the page into RCS and makes sure there is a fresh copy in
     *  the directory as well.
     */
    public void putPageText( WikiPage page, String text )
    {
        String pagename = page.getName();
        // Writes it in the dir.
        super.putPageText( page, text );

        log.debug( "Checking in text..." );

        try
        {
            String cmd = m_checkinCommand;
            
            String author = page.getAuthor();
            if( author == null ) author = "unknown";

            cmd = TextUtil.replaceString( cmd, "%s", mangleName(pagename)+FILE_EXT );
            cmd = TextUtil.replaceString( cmd, "%u", TextUtil.urlEncodeUTF8(author) );

            log.debug("Command = '"+cmd+"'");

            Process process = Runtime.getRuntime().exec( cmd, null, new File(getPageDirectory()) );

            process.waitFor();

            log.debug("Done, returned = "+process.exitValue());
        }
        catch( Exception e )
        {
            log.error("RCS checkin failed",e);
        }
    }

    // FIXME: Put the rcs date formats into properties as well.
    public Collection getVersionHistory( String page )
    {
        PatternMatcher matcher = new Perl5Matcher();
        PatternCompiler compiler = new Perl5Compiler();
        PatternMatcherInput input;

        log.debug("Getting RCS version history");

        ArrayList list = new ArrayList();        

        SimpleDateFormat rcsdatefmt = new SimpleDateFormat( RCSFMT_DATE );

        try
        {
            Pattern revpattern  = compiler.compile( PATTERN_REVISION );
            Pattern datepattern = compiler.compile( PATTERN_DATE );
            // This complicated pattern is required, since on Linux RCS adds
            // quotation marks, but on Windows, it does not.
            Pattern userpattern = compiler.compile( PATTERN_AUTHOR );

            String cmd = TextUtil.replaceString( m_fullLogCommand,
                                                 "%s",
                                                 mangleName(page)+FILE_EXT );
            
            Process process = Runtime.getRuntime().exec( cmd, null, new File(getPageDirectory()) );

            // FIXME: Should this use encoding as well?
            BufferedReader stdout = new BufferedReader( new InputStreamReader(process.getInputStream()) );

            String line;

            WikiPage info = null;

            while( (line = stdout.readLine()) != null )
            { 
                if( matcher.contains( line, revpattern ) )
                {
                    info = new WikiPage( page );

                    MatchResult result = matcher.getMatch();

                    int vernum = Integer.parseInt( result.group(1) );
                    info.setVersion( vernum );
                    list.add( info );
                }

                if( matcher.contains( line, datepattern ) )
                {
                    MatchResult result = matcher.getMatch();

                    Date d = rcsdatefmt.parse( result.group(1) );

                    info.setLastModified( d );
                }

                if( matcher.contains( line, userpattern ) )
                {
                    MatchResult result = matcher.getMatch();

                    info.setAuthor( TextUtil.urlDecodeUTF8(result.group(1)) );
                }
            }

            process.waitFor();

        }
        catch( Exception e )
        {
            log.error( "RCS log failed", e );
        }

        return list;
    }
}

{'fraction_non_alphanumeric': 0.09439672801635991, 'fraction_numerical': 0.0027811860940695297, 'mean_word_length': 1.794080676494115, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 18, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2490552', 'n_tokens_mistral': 6502, 'n_tokens_neox': 6165, 'n_words': 1852}