/** Sets the access flag of a member */
  @Override
  protected void setAccessFlag(final Member m) {
    final int mods = m.getModifiers();
    final Class c = m.getDeclaringClass();
    final int cmods = c.getModifiers();
    final String pkg = this.importationManager.getCurrentPackage();
    final String mp = getPackageName(c);
    final boolean samePkg = pkg.equals(mp);

    if (Modifier.isPublic(cmods) || samePkg) {
      if (Modifier.isPublic(mods)) {
        ((AccessibleObject) m).setAccessible(true);
      } else if (Modifier.isProtected(mods)) {
        if (c.isAssignableFrom(this.declaringClass.getSuperclass()) || samePkg) {
          ((AccessibleObject) m).setAccessible(true);
        }
      } else if (!Modifier.isPrivate(mods)) {
        if (samePkg) {
          ((AccessibleObject) m).setAccessible(true);
        }
      } else {
        if (this.declaringClass == c || isInnerClass(this.declaringClass, c)) {
          ((AccessibleObject) m).setAccessible(true);
        }
      }
    }
  }
Example #2
0
  /**
   * Appends the fields and values defined by the given object of the given Class.
   *
   * @param lhs the left hand object
   * @param rhs the right hand object
   * @param clazz the class to append details of
   * @param builder the builder to append to
   * @param useTransients whether to test transient fields
   * @param excludeFields array of field names to exclude from testing
   */
  private static void reflectionAppend(
      Object lhs,
      Object rhs,
      Class<?> clazz,
      EqualsBuilder builder,
      boolean useTransients,
      String[] excludeFields) {

    if (isRegistered(lhs, rhs)) {
      return;
    }

    try {
      register(lhs, rhs);
      Field[] fields = clazz.getDeclaredFields();
      AccessibleObject.setAccessible(fields, true);
      for (int i = 0; i < fields.length && builder.isEquals; i++) {
        Field f = fields[i];
        if (!Arrays.contains(excludeFields, f.getName())
            && (f.getName().indexOf('$') == -1)
            && (useTransients || !Modifier.isTransient(f.getModifiers()))
            && (!Modifier.isStatic(f.getModifiers()))) {
          try {
            builder.append(f.get(lhs), f.get(rhs));
          } catch (IllegalAccessException e) {
            // this can't happen. Would get a Security exception instead
            // throw a runtime exception in case the impossible happens.
            throw new InternalError("Unexpected IllegalAccessException");
          }
        }
      }
    } finally {
      unregister(lhs, rhs);
    }
  }
Example #3
0
 private static void reflectionAppend(
     Object obj,
     Object obj1,
     Class class1,
     CompareToBuilder comparetobuilder,
     boolean flag,
     String as[]) {
   Field afield[] = class1.getDeclaredFields();
   AccessibleObject.setAccessible(afield, true);
   int i = 0;
   do {
     if (i >= afield.length || comparetobuilder.comparison != 0) {
       return;
     }
     Field field = afield[i];
     if (!ArrayUtils.contains(as, field.getName())
         && field.getName().indexOf('$') == -1
         && (flag || !Modifier.isTransient(field.getModifiers()))
         && !Modifier.isStatic(field.getModifiers())) {
       try {
         comparetobuilder.append(field.get(obj), field.get(obj1));
       } catch (IllegalAccessException illegalaccessexception) {
         throw new InternalError("Unexpected IllegalAccessException");
       }
     }
     i++;
   } while (true);
 }
Example #4
0
  /**
   * Method called to check if we can use the passed method or constructor (wrt access restriction
   * -- public methods can be called, others usually not); and if not, if there is a work-around for
   * the problem.
   */
  public static void checkAndFixAccess(Member member) {
    // We know all members are also accessible objects...
    AccessibleObject ao = (AccessibleObject) member;

    /* 14-Jan-2009, tatu: It seems safe and potentially beneficial to
     *   always to make it accessible (latter because it will force
     *   skipping checks we have no use for...), so let's always call it.
     */
    // if (!ao.isAccessible()) {
    try {
      ao.setAccessible(true);
    } catch (SecurityException se) {
      /* 17-Apr-2009, tatu: Related to [JACKSON-101]: this can fail on
       *    platforms like EJB and Google App Engine); so let's
       *    only fail if we really needed it...
       */
      if (!ao.isAccessible()) {
        Class<?> declClass = member.getDeclaringClass();
        throw new IllegalArgumentException(
            "Can not access "
                + member
                + " (from class "
                + declClass.getName()
                + "; failed to set access: "
                + se.getMessage());
      }
    }
    // }
  }
Example #5
0
 private Method[] getMemberMethods() {
   if (memberMethods == null) {
     Method[] mm = type.getDeclaredMethods();
     AccessibleObject.setAccessible(mm, true);
     memberMethods = mm;
   }
   return memberMethods;
 }
