Package aQute.maven

Source Code of aQute.maven.XmlCodec

package aQute.maven;

import java.io.*;
import java.lang.reflect.*;
import java.net.*;
import java.util.*;

import javax.xml.stream.*;

import aQute.lib.converter.*;
import aQute.libg.reporter.*;
import aQute.maven.MavenRepository.PomImpl;
import aQute.struct.*;

/**
* Parse and XML pom.
*/
@SuppressWarnings({
    "unchecked", "rawtypes"
})
class XmlCodec extends ReporterAdapter {
  static XMLInputFactory  xif      = XMLInputFactory.newInstance();
  static {
    xif.setProperty(XMLInputFactory.IS_COALESCING, false);
    xif.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, false);
    xif.setProperty(XMLInputFactory.IS_VALIDATING, false);
    xif.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, false);
    xif.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, true);
  }
  boolean          debug;
  Map<String,String>    properties  = new HashMap<String,String>();

  public XmlCodec(Map<String,String> macros) {
    properties.putAll(macros);
  }

  public XmlCodec() {}

  public PomImpl parse(Reader in) throws Exception {
    try {

      XMLStreamReader rd = xif.createXMLStreamReader(in);

      try {
        while (true) {
          if (!rd.hasNext())
            throw new IllegalArgumentException("Contains no content");
          if (rd.next() == XMLStreamConstants.START_ELEMENT)
            break;
        }

        PomImpl pom = (PomImpl) parseStruct(PomImpl.class, rd);
        if (!rd.hasNext())
          error("Malformed XML, found element after end: %s", rd.getLocalName());

        pom.errors.addAll(getErrors());
        pom.warnings.addAll(getWarnings());
        return pom;
      }
      finally {
        rd.close();
      }
    }
    finally {
      in.close();
    }
  }

  /**
   * a) String b) list c) object
   *
   * @param type
   * @param rd
   * @return
   * @throws Exception
   */
  private Object parse(Type type, XMLStreamReader rd) throws Exception {
    if (type instanceof ParameterizedType) {
      ParameterizedType pt = (ParameterizedType) type;
      Class< ? > c = (Class< ? >) getRawType(pt);
      if (Map.class.isAssignableFrom(c))
        return parseMap(c, pt.getActualTypeArguments()[1], rd);
      else if (Collection.class.isAssignableFrom(c))
        return parseList(pt, rd);
      else {
        error("Parameterized type %s, only collection and map allowed at tag %s", type, rd.getLocalName());
      }
    }

    if (struct.class.isAssignableFrom((Class< ? >) type)) {
      return parseStruct((Class< ? extends struct>) type, rd);
    }

    // Only text left

    StringBuilder sb = new StringBuilder();
    while (rd.hasNext()) {
      int nextTag = rd.next();
      switch (nextTag) {
        case XMLStreamConstants.CHARACTERS :
          sb.append(rd.getText());
          break;
        case XMLStreamConstants.ENTITY_REFERENCE :
          String entity = rd.getLocalName();
          char replacement = Entities.getEntity(entity);
          if (replacement != 0)
            sb.append(replacement);
          else
            sb.append(entity);
          break;

        case XMLStreamConstants.START_ELEMENT :
          error("Parsing %s, which is not complex, so unexpected element %s", type, rd.getLocalName());
          break;

        case XMLStreamConstants.END_ELEMENT :
          if (sb.length() == 0)
            return null;
          return sb.toString().trim();
      }
    }
    error("No more tags for %s and not found closing tag %s", type, rd.getLocalName());
    return null;
  }

  private Class< ? > getRawType(Type t) {
    if (t instanceof Class< ? >)
      return (Class< ? >) t;

    if (t instanceof ParameterizedType)
      return getRawType(((ParameterizedType) t).getRawType());

    if (t instanceof GenericArrayType) {
      Class< ? > c = getRawType(((GenericArrayType) t).getGenericComponentType());
      return Array.newInstance(c, 0).getClass();
    }

    if (t instanceof WildcardType) {
      return getRawType(((WildcardType) t).getUpperBounds()[0]);
    }

    if (t instanceof TypeVariable< ? >) {
      return getRawType(((TypeVariable) t).getBounds()[0]);
    }

    error("Cannot determine raw type of %s", t);
    return null;
  }

  private Object parseMap(Class< ? > c, Type type, XMLStreamReader rd) throws Exception {
    String enclosingTagName = rd.getLocalName();
    Map<String,Object> map = new HashMap<String,Object>();

    while (rd.hasNext()) {
      int nextTag = rd.next();
      switch (nextTag) {
        case XMLStreamConstants.CHARACTERS :
          if (!rd.getText().trim().isEmpty()) {
            unexpectedText(enclosingTagName, rd.getText());
          }
          break;

        case XMLStreamConstants.START_ELEMENT :
          String name = rd.getLocalName();
          Object value;
          value = parseUndecided(rd);
          map.put(name, value);
          if (debug) {
            System.out.println(name + "=" + value);
          }
          break;

        case XMLStreamConstants.END_ELEMENT :
          return map;
      }
    }
    error("Unexpected eof for parsing map tag %s", enclosingTagName);
    return null;
  }

  private Object parseList(ParameterizedType type, XMLStreamReader rd) throws Exception {
    String enclosingTagName = rd.getLocalName();
    Collection<Object> result = (Collection<Object>) Converter.cnv(type, new Object[0]);
    while (rd.hasNext()) {
      int nextTag = rd.next();
      switch (nextTag) {
        case XMLStreamConstants.CHARACTERS :
          if (!rd.getText().trim().isEmpty())
            unexpectedText(enclosingTagName, rd.getText());
          break;

        case XMLStreamConstants.START_ELEMENT :
          // TODO verify that the same name is used?
          // TODO verify that the actual name is the parent - the last
          // s?
          result.add(parse(type.getActualTypeArguments()[0], rd));
          break;

        case XMLStreamConstants.END_ELEMENT :
          return result;
      }
    }
    return null;
  }

  private struct parseStruct(Class< ? extends struct> type, XMLStreamReader rd) throws Exception {
    struct object = type.newInstance();

    while (rd.hasNext()) {
      int nextTag = rd.next();
      outer: switch (nextTag) {
        case XMLStreamConstants.CHARACTERS :
          if (!rd.getText().trim().isEmpty()) {
            for (Field f : object.fields()) {
              if (f.getType() == String.class) {
                f.set(object, rd.getText());
                break outer;
              }
            }
            // Hmm, no string field
            if (object.__extra == null) {
              object.__extra = new HashMap<String,Object>();
            }
            String s = (String) object.__extra.get(".");
            if (s == null) {
              s = rd.getText();
            } else
              s += rd.getText();
            object.__extra.put(".", s);
          }
          break;

        case XMLStreamConstants.START_ELEMENT :
          String name = rd.getLocalName();
          Field field = object.getField(name);
          Object value;
          if (field == null) {
            Map<String,Object> map = object.__extra;
            if (map == null) {
              map = new HashMap<String,Object>();
              object.__extra = map;
            }

            map.put(name, value = parseUndecided(rd));

          } else {
            value = parse(field.getGenericType(), rd);
            try {
              if (field.getType() == URI.class) {
                value = value.toString().replaceAll("\\$\\{([^}]+)\\}", "++++$1++++");
              }
              field.set(object, Converter.cnv(field.getGenericType(), value));
            }
            catch (Exception e) {
              error("Cannot convert %s=%s to %s", name, value, field.getGenericType());
            }
          }
          if (debug) {
            System.out.println(name);
          }
          break;

        case XMLStreamConstants.END_ELEMENT :
          return object;
      }
    }
    throw new IllegalArgumentException("Unexpected eof");
  }

  private Object parseUndecided(XMLStreamReader rd) throws Exception {
    String enclosingTagName = rd.getLocalName();
    Map<String,Object> map = null;
    StringBuilder sb = new StringBuilder();

    while (rd.hasNext()) {
      int nextTag = rd.next();
      switch (nextTag) {
        case XMLStreamConstants.CHARACTERS :
          if (!rd.getText().trim().isEmpty()) {
            if (map != null)
              unexpectedText(enclosingTagName, rd.getText());
            sb.append(rd.getText());
          }
          break;

        case XMLStreamConstants.START_ELEMENT :
          String name = rd.getLocalName();
          if (map == null)
            map = new HashMap<String,Object>();

          map.put(name, parseUndecided(rd));
          if (debug) {
            System.out.println(name);
          }
          break;

        case XMLStreamConstants.END_ELEMENT :
          if (map != null)
            return map;

          if (sb.length() > 0)
            // TODO make trim method on sb
            return sb.toString().trim();
          return null;
      }
    }
    error("Unexpected eof in %s )", enclosingTagName);
    return null;
  }

  private void unexpectedText(String enclosingTag, String text) {
    if (text == null)
      return;

    text = text.trim();
    if (text.isEmpty())
      return;

    if (text.length() > 20)
      text = text.substring(0, 10) + "..." + text.substring(text.length() - 10);

    error("Parsing tag '%s'; Found text and members: '%s'", enclosingTag, text.trim());
  }

  public XmlCodec debug() {
    this.debug = true;
    return this;
  }
}
TOP

Related Classes of aQute.maven.XmlCodec

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.