Package org.jnetpcap.packet.structure

Source Code of org.jnetpcap.packet.structure.AnnotatedHeaderLengthMethod

/*
* 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.HashMap;
import java.util.Map;

import org.jnetpcap.nio.JBuffer;
import org.jnetpcap.packet.JHeader;
import org.jnetpcap.packet.annotate.Header;
import org.jnetpcap.packet.annotate.HeaderLength;
import org.jnetpcap.packet.annotate.HeaderLength.Type;

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

  /** The Constant cache. */
  private final static Map<Class<?>, AnnotatedHeaderLengthMethod[]> cache =
      new HashMap<Class<?>, AnnotatedHeaderLengthMethod[]>();

  /**
   * Inspect annotations within the class for length methods.
   *
   * @param c
   *          class to inspect
   * @return array containing length methods for various header "record"
   *         sub-structures
   */
  public static AnnotatedHeaderLengthMethod[] inspectClass(
      Class<? extends JHeader> c) {

    /*
     * Check if we have this method cached for this class.
     */
    if (cache.containsKey(c)) {
      return cache.get(c);
    }

    AnnotatedHeaderLengthMethod[] methods =
        new AnnotatedHeaderLengthMethod[HeaderLength.Type.values().length];

    Header header = c.getAnnotation(Header.class);
    if (header != null && header.length() != -1) {
      methods[HeaderLength.Type.HEADER.ordinal()] =
          new AnnotatedHeaderLengthMethod(c, header.length(),
              HeaderLength.Type.HEADER);
    }

    if (header != null && header.prefix() != -1) {
      methods[HeaderLength.Type.PREFIX.ordinal()] =
          new AnnotatedHeaderLengthMethod(c, header.prefix(),
              HeaderLength.Type.PREFIX);
    }

    if (header != null && header.gap() != -1) {
      methods[HeaderLength.Type.GAP.ordinal()] =
          new AnnotatedHeaderLengthMethod(c, header.gap(),
              HeaderLength.Type.GAP);
    }

    if (header != null && header.payload() != -1) {
      methods[HeaderLength.Type.PAYLOAD.ordinal()] =
          new AnnotatedHeaderLengthMethod(c, header.payload(),
              HeaderLength.Type.PAYLOAD);
    }

    if (header != null && header.postfix() != -1) {
      methods[HeaderLength.Type.POSTFIX.ordinal()] =
          new AnnotatedHeaderLengthMethod(c, header.postfix(),
              HeaderLength.Type.POSTFIX);
    }

    for (Method method : getMethods(c, HeaderLength.class)) {

      HeaderLength hl = method.getAnnotation(HeaderLength.class);

      if (methods[hl.value().ordinal()] != null) {
        throw new AnnotatedMethodException(c, "duplicate: "
            + methods[hl.value().ordinal()] + " property and " + method.getName()
            + "() method");
      }

      checkSignature(method);

      methods[hl.value().ordinal()] =
          new AnnotatedHeaderLengthMethod(method, hl.value());
    }

    if (methods[HeaderLength.Type.HEADER.ordinal()] == null) {
      throw new AnnotatedMethodException(c,
          "@HeaderLength annotated method not found");
    }

    cache.put(c, methods);
    return methods;
  }

  /** The static length. */
  private int staticLength;

  /** The type. */
  private final Type type;

  /**
   * Instantiates a new annotated header length method.
   *
   * @param method
   *          the method
   * @param type
   *          the type
   */
  private AnnotatedHeaderLengthMethod(Method method, HeaderLength.Type type) {
    super(method);
    this.type = type;

    this.staticLength = -1;
  }

  /**
   * Instantiates a new annotated header length method.
   *
   * @param c
   *          the c
   * @param length
   *          the length
   * @param type
   *          the type
   */
  public AnnotatedHeaderLengthMethod(
      Class<? extends JHeader> c,
      int length,
      HeaderLength.Type type) {
    this.staticLength = length;
    this.type = type;
  }

  /**
   * Gets the header length.
   *
   * @param buffer
   *          the buffer
   * @param offset
   *          the offset
   * @return the header length
   */
  public int getHeaderLength(JBuffer buffer, int offset) {

    if (this.staticLength != -1) {
      return this.staticLength;
    }

    /*
     * Invoke the static method: <code>public static int method(JBuffer, int)</code>
     */
    try {
      int length = (int) (Integer) this.method.invoke(null, buffer, offset);
      return length;
    } catch (IllegalArgumentException e) {
      throw new IllegalStateException(e);
    } catch (IllegalAccessException e) {
      throw new IllegalStateException(e);
    } catch (InvocationTargetException e) {
      throw new AnnotatedMethodException(declaringClass, e.getCause());
    }
  }

  /**
   * Gets the method.
   *
   * @return the method
   * @see org.jnetpcap.packet.structure.AnnotatedMethod#getMethod()
   */
  public final Method getMethod() {
    return this.method;
  }

  /**
   * Checks for static length.
   *
   * @return true, if successful
   */
  public boolean hasStaticLength() {
    return this.staticLength != -1;
  }

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

  /**
   * Check signature.
   *
   * @param method
   *          the method
   */
  private static void checkSignature(Method method) {

    Class<?> declaringClass = method.getDeclaringClass();

    if (method.isAnnotationPresent(HeaderLength.class) == false) {
      throw new AnnotatedMethodException(declaringClass,
          "@HeaderLength annotation missing for " + method.getName() + "()");
    }

    /*
     * Now make sure it has the right signature of: <code>static int
     * name(JBuffer, int)</code.
     */
    Class<?>[] t = method.getParameterTypes();
    if (t.length != 2 || t[0] != JBuffer.class || t[1] != int.class
        || method.getReturnType() != int.class) {

      throw new AnnotatedMethodException(declaringClass,
          "Invalid signature for " + method.getName() + "()");
    }

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

    }
  }

  /**
   * Clear cache.
   */
  public static void clearCache() {
    cache.clear();
  }

  /**
   * To string.
   *
   * @return the string
   * @see org.jnetpcap.packet.structure.AnnotatedMethod#toString()
   */
  public String toString() {
    if (method == null) {
      String property =
          (type == HeaderLength.Type.HEADER) ? "length" : type.toString()
              .toLowerCase();
      return "@Header(" + property + "=" + staticLength + ")";
    } else {
      return super.toString();
    }
  }

}
TOP

Related Classes of org.jnetpcap.packet.structure.AnnotatedHeaderLengthMethod

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.