private void addClass(Class<?> cls) {
    if (Throwable.class.isAssignableFrom(cls)) {
      if (!Throwable.class.equals(cls) && !Exception.class.equals(cls)) {
        walkReferences(cls);
      }
      addClass(String.class);
    } else {
      cls = JAXBUtils.getValidClass(cls);
      if (null != cls) {
        if (classes.contains(cls)) {
          return;
        }

        if (!cls.isInterface()) {
          classes.add(cls);
        }

        XmlSeeAlso xsa = cls.getAnnotation(XmlSeeAlso.class);
        if (xsa != null) {
          for (Class<?> c : xsa.value()) {
            addClass(c);
          }
        }
        XmlJavaTypeAdapter xjta = cls.getAnnotation(XmlJavaTypeAdapter.class);
        if (xjta != null) {
          // has an adapter.   We need to inspect the adapter and then
          // return as the adapter will handle the superclass
          // and interfaces and such
          Type t = getTypeFromXmlAdapter(xjta);
          if (t != null) {
            addType(t);
          }
          return;
        }

        if (cls.getSuperclass() != null) {
          // JAXB should do this, but it doesn't always.
          // in particular, older versions of jaxb don't
          addClass(cls.getSuperclass());
        }

        if (!cls.isInterface()) {
          walkReferences(cls);
        }
      }
    }
  }
  void addClass(Class<?> claz) {
    if (Throwable.class.isAssignableFrom(claz)) {
      if (!Throwable.class.equals(claz) && !Exception.class.equals(claz)) {
        walkReferences(claz);
      }
      addClass(String.class);
    } else if (claz.getName().startsWith("java.") || claz.getName().startsWith("javax.")) {
      return;
    } else {
      Class<?> cls = JAXBUtils.getValidClass(claz);
      if (cls == null
          && ReflectionUtil.getDeclaredConstructors(claz).length > 0
          && !Modifier.isAbstract(claz.getModifiers())) {
        if (LOG.isLoggable(Level.INFO)) {
          LOG.info(
              "Class "
                  + claz.getName()
                  + " does not have a default constructor which JAXB requires.");
        }
        // there is no init(), but other constructors
        Object factory = createFactory(claz, ReflectionUtil.getDeclaredConstructors(claz)[0]);
        unmarshallerProperties.put("com.sun.xml.bind.ObjectFactory", factory);
        cls = claz;
      }
      if (null != cls) {
        if (classes.contains(cls)) {
          return;
        }

        if (!cls.isInterface()) {
          classes.add(cls);
        }

        XmlSeeAlso xsa = cls.getAnnotation(XmlSeeAlso.class);
        if (xsa != null) {
          for (Class<?> c : xsa.value()) {
            addClass(c);
          }
        }
        XmlJavaTypeAdapter xjta = cls.getAnnotation(XmlJavaTypeAdapter.class);
        if (xjta != null) {
          // has an adapter.   We need to inspect the adapter and then
          // return as the adapter will handle the superclass
          // and interfaces and such
          Type t = Utils.getTypeFromXmlAdapter(xjta);
          if (t != null) {
            addType(t);
          }
          return;
        }

        if (cls.getSuperclass() != null) {
          // JAXB should do this, but it doesn't always.
          // in particular, older versions of jaxb don't
          addClass(cls.getSuperclass());
        }

        if (!cls.isInterface()) {
          walkReferences(cls);
        }
      }
    }
  }