Example #6
0
  public String toString(Object object) {
    if (object == null) {
      return "null";
    }
    if (visited.contains(object)) {
      return "...";
    }
    visited.add(object);
    Class clazz = object.getClass();
    if (clazz == String.class) {
      return (String) object;
    }
    if (clazz.isArray()) {
      String r = clazz.getComponentType() + "[]{";
      for (int i = 0; i < Array.getLength(object); i++) {
        if (i > 0) {
          r += ",";
        }
        Object val = Array.get(object, i);
        if (clazz.getComponentType().isPrimitive()) {
          r += val;
        } else {
          r += toString(val);
        }
      }
      return r + "}";
    }

    String r = clazz.getName();
    do {
      r += "[";
      Field[] fields = clazz.getDeclaredFields();
      AccessibleObject.setAccessible(fields, true);
      for (Field field : fields) {
        if (!Modifier.isStatic(field.getModifiers())) {
          if (!r.endsWith("[")) {
            r += ",";
          }
          r += field.getName() + "=";
          try {
            Class t = field.getType();
            Object val = field.get(object);
            if (t.isPrimitive()) {
              r += val;
            } else {
              r += toString(val);
            }
          } catch (IllegalAccessException e) {
            e.printStackTrace();
          }
        }
      }
      r += "]";
      clazz = clazz.getSuperclass();
    } while (clazz != null);
    return r;
  }
  /**
   * This method uses reflection to build a valid hash code.
   *
   * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This
   * means that it will throw a security exception if run under a security manager, if the
   * permissions are not set up correctly. It is also not as efficient as testing explicitly.
   *
   * <p>Transient members will not be used, as they are likely derived fields, and not part of the
   * value of the <code>Object</code>.
   *
   * <p>Static fields will not be tested. Superclass fields will be included.
   *
   * @param obj the object to create a <code>hashCode</code> for
   * @return the generated hash code, or zero if the given object is <code>null</code>
   */
  public static int reflectionHashCode(Object obj) {
    if (obj == null) return 0;

    Class<?> targetClass = obj.getClass();
    if (isArrayOfPrimitives(obj)) {
      // || ObjectUtils.isPrimitiveOrWrapper(targetClass)) {
      return ObjectUtils.nullSafeHashCode(obj);
    }

    if (targetClass.isArray()) {
      return reflectionHashCode((Object[]) obj);
    }

    if (obj instanceof Collection) {
      return reflectionHashCode((Collection<?>) obj);
    }

    if (obj instanceof Map) {
      return reflectionHashCode((Map<?, ?>) obj);
    }

    // determine whether the object's class declares hashCode() or has a
    // superClass other than java.lang.Object that declares hashCode()
    Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
    Method hashCodeMethod = ReflectionUtils.findMethod(clazz, "hashCode", new Class[0]);

    if (hashCodeMethod != null) {
      return obj.hashCode();
    }

    // could not find a hashCode other than the one declared by
    // java.lang.Object
    int hash = INITIAL_HASH;

    try {
      while (targetClass != null) {
        Field[] fields = targetClass.getDeclaredFields();
        AccessibleObject.setAccessible(fields, true);

        for (int i = 0; i < fields.length; i++) {
          Field field = fields[i];
          int modifiers = field.getModifiers();

          if (!Modifier.isStatic(modifiers) && !Modifier.isTransient(modifiers)) {
            hash = MULTIPLIER * hash + reflectionHashCode(field.get(obj));
          }
        }
        targetClass = targetClass.getSuperclass();
      }
    } catch (IllegalAccessException exception) {
      // ///CLOVER:OFF
      ReflectionUtils.handleReflectionException(exception);
      // ///CLOVER:ON
    }

    return hash;
  }
Example #8
0
 /**
  * Suppress access check against a reflection object. SecurityException is silently ignored.
  * Checks first if the object is already accessible.
  */
 public static void forceAccess(AccessibleObject accObject) {
   if (accObject.isAccessible() == true) {
     return;
   }
   try {
     accObject.setAccessible(true);
   } catch (SecurityException sex) {
     // ignore
   }
 }
Example #9
0
 /**
  * Changes the accessibility of a reflection object and returns the previous value. This method
  * can be used to set the accessibility of {@link Method} and {@link Field} instances.
  *
  * @param ao accessible object to set the accessibility on
  * @param accessible the accessibility statues to set on the object
  * @return the previous value of the accessibility flag
  */
 public static boolean exchangeAccessible(final AccessibleObject ao, final boolean accessible) {
   //
   // At least synchronize on the object so that users of this
   // particular method won't step on their toes.
   //
   synchronized (ao) {
     final boolean oldAccessible = ao.isAccessible();
     ao.setAccessible(accessible);
     return oldAccessible;
   }
 }
 /**
  * XXX Default access superclass workaround
  *
  * <p>When a public class has a default access superclass with public members, these members are
  * accessible. Calling them from compiled code works fine. Unfortunately, on some JVMs, using
  * reflection to invoke these members seems to (wrongly) prevent access even when the modifier is
  * public. Calling setAccessible(true) solves the problem but will only work from sufficiently
  * privileged code. Better workarounds would be gratefully accepted.
  *
  * @param o the AccessibleObject to set as accessible
  */
 static void setAccessibleWorkaround(AccessibleObject o) {
   if (o == null || o.isAccessible()) {
     return;
   }
   Member m = (Member) o;
   if (Modifier.isPublic(m.getModifiers())
       && isPackageAccess(m.getDeclaringClass().getModifiers())) {
     try {
       o.setAccessible(true);
     } catch (SecurityException e) { // NOPMD
       // ignore in favor of subsequent IllegalAccessException
     }
   }
 }
