Package org.huihoo.workflow.rules.compiler

Source Code of org.huihoo.workflow.rules.compiler.ScriptReader

//----------------------------BEGIN LICENSE----------------------------
/*
* Willow : the Open Source WorkFlow Project
* Distributable under GNU LGPL license by gun.org
*
* Copyright (C) 2004-2010 huihoo.org
* Copyright (C) 2004-2010  ZosaTapo <dertyang@hotmail.com>
*
* ====================================================================
* Project Homepage : http://www.huihoo.org/willow
* Source Forge     : http://sourceforge.net/projects/huihoo
* Mailing list     : willow@lists.sourceforge.net
*/
//----------------------------END  LICENSE-----------------------------
package org.huihoo.workflow.rules.compiler;
import java.io.CharArrayWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.util.Hashtable;
import org.huihoo.workflow.rules.Constants;
import org.huihoo.workflow.rules.ScriptException;
import org.huihoo.workflow.rules.config.ScriptCompilationContext;
import org.huihoo.workflow.rules.util.StringManager;
/**
* @author reic
*
* To change the template for this generated type comment go to
* Window - Preferences - Java - Code Generation - Code and Comments
*/
public class ScriptReader
{
  private static StringManager sm = StringManager.getManager(Constants.RESOURCE_BUNDLE_BASE);
  private Mark current = null;
  private ScriptCompilationContext context;
  private String encoding = null;
  protected ScriptReader(String file, ScriptCompilationContext ctx, String encoding) throws ScriptException, FileNotFoundException
  {
    this.context = ctx;
    this.encoding = encoding;
    if (this.encoding == null)
    {
      this.encoding = "ISO-8859-1";
    }
    loadFile(file, this.encoding);
  }
 
  protected ScriptReader(String content, ScriptCompilationContext ctx) throws ScriptException, FileNotFoundException
  {
    this.context = ctx;
    loadContent(content);
  }
 
  public static ScriptReader createGodjReader(String file, ScriptCompilationContext ctx, String encoding)
    throws ScriptException, FileNotFoundException
  {
    return new ScriptReader(file, ctx, encoding);
  }
 
  public static ScriptReader createGodjReader(String content, ScriptCompilationContext ctx)
    throws ScriptException, FileNotFoundException
  {
    return new ScriptReader(content, ctx);
  }
 
