001/*
002 * BridJ - Dynamic and blazing-fast native interop for Java.
003 * http://bridj.googlecode.com/
004 *
005 * Copyright (c) 2010-2013, Olivier Chafik (http://ochafik.com/)
006 * All rights reserved.
007 *
008 * Redistribution and use in source and binary forms, with or without
009 * modification, are permitted provided that the following conditions are met:
010 * 
011 *     * Redistributions of source code must retain the above copyright
012 *       notice, this list of conditions and the following disclaimer.
013 *     * Redistributions in binary form must reproduce the above copyright
014 *       notice, this list of conditions and the following disclaimer in the
015 *       documentation and/or other materials provided with the distribution.
016 *     * Neither the name of Olivier Chafik nor the
017 *       names of its contributors may be used to endorse or promote products
018 *       derived from this software without specific prior written permission.
019 * 
020 * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY
021 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
022 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
023 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
024 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
025 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
026 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
027 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
028 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
029 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
030 */
031package org.bridj.util;
032
033import java.lang.reflect.Constructor;
034import java.lang.reflect.ParameterizedType;
035import java.lang.reflect.Type;
036import java.lang.reflect.Method;
037import java.io.*;
038import java.lang.reflect.Array;
039import java.lang.reflect.GenericArrayType;
040import java.lang.reflect.TypeVariable;
041import java.lang.reflect.WildcardType;
042import java.nio.*;
043
044/**
045 * Miscellaneous utility methods.
046 *
047 * @author ochafik
048 */
049public class Utils {
050
051    public static int getEnclosedConstructorParametersOffset(Constructor c) {
052        Class<?> enclosingClass = c.getDeclaringClass().getEnclosingClass();
053        Class[] params = c.getParameterTypes();
054        int overrideOffset = params.length > 0 && enclosingClass != null && enclosingClass == params[0] ? 1 : 0;
055        return overrideOffset;
056    }
057
058    public static boolean isDirect(Buffer b) {
059        if (b instanceof ByteBuffer) {
060            return ((ByteBuffer) b).isDirect();
061        }
062        if (b instanceof IntBuffer) {
063            return ((IntBuffer) b).isDirect();
064        }
065        if (b instanceof LongBuffer) {
066            return ((LongBuffer) b).isDirect();
067        }
068        if (b instanceof DoubleBuffer) {
069            return ((DoubleBuffer) b).isDirect();
070        }
071        if (b instanceof FloatBuffer) {
072            return ((FloatBuffer) b).isDirect();
073        }
074        if (b instanceof ShortBuffer) {
075            return ((ShortBuffer) b).isDirect();
076        }
077        if (b instanceof CharBuffer) {
078            return ((CharBuffer) b).isDirect();
079        }
080        return false;
081    }
082
083    public static Object[] takeRight(Object[] array, int n) {
084        if (n == array.length) {
085            return array;
086        } else {
087            Object[] res = new Object[n];
088            System.arraycopy(array, array.length - n, res, 0, n);
089            return res;
090        }
091    }
092
093    public static Object[] takeLeft(Object[] array, int n) {
094        if (n == array.length) {
095            return array;
096        } else {
097            Object[] res = new Object[n];
098            System.arraycopy(array, 0, res, 0, n);
099            return res;
100        }
101    }
102
103    public static boolean isSignedIntegral(Type tpe) {
104        return tpe == int.class || tpe == Integer.class
105                || tpe == long.class || tpe == Long.class
106                || tpe == short.class || tpe == Short.class
107                || tpe == byte.class || tpe == Byte.class;
108    }
109
110    public static String toString(Type t) {
111        if (t == null) {
112            return "?";
113        }
114        if (t instanceof Class) {
115            return ((Class) t).getName();
116        }
117        return t.toString();
118    }
119
120    public static String toString(Throwable th) {
121        if (th == null)
122            return "<no trace>";
123        StringWriter sw = new StringWriter();
124        PrintWriter pw = new PrintWriter(sw);
125        th.printStackTrace(pw);
126        return sw.toString();
127    }
128
129    public static boolean eq(Object a, Object b) {
130        if ((a == null) != (b == null)) {
131            return false;
132        }
133        return !(a != null && !a.equals(b));
134    }
135
136    public static boolean containsTypeVariables(Type type) {
137        if (type instanceof TypeVariable) {
138            return true;
139        }
140        if (type instanceof ParameterizedType) {
141            ParameterizedType pt = (ParameterizedType) type;
142            for (Type t : pt.getActualTypeArguments()) {
143                if (containsTypeVariables(t)) {
144                    return true;
145                }
146            }
147        }
148        return false;
149    }
150
151    public static <T> Class<T> getClass(Type type) {
152        if (type == null) {
153            return null;
154        }
155        if (type instanceof Class<?>) {
156            return (Class<T>) type;
157        }
158        if (type instanceof ParameterizedType) {
159            return getClass(((ParameterizedType) type).getRawType());
160        }
161        if (type instanceof GenericArrayType) {
162            return (Class) Array.newInstance(getClass(((GenericArrayType) type).getGenericComponentType()), 0).getClass();
163        }
164        if (type instanceof WildcardType) {
165            return null;
166        }
167        if (type instanceof TypeVariable) {
168            Type[] bounds = ((TypeVariable) type).getBounds();
169            return getClass(bounds[0]);
170        }
171        throw new UnsupportedOperationException("Cannot infer class from type " + type);
172    }
173
174    public static Type getParent(Type type) {
175        if (type instanceof Class) {
176            return ((Class) type).getSuperclass();
177        } else // TODO handle templates !!!
178        {
179            return getParent(getClass(type));
180        }
181    }
182
183    public static Class[] getClasses(Type[] types) {
184        int n = types.length;
185        Class[] ret = new Class[n];
186        for (int i = 0; i < n; i++) {
187            ret[i] = getClass(types[i]);
188        }
189        return ret;
190    }
191
192    public static Type getUniqueParameterizedTypeParameter(Type type) {
193        return (type instanceof ParameterizedType) ? ((ParameterizedType) type).getActualTypeArguments()[0] : null;
194    }
195
196    public static boolean parametersComplyToSignature(Object[] values, Class[] parameterTypes) {
197        if (values.length != parameterTypes.length) {
198            return false;
199        }
200        for (int i = 0, n = values.length; i < n; i++) {
201            Object value = values[i];
202            Class parameterType = parameterTypes[i];
203            if (!parameterType.isInstance(value)) {
204                return false;
205            }
206        }
207        return true;
208    }
209}