Ranides Atterwim 10 gadi atpakaļ
vecāks
revīzija
9c3f5b8b7d

+ 142 - 142
assira1/src/main/java/net/ranides/assira/generic/Serializer.java

@@ -1,142 +1,142 @@
-/*
- * @author Ranides Atterwim <ranides@gmail.com>
- * @copyright Ranides Atterwim
- * @license WTFPL
- * @url http://ranides.net/projects/assira
- */
-package net.ranides.assira.generic;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.Serializable;
-import java.util.List;
-import net.ranides.assira.io.FileHelper;
-import net.ranides.assira.reflection.util.ObjectUtils;
-
-/**
- *
- * @author ranides
- * @todo (migration) assira
- */
-public final class Serializer {
-
-    private Serializer() {
-        // utility class
-    }
-
-    /**
-     * "Klonuje" obiekt serializując i deserializując go.
-     * @param <T>
-     * @param value
-     * @return
-     * @throws IOException
-     */
-    @SuppressWarnings("unchecked")
-    public static <T> T copy(T value) throws IOException {
-        return read( (Class<T>)value.getClass(), write(value));
-    }
-
-    public static byte[] write(Object value) throws IOException {
-        ByteArrayOutputStream orstream = new ByteArrayOutputStream();
-        ObjectOutputStream ostream = null;
-        try {
-            ostream = new ObjectOutputStream(orstream);
-            ostream.writeObject(value);
-            return orstream.toByteArray();
-        } finally {
-            FileHelper.close(ostream);
-        }
-    }
-
-    public static <T> T read(Class<T> clazz, byte[] data) throws IOException {
-        try {
-            ByteArrayInputStream irstream = new ByteArrayInputStream(data);
-            ObjectInputStream istream = new ObjectInputStream(irstream);
-            return clazz.cast(istream.readObject());
-        } catch(ClassNotFoundException cause) {
-            throw new AssertionError(cause);
-        }
-    }
-    
-    public static Object proxy(Object that, Object... params) {
-        return new Proxy(that, params);
-    }
-
-    public static SizeInfo sizeof(List<?> list) throws IOException {
-        ByteArrayOutputStream orstream = new ByteArrayOutputStream();
-        ObjectOutputStream ostream = null;
-        int h1 = list.size() / 2;
-        int h2 = list.size();
-        int s1 = 0, s2 = 0;
-        try {
-            ostream = new ObjectOutputStream(orstream);
-            for(int i=0; i<h1; i++) {
-                ostream.writeObject(list.get(i));
-            }
-            s1 = orstream.size();
-            for(int i=h1; i<h2; i++) {
-                ostream.writeObject(list.get(i));
-            }
-            s2 = orstream.size();
-        } finally {
-            FileHelper.close(ostream);
-            FileHelper.close(orstream);
-        }
-        int self = (s2-s1) / (h2-h1);
-        int attached = s1 - h1*self;
-        return new SizeInfo(s2, self, attached);
-    }
-
-    public static class SizeInfo {
-        private final int sum;
-        private final int self;
-        private final int attached;
-
-        public SizeInfo(int sum, int self, int attached) {
-            this.sum = sum;
-            this.self = self;
-            this.attached = attached;
-        }
-
-        public int sum() {
-            return sum;
-        }
-
-        public int self() {
-            return self;
-        }
-
-        public int attached() {
-            return attached;
-        }
-
-        @Override
-        public String toString() {
-            return String.format("sizeof = { sum : %d, self : %d, attached : %d }", sum, self, attached);
-        }
-
-    }
-    
-    @SuppressWarnings("PMD")
-    private static class Proxy implements Serializable {
-
-        private static final long serialVersionUID = 4L;
-
-        private final Class<?> clazz;
-        private final Object[] params;
-
-        public Proxy(Object that, Object... params) {
-            this.clazz = that.getClass();
-            this.params = params;
-        }
-
-        private Object readResolve() {
-            return ObjectUtils.create(clazz, params);
-        }
-
-    }
-
-}
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+package net.ranides.assira.generic;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.List;
+import net.ranides.assira.io.FileHelper;
+import net.ranides.assira.reflection.util.ObjectUtils;
+
+/**
+ *
+ * @author ranides
+ */
+public final class Serializer {
+
+    private Serializer() {
+        // utility class
+    }
+
+    /**
+     * "Klonuje" obiekt serializując i deserializując go.
+     * @param <T>
+     * @param value
+     * @return
+     * @throws IOException
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T copy(T value) throws IOException {
+        return read( (Class<T>)value.getClass(), write(value));
+    }
+
+    public static byte[] write(Object value) throws IOException {
+        ByteArrayOutputStream orstream = new ByteArrayOutputStream();
+        ObjectOutputStream ostream = null;
+        try {
+            ostream = new ObjectOutputStream(orstream);
+            ostream.writeObject(value);
+            return orstream.toByteArray();
+        } finally {
+            FileHelper.close(ostream);
+        }
+    }
+
+    public static <T> T read(Class<T> clazz, byte[] data) throws IOException {
+        try {
+            ByteArrayInputStream irstream = new ByteArrayInputStream(data);
+            ObjectInputStream istream = new ObjectInputStream(irstream);
+            return clazz.cast(istream.readObject());
+        } catch(ClassNotFoundException cause) {
+            throw new AssertionError(cause);
+        }
+    }
+    
+    public static Object proxy(Object that, Object... params) {
+        return new Proxy(that, params);
+    }
+
+    public static SizeInfo sizeof(List<?> list) throws IOException {
+        ByteArrayOutputStream orstream = new ByteArrayOutputStream();
+        ObjectOutputStream ostream = null;
+        int h1 = list.size() / 2;
+        int h2 = list.size();
+        int s1 = 0, s2 = 0;
+        try {
+            ostream = new ObjectOutputStream(orstream);
+            for(int i=0; i<h1; i++) {
+                ostream.writeObject(list.get(i));
+            }
+            s1 = orstream.size();
+            for(int i=h1; i<h2; i++) {
+                ostream.writeObject(list.get(i));
+            }
+            s2 = orstream.size();
+        } finally {
+            FileHelper.close(ostream);
+            FileHelper.close(orstream);
+        }
+        int self = (s2-s1) / (h2-h1);
+        int attached = s1 - h1*self;
+        return new SizeInfo(s2, self, attached);
+    }
+
+    public static class SizeInfo {
+        private final int sum;
+        private final int self;
+        private final int attached;
+
+        public SizeInfo(int sum, int self, int attached) {
+            this.sum = sum;
+            this.self = self;
+            this.attached = attached;
+        }
+
+        public int sum() {
+            return sum;
+        }
+
+        public int self() {
+            return self;
+        }
+
+        public int attached() {
+            return attached;
+        }
+
+        @Override
+        public String toString() {
+            return String.format("sizeof = { sum : %d, self : %d, attached : %d }", sum, self, attached);
+        }
+
+    }
+    
+    @SuppressWarnings("PMD")
+    private static class Proxy implements Serializable {
+
+        private static final long serialVersionUID = 4L;
+
+        private final Class<?> clazz;
+        private final Object[] params;
+
+        public Proxy(Object that, Object... params) {
+            this.clazz = that.getClass();
+            this.params = params;
+        }
+
+        private Object readResolve() {
+            // @todo (migration) assira Serializer.Proxy
+            return ObjectUtils.create(clazz, params);
+        }
+
+    }
+
+}

+ 99 - 99
assira1/src/main/java/net/ranides/assira/generic/Wrapper.java

@@ -1,99 +1,99 @@
-/*
- * @author Ranides Atterwim <ranides@gmail.com>
- * @copyright Ranides Atterwim
- * @license WTFPL
- * @url http://ranides.net/projects/assira
- */
-package net.ranides.assira.generic;
-
-import java.io.Serializable;
-import net.ranides.assira.reflection.GenericClass;
-import net.ranides.assira.text.LexicalCast;
-
-/**
- * Wrapper na referencję obiektu. Jedno z nielicznych zastosowań (zresztą dość
- * nieeleganckie) to przekazywanie wrappera jako argument funkcji, która za jego
- * pomocą zwraca wynik.
- * <p>
- * Sygnalizowanie wyników za pomocą zmian stanu argumentów przekazanych funkcji
- * nie jest dobrą praktyką, ale czasem (rzadko) upraszcza API.
- * </p>
- * @param <T>
- * @author ranides
- * @todo (migration) assira
- */
-public abstract class Wrapper<T> {
-    
-    public static <Q> Wrapper<Q> make() {
-        return new CWrapper<>(null);
-    }
-    
-    public static <Q> Wrapper<Q> make(Q value) {
-        return new CWrapper<>(value);
-    }
-
-    /**
-     * Returns value of referenced object
-     * @return
-     */
-    public abstract T get();
-
-    /**
-     * Change value of referenced object
-     * @param value
-     */
-    public abstract void set(T value);
-    
-    /**
-     * Changes value, automatically casting passed argument, if necessary
-     * @param value 
-     */
-    public abstract void put(Object value);
-
-    /**
-     * Returns type of referenced object. Implementations <i>should</i> do as much as possible
-     * to return most informative result. For example, it is allowed to merge 
-     * current runtime class (erasure) with generic parameters extracted
-     * from declaration.
-     * <p>
-     * Please note that it isn't guaranteed in any way, that return value will
-     * represent most concrete class of stored value. For example, it <i>could</i>
-     * be {@code TypeToken&lt;T&gt;} but in extremal cases, it is allowed to return
-     * even {@code Object.class}.
-     * </p>
-     * @return 
-     */
-    public abstract GenericClass type();
-
-    private static class CWrapper<Q> extends Wrapper<Q> implements Serializable {
-        
-        private static final long serialVersionUID = 3L;
-        
-        private Q value;
-
-        public CWrapper(Q value) {
-            this.value = value;
-        }
-
-        @Override
-        public Q get() {
-            return value;
-        }
-
-        @Override
-        public void set(Q value) {
-            this.value = value;
-        }
-
-        @Override
-        public void put(Object value) {
-            this.value = LexicalCast.cast(value, type());
-        }
-
-        @Override
-        public GenericClass type() {
-            return new TypeToken<Q>(){};
-        }
-        
-    }
-}
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+package net.ranides.assira.generic;
+
+import java.io.Serializable;
+import net.ranides.assira.reflection.GenericClass;
+import net.ranides.assira.text.LexicalCast;
+
+/**
+ * Wrapper na referencję obiektu. Jedno z nielicznych zastosowań (zresztą dość
+ * nieeleganckie) to przekazywanie wrappera jako argument funkcji, która za jego
+ * pomocą zwraca wynik.
+ * <p>
+ * Sygnalizowanie wyników za pomocą zmian stanu argumentów przekazanych funkcji
+ * nie jest dobrą praktyką, ale czasem (rzadko) upraszcza API.
+ * </p>
+ * @param <T>
+ * @author ranides
+ */
+public abstract class Wrapper<T> {
+    
+    public static <Q> Wrapper<Q> make() {
+        return new CWrapper<>(null);
+    }
+    
+    public static <Q> Wrapper<Q> make(Q value) {
+        return new CWrapper<>(value);
+    }
+
+    /**
+     * Returns value of referenced object
+     * @return
+     */
+    public abstract T get();
+
+    /**
+     * Change value of referenced object
+     * @param value
+     */
+    public abstract void set(T value);
+    
+    /**
+     * Changes value, automatically casting passed argument, if necessary
+     * @param value 
+     */
+    public abstract void put(Object value);
+
+    /**
+     * Returns type of referenced object. Implementations <i>should</i> do as much as possible
+     * to return most informative result. For example, it is allowed to merge 
+     * current runtime class (erasure) with generic parameters extracted
+     * from declaration.
+     * <p>
+     * Please note that it isn't guaranteed in any way, that return value will
+     * represent most concrete class of stored value. For example, it <i>could</i>
+     * be {@code TypeToken&lt;T&gt;} but in extremal cases, it is allowed to return
+     * even {@code Object.class}.
+     * </p>
+     * @return 
+     * @todo (migration) GenericClass#type
+     */
+    public abstract GenericClass type();
+
+    private static class CWrapper<Q> extends Wrapper<Q> implements Serializable {
+        
+        private static final long serialVersionUID = 3L;
+        
+        private Q value;
+
+        public CWrapper(Q value) {
+            this.value = value;
+        }
+
+        @Override
+        public Q get() {
+            return value;
+        }
+
+        @Override
+        public void set(Q value) {
+            this.value = value;
+        }
+
+        @Override
+        public void put(Object value) {
+            this.value = LexicalCast.cast(value, type());
+        }
+
+        @Override
+        public GenericClass type() {
+            return new TypeToken<Q>(){};
+        }
+        
+    }
+}

+ 132 - 133
assira1/src/main/java/net/ranides/assira/reflection/util/MemberUtils.java

@@ -1,133 +1,132 @@
-/*
- *  @author Ranides Atterwim <ranides@gmail.com>
- *  @copyright Ranides Atterwim
- *  @license WTFPL
- *  @url http://ranides.net/projects/assira
- */
-
-package net.ranides.assira.reflection.util;
-
-import java.lang.reflect.Member;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-
-/**
- *
- * @author ranides
- * @todo (migration) assira (reflection)
- */
-public final class MemberUtils {
-    
-    
-    private MemberUtils() { /* utility class */ }
-    
-    public static boolean isVolatile(Member member) {
-        return Modifier.isVolatile(member.getModifiers());
-    }
-
-    public static boolean isTransient(Member member) {
-        return Modifier.isTransient(member.getModifiers());
-    }
-
-    public static boolean isSynchronized(Member member) {
-        return Modifier.isSynchronized(member.getModifiers());
-    }
-
-    public static boolean isStrict(Member member) {
-        return Modifier.isStrict(member.getModifiers());
-    }
-
-    public static boolean isStatic(Member member) {
-        return Modifier.isStatic(member.getModifiers());
-    }
-
-    public static boolean isPublic(Member member) {
-        return Modifier.isPublic(member.getModifiers());
-    }
-
-    public static boolean isProtected(Member member) {
-        return Modifier.isProtected(member.getModifiers());
-    }
-
-    public static boolean isPrivate(Member member) {
-        return Modifier.isPrivate(member.getModifiers());
-    }
-
-    public static boolean isNative(Member member) {
-        return Modifier.isNative(member.getModifiers());
-    }
-
-    public static boolean isInterface(Member member) {
-        return Modifier.isInterface(member.getModifiers());
-    }
-
-    public static boolean isFinal(Member member) {
-        return Modifier.isFinal(member.getModifiers());
-    }
-
-    public static boolean isAbstract(Member member) {
-        return Modifier.isAbstract(member.getModifiers());
-    }
-    
-    /**
-     * Sprawdza czy podana metoda może być traktowana jako getter 
-     * (np {@code getValue}). Akceptuje gettery o nazwie w formie {@code isEnabled}, 
-     * o ile zwracają typ {@code bool} .
-     * @param text
-     * @return
-     */
-    @SuppressWarnings("PMD")
-    public static boolean isGetter(Method method) {
-        final Class<?> ctype = method.getDeclaringClass();
-        final Class<?> rtype = method.getReturnType();
-        
-        // eliminacja na podstawie deklaracji
-        if(Object.class.equals(ctype)) {
-            return false;
-        }
-        if(method.getParameterTypes().length != 0) {
-            return false;
-        }
-        if(Void.class.equals(rtype) || void.class.equals(rtype)) {
-            return false;
-        }
-        String name = method.getName();
-        // akceptacja klasycznego gettera
-        if(name.startsWith("get") && name.length()>3 && Character.isUpperCase(name.charAt(3)) ) {
-            return true;
-        }
-        // akceptacja gettera logicznego "isValue"
-        if(name.startsWith("is") && name.length()>2 && Character.isUpperCase(name.charAt(2)) && ClassTraits.isBool(rtype) ) {
-            return true;
-        }
-        return false;
-    }
-    
-    /**
-     * Sprawdza czy podana metoda może być traktowana jako setter.
-     * @param text
-     * @return
-     */
-    public static boolean isSetter(Method method) {
-        final Class<?> ctype = method.getDeclaringClass();
-        final Class<?> rtype = method.getReturnType();
-        
-        // eliminacja na podstawie deklaracji
-        if(Object.class.equals(ctype)) {
-            return false;
-        }
-        if(method.getParameterTypes().length != 1) {
-            return false;
-        }
-        if(!Void.class.equals(rtype) && !void.class.equals(rtype) && !ctype.equals(rtype)) {
-            return false;
-        }
-        String name = method.getName();
-        // akceptacja klasycznego settera
-        if(name.startsWith("set") && name.length()>3 && Character.isUpperCase(name.charAt(3)) ) {
-            return true;
-        }
-        return false;
-    }
-    
-}
+/*
+ *  @author Ranides Atterwim <ranides@gmail.com>
+ *  @copyright Ranides Atterwim
+ *  @license WTFPL
+ *  @url http://ranides.net/projects/assira
+ */
+
+package net.ranides.assira.reflection.util;
+
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+/**
+ *
+ * @author ranides
+ */
+public final class MemberUtils {
+    
+    
+    private MemberUtils() { /* utility class */ }
+    
+    public static boolean isVolatile(Member member) {
+        return Modifier.isVolatile(member.getModifiers());
+    }
+
+    public static boolean isTransient(Member member) {
+        return Modifier.isTransient(member.getModifiers());
+    }
+
+    public static boolean isSynchronized(Member member) {
+        return Modifier.isSynchronized(member.getModifiers());
+    }
+
+    public static boolean isStrict(Member member) {
+        return Modifier.isStrict(member.getModifiers());
+    }
+
+    public static boolean isStatic(Member member) {
+        return Modifier.isStatic(member.getModifiers());
+    }
+
+    public static boolean isPublic(Member member) {
+        return Modifier.isPublic(member.getModifiers());
+    }
+
+    public static boolean isProtected(Member member) {
+        return Modifier.isProtected(member.getModifiers());
+    }
+
+    public static boolean isPrivate(Member member) {
+        return Modifier.isPrivate(member.getModifiers());
+    }
+
+    public static boolean isNative(Member member) {
+        return Modifier.isNative(member.getModifiers());
+    }
+
+    public static boolean isInterface(Member member) {
+        return Modifier.isInterface(member.getModifiers());
+    }
+
+    public static boolean isFinal(Member member) {
+        return Modifier.isFinal(member.getModifiers());
+    }
+
+    public static boolean isAbstract(Member member) {
+        return Modifier.isAbstract(member.getModifiers());
+    }
+    
+    /**
+     * Sprawdza czy podana metoda może być traktowana jako getter 
+     * (np {@code getValue}). Akceptuje gettery o nazwie w formie {@code isEnabled}, 
+     * o ile zwracają typ {@code bool} .
+     * @param text
+     * @return
+     */
+    @SuppressWarnings("PMD")
+    public static boolean isGetter(Method method) {
+        final Class<?> ctype = method.getDeclaringClass();
+        final Class<?> rtype = method.getReturnType();
+        
+        // eliminacja na podstawie deklaracji
+        if(Object.class.equals(ctype)) {
+            return false;
+        }
+        if(method.getParameterTypes().length != 0) {
+            return false;
+        }
+        if(Void.class.equals(rtype) || void.class.equals(rtype)) {
+            return false;
+        }
+        String name = method.getName();
+        // akceptacja klasycznego gettera
+        if(name.startsWith("get") && name.length()>3 && Character.isUpperCase(name.charAt(3)) ) {
+            return true;
+        }
+        // akceptacja gettera logicznego "isValue"
+        if(name.startsWith("is") && name.length()>2 && Character.isUpperCase(name.charAt(2)) && ClassTraits.isBool(rtype) ) {
+            return true;
+        }
+        return false;
+    }
+    
+    /**
+     * Sprawdza czy podana metoda może być traktowana jako setter.
+     * @param text
+     * @return
+     */
+    public static boolean isSetter(Method method) {
+        final Class<?> ctype = method.getDeclaringClass();
+        final Class<?> rtype = method.getReturnType();
+        
+        // eliminacja na podstawie deklaracji
+        if(Object.class.equals(ctype)) {
+            return false;
+        }
+        if(method.getParameterTypes().length != 1) {
+            return false;
+        }
+        if(!Void.class.equals(rtype) && !void.class.equals(rtype) && !ctype.equals(rtype)) {
+            return false;
+        }
+        String name = method.getName();
+        // akceptacja klasycznego settera
+        if(name.startsWith("set") && name.length()>3 && Character.isUpperCase(name.charAt(3)) ) {
+            return true;
+        }
+        return false;
+    }
+    
+}

+ 99 - 98
assira1/src/main/java/net/ranides/assira/reflection/util/MethodUtils.java

@@ -1,98 +1,99 @@
-/*
- * @author Ranides Atterwim <ranides@gmail.com>
- * @copyright Ranides Atterwim
- * @license WTFPL
- * @url http://ranides.net/projects/assira
- */
-package net.ranides.assira.reflection.util;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.Arrays;
-import java.util.List;
-import net.ranides.assira.asm.MethodInspectorVM;
-import net.ranides.assira.reflection.GenericClass;
-import net.ranides.assira.reflection.InspectException;
-import net.ranides.assira.reflection.InvokeException;
-import net.ranides.assira.reflection.GenericParam;
-import static net.ranides.assira.reflection.util.ReflectUtils.access;
-
-/**
- *
- * @author Ranides Atterwim <ranides@gmail.com>
- * @todo (migration) assira (reflection)
- */
-public final class MethodUtils {
-    
-    private MethodUtils() {
-        // utility class
-    }
-
-    /**
-     * Ustala typ zwracany przez przekazaną metodę. W przeciwieństwie do
-     * Reflection API, obsługuje również typy generyczne, wykrywając generic parameters.
-     * @param method
-     * @return
-     */
-    public static GenericClass typeof(Method method) {
-        return MethodInspectorVM.typeof(method);
-    }
-
-    /**
-     * Zwraca listę argumentów pobieranych przez metodę. Reflection API pozwala
-     * jedynie ustalić typy argumentów, bez nazw. Nie wspiera również typów generycznych.
-     * Poniższa metoda umożliwia ustalenie zarówno nazw, jak i parametrów typów
-     * generycznych.
-     * @param method
-     * @return
-     */
-    public static List<GenericParam> params(Method method) {
-        return MethodInspectorVM.params(method);
-    }
-    
-    /**
-     * Sprawdza, czy podana metoda jest nadpisana przez metodę (override). Cały dowcip
-     * to obsługa metod package-scope, które może przeładować klasa z tego samego
-     * pakietu, a z innego nie.
-     * @param candidate 
-     * @param original 
-     * @return 
-     */
-    public static boolean overrides(Method candidate, Method original) {
-        if( !original.getName().equals(candidate.getName()) ) {
-            return false;
-        }
-        if( MemberUtils.isPrivate(original) ) {
-            return false;
-        }
-        // package scope check
-        if( !MemberUtils.isPublic(original) && !MemberUtils.isProtected(original)) {
-            Package opackage = original.getDeclaringClass().getPackage();
-            Package cpackage = candidate.getDeclaringClass().getPackage();
-            if( !opackage.equals(cpackage) ) {
-                return false;
-            }
-        }
-        return Arrays.equals(original.getParameterTypes(), candidate.getParameterTypes());
-    }
-    
-    /**
-     * Wywołuje na rzecz obiektu podaną metodę. 
-     * @param object
-     * @param method
-     * @param arguments
-     * @return
-     * @throws InspectException
-     */
-    public static Object invoke(Object object, Method method, Object... arguments) throws InspectException, InvokeException {
-        assert object != null || MemberUtils.isStatic(method);
-        try {
-            return access(method).invoke(object, arguments);
-        } catch (IllegalAccessException | IllegalArgumentException ex) {
-            throw new InspectException(ex);
-        } catch (InvocationTargetException ex) {
-            throw new InvokeException(ex);
-        }
-    }
-    
-}
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+package net.ranides.assira.reflection.util;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.List;
+import net.ranides.assira.asm.MethodInspectorVM;
+import net.ranides.assira.reflection.GenericClass;
+import net.ranides.assira.reflection.InspectException;
+import net.ranides.assira.reflection.InvokeException;
+import net.ranides.assira.reflection.GenericParam;
+import static net.ranides.assira.reflection.util.ReflectUtils.access;
+
+/**
+ *
+ * @author Ranides Atterwim <ranides@gmail.com>
+ */
+public final class MethodUtils {
+    
+    private MethodUtils() {
+        // utility class
+    }
+
+    /**
+     * Ustala typ zwracany przez przekazaną metodę. W przeciwieństwie do
+     * Reflection API, obsługuje również typy generyczne, wykrywając generic parameters.
+     * @param method
+     * @return
+     * @todo (migration) assira (reflection) MethodUtils#typef
+     */
+    public static GenericClass typeof(Method method) {
+        return MethodInspectorVM.typeof(method);
+    }
+
+    /**
+     * Zwraca listę argumentów pobieranych przez metodę. Reflection API pozwala
+     * jedynie ustalić typy argumentów, bez nazw. Nie wspiera również typów generycznych.
+     * Poniższa metoda umożliwia ustalenie zarówno nazw, jak i parametrów typów
+     * generycznych.
+     * @param method
+     * @return
+     * @todo (migration) assira (reflection) MethodUtils#params
+     */
+    public static List<GenericParam> params(Method method) {
+        return MethodInspectorVM.params(method);
+    }
+    
+    /**
+     * Sprawdza, czy podana metoda jest nadpisana przez metodę (override). Cały dowcip
+     * to obsługa metod package-scope, które może przeładować klasa z tego samego
+     * pakietu, a z innego nie.
+     * @param candidate 
+     * @param original 
+     * @return 
+     */
+    public static boolean overrides(Method candidate, Method original) {
+        if( !original.getName().equals(candidate.getName()) ) {
+            return false;
+        }
+        if( MemberUtils.isPrivate(original) ) {
+            return false;
+        }
+        // package scope check
+        if( !MemberUtils.isPublic(original) && !MemberUtils.isProtected(original)) {
+            Package opackage = original.getDeclaringClass().getPackage();
+            Package cpackage = candidate.getDeclaringClass().getPackage();
+            if( !opackage.equals(cpackage) ) {
+                return false;
+            }
+        }
+        return Arrays.equals(original.getParameterTypes(), candidate.getParameterTypes());
+    }
+    
+    /**
+     * Wywołuje na rzecz obiektu podaną metodę. 
+     * @param object
+     * @param method
+     * @param arguments
+     * @return
+     * @throws InspectException
+     */
+    public static Object invoke(Object object, Method method, Object... arguments) throws InspectException, InvokeException {
+        assert object != null || MemberUtils.isStatic(method);
+        try {
+            return access(method).invoke(object, arguments);
+        } catch (IllegalAccessException | IllegalArgumentException ex) {
+            throw new InspectException(ex);
+        } catch (InvocationTargetException ex) {
+            throw new InvokeException(ex);
+        }
+    }
+    
+}

+ 105 - 106
assira1/src/main/java/net/ranides/assira/reflection/util/ReflectUtils.java

@@ -1,106 +1,105 @@
-/*
- * @author Ranides Atterwim <ranides@gmail.com>
- * @copyright Ranides Atterwim
- * @license WTFPL
- * @url http://ranides.net/projects/assira
- */
-package net.ranides.assira.reflection.util;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.reflect.AccessibleObject;
-import net.ranides.assira.text.StringLoader;
-
-/**
- *
- * @author ranides
- * @todo (migration) assira (reflection)
- */
-public final class ReflectUtils {
-    
-    private ReflectUtils() { /* utility class */ }
-    
-    /**
-     * Próbuje wymusić prawa dostępu do podanego obiektu uzyskanego za pomocą refleksji
-     * (np zyskać uprawnienia do wywołania prywatnej metody, albo odczytu prywatnego pola).
-     * @param <T>
-     * @param object
-     * @return
-     */
-    public static <T extends AccessibleObject> T access(T object) {
-        if( !object.isAccessible() ) { object.setAccessible(true); }
-        return object;
-    }
-    
-    /**
-     * Zwraca zawartość pliku źródłowego, w którym zapisana jest podana klasa. 
-     * Oczywiście, to nie działa idealnie dla klas, które nie mają pliku źródłowego
-     * w sensie stricte. Dla klas zagnieżdżonych albo anonimowych zwracana 
-     * jest cała zawartość, w którym je zapisano, a nie tylko fragment. 
-     * <p>
-     * Kod źródłowy musi być dostępny dla ClassLoadera powiązanego z bieżącym wątkiem.
-     * </p>
-     * 
-     * @param classname
-     * @return 
-     */
-    public static String getSource(String classname) {
-        return readSourceCode(Thread.currentThread().getContextClassLoader(), classname);
-    }
-    
-    /**
-     * Zwraca zawartość pliku źródłowego, w którym zapisana jest podana klasa. 
-     * Oczywiście, to nie działa idealnie dla klas, które nie mają pliku źródłowego
-     * w sensie stricte. Dla klas zagnieżdżonych albo anonimowych zwracana 
-     * jest cała zawartość, w którym je zapisano, a nie tylko fragment. 
-     * <p>
-     * Kod źródłowy musi być dostępny dla classloadera, który załadował klasę.
-     * </p>
-     * @param clazz
-     * @return 
-     */
-    public static String getSource(Class<?> clazz) {
-        return readSourceCode(clazz.getClassLoader(), clazz.getName());
-    }
-    
-    private static String readSourceCode(ClassLoader loader, String classname) {
-        String file = classname.replace('.', '/').replaceAll("\\$.+", "") + ".java";
-        InputStream istream = loader.getResourceAsStream(file);
-        if(istream != null) {
-            return StringLoader.fromStream(istream);
-        }
-        if(new File(file).exists() ) {
-            return StringLoader.fromFile(file);
-        }
-        if(new File("src/test/java/" + file).exists() ) {
-            return StringLoader.fromFile("src/test/java/" + file);
-        }
-        if(new File("src/test/main/" + file).exists() ) {
-            return StringLoader.fromFile("src/test/main/" + file);
-        }
-        throw new AssertionError(new IOException("unknown location of file: " + file));
-    }
-    
-    /**
-     * Zwraca lokalizację, w której został wyszukany odpowiedni plik .class z
-     * definicją załadowanej klasy. Lokalizacja nie wskazuje na  konkretny
-     * plik .class, aby uzyskać pełną ścieżkę, należy uzyć metody {@link #getFQLocation}
-     * @param clazz
-     * @return
-     */
-    public static String getLocation(Class<?> clazz) {
-        return clazz.getProtectionDomain().getCodeSource().getLocation().getFile();
-    }
-    
-    /**
-     * Zwraca ścieżkę do pliku .class, z którego została załadowana klasa. Aby
-     * uzyskać lokalizację, w której rozpoczęto wyszukiwanie pliku .class, należy
-     * użyć metody {@link #getLocation}
-     * @param clazz
-     * @return
-     */
-    public static String getFQLocation(Class<?> clazz) {
-        return clazz.getClassLoader().getResource( clazz.getName().replace('.', '/') + ".class" ).getFile();
-    }
-}
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+package net.ranides.assira.reflection.util;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.AccessibleObject;
+import net.ranides.assira.text.StringLoader;
+
+/**
+ *
+ * @author ranides
+ */
+public final class ReflectUtils {
+    
+    private ReflectUtils() { /* utility class */ }
+    
+    /**
+     * Próbuje wymusić prawa dostępu do podanego obiektu uzyskanego za pomocą refleksji
+     * (np zyskać uprawnienia do wywołania prywatnej metody, albo odczytu prywatnego pola).
+     * @param <T>
+     * @param object
+     * @return
+     */
+    public static <T extends AccessibleObject> T access(T object) {
+        if( !object.isAccessible() ) { object.setAccessible(true); }
+        return object;
+    }
+    
+    /**
+     * Zwraca zawartość pliku źródłowego, w którym zapisana jest podana klasa. 
+     * Oczywiście, to nie działa idealnie dla klas, które nie mają pliku źródłowego
+     * w sensie stricte. Dla klas zagnieżdżonych albo anonimowych zwracana 
+     * jest cała zawartość, w którym je zapisano, a nie tylko fragment. 
+     * <p>
+     * Kod źródłowy musi być dostępny dla ClassLoadera powiązanego z bieżącym wątkiem.
+     * </p>
+     * 
+     * @param classname
+     * @return 
+     */
+    public static String getSource(String classname) {
+        return readSourceCode(Thread.currentThread().getContextClassLoader(), classname);
+    }
+    
+    /**
+     * Zwraca zawartość pliku źródłowego, w którym zapisana jest podana klasa. 
+     * Oczywiście, to nie działa idealnie dla klas, które nie mają pliku źródłowego
+     * w sensie stricte. Dla klas zagnieżdżonych albo anonimowych zwracana 
+     * jest cała zawartość, w którym je zapisano, a nie tylko fragment. 
+     * <p>
+     * Kod źródłowy musi być dostępny dla classloadera, który załadował klasę.
+     * </p>
+     * @param clazz
+     * @return 
+     */
+    public static String getSource(Class<?> clazz) {
+        return readSourceCode(clazz.getClassLoader(), clazz.getName());
+    }
+    
+    private static String readSourceCode(ClassLoader loader, String classname) {
+        String file = classname.replace('.', '/').replaceAll("\\$.+", "") + ".java";
+        InputStream istream = loader.getResourceAsStream(file);
+        if(istream != null) {
+            return StringLoader.fromStream(istream);
+        }
+        if(new File(file).exists() ) {
+            return StringLoader.fromFile(file);
+        }
+        if(new File("src/test/java/" + file).exists() ) {
+            return StringLoader.fromFile("src/test/java/" + file);
+        }
+        if(new File("src/test/main/" + file).exists() ) {
+            return StringLoader.fromFile("src/test/main/" + file);
+        }
+        throw new AssertionError(new IOException("unknown location of file: " + file));
+    }
+    
+    /**
+     * Zwraca lokalizację, w której został wyszukany odpowiedni plik .class z
+     * definicją załadowanej klasy. Lokalizacja nie wskazuje na  konkretny
+     * plik .class, aby uzyskać pełną ścieżkę, należy uzyć metody {@link #getFQLocation}
+     * @param clazz
+     * @return
+     */
+    public static String getLocation(Class<?> clazz) {
+        return clazz.getProtectionDomain().getCodeSource().getLocation().getFile();
+    }
+    
+    /**
+     * Zwraca ścieżkę do pliku .class, z którego została załadowana klasa. Aby
+     * uzyskać lokalizację, w której rozpoczęto wyszukiwanie pliku .class, należy
+     * użyć metody {@link #getLocation}
+     * @param clazz
+     * @return
+     */
+    public static String getFQLocation(Class<?> clazz) {
+        return clazz.getClassLoader().getResource( clazz.getName().replace('.', '/') + ".class" ).getFile();
+    }
+}

+ 157 - 156
assira1/src/main/java/net/ranides/assira/text/StringLoader.java

@@ -1,156 +1,157 @@
-/*
- *  @author Ranides Atterwim <ranides@gmail.com>
- *  @copyright Ranides Atterwim
- *  @license WTFPL
- *  @url http://ranides.net/projects/assira
- */
-
-package net.ranides.assira.text;
-
-import net.ranides.assira.io.RIOException;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.io.StreamTokenizer;
-import java.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Scanner;
-import net.ranides.assira.io.FileHelper;
-
-/**
- *
- * @author ranides
- */
-public final class StringLoader {
-
-    private StringLoader() { }
-
-    public static String fromReader(Reader reader) {
-        Scanner scanner = null;
-        try {
-            scanner = new Scanner(reader);
-            return scanner.useDelimiter("\\Z").next();
-        } finally {
-            FileHelper.close(scanner);
-        }
-    }
-
-    public static String fromStream(InputStream istream, Charset charset) {
-        Scanner scanner = null;
-        try {
-            scanner = new Scanner(istream, charset.name());
-            return scanner.useDelimiter("\\Z").next();
-        } finally {
-            FileHelper.close(scanner);
-        }
-    }
-
-    public static String fromStream(InputStream istream) {
-        return fromStream(istream, TextEncoding.NIO_UTF8);
-    }
-
-
-    public static String fromFile(File file, Charset charset) throws RIOException {
-        try {
-            return fromStream( new FileInputStream(file), charset );
-        } catch(IOException cause) {
-            throw new RIOException(cause);
-        }
-    }
-
-    public static String fromFile(File file) throws RIOException {
-        return fromFile(file, TextEncoding.NIO_UTF8);
-    }
-
-    public static String fromFile(String path, Charset charset) throws RIOException {
-        return fromFile(new File(path), charset);
-    }
-
-    public static String fromFile(String path) throws RIOException {
-        return fromFile(path, TextEncoding.NIO_UTF8 );
-    }
-
-    /**
-     * Ładuje plik ".properties", zachowując kolejność wpisów.
-     */
-    public static LinkedHashMap<String,String> loadProperties(Reader reader) throws RIOException {
-		// @todo (prev # 3) loadProperties spieprzone.
-        try {
-            LinkedHashMap<String,String> target = new LinkedHashMap<>();
-            StreamTokenizer tokenizer =new StreamTokenizer(new BufferedReader(reader));
-
-            // treat space, alpha, numbers and most punctuation as ordinary char
-            tokenizer.wordChars(' ', '_');
-            tokenizer.commentChar('#');
-            tokenizer.whitespaceChars('=', '=');// ignore equal, just separates fields
-            tokenizer.eolIsSignificant(true);
-            
-            while (true) {
-                tokenizer.nextToken();
-                if (tokenizer.ttype == StreamTokenizer.TT_EOF) { 
-                    return target;
-                }
-                if (tokenizer.ttype == StreamTokenizer.TT_EOL) { 
-                    continue; 
-                }
-                String key = tokenizer.sval.trim();
-                tokenizer.nextToken();
-                String value = tokenizer.sval.trim();
-                target.put(key, value);
-            }
-        } catch(IOException cause) {
-            throw new RIOException(cause);
-        } finally {  
-            FileHelper.close(reader);
-        }
-    }
-    
-    public static List<String> linesFromReader(Reader ireader) throws RIOException {
-        BufferedReader reader = null;
-        ArrayList<String> result = new ArrayList<>();
-        try {
-            reader = new BufferedReader(ireader);
-            String line;
-            while( null != (line=reader.readLine())) {
-                result.add(line);
-            }
-        } catch(IOException cause) {
-            throw new RIOException(cause);
-        } finally {
-            FileHelper.close(reader);
-        }
-        result.trimToSize();
-        return result;
-    }
-    
-    public static List<String> linesFromStream(InputStream istream, Charset charset) throws RIOException {
-        return linesFromReader(new BufferedReader(new InputStreamReader(istream, charset)));
-    }
-    
-    public static List<String> linesFromFile(File file, Charset charset) throws RIOException {
-        try {
-            return linesFromStream(new FileInputStream(file), charset);
-        } catch(IOException cause) {
-            throw new RIOException(cause);
-        }
-    }
-    
-    public static List<String> linesFromFile(String file, Charset charset) throws RIOException {
-        return linesFromFile(new File(file), charset);
-    }
-    
-    public static List<String> linesFromFile(File file) throws RIOException {
-        return linesFromFile(file, TextEncoding.NIO_UTF8);
-    }
-    
-    public static List<String> linesFromFile(String file) throws RIOException {
-        return linesFromFile(file, TextEncoding.NIO_UTF8);
-    }
-    
-}
+/*
+ *  @author Ranides Atterwim <ranides@gmail.com>
+ *  @copyright Ranides Atterwim
+ *  @license WTFPL
+ *  @url http://ranides.net/projects/assira
+ */
+
+package net.ranides.assira.text;
+
+import net.ranides.assira.io.RIOException;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.StreamTokenizer;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Scanner;
+import net.ranides.assira.io.FileHelper;
+
+/**
+ *
+ * @author ranides
+ * @todo (migration) assira
+ */
+public final class StringLoader {
+
+    private StringLoader() { }
+
+    public static String fromReader(Reader reader) {
+        Scanner scanner = null;
+        try {
+            scanner = new Scanner(reader);
+            return scanner.useDelimiter("\\Z").next();
+        } finally {
+            FileHelper.close(scanner);
+        }
+    }
+
+    public static String fromStream(InputStream istream, Charset charset) {
+        Scanner scanner = null;
+        try {
+            scanner = new Scanner(istream, charset.name());
+            return scanner.useDelimiter("\\Z").next();
+        } finally {
+            FileHelper.close(scanner);
+        }
+    }
+
+    public static String fromStream(InputStream istream) {
+        return fromStream(istream, TextEncoding.NIO_UTF8);
+    }
+
+
+    public static String fromFile(File file, Charset charset) throws RIOException {
+        try {
+            return fromStream( new FileInputStream(file), charset );
+        } catch(IOException cause) {
+            throw new RIOException(cause);
+        }
+    }
+
+    public static String fromFile(File file) throws RIOException {
+        return fromFile(file, TextEncoding.NIO_UTF8);
+    }
+
+    public static String fromFile(String path, Charset charset) throws RIOException {
+        return fromFile(new File(path), charset);
+    }
+
+    public static String fromFile(String path) throws RIOException {
+        return fromFile(path, TextEncoding.NIO_UTF8 );
+    }
+
+    /**
+     * Ładuje plik ".properties", zachowując kolejność wpisów.
+     */
+    public static LinkedHashMap<String,String> loadProperties(Reader reader) throws RIOException {
+		// @todo (prev # 3) loadProperties spieprzone.
+        try {
+            LinkedHashMap<String,String> target = new LinkedHashMap<>();
+            StreamTokenizer tokenizer =new StreamTokenizer(new BufferedReader(reader));
+
+            // treat space, alpha, numbers and most punctuation as ordinary char
+            tokenizer.wordChars(' ', '_');
+            tokenizer.commentChar('#');
+            tokenizer.whitespaceChars('=', '=');// ignore equal, just separates fields
+            tokenizer.eolIsSignificant(true);
+            
+            while (true) {
+                tokenizer.nextToken();
+                if (tokenizer.ttype == StreamTokenizer.TT_EOF) { 
+                    return target;
+                }
+                if (tokenizer.ttype == StreamTokenizer.TT_EOL) { 
+                    continue; 
+                }
+                String key = tokenizer.sval.trim();
+                tokenizer.nextToken();
+                String value = tokenizer.sval.trim();
+                target.put(key, value);
+            }
+        } catch(IOException cause) {
+            throw new RIOException(cause);
+        } finally {  
+            FileHelper.close(reader);
+        }
+    }
+    
+    public static List<String> linesFromReader(Reader ireader) throws RIOException {
+        BufferedReader reader = null;
+        ArrayList<String> result = new ArrayList<>();
+        try {
+            reader = new BufferedReader(ireader);
+            String line;
+            while( null != (line=reader.readLine())) {
+                result.add(line);
+            }
+        } catch(IOException cause) {
+            throw new RIOException(cause);
+        } finally {
+            FileHelper.close(reader);
+        }
+        result.trimToSize();
+        return result;
+    }
+    
+    public static List<String> linesFromStream(InputStream istream, Charset charset) throws RIOException {
+        return linesFromReader(new BufferedReader(new InputStreamReader(istream, charset)));
+    }
+    
+    public static List<String> linesFromFile(File file, Charset charset) throws RIOException {
+        try {
+            return linesFromStream(new FileInputStream(file), charset);
+        } catch(IOException cause) {
+            throw new RIOException(cause);
+        }
+    }
+    
+    public static List<String> linesFromFile(String file, Charset charset) throws RIOException {
+        return linesFromFile(new File(file), charset);
+    }
+    
+    public static List<String> linesFromFile(File file) throws RIOException {
+        return linesFromFile(file, TextEncoding.NIO_UTF8);
+    }
+    
+    public static List<String> linesFromFile(String file) throws RIOException {
+        return linesFromFile(file, TextEncoding.NIO_UTF8);
+    }
+    
+}