  public boolean hasMoreInput() throws ScriptException
  {
    if (current.cursor >= current.stream.length)
    {
      return false;
    }
    return true;
  }
  public int nextChar() throws ScriptException
  {
    if (!hasMoreInput())
      return -1;
    int ch = current.stream[current.cursor];
    current.cursor++;
    if (ch == '\n')
    {
      current.line++;
      current.col = 0;
    }
    else
    {
      current.col++;
    }
    return ch;
  }
  /**
   * Gets Content until the next potential RULE element.  Because all elements
   * begin with a '&lt;' we can just move until we see the next one.
   */
  String nextContent()
  {
    int cur_cursor = current.cursor;
    int len = current.stream.length;
    char ch;
    if (peekChar() == '\n')
    {
      current.line++;
      current.col = 0;
    }
    else
    {
      current.col++;
    }
    // pure obsfuscated genius!
    while ((++current.cursor < len) && ((ch = current.stream[current.cursor]) != '<'))
    {
      if (ch == '\n')
      {
        current.line++;
        current.col = 0;
      }
      else
      {
        current.col++;
      }
    }
    return new String(current.stream, cur_cursor, current.cursor - cur_cursor);
  }
  char[] getChars(Mark start, Mark stop) throws ScriptException
  {
    Mark oldstart = mark();
    reset(start);
    CharArrayWriter caw = new CharArrayWriter();
    while (!stop.equals(mark()))
      caw.write(nextChar());
    caw.close();
    reset(oldstart);
    return caw.toCharArray();
  }
  public int peekChar()
  {
    return current.stream[current.cursor];
  }
  public Mark mark()
  {
    return new Mark(current);
  }
  public void reset(Mark mark)
  {
    current = new Mark(mark);
  }
  public boolean matchesIgnoreCase(String string) throws ScriptException
  {
    Mark mark = mark();
    int ch = 0;
    int i = 0;
    do
    {
      ch = nextChar();
      if (Character.toLowerCase((char) ch) != string.charAt(i++))
      {
        reset(mark);
        return false;
      }
    }
    while (i < string.length());
    reset(mark);
    return true;
  }
  public boolean matches(String string) throws ScriptException
  {
    Mark mark = mark();
    int ch = 0;
    int i = 0;
    do
    {
      ch = nextChar();
      if (((char) ch) != string.charAt(i++))
      {
        reset(mark);
        return false;
      }
    }
    while (i < string.length());
    reset(mark);
    return true;
  }
  public void advance(int n) throws ScriptException
  {
    while (--n >= 0)
      nextChar();
  }
  public int skipSpaces() throws ScriptException
  {
    int i = 0;
    while (isSpace())
    {
      i++;
      nextChar();
    }
    return i;
  }
  /**
   * Skip until the given string is matched in the stream.
   * When returned, the context is positioned past the end of the match.
   * @param s The String to match.
   * @return A non-null <code>Mark</code> instance if found,
   * <strong>null</strong> otherwise.
   */
  public Mark skipUntil(String limit) throws ScriptException
  {
    Mark ret = null;
    int limlen = limit.length();
    int ch;
    skip : for (ret = mark(), ch = nextChar(); ch != -1; ret = mark(), ch = nextChar())
    {
      if (ch == limit.charAt(0))
      {
        for (int i = 1; i < limlen; i++)
        {
          if (Character.toLowerCase((char) nextChar()) != limit.charAt(i))
            continue skip;
        }
        return ret;
      }
    }
    return null;
  }
  final boolean isSpace()
  {
    return peekChar() <= ' ';
  }
  /**
   * Parse a space delimited token.
   * If quoted the token will consume all characters up to a matching quote,
   * otherwise, it consumes up to the first delimiter character.
   * @param quoted If <strong>true</strong> accept quoted strings.
   */
  public String parseToken(boolean quoted) throws ScriptException
  {
    StringBuffer stringBuffer = new StringBuffer();
    skipSpaces();
    stringBuffer.setLength(0);
    int ch = peekChar();
    if (quoted)
    {
      if (ch == '"' || ch == '\'')
      {
        char endQuote = ch == '"' ? '"' : '\'';
        // Consume the open quote:
        ch = nextChar();
        for (ch = nextChar(); ch != -1 && ch != endQuote; ch = nextChar())
        {
          if (ch == '\\')
            ch = nextChar();
          stringBuffer.append((char) ch);
        }
        // Check end of quote, skip closing quote:
        if (ch == -1)
        {
          throw new ScriptException(mark(), sm.getString("script.error.quotes.unterminated"));
        }
      }
      else
      {
        throw new ScriptException(mark(), sm.getString("script.error.attr.quoted"));
      }
    }
    else
    {
      if (!isDelimiter()) // Read value until delimiter is found:
        do
        {
          ch = nextChar();
          // Take care of the quoting here.
          if (ch == '\\')
          {
            if (peekChar() == '"' || peekChar() == '\'' || peekChar() == '>' || peekChar() == '%')
              ch = nextChar();
          }
          stringBuffer.append((char) ch);
        }
        while (!isDelimiter());
    }
    return stringBuffer.toString();
  }
  /**
   * Parse an attribute/value pair, and store it in provided hash table.
   * The attribute/value pair is defined by:
   * <pre>
   * av := spaces token spaces '=' spaces token spaces
   * </pre>
   * Where <em>token</em> is defined by <code>parseToken</code> and
   * <em>spaces</em> is defined by <code>skipSpaces</code>.
   * The name is always considered case insensitive, hence stored in its
   * lower case version.
   * @param into The Hashtable instance to save the result to.
   */
  private void parseAttributeValue(Hashtable into) throws ScriptException
  {
    // Get the attribute name:
    skipSpaces();
    String name = parseToken(false);
    // Check for an equal sign:
    skipSpaces();
    if (peekChar() != '=')
    {
      throw new ScriptException(mark(), sm.getString("script.error.attr.novalue", new Object[] { name }));
    }
    char ch = (char) nextChar();
    // Get the attribute value:
    skipSpaces();
    String value = parseToken(true);
    skipSpaces();
    // Add the binding to the provided hashtable:
    into.put(name, value);
    return;
  }
  /**
   * Parse some tag attributes.
   * The stream is assumed to be positioned right after the tag name. The
   * syntax recognized is:
   * <pre>
   * tag-attrs := empty | attr-list ("&gt;" | "--&gt;" | %&gt;)
   * attr-list := empty | av spaces attr-list
   * empty     := spaces
   * </pre>
   * Where <em>av</em> is defined by <code>parseAttributeValue</code>.
   * @return A Hashtable mapping String instances (variable names) into
   * String instances (variable values).
   */
  public Hashtable parseTagAttributes() throws ScriptException
  {
    Hashtable values = new Hashtable(11);
    while (true)
    {
      skipSpaces();
      int ch = peekChar();
      if (ch == '>')
      {
        return values;
      }
      if (ch == '-')
      {
        Mark mark = mark();
        nextChar();
        // Close NCSA like attributes "->"
        try
        {
          if (nextChar() == '-' && nextChar() == '>')
            return values;
        }
        finally
        {
          reset(mark);
        }
      }
      else if (ch == '%')
      {
        Mark mark = mark();
        nextChar();
        // Close variable like attributes "%>"
        try
        {
          if (nextChar() == '>')
            return values;
        }
        finally
        {
          reset(mark);
        }
      }
      else if (ch == '/')
      {
        Mark mark = mark();
        nextChar();
        // XMLesque Close tags
        try
        {
          if (nextChar() == '>')
            return values;
        }
        finally
        {
          reset(mark);
        }
      }
      if (ch == -1)
        break;
      // Parse as an attribute=value:
      parseAttributeValue(values);
    }
    // Reached EOF:
    throw new ScriptException(mark(), sm.getString("script.error.tag.attr.unterminated"));
  }
  /**
   * Parse utils - Is current character a token delimiter ?
   * Delimiters are currently defined to be =, &gt;, &lt;, ", and ' or any
   * any space character as defined by <code>isSpace</code>.
   * @return A boolean.
   */
  private boolean isDelimiter() throws ScriptException
  {
    if (!isSpace())
    {
      int ch = peekChar();
      // Look for a single-char work delimiter:
      if (ch == '=' || ch == '>' || ch == '"' || ch == '\'' || ch == '/')
        return true;
      // Look for an end-of-comment or end-of-tag:   
      if (ch == '-')
      {
        Mark mark = mark();
        if (((ch = nextChar()) == '>') || ((ch == '-') && (nextChar() == '>')))
        {
          reset(mark);
          return true;
        }
        else
        {
          reset(mark);
          return false;
        }
      }
      return false;
    }
    else
    {
      return true;
    }
  }
  private void loadFile(String file, String encoding) throws ScriptException, FileNotFoundException
  {
    loadFile(new File(file), encoding);
  }
  private void loadFile(File file, String encoding) throws ScriptException, FileNotFoundException
  {
    // Default encoding if needed:
    if (encoding == null)
    {
      encoding = this.encoding;
    }
    InputStreamReader reader = null;
    try
    {
      reader = new InputStreamReader(new FileInputStream(file), encoding);
      CharArrayWriter caw = new CharArrayWriter();
      char buf[] = new char[1024];
      for (int i = 0;(i = reader.read(buf)) != -1;)
        caw.write(buf, 0, i);
      caw.close();
      current = new Mark(this, caw.toCharArray(), file.getPath());
    }
    catch (FileNotFoundException fnfe)
    {
      throw fnfe;
    }
    catch (Throwable ex)
    {
      throw new ScriptException(sm.getString("script.error.file.cannot.read", new Object[] { file }));
    }
    finally
    {
      if (reader != null)
      {
        try
        {
          reader.close();
        }
        catch (Exception any)
        {
        }
      }
    }
  }
  private void loadContent(String content)
  {
    StringReader reader = new StringReader(content);
    try
    {
      CharArrayWriter caw = new CharArrayWriter();
      char buf[] = new char[1024];
      for (int i = 0;(i = reader.read(buf)) != -1;)
        caw.write(buf, 0, i);
      caw.close();
      current = new Mark(this, caw.toCharArray(), null);
    }
    catch (IOException ex)
    {
    }
    finally
    {
      try
      {
        reader.close();
      }
      catch (Exception any)
      {
      }
    }
  }
}
TOP

Related Classes of org.huihoo.workflow.rules.compiler.ScriptReader

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.