예제 #1
0
  public static Object invokeSuperclassMethodImpl(
      BshClassManager bcm, Object instance, String methodName, Object[] args)
      throws UtilEvalError, ReflectError, InvocationTargetException {
    String superName = ClassGeneratorUtil.BSHSUPER + methodName;

    // look for the specially named super delegate method
    Class clas = instance.getClass();
    Method superMethod =
        Reflect.resolveJavaMethod(bcm, clas, superName, Types.getTypes(args), false /*onlyStatic*/);
    if (superMethod != null) return Reflect.invokeMethod(superMethod, instance, args);

    // No super method, try to invoke regular method
    // could be a superfluous "super." which is legal.
    Class superClass = clas.getSuperclass();
    superMethod =
        Reflect.resolveExpectedJavaMethod(
            bcm, superClass, instance, methodName, args, false /*onlyStatic*/);
    return Reflect.invokeMethod(superMethod, instance, args);
  }
예제 #2
0
  /**
   * Converts an HTML document to XML.
   *
   * @param io io reference
   * @param opts html options
   * @return parser
   * @throws IOException I/O exception
   */
  private static IO toXML(final IO io, final HtmlOptions opts) throws IOException {
    // reader could not be initialized; fall back to XML
    if (READER == null) return io;

    try {
      // tries to extract the encoding from the input
      final TextInput ti = new TextInput(io);
      String enc = ti.encoding();
      final byte[] content = ti.content();

      // looks for a charset definition
      final byte[] encoding = token("charset=");
      int cs = indexOf(content, encoding);
      if (cs > 0) {
        // extracts the encoding string
        cs += encoding.length;
        int ce = cs;
        final int cl = content.length;
        while (++ce < cl && content[ce] > 0x28) ;
        enc = string(substring(content, cs, ce));
      }

      // define input
      final InputSource is = new InputSource(new ArrayInput(content));
      is.setEncoding(supported(enc) ? normEncoding(enc) : UTF8);
      // define output
      final StringWriter sw = new StringWriter();
      final XMLReader reader = (XMLReader) Reflect.get(READER);
      final Object writer = Reflect.get(WRITER, sw);

      // set TagSoup options
      if (opts.get(HtmlOptions.HTML)) {
        reader.setFeature("http://xml.org/sax/features/namespaces", false);
        opt("method", "html");
        opt("omit-xml-declaration", "yes");
      }
      if (opts.get(HtmlOptions.NONS))
        reader.setFeature("http://xml.org/sax/features/namespaces", false);
      if (opts.get(HtmlOptions.OMITXML)) opt("omit-xml-declaration", "yes");
      if (opts.get(HtmlOptions.NOBOGONS)) reader.setFeature(FEATURES + "ignore-bogons", true);
      if (opts.get(HtmlOptions.NODEFAULTS))
        reader.setFeature(FEATURES + "default-attributes", false);
      if (opts.get(HtmlOptions.NOCOLONS)) reader.setFeature(FEATURES + "translate-colons", true);
      if (opts.get(HtmlOptions.NORESTART)) reader.setFeature(FEATURES + "restart-elements", false);
      if (opts.get(HtmlOptions.IGNORABLE))
        reader.setFeature(FEATURES + "ignorable-whitespace", true);
      if (opts.get(HtmlOptions.EMPTYBOGONS)) reader.setFeature(FEATURES + "bogons-empty", true);
      if (opts.get(HtmlOptions.ANY)) reader.setFeature(FEATURES + "bogons-empty", false);
      if (opts.get(HtmlOptions.NOROOTBOGONS)) reader.setFeature(FEATURES + "root-bogons", false);
      if (opts.get(HtmlOptions.NOCDATA)) reader.setFeature(FEATURES + "cdata-elements", false);
      if (opts.get(HtmlOptions.LEXICAL))
        reader.setProperty("http://xml.org/sax/properties/lexical-handler", writer);
      if (opts.contains(HtmlOptions.METHOD)) opt("method", opts.get(HtmlOptions.METHOD));
      if (opts.contains(HtmlOptions.DOCTYPESYS))
        opt("doctype-system", opts.get(HtmlOptions.DOCTYPESYS));
      if (opts.contains(HtmlOptions.DOCTYPEPUB))
        opt("doctype-public", opts.get(HtmlOptions.DOCTYPEPUB));
      if (opts.contains(HtmlOptions.ENCODING)) is.setEncoding(opts.get(HtmlOptions.ENCODING));
      // end TagSoup options

      reader.setContentHandler((ContentHandler) writer);
      reader.parse(is);
      return new IOContent(token(sw.toString()), io.name());

    } catch (final SAXException ex) {
      Util.errln(ex);
      return io;
    }
  }
예제 #3
0
/**
 * This class uses TagSoup to convert HTML input to well-formed XML. If TagSoup is not found in the
 * classpath, the original document is passed on.
 *
 * <p>TagSoup was written by John Cowan and is based on the Apache 2.0 License: {@code
 * http://home.ccil.org/~cowan/XML/tagsoup/}.
 *
 * @author BaseX Team 2005-14, BSD License
 * @author Christian Gruen
 */