Example #11
0
  /**
   * Return information about the scripting variables to be created.
   *
   * @param data the input data
   * @return VariableInfo array of variable information
   */
  @SuppressWarnings("unchecked")
  public VariableInfo[] getVariableInfo(TagData data) {
    // loop through and expose all attributes
    List<VariableInfo> vars = new ArrayList<VariableInfo>();

    try {
      String clazz = data.getAttributeString("className");

      if (clazz == null) {
        clazz = Constants.class.getName();
      }

      Class c = Class.forName(clazz);

      // if no var specified, get all
      if (data.getAttributeString("var") == null) {
        Field[] fields = c.getDeclaredFields();

        AccessibleObject.setAccessible(fields, true);

        for (Field field : fields) {
          String type = field.getType().getName();
          vars.add(
              new VariableInfo(
                  field.getName(),
                  ((field.getType().isArray())
                      ? type.substring(2, type.length() - 1) + "[]"
                      : type),
                  true,
                  VariableInfo.AT_END));
        }
      } else {
        String var = data.getAttributeString("var");
        String type = c.getField(var).getType().getName();
        vars.add(
            new VariableInfo(
                c.getField(var).getName(),
                ((c.getField(var).getType().isArray())
                    ? type.substring(2, type.length() - 1) + "[]"
                    : type),
                true,
                VariableInfo.AT_END));
      }
    } catch (Exception cnf) {
      log.error(cnf.getMessage());
      cnf.printStackTrace();
    }

    return vars.toArray(new VariableInfo[] {});
  }
  /**
   * Compares the declared primitives of two instances of a class
   *
   * @param <T> type of the instances
   * @param cls type to compare the declared fields for
   * @param instance1 first instance to test
   * @param instance2 second instance to test
   * @return a list of differing primitives
   * @throws IllegalAccessException
   * @throws IllegalArgumentException
   */
  public static <T> ArrayList<Field> compareDeclaredPrimitives(
      Class<? extends T> cls, T instance1, T instance2)
      throws IllegalArgumentException, IllegalAccessException {
    ArrayList<Field> differingFields = new ArrayList<Field>();
    Field[] fields = cls.getDeclaredFields();
    AccessibleObject.setAccessible(fields, true);

    for (Field field : fields) {
      if (field.getType().isPrimitive()
          && !isPrimitiveFieldContentTheSame(instance1, instance2, field)) {
        differingFields.add(field);
      }
    }

    return differingFields;
  }
Example #13
0
  public static void makeAccessible(final AccessibleObject object) {
    if (!object.isAccessible()) {
      if (System.getSecurityManager() == null) {
        object.setAccessible(true);
      } else {
        AccessController.doPrivileged(
            new PrivilegedAction<Object>() {

              @Override
              public Object run() {
                object.setAccessible(true);
                return null;
              }
            });
      }
    }
  }
Example #14
0
 /**
  * XXX Default access superclass workaround.
  *
  * <p>When a {@code public} class has a default access superclass with {@code public} members,
  * these members are accessible. Calling them from compiled code works fine. Unfortunately, on
  * some JVMs, using reflection to invoke these members seems to (wrongly) prevent access even when
  * the modifier is {@code public}. Calling {@code setAccessible(true)} solves the problem but will
  * only work from sufficiently privileged code. Better workarounds would be gratefully accepted.
  *
  * @param o the AccessibleObject to set as accessible
  * @return a boolean indicating whether the accessibility of the object was set to true.
  */
 static boolean setAccessibleWorkaround(final AccessibleObject o) {
   if (o == null || o.isAccessible()) {
     return false;
   }
   final Member m = (Member) o;
   if (!o.isAccessible()
       && Modifier.isPublic(m.getModifiers())
       && isPackageAccess(m.getDeclaringClass().getModifiers())) {
     try {
       o.setAccessible(true);
       return true;
     } catch (final SecurityException e) { // NOPMD
       // ignore in favor of subsequent IllegalAccessException
     }
   }
   return false;
 }
Example #15
0
 private static <T extends Annotation> AnnotationMetadata<T> randomAnnotation(
     Class<T> annotationClass, Map<String, Object> properties) {
   Map<String, Object> allProps = new LinkedHashMap<String, Object>();
   Map<String, Object> defaults =
       hasAnnotationType ? getAnnotationDefaults(annotationClass) : new HashMap<String, Object>();
   Method[] mm = annotationClass.getDeclaredMethods();
   AccessibleObject.setAccessible(mm, true);
   for (Method method : mm) {
     String name = method.getName();
     if (properties.containsKey(name)) allProps.put(name, properties.get(name));
     else {
       Object o = defaults.get(name);
       if (o == null) o = getTypeDefaults(method.getReturnType());
       allProps.put(name, o);
     }
   }
   return new AnnotationMetadata<T>(annotationClass, allProps);
 }
