<commit_before>package com.izforge.izpack.core.rules.process;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.izforge.izpack.api.adaptator.IXMLElement;
import com.izforge.izpack.api.adaptator.impl.XMLElementImpl;
import com.izforge.izpack.api.data.Variables;
import com.izforge.izpack.api.rules.Condition;

public class ContainsCondition extends Condition {

  private static final long serialVersionUID = 114116957546161583L;

  private static final transient Logger logger = Logger
      .getLogger(ContainsCondition.class.getName());

  private static final String VALUE_ELEMENT_NAME = "value";
  private static final String VALUE_ATTR_REGEX_NAME = "regex";
  private static final String VALUE_ATTR_CASEINSENSITIVE_NAME = "caseInsensitive";
  private static final String VALUE_ATTR_BYLINE_NAME = "byLine";

  private ContentType contentType;
  private String source = null;
  private String value = null;
  private boolean isRegEx = false;
  private boolean isCaseInsensitive = false;
  private boolean isByLine = true;

  private Pattern pattern = null;

  public ContainsCondition() {
  }

  @Override
  public boolean isTrue()
  {

    if (this.source == null) {
        return false;
    }

    Variables variables = getInstallData().getVariables();
    String content = null;

    // resolve variables in <value>; 
    // must be done on each call again, because content could change 
    String resolvedValue = variables.replace(this.value);

    switch (contentType) {
    case STRING:
        content = variables.replace(this.source);
        break;

    case VARIABLE:
        content = this.getInstallData().getVariable(this.source);
        break;

    case FILE:
        File file = new File(variables.replace(this.source));
        if (isByLine)
        {
            BufferedReader in = null;
            try
            {
                return matchesByLine(new FileReader(file), resolvedValue);
            }
            catch (FileNotFoundException e)
            {
                logger.log(Level.WARNING, e.getMessage());
                return false;
            }
            finally {
                if (in != null)
                {
                    try
                    {
                        in.close();
                    }
                    catch (IOException e) {}
                }
            }
        }
        else
        {
            byte[] buffer = new byte[(int) file.length()];
            BufferedInputStream f = null;
            try
            {
                f = new BufferedInputStream(new FileInputStream(file));
                f.read(buffer);
                if (f != null) try
                {
                    f.close();
                }
                catch (IOException ignored)
                {}
            }
            catch (IOException e)
            {
                logger.log(Level.WARNING, e.getMessage());
                return false;
            }
            content = new String(buffer);
        }
      break;

    default:
      logger.warning("Illegal source type '" + contentType.getAttribute()
          + "' for condition \"" + getId() + "\"");
      break;
    }

    if (content == null)
      return false;

    if (isRegEx)
    {
        pattern = Pattern.compile(resolvedValue);
        if (isByLine)
        {
            return matchesByLine(new StringReader(content), resolvedValue);
        }
    }

    return matchesString(content, resolvedValue);
  }

  private boolean matchesByLine(Reader reader, String value)
  {
      BufferedReader in = null;
      try
      {
          in = new BufferedReader(reader);
          for (String line = in.readLine(); line != null; line = in.readLine())
          {
              if (matchesString(line, value))
              {
                  return true;
              }
          }
      }<commit_msg>IZPACK-1411: Avoid NPE for <value byLine="true" regex="true">my.*pattern</value> in combination with a <file> source<commit_after>package com.izforge.izpack.core.rules.process;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.izforge.izpack.api.adaptator.IXMLElement;
import com.izforge.izpack.api.adaptator.impl.XMLElementImpl;
import com.izforge.izpack.api.data.Variables;
import com.izforge.izpack.api.rules.Condition;

public class ContainsCondition extends Condition {

  private static final long serialVersionUID = 114116957546161583L;

  private static final transient Logger logger = Logger
      .getLogger(ContainsCondition.class.getName());

  private static final String VALUE_ELEMENT_NAME = "value";
  private static final String VALUE_ATTR_REGEX_NAME = "regex";
  private static final String VALUE_ATTR_CASEINSENSITIVE_NAME = "caseInsensitive";
  private static final String VALUE_ATTR_BYLINE_NAME = "byLine";

  private ContentType contentType;
  private String source = null;
  private String value = null;
  private boolean isRegEx = false;
  private boolean isCaseInsensitive = false;
  private boolean isByLine = true;

  private Pattern pattern = null;

  public ContainsCondition() {
  }

  @Override
  public boolean isTrue()
  {

    if (this.source == null) {
        return false;
    }

    Variables variables = getInstallData().getVariables();
    String content = null;

    // resolve variables in <value>; 
    // must be done on each call again, because content could change 
    String resolvedValue = variables.replace(this.value);

    if (isRegEx)
    {
        pattern = Pattern.compile(resolvedValue);
    }

    switch (contentType) {
    case STRING:
        content = variables.replace(this.source);
        break;

    case VARIABLE:
        content = this.getInstallData().getVariable(this.source);
        break;

    case FILE:
        File file = new File(variables.replace(this.source));
        if (isByLine)
        {
            BufferedReader in = null;
            try
            {
                return matchesByLine(new FileReader(file), resolvedValue);
            }
            catch (FileNotFoundException e)
            {
                logger.log(Level.WARNING, e.getMessage());
                return false;
            }
            finally {
                if (in != null)
                {
                    try
                    {
                        in.close();
                    }
                    catch (IOException e) {}
                }
            }
        }
        else
        {
            byte[] buffer = new byte[(int) file.length()];
            BufferedInputStream f = null;
            try
            {
                f = new BufferedInputStream(new FileInputStream(file));
                f.read(buffer);
                if (f != null) try
                {
                    f.close();
                }
                catch (IOException ignored)
                {}
            }
            catch (IOException e)
            {
                logger.log(Level.WARNING, e.getMessage());
                return false;
            }
            content = new String(buffer);
        }
      break;

    default:
      logger.warning("Illegal source type '" + contentType.getAttribute()
          + "' for condition \"" + getId() + "\"");
      break;
    }

    if (content == null)
      return false;

    if (isRegEx)
    {
        if (isByLine)
        {
            return matchesByLine(new StringReader(content), resolvedValue);
        }
    }

    return matchesString(content, resolvedValue);
  }

  private boolean matchesByLine(Reader reader, String value)
  {
      BufferedReader in = null;
      try
      {
          in = new BufferedReader(reader);
          for (String line = in.readLine(); line != null; line = in.readLine())
          {
              if (matchesString(line, value))
              {
                  return true;
              }
          }
      }
{'fraction_non_alphanumeric': 0.09335170513262142, 'fraction_numerical': 0.004592949822023194, 'mean_word_length': 1.910123621784163, 'pattern_counts': {'":': 0, '<': 8, '<?xml version=': 0, '>': 8, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5940139', 'n_tokens_mistral': 2398, 'n_tokens_neox': 2281, 'n_words': 570}