public final class HtmlParser extends XMLParser {
  /** Name of HTML Parser. */
  private static final String NAME = "TagSoup";
  /** TagSoup URL. */
  private static final String FEATURES = "http://www.ccil.org/~cowan/tagsoup/features/";

  /** XML parser class string. */
  private static final String PCLASS = "org.ccil.cowan.tagsoup.Parser";
  /** XML writer class string. */
  private static final String WCLASS = "org.ccil.cowan.tagsoup.XMLWriter";
  /** HTML reader. */
  private static final Class<?> READER = Reflect.find(PCLASS);
  /** HTML writer. */
  private static final Constructor<?> WRITER = Reflect.find(Reflect.find(WCLASS), Writer.class);
  /** XML writer output property method. */
  private static final Method METHOD =
      Reflect.method(
          Reflect.find(WCLASS), "setOutputProperty", new Class[] {String.class, String.class});

  /**
   * Checks if a CatalogResolver is available.
   *
   * @return result of check
   */
  public static boolean available() {
    return READER != null;
  }

  /**
   * Returns the name of the parser, or an empty string.
   *
   * @return name of parser
   */
  public static String parser() {
    return available() ? NAME : "";
  }

  /**
   * Constructor.
   *
   * @param source document source
   * @param opts database options
   * @throws IOException I/O exception
   */
  public HtmlParser(final IO source, final MainOptions opts) throws IOException {
    this(source, opts, opts.get(MainOptions.HTMLPARSER));
  }

  /**
   * Constructor.
   *
   * @param source document source
   * @param opts database options
   * @param hopts html options
   * @throws IOException I/O exception
   */
  public HtmlParser(final IO source, final MainOptions opts, final HtmlOptions hopts)
      throws IOException {
    super(toXML(source, hopts), opts);
  }

  /**
   * Converts an HTML document to XML.
   *
   * @param io io reference
   * @param opts html options
   * @return parser
   * @throws IOException I/O exception
   */
  private static IO toXML(final IO io, final HtmlOptions opts) throws IOException {
    // reader could not be initialized; fall back to XML
    if (READER == null) return io;

    try {
      // tries to extract the encoding from the input
      final TextInput ti = new TextInput(io);
      String enc = ti.encoding();
      final byte[] content = ti.content();

      // looks for a charset definition
      final byte[] encoding = token("charset=");
      int cs = indexOf(content, encoding);
      if (cs > 0) {
        // extracts the encoding string
        cs += encoding.length;
        int ce = cs;
        final int cl = content.length;
        while (++ce < cl && content[ce] > 0x28) ;
        enc = string(substring(content, cs, ce));
      }

      // define input
      final InputSource is = new InputSource(new ArrayInput(content));
      is.setEncoding(supported(enc) ? normEncoding(enc) : UTF8);
      // define output
      final StringWriter sw = new StringWriter();
      final XMLReader reader = (XMLReader) Reflect.get(READER);
      final Object writer = Reflect.get(WRITER, sw);

      // set TagSoup options
      if (opts.get(HtmlOptions.HTML)) {
        reader.setFeature("http://xml.org/sax/features/namespaces", false);
        opt("method", "html");
        opt("omit-xml-declaration", "yes");
      }
      if (opts.get(HtmlOptions.NONS))
        reader.setFeature("http://xml.org/sax/features/namespaces", false);
      if (opts.get(HtmlOptions.OMITXML)) opt("omit-xml-declaration", "yes");
      if (opts.get(HtmlOptions.NOBOGONS)) reader.setFeature(FEATURES + "ignore-bogons", true);
      if (opts.get(HtmlOptions.NODEFAULTS))
        reader.setFeature(FEATURES + "default-attributes", false);
      if (opts.get(HtmlOptions.NOCOLONS)) reader.setFeature(FEATURES + "translate-colons", true);
      if (opts.get(HtmlOptions.NORESTART)) reader.setFeature(FEATURES + "restart-elements", false);
      if (opts.get(HtmlOptions.IGNORABLE))
        reader.setFeature(FEATURES + "ignorable-whitespace", true);
      if (opts.get(HtmlOptions.EMPTYBOGONS)) reader.setFeature(FEATURES + "bogons-empty", true);
      if (opts.get(HtmlOptions.ANY)) reader.setFeature(FEATURES + "bogons-empty", false);
      if (opts.get(HtmlOptions.NOROOTBOGONS)) reader.setFeature(FEATURES + "root-bogons", false);
      if (opts.get(HtmlOptions.NOCDATA)) reader.setFeature(FEATURES + "cdata-elements", false);
      if (opts.get(HtmlOptions.LEXICAL))
        reader.setProperty("http://xml.org/sax/properties/lexical-handler", writer);
      if (opts.contains(HtmlOptions.METHOD)) opt("method", opts.get(HtmlOptions.METHOD));
      if (opts.contains(HtmlOptions.DOCTYPESYS))
        opt("doctype-system", opts.get(HtmlOptions.DOCTYPESYS));
      if (opts.contains(HtmlOptions.DOCTYPEPUB))
        opt("doctype-public", opts.get(HtmlOptions.DOCTYPEPUB));
      if (opts.contains(HtmlOptions.ENCODING)) is.setEncoding(opts.get(HtmlOptions.ENCODING));
      // end TagSoup options

      reader.setContentHandler((ContentHandler) writer);
      reader.parse(is);
      return new IOContent(token(sw.toString()), io.name());

    } catch (final SAXException ex) {
      Util.errln(ex);
      return io;
    }
  }