Example #16
0
  /**
   * Main method that does processing and exposes Constants in specified scope
   *
   * @return int
   * @throws JspException if processing fails
   */
  @Override
  public int doStartTag() throws JspException {
    // Using reflection, get the available field names in the class
    Class c = null;
    int toScope = PageContext.PAGE_SCOPE;

    if (scope != null) {
      toScope = getScope(scope);
    }

    try {
      c = Class.forName(clazz);
    } catch (ClassNotFoundException cnf) {
      log.error("ClassNotFound - maybe a typo?");
      throw new JspException(cnf.getMessage());
    }

    try {
      // if var is null, expose all variables
      if (var == null) {
        Field[] fields = c.getDeclaredFields();

        AccessibleObject.setAccessible(fields, true);

        for (Field field : fields) {
          pageContext.setAttribute(field.getName(), field.get(this), toScope);
        }
      } else {
        try {
          Object value = c.getField(var).get(this);
          pageContext.setAttribute(c.getField(var).getName(), value, toScope);
        } catch (NoSuchFieldException nsf) {
          log.error(nsf.getMessage());
          throw new JspException(nsf);
        }
      }
    } catch (IllegalAccessException iae) {
      log.error("Illegal Access Exception - maybe a classloader issue?");
      throw new JspException(iae);
    }

    // Continue processing this page
    return (SKIP_BODY);
  }
  /**
   * Construct a variable
   *
   * @param aType the type
   * @param aName the name
   * @param aValue the value
   */
  public Variable(Class<?> aType, String aName, Object aValue) {
    type = aType;
    name = aName;
    value = aValue;
    fields = new ArrayList<Field>();

    // find all fields if we have a class type except we don't expand strings and null values

    if (!type.isPrimitive() && !type.isArray() && !type.equals(String.class) && value != null) {
      // get fields from the class and all superclasses
      for (Class<?> c = value.getClass(); c != null; c = c.getSuperclass()) {
        Field[] fs = c.getDeclaredFields();
        AccessibleObject.setAccessible(fs, true);

        // get all nonstatic fields
        for (Field f : fs) if ((f.getModifiers() & Modifier.STATIC) == 0) fields.add(f);
      }
    }
  }
Example #18
0
 protected void dumpObject(CodeWriter w, Object obj, Map<Object, Object> cache) {
   w.write(" fields {");
   w.allowBreak(2);
   w.begin(0);
   try {
     Field[] declaredFields = obj.getClass().getDeclaredFields();
     java.lang.reflect.AccessibleObject.setAccessible(declaredFields, true);
     for (int i = 0; i < declaredFields.length; i++) {
       if (Modifier.isStatic(declaredFields[i].getModifiers())) continue;
       w.begin(4);
       w.write(declaredFields[i].getName() + ": ");
       w.allowBreak(0);
       try {
         Object o = declaredFields[i].get(obj);
         if (o != null) {
           Class<?> rtType = o.getClass();
           w.write("<" + rtType.toString() + ">:");
           w.allowBreak(0);
           w.write(o.toString());
           w.allowBreak(4);
           if (!Object.class.equals(rtType)
               && !dontDump(rtType)
               && !rtType.isArray()
               && !(cache.containsKey(o) && cache.get(o) == o)) {
             cache.put(o, o);
             dumpObject(w, o, cache);
           }
         } else {
           w.write("null");
         }
       } catch (IllegalAccessException exn) {
         w.write("##[" + exn.getMessage() + "]");
       }
       w.end();
       w.allowBreak(0);
     }
   } catch (SecurityException exn) {
   } finally {
     w.end();
     w.allowBreak(0);
     w.write("}");
   }
 }
Example #19
0
  protected void dumpObject(Object obj, Set<Object> cache) {
    if (obj == null) {
      w.write("null");
      return;
    }

    w.write(StringUtil.getShortNameComponent(obj.getClass().getName()));

    //        w.allowBreak(0, " ");
    //        w.write(obj.toString());

    if (cache.contains(obj)) {
      return;
    }
    cache.add(obj);

    w.allowBreak(1, " ");
    w.begin(0);

    try {
      Field[] fields = obj.getClass().getDeclaredFields();
      java.lang.reflect.AccessibleObject.setAccessible(fields, true);
      for (int i = 0; i < fields.length; i++) {
        Field field = fields[i];
        if ((field.getModifiers() & modifiersMask) != 0) continue;
        w.write("(");
        w.write(field.getName());
        w.allowBreak(1, " ");
        try {
          Object o = field.get(obj);
          dumpObject(o, cache);
        } catch (IllegalAccessException exn) {
          w.write("##[" + exn.getMessage() + "]");
        }
        w.write(")");
        w.newline(0);
      }
    } catch (SecurityException exn) {
    }

    w.end();
  }
