com.l2jfree.network.mmocore.packethandlers.PacketDefinition.java Source code

Java tutorial

Introduction

Here is the source code for com.l2jfree.network.mmocore.packethandlers.PacketDefinition.java

Source

/*
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU 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 General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 */
package com.l2jfree.network.mmocore.packethandlers;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.ArrayUtils;

import com.l2jfree.network.mmocore.MMOConnection;
import com.l2jfree.network.mmocore.ReceivablePacket;
import com.l2jfree.network.mmocore.SendablePacket;
import com.l2jfree.util.HexUtil;
import com.l2jfree.util.jar.ClassFinder;

/**
 * @author NB4L1
 * @param <T>
 * @param <RP>
 * @param <SP>
 * @param <S>
 */
public class PacketDefinition<T extends MMOConnection<T, RP, SP>, RP extends ReceivablePacket<T, RP, SP>, SP extends SendablePacket<T, RP, SP>, S extends Enum<S>> {
    public static List<Class<?>> findClasses(String packageName) throws Exception {
        final List<Class<?>> classes = new ArrayList<Class<?>>();

        for (Class<?> c : ClassFinder.findClasses(packageName))
            if (isInstanceable(c))
                classes.add(c);

        return classes;
    }

    public static List<Class<?>> findClasses(Class<?> clazz) {
        while (clazz.getEnclosingClass() != null)
            clazz = clazz.getEnclosingClass();

        final List<Class<?>> classes = new ArrayList<Class<?>>();

        classes.add(clazz);

        for (int i = 0; i < classes.size(); i++)
            for (Class<?> c : classes.get(i).getDeclaredClasses())
                if (!classes.contains(c))
                    if (isInstanceable(c))
                        classes.add(c);

        return classes;
    }

    public static boolean isInstanceable(Class<?> clazz) {
        try {
            findConstructor(clazz);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public static <T> Constructor<T> findConstructor(Class<T> clazz) throws Exception {
        // easier than checking all the modifiers, visibility, type, etc :)
        final Constructor<T> constructor = clazz.getConstructor();

        // try to instance, and return the constructor only on success
        constructor.newInstance();

        return constructor;
    }

    public static Integer findOpcode(Class<?> clazz, String fieldName, boolean required) throws Exception {
        // easier than checking all the modifiers, visibility, type, etc :)
        final Field field;
        try {
            field = clazz.getField(fieldName);
        } catch (NoSuchFieldException e) {
            if (required) {
                System.err.println("Missing 'public static final int " + fieldName + "'!");
                throw e;
            } else
                return null; // ignore as it was expected
        }

        return field.getInt(null);
    }

    @SuppressWarnings("unchecked")
    public static <S> S[] findStates(Class<?> clazz, S... defaultStates) throws Exception {
        // easier than checking all the modifiers, visibility, type, etc :)
        final Field field;
        try {
            field = clazz.getField("STATES");
        } catch (NoSuchFieldException e) {
            return defaultStates;
        }

        return (S[]) field.get(null);
    }

    public static String toString(int... opcodes) {
        final StringBuilder sb = new StringBuilder();

        sb.append("[");
        for (int i = 0; i < opcodes.length; i++) {
            if (i != 0)
                sb.append(":");
            sb.append(" 0x").append(HexUtil.fillHex(opcodes[i], 2)).append(" ");
        }
        sb.append("]");

        return sb.toString();
    }

    private final Class<? extends RP> _clazz;
    private final Constructor<? extends RP> _constructor;
    private final int[] _opcodes;
    private final S[] _states;

    public PacketDefinition(Class<? extends RP> clazz, S... defaultStates) throws Exception {
        _clazz = clazz;
        _constructor = findConstructor(clazz);

        final List<Integer> opcodes = new ArrayList<Integer>();

        opcodes.add(findOpcode(clazz, "OPCODE", true));

        for (int i = 2;; i++) {
            final Integer opcode = findOpcode(clazz, "OPCODE_" + i, false);
            if (opcode != null)
                opcodes.add(opcode);
            else
                break; // break as it was expected
        }

        _opcodes = ArrayUtils.toPrimitive(opcodes.toArray(new Integer[opcodes.size()]));
        _states = findStates(clazz, defaultStates);

        System.out.println(toString());
    }

    @Override
    public String toString() {
        return toString(getOpcodes()) + " " + getClassName();
    }

    public String getClassName() {
        return _clazz.getCanonicalName().replace(_clazz.getPackage().getName() + ".", "");
    }

    public Constructor<? extends RP> getConstructor() {
        return _constructor;
    }

    public int[] getOpcodes() {
        return _opcodes;
    }

    public S[] getStates() {
        return _states;
    }

    public RP newInstance() {
        try {
            return _constructor.newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}