Package org.jnetpcap.packet.structure

Source Code of org.jnetpcap.packet.structure.AnnotatedFieldMethod$StringFunction

/*
* Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Sly Technologies, Inc.
*
* This file is part of jNetPcap.
*
* jNetPcap is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package org.jnetpcap.packet.structure;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.List;

import org.jnetpcap.packet.JHeader;
import org.jnetpcap.packet.annotate.Dynamic;
import org.jnetpcap.packet.annotate.Field;
import org.jnetpcap.packet.annotate.FieldDefinitionException;

// TODO: Auto-generated Javadoc
/**
* The Class AnnotatedFieldMethod.
*
* @author Mark Bednarczyk
* @author Sly Technologies, Inc.
*/
public abstract class AnnotatedFieldMethod
    extends AnnotatedMethod {

  /**
   * The Class BooleanFunction.
   */
  private static class BooleanFunction
      extends AnnotatedFieldMethod {

    /** The has static value. */
    private boolean hasStaticValue = false;

    /** The value. */
    private boolean value;

    /**
     * Instantiates a new boolean function.
     *
     * @param field
     *          the field
     * @param function
     *          the function
     */
    public BooleanFunction(AnnotatedField field, Field.Property function) {
      super(field, function);

      setValue(true); // Static fields are always available
    }

    /**
     * Instantiates a new boolean function.
     *
     * @param method
     *          the method
     * @param function
     *          the function
     */
    public BooleanFunction(Method method, Field.Property function) {
      super(method, function);
    }

    /*
     * (non-Javadoc)
     *
     * @see org.jnetpcap.packet.AnnotatedFieldMethod#booleanMethod(org.jnetpcap.packet.JHeader)
     */
    /**
     * Boolean method.
     *
     * @param header
     *          the header
     * @param name
     *          the name
     * @return true, if successful
     * @see org.jnetpcap.packet.structure.AnnotatedFieldMethod#booleanMethod(org.jnetpcap.packet.JHeader,
     *      java.lang.String)
     */
    @Override
    public boolean booleanMethod(JHeader header, String name) {
      return execute(header, name);
    }

    /**
     * Config from field.
     *
     * @param field
     *          the field
     * @see org.jnetpcap.packet.structure.AnnotatedFieldMethod#configFromField(org.jnetpcap.packet.structure.AnnotatedField)
     */
    public final void configFromField(AnnotatedField field) {

      switch (function) {
        case CHECK:
          break;

        default:
          throw new HeaderDefinitionError("Invalid Dynamic function type "
              + function.toString());

      }

      if (hasStaticValue == false && method == null) {
        throw new FieldDefinitionException(field, "Missing '"
            + function.name().toLowerCase() + "' property. [@Dynamic(Property."
            + function.name() + ")]");
      }
    }

    /**
     * Execute.
     *
     * @param header
     *          the header
     * @param name
     *          the name
     * @return true, if successful
     */
    public boolean execute(JHeader header, String name) {
      if (hasStaticValue) {
        return this.value;
      }

      try {
        if (isMapped) {
          return (boolean) (Boolean) method.invoke(header, name);
        } else {
          return (boolean) (Boolean) method.invoke(header);
        }

      } catch (IllegalArgumentException e) {
        throw new IllegalStateException(e);
      } catch (IllegalAccessException e) {
        throw new IllegalStateException(e);
      } catch (InvocationTargetException e) {
        throw new AnnotatedMethodException(declaringClass, e);
      }
    }

    /**
     * Sets the value.
     *
     * @param value
     *          the new value
     */
    private void setValue(boolean value) {
      hasStaticValue = true;
      this.value = value;
    }
  }

  /**
   * The Class IntFunction.
   */
  private static class IntFunction
      extends AnnotatedFieldMethod {

    /** The has static value. */
    private boolean hasStaticValue = false;

    /** The value. */
    private int value;

    /**
     * Instantiates a new int function.
     *
     * @param field
     *          the field
     * @param function
     *          the function
     */
    public IntFunction(AnnotatedField field, Field.Property function) {
      super(field, function);

      configFromField(field);

    }

    /**
     * Instantiates a new int function.
     *
     * @param field
     *          the field
     * @param function
     *          the function
     * @param staticValue
     *          the static value
     */
    public IntFunction(AnnotatedField field, Field.Property function,
        int staticValue) {
      super(field, function);

      setValue(staticValue);
    }

    /**
     * Instantiates a new int function.
     *
     * @param method
     *          the method
     * @param function
     *          the function
     */
    public IntFunction(Method method, Field.Property function) {
      super(method, function);
    }

    /**
     * Config from field.
     *
     * @param field
     *          the field
     * @see org.jnetpcap.packet.structure.AnnotatedFieldMethod#configFromField(org.jnetpcap.packet.structure.AnnotatedField)
     */
    public final void configFromField(AnnotatedField field) {

      switch (function) {
        case LENGTH:
          if (field.getLength() != -1) {
            setValue(field.getLength());
          }
          break;

        case OFFSET:
          if (field.getOffset() != -1) {
            setValue(field.getOffset());
          }
          break;

        default:
          throw new HeaderDefinitionError("Invalid Dynamic function type "
              + function.toString());

      }

      if (hasStaticValue == false && method == null) {
        throw new FieldDefinitionException(field, "Missing '"
            + function.name().toLowerCase() + "' property. [@Field("
            + function.name().toLowerCase() + "=<int>) or @Dynamic(Property."
            + function.name() + ")]");
      }

    }

    /**
     * Execute.
     *
     * @param header
     *          the header
     * @param name
     *          the name
     * @return the int
     */
    public int execute(JHeader header, String name) {
      if (hasStaticValue) {
        return this.value;
      }

      try {
        if (isMapped) {
          return (int) (Integer) method.invoke(header, name);
        } else {
          return (int) (Integer) method.invoke(header);
        }

      } catch (IllegalArgumentException e) {
        throw new IllegalStateException(e);
      } catch (IllegalAccessException e) {
        throw new IllegalStateException(e);
      } catch (InvocationTargetException e) {
        throw new AnnotatedMethodException(declaringClass, e);
      }
    }

    /*
     * (non-Javadoc)
     *
     * @see org.jnetpcap.packet.AnnotatedFieldMethod#intMethod(org.jnetpcap.packet.JHeader)
     */
    /**
     * Int method.
     *
     * @param header
     *          the header
     * @param name
     *          the name
     * @return the int
     * @see org.jnetpcap.packet.structure.AnnotatedFieldMethod#intMethod(org.jnetpcap.packet.JHeader,
     *      java.lang.String)
     */
    @Override
    public int intMethod(JHeader header, String name) {
      return execute(header, name);
    }

    /**
     * Sets the value.
     *
     * @param value
     *          the new value
     */
    private void setValue(int value) {
      hasStaticValue = true;
      this.value = value;
    }
  }

  /**
   * The Class LongFunction.
   */
  private static class LongFunction
      extends AnnotatedFieldMethod {

    /** The has static value. */
    private boolean hasStaticValue = false;

    /** The value. */
    private long value;

    /**
     * Instantiates a new long function.
     *
     * @param field
     *          the field
     * @param function
     *          the function
     */
    public LongFunction(AnnotatedField field, Field.Property function) {
      super(field, function);

      configFromField(field);

    }

    /**
     * Instantiates a new long function.
     *
     * @param field
     *          the field
     * @param function
     *          the function
     * @param staticValue
     *          the static value
     */
    public LongFunction(AnnotatedField field, Field.Property function,
        long staticValue) {
      super(field, function);

      setValue(staticValue);
    }

    /**
     * Instantiates a new long function.
     *
     * @param method
     *          the method
     * @param function
     *          the function
     */
    public LongFunction(Method method, Field.Property function) {
      super(method, function);
    }

    /**
     * Config from field.
     *
     * @param field
     *          the field
     * @see org.jnetpcap.packet.structure.AnnotatedFieldMethod#configFromField(org.jnetpcap.packet.structure.AnnotatedField)
     */
    public final void configFromField(AnnotatedField field) {

      switch (function) {

        case MASK:

          setValue(field.getMask());
          break;

        default:
          throw new HeaderDefinitionError("Invalid Dynamic function type "
              + function.toString());

      }

      if (hasStaticValue == false && method == null) {
        throw new FieldDefinitionException(field, "Missing '"
            + function.name().toLowerCase() + "' property. [@Field("
            + function.name().toLowerCase() + "=<int>) or @Dynamic(Property."
            + function.name() + ")]");
      }

    }

    /**
     * Execute.
     *
     * @param header
     *          the header
     * @param name
     *          the name
     * @return the long
     */
    public long execute(JHeader header, String name) {
      if (hasStaticValue) {
        return this.value;
      }

      try {
        if (isMapped) {
          return (long) (Long) method.invoke(header, name);
        } else {
          return (long) (Long) method.invoke(header);
        }

      } catch (IllegalArgumentException e) {
        throw new IllegalStateException(e);
      } catch (IllegalAccessException e) {
        throw new IllegalStateException(e);
      } catch (InvocationTargetException e) {
        throw new AnnotatedMethodException(declaringClass, e);
      }
    }

    /*
     * (non-Javadoc)
     *
     * @see org.jnetpcap.packet.AnnotatedFieldMethod#longMethod(org.jnetpcap.packet.JHeader)
     */
    /**
     * Long method.
     *
     * @param header
     *          the header
     * @param name
     *          the name
     * @return the long
     * @see org.jnetpcap.packet.structure.AnnotatedFieldMethod#longMethod(org.jnetpcap.packet.JHeader,
     *      java.lang.String)
     */
    @Override
    public long longMethod(JHeader header, String name) {
      return execute(header, name);
    }

    /**
     * Sets the value.
     *
     * @param mask
     *          the new value
     */
    private void setValue(long mask) {
      hasStaticValue = true;
      this.value = mask;
    }
  }

  /**
   * The Class ObjectFunction.
   */
  private static class ObjectFunction
      extends AnnotatedFieldMethod {

    /**
     * Instantiates a new object function.
     *
     * @param field
     *          the field
     * @param fuction
     *          the fuction
     */
    public ObjectFunction(AnnotatedField field, Field.Property fuction) {
      super(field, fuction, field.getMethod());

    }

    /**
     * Instantiates a new object function.
     *
     * @param method
     *          the method
     * @param function
     *          the function
     */
    public ObjectFunction(Method method, Field.Property function) {
      super(method, function);
    }

    /**
     * Config from field.
     *
     * @param field
     *          the field
     * @see org.jnetpcap.packet.structure.AnnotatedFieldMethod#configFromField(org.jnetpcap.packet.structure.AnnotatedField)
     */
    public final void configFromField(AnnotatedField field) {

      switch (function) {
        case VALUE:
          if (method == null) {
            throw new HeaderDefinitionError(field.getDeclaringClass(),
                "no method set for field value getter [" + field.getName()
                    + "]");
          }
          break;

        default:
          throw new HeaderDefinitionError(field.getDeclaringClass(),
              "Invalid Dynamic function type " + function.toString());

      }

      if (method == null) {
        throw new FieldDefinitionException(field, "Missing field accessor '"
            + function.name().toLowerCase() + "' property. [@Dynamic(Property."
            + function.name() + ")]");
      }
    }

    /**
     * Execute.
     *
     * @param header
     *          the header
     * @param name
     *          the name
     * @return the object
     */
    public Object execute(JHeader header, String name) {

      try {
        if (isMapped) {
          return method.invoke(header, name);
        } else {
          return method.invoke(header);
        }

      } catch (IllegalArgumentException e) {
        throw new IllegalStateException(e);
      } catch (IllegalAccessException e) {
        throw new IllegalStateException(e);
      } catch (InvocationTargetException e) {
        throw new AnnotatedMethodException(declaringClass, e.getMessage(), e);
      }
    }

    /*
     * (non-Javadoc)
     *
     * @see org.jnetpcap.packet.AnnotatedFieldMethod#objectMethod(org.jnetpcap.packet.JHeader)
     */
    /**
     * Object method.
     *
     * @param header
     *          the header
     * @param name
     *          the name
     * @return the object
     * @see org.jnetpcap.packet.structure.AnnotatedFieldMethod#objectMethod(org.jnetpcap.packet.JHeader,
     *      java.lang.String)
     */
    @Override
    public Object objectMethod(JHeader header, String name) {
      return execute(header, name);
    }
  }

  /**
   * The Class StringFunction.
   */
  private static class StringFunction
      extends AnnotatedFieldMethod {

    /** The has static value. */
    private boolean hasStaticValue = false;

    /** The value. */
    private String value;

    /**
     * Instantiates a new string function.
     *
     * @param field
     *          the field
     * @param function
     *          the function
     */
    public StringFunction(AnnotatedField field, Field.Property function) {
      super(field, function);

      configFromField(field);
    }

    /**
     * Instantiates a new string function.
     *
     * @param method
     *          the method
     * @param function
     *          the function
     */
    public StringFunction(Method method, Field.Property function) {
      super(method, function);
    }

    /**
     * Config from field.
     *
     * @param field
     *          the field
     * @see org.jnetpcap.packet.structure.AnnotatedFieldMethod#configFromField(org.jnetpcap.packet.structure.AnnotatedField)
     */
    public final void configFromField(AnnotatedField field) {

      switch (function) {
        case UNITS:
          if (field.getUnits().length() != 0) {
            setValue(field.getUnits());
          } else if (method == null) {
            setValue(null);
          }
          break;
        case DISPLAY:
          if (field.getDisplay().length() != 0) {
            setValue(field.getDisplay());
          } else if (method == null) {
            setValue(null);
          }
          break;

        case DESCRIPTION:
          if (field.getDescription().length() != 0) {
            setValue(field.getDescription());
          } else if (method == null) {
            setValue(null);
          }
          break;

        default:
          throw new HeaderDefinitionError("Invalid Dynamic function type "
              + function.toString());

      }

      if (hasStaticValue == false && method == null) {
        throw new FieldDefinitionException(field, "Missing '"
            + function.name().toLowerCase() + "' property. [@Field("
            + function.name().toLowerCase()
            + "=<string>) or @Dynamic(Property." + function.name() + ")]");
      }
    }

    /**
     * Execute.
     *
     * @param header
     *          the header
     * @param name
     *          the name
     * @return the string
     */
    public String execute(JHeader header, String name) {
      if (hasStaticValue) {
        return this.value;
      }

      try {
        if (isMapped) {
          return (String) method.invoke(header, name);
        } else {
          return (String) method.invoke(header);
        }

      } catch (IllegalArgumentException e) {
        throw new IllegalStateException(e);
      } catch (IllegalAccessException e) {
        throw new IllegalStateException(e);
      } catch (InvocationTargetException e) {
        throw new AnnotatedMethodException(declaringClass, e);
      }
    }

    /**
     * Sets the value.
     *
     * @param value
     *          the new value
     */
    private void setValue(String value) {
      hasStaticValue = true;
      this.value = value;
    }

    /*
     * (non-Javadoc)
     *
     * @see org.jnetpcap.packet.AnnotatedFieldMethod#StringMethod(org.jnetpcap.packet.JHeader)
     */
    /**
     * String method.
     *
     * @param header
     *          the header
     * @param name
     *          the name
     * @return the string
     * @see org.jnetpcap.packet.structure.AnnotatedFieldMethod#stringMethod(org.jnetpcap.packet.JHeader,
     *      java.lang.String)
     */
    @Override
    public String stringMethod(JHeader header, String name) {
      return execute(header, name);
    }
  }

  /**
   * Check annotation.
   *
   * @param method
   *          the method
   * @param fields
   *          the fields
   */
  public static void checkAnnotation(Method method, List<AnnotatedField> fields) {

    Dynamic runtime = method.getAnnotation(Dynamic.class);

    if (runtime.field().length() != 0) {

      boolean found = false;
      final String name = runtime.field();
      for (AnnotatedField f : fields) {
        if (f.getName().equals(name)) {
          found = true;
          break;
        }
      }

      if (!found) {
        throw new HeaderDefinitionError("field name defined in annotation ");
      }

    }
  }

  /**
   * Check signature.
   *
   * @param method
   *          the method
   * @param c
   *          the c
   */
  private static void checkSignature(Method method, Class<?> c) {
    final Class<?> declaringClass = method.getDeclaringClass();

    /*
     * Now make sure it has the right signature of: <code>String name()</code.
     */
    final Class<?>[] sig = method.getParameterTypes();
    if ((sig.length == 1 && sig[0] != String.class) || sig.length > 1
        || method.getReturnType() != c) {
      throw new AnnotatedMethodException(declaringClass,
          "Invalid signature for " + method.getName() + "()");
    }

    if ((method.getModifiers() & Modifier.STATIC) != 0) {
      throw new AnnotatedMethodException(declaringClass, method.getName()
          + "()" + " can not be declared static");
    }
  }

  /**
   * Generate function.
   *
   * @param function
   *          the function
   * @param field
   *          the field
   * @return the annotated field method
   */
  public static AnnotatedFieldMethod generateFunction(
      Field.Property function,
      AnnotatedField field) {

    switch (function) {
      case LENGTH:
      case OFFSET:
        return new IntFunction(field, function);

      case MASK:
        return new LongFunction(field, function);

      case VALUE:
        return new ObjectFunction(field, function);

      case CHECK:
        return new BooleanFunction(field, function);

      case UNITS:
      case DISPLAY:
      case DESCRIPTION:
        return new StringFunction(field, function);

      default:
        throw new HeaderDefinitionError("Unsupported Dynamic function type "
            + function.toString());
    }

  }

  /**
   * Guess field name.
   *
   * @param name
   *          the name
   * @return the string
   */
  private static String guessFieldName(String name) {
    if (name.startsWith("has")) {
      String cap = name.replace("has", "");
      char u = cap.charAt(0);
      char l = Character.toLowerCase(u);
      return cap.replace(u, l);
    } else if (name.endsWith("Description")) {
      return name.replace("Description", "");
    } else if (name.endsWith("Offset")) {
      return name.replace("Offset", "");
    } else if (name.endsWith("Length")) {
      return name.replace("Length", "");
    } else if (name.endsWith("Mask")) {
      return name.replace("Mask", "");
    } else if (name.endsWith("Value")) {
      return name.replace("Value", "");
    } else if (name.endsWith("Display")) {
      return name.replace("Display", "");
    } else if (name.endsWith("Units")) {
      return name.replace("Units", "");
    } else if (name.endsWith("Format")) {
      return name.replace("Format", "");
    } else {
      return name;
    }
  }

  /**
   * Inspect method.
   *
   * @param method
   *          the method
   * @return the annotated field method
   */
  public static AnnotatedFieldMethod inspectMethod(Method method) {

    Dynamic runtime = method.getAnnotation(Dynamic.class);

    Field.Property function = runtime.value();
    switch (function) {
      case LENGTH:
      case OFFSET:
        checkSignature(method, int.class);
        return new IntFunction(method, function);

      case MASK:
        checkSignature(method, long.class);
        return new LongFunction(method, function);

      case VALUE:
        checkSignature(method, Object.class);

        return new ObjectFunction(method, function);

      case CHECK:
        checkSignature(method, boolean.class);
        return new BooleanFunction(method, function);

      case DISPLAY:
      case DESCRIPTION:
        checkSignature(method, String.class);
        return new StringFunction(method, function);

      default:
        throw new HeaderDefinitionError("Unsupported Dynamic function type "
            + function.toString());
    }
  }

  /** The field. */
  protected final String field;

  /** The function. */
  protected final Field.Property function;

  /**
   * Instantiates a new annotated field method.
   *
   * @param field
   *          the field
   * @param function
   *          the function
   */
  public AnnotatedFieldMethod(AnnotatedField field, Field.Property function) {
    super();
    this.function = function;

    this.field = field.getName();
  }

  /**
   * Instantiates a new annotated field method.
   *
   * @param field
   *          the field
   * @param function
   *          the function
   * @param method
   *          the method
   */
  public AnnotatedFieldMethod(AnnotatedField field, Field.Property function,
      Method method) {
    super(method);
    this.function = function;

    this.field = field.getName();
  }

  /**
   * Instantiates a new annotated field method.
   *
   * @param method
   *          the method
   * @param function
   *          the function
   */
  public AnnotatedFieldMethod(Method method, Field.Property function) {
    super(method);
    this.function = function;

    Dynamic runtime = method.getAnnotation(Dynamic.class);
    if (runtime == null) {
      throw new HeaderDefinitionError(method.getDeclaringClass(),
          "unable get field's annotated runtime");
    }

    if (runtime.field().length() != 0) {
      this.field = runtime.field();
    } else {
      this.field = guessFieldName(method.getName());
    }
  }

  /**
   * Boolean method.
   *
   * @param header
   *          the header
   * @param name
   *          the name
   * @return true, if successful
   */
  public boolean booleanMethod(JHeader header, String name) {
    throw new UnsupportedOperationException(
        "this return type is invalid for this function type");
  }

  /**
   * Config from field.
   *
   * @param field
   *          the field
   */
  public abstract void configFromField(AnnotatedField field);

  /**
   * Gets the field name.
   *
   * @return the field name
   */
  public String getFieldName() {
    return field;
  }

  /**
   * Gets the function.
   *
   * @return the function
   */
  public final Field.Property getFunction() {
    return this.function;
  }

  /**
   * Int method.
   *
   * @param header
   *          the header
   * @param name
   *          the name
   * @return the int
   */
  public int intMethod(JHeader header, String name) {
    throw new UnsupportedOperationException(
        "this return type is invalid for this function type");
  }

  /**
   * Object method.
   *
   * @param header
   *          the header
   * @param name
   *          the name
   * @return the object
   */
  public Object objectMethod(JHeader header, String name) {
    throw new UnsupportedOperationException(
        "this return type is invalid for this function type");
  }

  /**
   * String method.
   *
   * @param header
   *          the header
   * @param name
   *          the name
   * @return the string
   */
  public String stringMethod(JHeader header, String name) {
    throw new UnsupportedOperationException(
        "this return type is invalid for this function type");
  }

  /*
   * (non-Javadoc)
   *
   * @see org.jnetpcap.packet.AnnotatedMethod#validateSignature(java.lang.reflect.Method)
   */
  /**
   * Validate signature.
   *
   * @param method
   *          the method
   * @see org.jnetpcap.packet.structure.AnnotatedMethod#validateSignature(java.lang.reflect.Method)
   */
  @Override
  protected void validateSignature(Method method) {
  }

  /**
   * Long method.
   *
   * @param header
   *          the header
   * @param name
   *          the name
   * @return the long
   */
  public long longMethod(JHeader header, String name) {
    throw new UnsupportedOperationException(
        "this return type is invalid for this function type");
  }

}
TOP

Related Classes of org.jnetpcap.packet.structure.AnnotatedFieldMethod$StringFunction

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.