Example #20
0
  private Constructor<?>[] getAccessibleConstructors(boolean includePrivate) {
    // The JVM currently doesn't allow changing access on java.lang.Class
    // constructors, so don't try
    if (includePrivate && cl != ScriptRuntime.ClassClass) {
      try {
        Constructor<?>[] cons = cl.getDeclaredConstructors();
        AccessibleObject.setAccessible(cons, true);

        return cons;
      } catch (SecurityException e) {
        // Fall through to !includePrivate case
        Context.reportWarning(
            "Could not access constructor "
                + " of class "
                + cl.getName()
                + " due to lack of privileges.");
      }
    }
    return cl.getConstructors();
  }
Example #21
0
 private void navigateClassFields(Object obj, Class<?> clazz, Visitor visitor) {
   Field[] fields = clazz.getDeclaredFields();
   AccessibleObject.setAccessible(fields, true);
   for (Field f : fields) {
     FieldAttributes fieldAttributes = new FieldAttributes(clazz, f);
     if (exclusionStrategy.shouldSkipField(fieldAttributes)
         || exclusionStrategy.shouldSkipClass(fieldAttributes.getDeclaredClass())) {
       continue; // skip
     }
     TypeInfo fieldTypeInfo = TypeInfoFactory.getTypeInfoForField(f, objTypePair.type);
     Type declaredTypeOfField = fieldTypeInfo.getActualType();
     boolean visitedWithCustomHandler =
         visitor.visitFieldUsingCustomHandler(fieldAttributes, declaredTypeOfField, obj);
     if (!visitedWithCustomHandler) {
       if (fieldTypeInfo.isArray()) {
         visitor.visitArrayField(fieldAttributes, declaredTypeOfField, obj);
       } else {
         visitor.visitObjectField(fieldAttributes, declaredTypeOfField, obj);
       }
     }
   }
 }
Example #22
0
  protected void scanOptions(final Object object) {
    final Class<?> class1 = object.getClass();

    final List<Field> fields = new LinkedList<Field>();
    final List<Method> privateMethods = new LinkedList<Method>();

    final List<Method> otherPackageNonPrivateMethods = new LinkedList<Method>();

    final List<Method> currentPackageNonPrivateMethods = new LinkedList<Method>();

    Class<?> parentClass = class1;
    while (parentClass != null && !parentClass.equals(Object.class)) {
      // We cannot override fields in child classes, so we simple collect
      // all fields we found
      fields.addAll(Arrays.asList(parentClass.getDeclaredFields()));

      // for methods, we need to respect overridden methods when
      // inspecting the parent classes
      for (final Method method : parentClass.getDeclaredMethods()) {
        if (isPrivate(method)) {
          privateMethods.add(method);
        } else if (isPublicOrProtected(method)) {
          if (!containsMethod(otherPackageNonPrivateMethods, method)
              && !containsMethod(currentPackageNonPrivateMethods, method)) {
            currentPackageNonPrivateMethods.add(method);
          }
        } else if (isPackagePrivate(method)) {
          // if (!containsMethod(publicOrProtectedMethods, method)) {
          // method not overloaded
          if (isPackagePrivate(method)) {
            if (!containsMethod(currentPackageNonPrivateMethods, method)) {
              currentPackageNonPrivateMethods.add(method);
            }
          }
        }
      }

      final Package pack = parentClass.getPackage();
      parentClass = parentClass.getSuperclass();
      if ((pack == null && parentClass.getPackage() != null)
          || (pack != null && !pack.equals(parentClass.getPackage()))) {
        otherPackageNonPrivateMethods.addAll(currentPackageNonPrivateMethods);
        currentPackageNonPrivateMethods.clear();
      }
    }

    // inspect elements
    final Set<AccessibleObject> elements = new LinkedHashSet<AccessibleObject>();
    elements.addAll(fields);
    elements.addAll(privateMethods);
    elements.addAll(otherPackageNonPrivateMethods);
    elements.addAll(currentPackageNonPrivateMethods);

    for (final AccessibleObject element : elements) {

      if (element instanceof Field && element.getAnnotation(CmdOptionDelegate.class) != null) {
        debug("Found delegate object at: {0}", element);
        try {
          final boolean origAccessibleFlag = element.isAccessible();
          if (!origAccessibleFlag) {
            element.setAccessible(true);
          }
          final Object delegate = ((Field) element).get(object);
          if (!origAccessibleFlag) {
            // do not leave doors open
            element.setAccessible(origAccessibleFlag);
          }
          if (delegate != null) {
            scanOptions(delegate);
          }
        } catch (final IllegalArgumentException e) {
          debug("Could not scan delegate object at: {0}", element);
        } catch (final IllegalAccessException e) {
          debug("Could not scan delegate object at: {0}", element);
        }
        continue;
      }

      final CmdOption anno = element.getAnnotation(CmdOption.class);
      if (anno == null) {
        continue;
      }

      if (element instanceof Field && Modifier.isFinal(((Field) element).getModifiers())) {
        debug("Detected option on final field: {0}", element);
        // continue;
      }

      final String[] names = anno.names();

      final CmdOptionHandler handler = findHandler(element, anno.args().length, anno.handler());
      if (handler == null) {
        final PreparedI18n msg =
            i18n.preparetr(
                "No suitable handler found for option(s): {0} ({1} argument(s))",
                FList.mkString(anno.names(), ","), anno.args().length);
        throw new CmdlineParserException(msg.notr(), msg.tr());
      }

      if (names == null || names.length == 0) {
        // No names means this is the ONLY parameter
        if (parameter != null) {
          final PreparedI18n msg =
              i18n.preparetr(
                  "More than one parameter definition found. First definition: {0} Second definition: {1}",
                  parameter.getElement(), element);
          throw new CmdlineParserException(msg.notr(), msg.tr());
        }
        // TODO: should we ignore the help parameter?
        final OptionHandle paramHandle =
            new OptionHandle(
                new String[] {},
                anno.description(),
                handler,
                object,
                element,
                anno.args(),
                anno.minCount(),
                anno.maxCount(),
                false /*
                       * cannot
                       * be
                       * a
                       * help
                       * option
                       */,
                anno.hidden(),
                anno.requires(),
                anno.conflictsWith());

        if (paramHandle.getArgsCount() <= 0) {
          final PreparedI18n msg =
              i18n.preparetr("Parameter definition must support at least on argument.");
          throw new CmdlineParserException(msg.notr(), msg.tr());
        }
        parameter = paramHandle;

      } else {
        final OptionHandle option =
            new OptionHandle(
                names,
                anno.description(),
                handler,
                object,
                element,
                anno.args(),
                anno.minCount(),
                anno.maxCount(),
                anno.isHelp(),
                anno.hidden(),
                anno.requires(),
                anno.conflictsWith());

        for (final String name : names) {
          if (quickCommandMap.containsKey(name) || quickOptionMap.containsKey(name)) {
            final PreparedI18n msg =
                i18n.preparetr(
                    "Duplicate command/option name \"{0}\" found in: {1}", name, element);
            throw new CmdlineParserException(msg.notr(), msg.tr());
          }
          quickOptionMap.put(name, option);
        }
        options.add(option);
      }
    }
  }
