Package org.jnetpcap.packet.structure

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

/*
* 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.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.jnetpcap.packet.JHeader;
import org.jnetpcap.packet.JPacket;
import org.jnetpcap.packet.annotate.Bind;


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

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

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

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

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

    /*
     * Now make sure it has the right signature of: <code>static int
     * name(JBuffer, int)</code.
     */
    final Class<?>[] sig = method.getParameterTypes();
    if (sig.length != 2 || sig[0] != JPacket.class
        || sig[1].isAssignableFrom(JHeader.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");
    }
  }

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

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

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

    /*
     * Now make sure it has the right signature of: <code>static int
     * name(JBuffer, int)</code.
     */
    final Class<?>[] sig = method.getParameterTypes();
    if (sig.length != 2 || sig[0] != JPacket.class
        || sig[1].isAssignableFrom(JHeader.class)) {
      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");
    }
  }

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

  /**
   * Inspect class.
   *
   * @param c
   *          the c
   * @param errors
   *          the errors
   * @return the annotated bind method[]
   */
  public static AnnotatedBindMethod[] inspectClass(
      final Class<?> c,
      final List<HeaderDefinitionError> errors) {

    if (cache.containsKey(c)) {
      return cache.get(c);
    }

    /*
     * We use a linked list as the normal Array.asList comes up with a version
     * that doesn't support the Iterator.remove() method. ArrayList and LinkList
     * both do.
     */
    AnnotatedBindMethod[] unchecked = inspectAnyClass(c, errors);
    final List<AnnotatedBindMethod> list =
        new LinkedList<AnnotatedBindMethod>(Arrays.asList(unchecked));

    for (final Iterator<AnnotatedBindMethod> i = list.iterator(); i.hasNext();) {
      final AnnotatedBindMethod b = i.next();
      /*
       * Also need to check and make sure that for general classes, there is
       * also a "from" parameter, which does not have to be present int JHeader
       * declaring class case.
       */
      final Bind bind = b.getMethod().getAnnotation(Bind.class);
      final Class<? extends JHeader> source = bind.from();

      if (source == JHeader.class) {
        errors.add(new HeaderDefinitionError(c,
            "missing annotated 'from' declaration for method "
                + b.getMethod().getName() + "()"));

        i.remove();
      }
    }

    /*
     * Now update cache after our check since removed values may have also been
     * cached.
     */
    final AnnotatedBindMethod[] bounds =
        list.toArray(new AnnotatedBindMethod[list.size()]);

    cache.put(c, bounds);

    return bounds;
  }

  /**
   * Inspect any class.
   *
   * @param <T>
   *          the generic type
   * @param c
   *          the c
   * @param errors
   *          the errors
   * @return the annotated bind method[]
   */
  private static <T extends JHeader> AnnotatedBindMethod[] inspectAnyClass(
      final Class<?> c,
      final List<HeaderDefinitionError> errors) {

    if (cache.containsKey(c)) {
      return cache.get(c);
    }

    final List<AnnotatedBindMethod> list = new ArrayList<AnnotatedBindMethod>();
    Class<? extends JHeader> target = null;

    for (final Method method : c.getMethods()) {

      try {
        if (method.isAnnotationPresent(Bind.class)) {

          checkSignature(method);

          final Bind bind = method.getAnnotation(Bind.class);
          target = bind.to();
          final AnnotatedBindMethod boundMethod =
              new AnnotatedBindMethod(target, method);

          list.add(boundMethod);
        }
      } catch (final AnnotatedMethodException e) {
        errors.add(e);
      }

    }

    final AnnotatedBindMethod[] isBounds =
        list.toArray(new AnnotatedBindMethod[list.size()]);

    cache.put(c, isBounds);

    return isBounds;
  }

  /**
   * Inspect object.
   *
   * @param object
   *          the object
   * @param errors
   *          the errors
   * @return the annotated bind method[]
   */
  public static AnnotatedBindMethod[] inspectObject(
      final Object object,
      final List<HeaderDefinitionError> errors) {

    Class<?> c = object.getClass();

    if (cache.containsKey(c)) {
      return cache.get(c);
    }

    final List<AnnotatedBindMethod> list = new ArrayList<AnnotatedBindMethod>();
    Class<? extends JHeader> target = null;

    if (c.getSuperclass() != Object.class) {
      errors.add(new AnnotatedMethodException(
          "bindings using annonymous classes can only extend Object class"));

      return new AnnotatedBindMethod[0];
    }

    for (final Method method : c.getMethods()) {

      try {
        if (method.isAnnotationPresent(Bind.class)) {

          checkNonStaticSignature(method);

          final Bind bind = method.getAnnotation(Bind.class);
          target = bind.to();
          final AnnotatedBindMethod boundMethod =
              new AnnotatedBindMethod(target, method, object);

          list.add(boundMethod);
        }
      } catch (final AnnotatedMethodException e) {
        errors.add(e);
      }

    }

    final AnnotatedBindMethod[] binds =
        list.toArray(new AnnotatedBindMethod[list.size()]);

    cache.put(c, binds);

    return binds;
  }

  /**
   * Inspect j header class.
   *
   * @param <T>
   *          the generic type
   * @param c
   *          the c
   * @param errors
   *          the errors
   * @return the annotated bind method[]
   */
  public static <T extends JHeader> AnnotatedBindMethod[] inspectJHeaderClass(
      final Class<? extends JHeader> c,
      final List<HeaderDefinitionError> errors) {

    return inspectAnyClass(c, errors);
  }

  /**
   * Instantiates a new annotated bind method.
   *
   * @param target
   *          the target
   * @param method
   *          the method
   * @param object
   *          the object
   */
  private AnnotatedBindMethod(final Class<? extends JHeader> target,
      final Method method, final Object object) {
    super(method, object);
  }

  /**
   * Instantiates a new annotated bind method.
   *
   * @param target
   *          the target
   * @param method
   *          the method
   */
  private AnnotatedBindMethod(final Class<? extends JHeader> target,
      final Method method) {
    super(method);
  }

  /**
   * Checks if is bound.
   *
   * @param packet
   *          the packet
   * @param offset
   *          the offset
   * @param header
   *          the header
   * @return true, if is bound
   */
  public boolean isBound(
      final JPacket packet,
      final int offset,
      final JHeader header) {

    try {
      return (Boolean) method.invoke(object, packet, header);
    } catch (final IllegalArgumentException e) {
      throw new IllegalStateException(e);
    } catch (final IllegalAccessException e) {
      throw new IllegalStateException(e);
    } catch (final InvocationTargetException e) {
      throw new AnnotatedMethodException(declaringClass, e);
    }
  }

  /**
   * Validate signature.
   *
   * @param method
   *          the method
   * @see org.jnetpcap.packet.structure.AnnotatedMethod#validateSignature(java.lang.reflect.Method)
   */
  @Override
  protected void validateSignature(final Method method) {
   
    if (object == null) {
      checkSignature(method);
    } else {
      checkNonStaticSignature(method);
    }
  }
}
TOP

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

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.