  /**
   * Reflection invoke XMLWriter.setOutputProperty().
   *
   * @param name property
   * @param value value
   */
  private static void opt(final String name, final String value) {
    Reflect.invoke(METHOD, WRITER, name, value);
  }
}
예제 #4
0
 /**
  * Reflection invoke XMLWriter.setOutputProperty().
  *
  * @param name property
  * @param value value
  */
 private static void opt(final String name, final String value) {
   Reflect.invoke(METHOD, WRITER, name, value);
 }
예제 #5
0
  /**
   * Parse the BSHBlock for for the class definition and generate the class using ClassGenerator.
   */
  public static Class generateClassImpl(
      String name,
      Modifiers modifiers,
      Class[] interfaces,
      Class superClass,
      BSHBlock block,
      boolean isInterface,
      CallStack callstack,
      Interpreter interpreter)
      throws EvalError {
    // Scripting classes currently requires accessibility
    // This can be eliminated with a bit more work.
    try {
      Capabilities.setAccessibility(true);
    } catch (Capabilities.Unavailable e) {
      throw new EvalError(
          "Defining classes currently requires reflective Accessibility.", block, callstack);
    }

    NameSpace enclosingNameSpace = callstack.top();
    String packageName = enclosingNameSpace.getPackage();
    String className =
        enclosingNameSpace.isClass ? (enclosingNameSpace.getName() + "$" + name) : name;
    String fqClassName = packageName == null ? className : packageName + "." + className;

    BshClassManager bcm = interpreter.getClassManager();
    // Race condition here...
    bcm.definingClass(fqClassName);

    // Create the class static namespace
    NameSpace classStaticNameSpace = new NameSpace(enclosingNameSpace, className);
    classStaticNameSpace.isClass = true;

    callstack.push(classStaticNameSpace);

    // Evaluate any inner class class definitions in the block
    // effectively recursively call this method for contained classes first
    block.evalBlock(callstack, interpreter, true /*override*/, ClassNodeFilter.CLASSCLASSES);

    // Generate the type for our class
    Variable[] variables = getDeclaredVariables(block, callstack, interpreter, packageName);
    DelayedEvalBshMethod[] methods = getDeclaredMethods(block, callstack, interpreter, packageName);

    ClassGeneratorUtil classGenerator =
        new ClassGeneratorUtil(
            modifiers,
            className,
            packageName,
            superClass,
            interfaces,
            variables,
            methods,
            classStaticNameSpace,
            isInterface);
    byte[] code = classGenerator.generateClass();

    // if debug, write out the class file to debugClasses directory
    if (DEBUG_DIR != null)
      try {
        FileOutputStream out = new FileOutputStream(DEBUG_DIR + '/' + className + ".class");
        out.write(code);
        out.close();
      } catch (IOException e) {
        throw new IllegalStateException(
            "cannot create file " + DEBUG_DIR + '/' + className + ".class", e);
      }

    // Define the new class in the classloader
    Class genClass = bcm.defineClass(fqClassName, code);

    // import the unq name into parent
    enclosingNameSpace.importClass(fqClassName.replace('$', '.'));

    try {
      classStaticNameSpace.setLocalVariable(
          ClassGeneratorUtil.BSHINIT, block, false /*strictJava*/);
    } catch (UtilEvalError e) {
      throw new InterpreterError("unable to init static: " + e);
    }

    // Give the static space its class static import
    // important to do this after all classes are defined
    classStaticNameSpace.setClassStatic(genClass);

    // evaluate the static portion of the block in the static space
    block.evalBlock(callstack, interpreter, true /*override*/, ClassNodeFilter.CLASSSTATIC);

    callstack.pop();

    if (!genClass.isInterface()) {
      // Set the static bsh This callback
      String bshStaticFieldName = ClassGeneratorUtil.BSHSTATIC + className;
      try {
        LHS lhs = Reflect.getLHSStaticField(genClass, bshStaticFieldName);
        lhs.assign(classStaticNameSpace.getThis(interpreter), false /*strict*/);
      } catch (Exception e) {
        throw new InterpreterError("Error in class gen setup: " + e);
      }
    }

    bcm.doneDefiningClass(fqClassName);
    return genClass;
  }