Example #23
0
 @Override
 public Object run() {
   accessible.setAccessible(true);
   return null;
 }
 public Void run() {
   member.setAccessible(true);
   return null;
 }
Example #25
0
  public void parse(
      final boolean dryrun, final boolean detectHelpAndSkipValidation, String... cmdline) {
    if (log.isDebugEnabled()) {
      log.debug(
          "About to start parsing. dryrun: "
              + dryrun
              + ", detectHelpAndSkipValidation: "
              + detectHelpAndSkipValidation
              + ", state: "
              + debugState("  "));
    }

    if (defaultCommandName != null && !quickCommandMap.containsKey(defaultCommandName)) {
      final PreparedI18n msg =
          i18n.preparetr("Default command \"{0}\" is not a known command.", defaultCommandName);
      throw new CmdlineParserException(msg.notr(), msg.tr());
    }

    // Avoid null access
    cmdline = cmdline == null ? new String[] {} : cmdline;

    if (argsFromFilePrefix.isDefined()) {
      cmdline =
          FList.flatMap(
                  cmdline,
                  new F1<String, List<String>>() {
                    @Override
                    public List<String> apply(final String arg) {
                      if (arg.startsWith(argsFromFilePrefix.get())) {
                        debug("Expanding {0} into argument list", arg);
                        final File file = new File(arg.substring(1));
                        if (file.exists() && file.isFile()) {
                          try {
                            final BufferedReader reader = new BufferedReader(new FileReader(file));
                            final List<String> args = new LinkedList<String>();
                            String line;
                            while ((line = reader.readLine()) != null) {
                              // if (line.trim().length() > 0) {
                              args.add(line);
                              // }
                            }
                            reader.close();
                            return args;
                          } catch (final FileNotFoundException e) {
                            final PreparedI18n msg =
                                i18n.preparetr("File referenced via {0} does not exist.", arg);
                            throw new CmdlineParserException(msg.notr(), e, msg.tr());
                          } catch (final IOException e) {
                            final PreparedI18n msg =
                                i18n.preparetr("File referenced via {0} could not be read.", arg);
                            throw new CmdlineParserException(msg.notr(), e, msg.tr());
                          }
                        } else {
                          final PreparedI18n msg =
                              i18n.preparetr("File referenced via {0} does not exist.", arg);
                          throw new CmdlineParserException(msg.notr(), msg.tr());
                        }
                      } else {
                        return Arrays.asList(arg);
                      }
                    }
                  })
              .toArray(new String[0]);
    }

    if (!dryrun) {
      debug("Parsing...");
      // Check without applying anything
      parse(true, detectHelpAndSkipValidation, cmdline);
    }

    if (dryrun) {
      validateOptions();
    }

    // Should be set to false, if an stopOption was found and parsing of
    // options is no longer allowed
    boolean parseOptions = true;
    final String stopOption = "--";

    // optionCount counts the occurrence for each option handle in the
    // cmdline
    final Map<OptionHandle, Integer> optionCount = new LinkedHashMap<OptionHandle, Integer>();
    for (final OptionHandle option : options) {
      optionCount.put(option, 0);
    }
    if (parameter != null) {
      optionCount.put(parameter, 0);
    }

    boolean helpDetected = false;

    // Actually iterate over the command line elements
    for (int index = 0; index < cmdline.length; ++index) {
      final String param = cmdline[index];
      if (parseOptions && stopOption.equals(param)) {
        parseOptions = false;

      } else if (debugAllowed && param.equals("--CMDOPTION_DEBUG")) {
        if (!debugMode) {
          debugMode = true;
          debug("Enabled debug mode\n" + debugState(""));
        }

      } else if (parseOptions && quickOptionMap.containsKey(param)) {
        // Found an option
        final OptionHandle optionHandle = quickOptionMap.get(param);
        optionCount.put(optionHandle, optionCount.get(optionHandle) + 1);
        if (optionHandle.isHelp()) {
          debug("Detected a help request through: " + param);
          helpDetected = true;
        }

        if (cmdline.length <= index + optionHandle.getArgsCount()) {
          final PreparedI18n msg =
              i18n.preparetr(
                  "Missing arguments(s): {0}. Option \"{1}\" requires {2} arguments, but you gave {3}.",
                  FList.mkString(
                      Arrays.asList(optionHandle.getArgs())
                          .subList(cmdline.length - index - 1, optionHandle.getArgsCount()),
                      ", "),
                  param,
                  optionHandle.getArgsCount(),
                  cmdline.length - index - 1);
          throw new CmdlineParserException(msg.notr(), msg.tr());
        }
        // slurp next cmdline arguments into option arguments
        final String[] optionArgs =
            Arrays.copyOfRange(cmdline, index + 1, index + 1 + optionHandle.getArgsCount());
        index += optionHandle.getArgsCount();

        final AccessibleObject element = optionHandle.getElement();
        final CmdOptionHandler handler = optionHandle.getCmdOptionHandler();

        if (!dryrun) {
          try {
            final boolean origAccessibleFlag = element.isAccessible();
            if (!origAccessibleFlag) {
              element.setAccessible(true);
            }
            handler.applyParams(optionHandle.getObject(), element, optionArgs, param);
            if (!origAccessibleFlag) {
              // do not leave doors open
              element.setAccessible(origAccessibleFlag);
            }
          } catch (final CmdOptionHandlerException e) {
            throw new CmdlineParserException(e.getMessage(), e, e.getLocalizedMessage());
          } catch (final Exception e) {
            final PreparedI18n msg =
                i18n.preparetr(
                    "Could not apply parameters {0} to field/method {1}",
                    Arrays.toString(optionArgs), element);
            throw new CmdlineParserException(msg.notr(), e, msg.tr());
          }
        }
      } else if (parseOptions && quickCommandMap.containsKey(param)) {
        // Found a command
        final CommandHandle commandHandle = quickCommandMap.get(param);
        if (!dryrun) {
          parsedCommandName = param;
        }
        // Delegate parsing of the rest of the cmdline to the command
        commandHandle
            .getCmdlineParser()
            .parse(
                dryrun,
                detectHelpAndSkipValidation,
                Arrays.copyOfRange(cmdline, index + 1, cmdline.length));
        // Stop parsing
        break;

      } else if (parameter == null
          && defaultCommandName != null
          && quickCommandMap.containsKey(defaultCommandName)) {
        // Assume a default command inserted here
        debug(
            "Unsupported option '"
                + param
                + "' found, assuming default command: "
                + defaultCommandName);
        final CommandHandle commandHandle = quickCommandMap.get(defaultCommandName);

        if (!dryrun) {
          parsedCommandName = defaultCommandName;
        }
        // Delegate parsing of the rest of the cmdline to the command
        commandHandle
            .getCmdlineParser()
            .parse(
                dryrun,
                detectHelpAndSkipValidation,
                Arrays.copyOfRange(cmdline, index, cmdline.length));
        // Stop parsing
        break;

      } else if (parameter != null) {
        // Found a parameter
        optionCount.put(parameter, optionCount.get(parameter) + 1);

        if (cmdline.length <= index + parameter.getArgsCount() - 1) {
          final int countOfGivenParams = cmdline.length - index;
          final PreparedI18n msg =
              i18n.preparetr(
                  "Missing arguments: {0} Parameter requires {1} arguments, but you gave {2}.",
                  Arrays.asList(parameter.getArgs())
                      .subList(countOfGivenParams, parameter.getArgsCount()),
                  parameter.getArgsCount(),
                  countOfGivenParams);
          throw new CmdlineParserException(msg.notr(), msg.tr());
        }
        // slurp next cmdline arguments into option arguments
        final String[] optionArgs =
            Arrays.copyOfRange(cmdline, index, index + parameter.getArgsCount());
        // -1, because index gets increased by one at end of for-loop
        index += parameter.getArgsCount() - 1;

        final AccessibleObject element = parameter.getElement();
        final CmdOptionHandler handler = parameter.getCmdOptionHandler();

        if (!dryrun) {
          try {
            debug("Apply main parameter from parameters: {0}", FList.mkString(optionArgs, ", "));
            final boolean origAccessibleFlag = element.isAccessible();
            if (!origAccessibleFlag) {
              element.setAccessible(true);
            }
            handler.applyParams(parameter.getObject(), element, optionArgs, param);
            if (!origAccessibleFlag) {
              // do not leave doors open
              element.setAccessible(origAccessibleFlag);
            }
          } catch (final CmdOptionHandlerException e) {
            throw new CmdlineParserException(e.getMessage(), e, e.getLocalizedMessage());
          } catch (final Exception e) {
            final PreparedI18n msg =
                i18n.preparetr(
                    "Could not apply parameters {0} to field/method {1}",
                    Arrays.toString(optionArgs), element);
            throw new CmdlineParserException(msg.notr(), e, msg.tr());
          }
        }

      } else {
        final PreparedI18n msg =
            i18n.preparetr("Unsupported option or parameter found: {0}", param);
        throw new CmdlineParserException(msg.notr(), msg.tr());
      }
    }

    if (!detectHelpAndSkipValidation || !helpDetected) {
      // Validate optionCount matches allowed
      for (final Entry<OptionHandle, Integer> optionC : optionCount.entrySet()) {
        final OptionHandle option = optionC.getKey();
        final Integer count = optionC.getValue();
        if (count < option.getMinCount()
            || (option.getMaxCount() > 0 && count > option.getMaxCount())) {
          final PreparedI18n rangeMsg;
          if (option.getMaxCount() < 0) {
            rangeMsg = i18n.preparetr("at least {0}", option.getMinCount());
          } else {
            if (option.getMinCount() == option.getMaxCount()) {
              rangeMsg = i18n.preparetr("exactly {0}", option.getMinCount());
            } else {
              rangeMsg =
                  i18n.preparetr("between {0} and {1}", option.getMinCount(), option.getMaxCount());
            }
          }
          final String msg;
          final Object[] msgArgs;
          final Object[] msgArgsTr;
          if (option.getNames() == null || option.getNames().length == 0) {
            msg =
                I18n.marktr(
                    "Main parameter \"{0}\" was given {1} times, but must be given {2} times");
            msgArgs = new Object[] {FList.mkString(option.getArgs(), " "), count, rangeMsg.notr()};
            msgArgsTr = new Object[] {FList.mkString(option.getArgs(), " "), count, rangeMsg.tr()};
          } else {
            msg = I18n.marktr("Option \"{0}\" was given {1} times, but must be given {2} times");
            msgArgs = new Object[] {option.getNames()[0], count, rangeMsg.notr()};
            msgArgsTr = new Object[] {option.getNames()[0], count, rangeMsg.tr()};
          }
          throw new CmdlineParserException(
              MessageFormat.format(msg, msgArgs), i18n.tr(msg, msgArgsTr));
        }
      }

      // Validate required options because of 'required' attribute in
      // other options
      for (final Entry<OptionHandle, Integer> optionC : optionCount.entrySet()) {
        if (optionC.getValue() > 0) {
          final OptionHandle calledOption = optionC.getKey();
          for (final String required : calledOption.getRequires()) {
            // check, of an option was called with that name, if
            // not, this is an error
            final OptionHandle reqOptionHandle = quickOptionMap.get(required);
            if (reqOptionHandle == null) {
              // required option does not exists, error
              // TODO: error

            } else {
              final Integer reqOptionCount = optionCount.get(reqOptionHandle);
              if (reqOptionCount == null || reqOptionCount.intValue() <= 0) {
                // required option was not called, this is an
                // error
                final PreparedI18n msg =
                    i18n.preparetr(
                        "When using option \"{0}\" also option \"{1}\" must be given.",
                        calledOption.getNames()[0], required);
                throw new CmdlineParserException(msg.notr(), msg.tr());
              }
            }
          }
          for (final String conflict : calledOption.getConflictsWith()) {
            // check, of an option was called with that name, if
            // not, this is an error
            final OptionHandle conflictOptionHandle = quickOptionMap.get(conflict);
            if (conflictOptionHandle == null) {
              // conflicting option does not exists, error
              // TODO: error

            } else {
              final Integer conflictOptionCount = optionCount.get(conflictOptionHandle);
              if (conflictOptionCount != null && conflictOptionCount.intValue() > 0) {
                // conflicting option was called, this is an
                // conflict
                final PreparedI18n msg =
                    i18n.preparetr(
                        "Options \"{0}\" and \"{1}\" cannot be used at the same time.",
                        calledOption.getNames()[0], conflict);
                throw new CmdlineParserException(msg.notr(), msg.tr());
              }
            }
          }
        }
      }
    }
  }