Advertisement
Chiddix

Mercury v1.0.1

Jul 29th, 2014
290
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 5.82 KB | None | 0 0
  1. package me.rabrg.mercury;
  2.  
  3. import java.io.DataInputStream;
  4. import java.io.DataOutputStream;
  5. import java.io.InputStream;
  6. import java.io.OutputStream;
  7. import java.lang.reflect.Field;
  8. import java.lang.reflect.Modifier;
  9.  
  10. import me.rabrg.mercury.event.Event;
  11. import me.rabrg.mercury.event.handler.EventHandler;
  12.  
  13. /**
  14.  * The core class of the Mercury networking API.
  15.  * @author Ryan Greene
  16.  *
  17.  */
  18. public final class Mercury {
  19.  
  20.     /**
  21.      * The modifiers field for allowing modification of final fields.
  22.      */
  23.     private static Field modifiersField;
  24.  
  25.      static {
  26.          try {
  27.             modifiersField = Field.class.getDeclaredField("modifiers");
  28.         } catch (final Exception e) {
  29.             System.out.println("Exception thrown while getting modifiers field " + e);
  30.             System.exit(0);
  31.         }
  32.          modifiersField.setAccessible(true);
  33.      }
  34.  
  35.     /**
  36.      * An array containing all registered events.
  37.      */
  38.     private Class<Event>[] events;
  39.  
  40.     /**
  41.      * An array containing all registered event handlers.
  42.      */
  43.     private EventHandler<Event>[] eventHandlers;
  44.  
  45.     /**
  46.      * The current index for registering events.
  47.      */
  48.     private int index;
  49.  
  50.     /**
  51.      * The input stream used to read events.
  52.      */
  53.     private final DataInputStream input;
  54.  
  55.     /**
  56.      * The output stream used to write events.
  57.      */
  58.     private final DataOutputStream output;
  59.  
  60.     /**
  61.      * Constructs a new mercury instance with the specified input and output streams.
  62.      * @param input The input stream used to read events.
  63.      * @param output The output stream used to write events.
  64.      */
  65.     @SuppressWarnings("unchecked")
  66.     public Mercury(final InputStream input, final OutputStream output) {
  67.         events = new Class[1];
  68.         eventHandlers = new EventHandler[1];
  69.         index = 0;
  70.         this.input = new DataInputStream(input);
  71.         this.output = new DataOutputStream(output);
  72.     }
  73.  
  74.     /**
  75.      * Registers the specified event to an opcode and the specified event handler.
  76.      * @param event The event being registered.
  77.      * @param eventHandler The handler of the event.
  78.      */
  79.     @SuppressWarnings("unchecked")
  80.     public void registerEvent(final Class<? extends Event> event, final EventHandler<? extends Event> eventHandler) {
  81.         if (index == events.length) {
  82.             Class<Event>[] eventsExpanded = new Class[events.length + 1];
  83.             System.arraycopy(events, 0, eventsExpanded, 0, events.length);
  84.             events = eventsExpanded;
  85.            
  86.             EventHandler<Event>[] eventHandlersExpanded = new EventHandler[eventHandlers.length + 1];
  87.             System.arraycopy(eventHandlers, 0, eventHandlersExpanded, 0, eventHandlers.length);
  88.             eventHandlers = eventHandlersExpanded;
  89.         }
  90.         events[index] = (Class<Event>) event;
  91.         eventHandlers[index++] = (EventHandler<Event>) eventHandler;
  92.     }
  93.  
  94.     /**
  95.      * Writes the specified event to the output stream.
  96.      * @param event The event being written.
  97.      * @throws Exception If an exception is thrown.
  98.      */
  99.     public void writeEvent(final Event event) throws Exception {
  100.         int opcode = -1;
  101.         for (int i = 0; i < events.length; i++) {
  102.             if (events[i] == event.getClass()) {
  103.                 opcode = i;
  104.                 break;
  105.             }
  106.         }
  107.         if (opcode == -1) {
  108.             throw new IllegalArgumentException("The specified event is not registered " + event);
  109.         }
  110.         output.writeByte(opcode);
  111.         for (final Field field : event.getClass().getDeclaredFields()) {
  112.             field.setAccessible(true);
  113.             modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
  114.            
  115.             final Class<?> type = field.getType();
  116.             if (type == byte.class) {
  117.                 output.write(field.getByte(event));
  118.             } else if (type == short.class) {
  119.                 output.writeShort(field.getShort(event));
  120.             } else if (type == int.class) {
  121.                 output.writeInt(field.getInt(event));
  122.             } else if (type == long.class) {
  123.                 output.writeLong(field.getLong(event));
  124.             } else if (type == float.class) {
  125.                 output.writeFloat(field.getFloat(event));
  126.             } else if (type == double.class) {
  127.                 output.writeDouble(field.getDouble(event));
  128.             } else if (type == boolean.class) {
  129.                 output.writeBoolean(field.getBoolean(event));
  130.             } else if (type == char.class) {
  131.                 output.writeChar(field.getChar(event));
  132.             } else if (type == String.class) {
  133.                 output.writeUTF((String) field.get(event));
  134.             } else {
  135.                 throw new IllegalStateException("The type " + type + " is not handled");
  136.             }
  137.         }
  138.         output.flush();
  139.     }
  140.  
  141.     /**
  142.      * Reads an event from the input stream and passes it to its event handler.
  143.      * @throws Exception If an exception is thrown.
  144.      */
  145.     public void readEvent() throws Exception {
  146.         final int opcode = input.readByte();
  147.         Event event = null;
  148.         EventHandler<Event> eventHandler = null;
  149.         try {
  150.             event = (Event) events[opcode].newInstance();
  151.             eventHandler = eventHandlers[opcode];
  152.         } catch (final Exception e) {
  153.             throw new IllegalStateException("Read opcode " + opcode + " but no event registered to it", e);
  154.         }
  155.         for (final Field field : event.getClass().getDeclaredFields()) {
  156.             field.setAccessible(true);
  157.             modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
  158.            
  159.             final Class<?> type = field.getType();
  160.             if (type == byte.class) {
  161.                 field.setByte(event, input.readByte());
  162.             } else if (type == short.class) {
  163.                 field.setShort(event, input.readShort());
  164.             } else if (type == int.class) {
  165.                 field.setInt(event, input.readInt());
  166.             } else if (type == long.class) {
  167.                 field.setLong(event, input.readLong());
  168.             } else if (type == float.class) {
  169.                 field.setFloat(event, input.readFloat());
  170.             } else if (type == double.class) {
  171.                 field.setDouble(event, input.readDouble());
  172.             } else if (type == boolean.class) {
  173.                 field.setBoolean(event, input.readBoolean());
  174.             } else if (type == char.class) {
  175.                 field.setChar(event, input.readChar());
  176.             } else if (type == String.class) {
  177.                 field.set(event, input.readUTF());
  178.             } else {
  179.                 throw new IllegalStateException("The type " + type + " is not handled");
  180.             }
  181.         }
  182.         eventHandler.handleEvent(event);
  183.     }
  184. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement