diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,18 @@
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,4 @@
+import Distribution.Simple
+
+main = defaultMain
+
diff --git a/java-reflect.cabal b/java-reflect.cabal
new file mode 100644
--- /dev/null
+++ b/java-reflect.cabal
@@ -0,0 +1,29 @@
+name:           java-reflect
+version:        0.9
+
+license:        MIT
+license-file:   LICENSE
+
+author:         Julian Fleischer <julian.fleischer@fu-berlin.de>
+maintainer:     Julian Fleischer <julian.fleischer@fu-berlin.de>
+
+stability:      experimental
+category:       Foreign, Java, JVM, FFI Tools
+
+cabal-version:  >= 1.8
+
+synopsis:       Tools for reflecting on Java classes.
+description:    Tools for reflecting on Java classes.
+               
+build-type:     Simple
+
+Library
+    build-depends:      base >= 4.5 && < 5
+                        , java-bridge == 0.9
+                        , containers >= 0.4.2.1
+
+    hs-source-dirs:     src
+
+    exposed-modules:    Language.Java.Reflect
+                        , Language.Java.Reflect.Types
+
diff --git a/src/Language/Java/Reflect.hs b/src/Language/Java/Reflect.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Java/Reflect.hs
@@ -0,0 +1,584 @@
+{-# LANGUAGE Haskell2010 #-}
+{-# OPTIONS
+    -Wall
+    -fno-warn-missing-signatures
+    -fno-warn-name-shadowing
+ #-}
+
+-- |
+-- Module       : Foreign.Java.Bindings.ReflectJava
+-- Copyright    : (c) Julian Fleischer 2013
+-- License      : MIT (See LICENSE file in cabal package)
+--
+-- Maintainer   : julian.fleischer@fu-berlin.de
+-- Stability    : provisional
+--
+-- Methods for reflecting Java classes using a JVM as source of information.
+module Language.Java.Reflect (
+    findClasses,
+    reflectClasses,
+
+    module Language.Java.Reflect.Types
+
+  ) where
+
+
+import Language.Java.Reflect.Types
+
+import qualified Data.Map as Map
+import Data.Map (Map)
+
+import qualified Data.Set as Set
+import Data.Set (Set)
+
+import Data.Int
+import Data.Word
+import Data.Maybe (fromJust)
+
+import Foreign.Java
+import Foreign.Java.Utils
+
+
+definitely = maybe (error "The impossible happened! Please report this as a bug.")
+
+
+-- (
+--  [Methods = [types] ],
+--  (Maybe Parentclass, [Interfaces])
+-- )
+type Class = ([String], (Maybe String, [String]))
+
+
+findClasses :: Word32 -> [String] -> Java [String] --Java (Map String Class)
+findClasses maxDepth classNamesToFind = do
+
+    (Just clazz)   <- getClass "java.lang.Class"
+    (Just cMethod) <- getClass "java.lang.reflect.Method"
+    (Just cConstr) <- getClass "java.lang.reflect.Constructor"
+    (Just cField)  <- getClass "java.lang.reflect.Field"
+
+    getMethods <- clazz `bindMethod` "getMethods"
+        ::= array (object "java.lang.reflect.Method")
+    getConstructors <- clazz `bindMethod` "getConstructors"
+        ::= array (object "java.lang.reflect.Constructor")
+    getFields <- clazz `bindMethod` "getFields"
+        ::= array (object "java.lang.reflect.Field")
+
+    getFieldType <- cField `bindMethod` "getType"
+        ::= object "java.lang.Class"
+    getReturnType <- cMethod `bindMethod` "getReturnType"
+        ::= object "java.lang.Class"
+    getClassName <- clazz `bindMethod` "getName"
+        ::= string
+    getParametersM <- cMethod `bindMethod` "getParameterTypes"
+        ::= array (object "java.lang.Class")
+    getParametersC <- cConstr `bindMethod` "getParameterTypes"
+        ::= array (object "java.lang.Class")
+    getSuperclass <- clazz `bindMethod` "getSuperclass"
+        ::= object "java.lang.Class"
+    getInterfaces <- clazz `bindMethod` "getInterfaces"
+        ::= array (object "java.lang.Class")
+
+    (Just classLoader) <- getClass "java.lang.ClassLoader"
+    getSystemClassLoader <- classLoader `bindStaticMethod` "getSystemClassLoader"
+        ::= object "java.lang.ClassLoader"
+    (Just systemClassLoader) <- getSystemClassLoader
+
+    (Just loadClass) <- classLoader `getMethod` "loadClass"
+        ::= string --> boolean --> object "java.lang.Class"
+
+    let getClass' :: String -> Java (Maybe JObject)
+        getClass' clazz = callMethodE loadClass systemClassLoader clazz False
+            >>= return . either (const Nothing) id
+
+        readClass :: JObject -> Java Class
+        readClass clazz = do
+            constructors <- getConstructors clazz
+                >>= toList . fromJust
+                >>= mapM (readConstructor . fromJust)
+                >>= return . concat
+            methods <- getMethods clazz
+                >>= toList . fromJust
+                >>= mapM (readMethod . fromJust)
+                >>= return . concat
+            fields <- getFields clazz
+                >>= toList . fromJust
+                >>= mapM (readField . fromJust)
+            superclass <- getSuperclass clazz
+                >>= maybe (return Nothing) getClassName
+            interfaces <- getInterfaces clazz
+                >>= toList . fromJust
+                >>= mapM (getClassName . fromJust)
+                >>= return . map fromJust
+            return (constructors ++ fields ++ methods, (superclass, interfaces))
+
+        readField :: JObject -> Java String
+        readField field = do
+            (Just fieldType) <- getFieldType field >>= getClassName . fromJust
+
+            return fieldType
+
+        readMethod :: JObject -> Java [String]
+        readMethod method = do
+            args <- readMethodParameters method
+--          excs <- readMethodExceptions method
+            (Just returnType) <- getReturnType method >>= getClassName . fromJust
+            
+            return (returnType : args)
+
+        readConstructor :: JObject -> Java [String]
+        readConstructor constr = do
+            args <- readConstructorParameters constr
+--          excs <- readConstructorExceptions constr
+            
+            return args
+
+        readMethodParameters :: JObject -> Java [String]
+        readMethodParameters method = getParametersM method
+            >>= toList . fromJust
+            >>= mapM (getClassName . fromJust)
+            >>= return . map fromJust
+
+        readConstructorParameters :: JObject -> Java [String]
+        readConstructorParameters method = getParametersC method
+            >>= toList . fromJust
+            >>= mapM (getClassName . fromJust)
+            >>= return . map fromJust
+
+        readReferences :: Class -> [String]
+        readReferences (refs1, (super, ifaces)) =
+            let refs2 = maybe ifaces (: ifaces) super
+            in refs2 ++ refs1
+
+        isPrimitive x = head x == '[' || x `elem` ["byte", "short", "int", "long",
+                                                   "float", "double", "boolean", "char",
+                                                   "void"]
+
+        resolve :: Map String Class -> Set String -> [String]
+                -> Java (Map String Class, Set String)
+        resolve map set css = case css of
+            (x:xs) -> if x `Map.member` map
+                then do resolve map set xs
+                else getClass' x >>= maybe (resolve map set xs) (\clazz -> do
+                        clazz' <- readClass clazz
+                        let newClasses = Set.filter (`Map.notMember` map)
+                                            $ Set.fromList (readReferences clazz')
+                        resolve (Map.insert x clazz' map)
+                                (newClasses `Set.union` set)
+                                xs)
+            [] -> do return (map, Set.filter (not . isPrimitive) set)
+
+        findAll :: Word32 -> Map String Class -> [String] -> Java (Map String Class)
+        findAll 0 classes _xs = return classes
+        findAll limit classes xs = do
+            (classes', new) <- resolve classes Set.empty xs
+            if Set.null new
+                then return classes'
+                else findAll (pred limit) classes' (Set.toList new)
+    
+    Map.keys `fmap` findAll maxDepth Map.empty classNamesToFind
+
+reflectClasses :: [String] -> Java [JavaClass]
+reflectClasses classes = do
+
+    (Just clazz)     <- getClass "java.lang.Class"
+    (Just cField)    <- getClass "java.lang.reflect.Field"
+    (Just cMethod)   <- getClass "java.lang.reflect.Method"
+    (Just cConstr)   <- getClass "java.lang.reflect.Constructor"
+    (Just cTypeV)    <- getClass "java.lang.reflect.TypeVariable"
+    (Just cParamT)   <- getClass "java.lang.reflect.ParameterizedType"
+    (Just cWildT)    <- getClass "java.lang.reflect.WildcardType"
+    (Just cGenArrT)  <- getClass "java.lang.reflect.GenericArrayType"
+    (Just cEnum)     <- getClass "java.lang.Enum"
+    (Just modifiers) <- getClass "java.lang.reflect.Modifier"
+
+    getMethods <- clazz `bindMethod` "getMethods"
+        ::= array (object "java.lang.reflect.Method")
+    getFields <- clazz `bindMethod` "getFields"
+        ::= array (object "java.lang.reflect.Field")
+    getReturnType <- cMethod `bindMethod` "getReturnType"
+        ::= object "java.lang.Class"
+    getName <- clazz `bindMethod` "getName"
+        ::= string
+    getMethodName <- cMethod `bindMethod` "getName"
+        ::= string
+    getFieldName <- cField `bindMethod` "getName"
+        ::= string
+    getFieldType <- cField `bindMethod` "getType"
+        ::= object "java.lang.Class"
+    getGenericType <- cField `bindMethod` "getGenericType"
+        ::= object "java.lang.reflect.Type"
+    getParameters <- cMethod `bindMethod` "getParameterTypes"
+        ::= array (object "java.lang.Class")
+    getParameters' <- cConstr `bindMethod` "getParameterTypes"
+        ::= array (object "java.lang.Class")
+    getGenericParametersM <- cMethod `bindMethod` "getGenericParameterTypes"
+        ::= array (object "java.lang.reflect.Type")
+    getGenericParametersC <- cConstr `bindMethod` "getGenericParameterTypes"
+        ::= array (object "java.lang.reflect.Type")
+    getGenericReturnType <- cMethod `bindMethod` "getGenericReturnType"
+        ::= object "java.lang.reflect.Type"
+    getSuperclass <- clazz `bindMethod` "getSuperclass"
+        ::= object "java.lang.Class"
+    getInterfaces <- clazz `bindMethod` "getInterfaces"
+        ::= array (object "java.lang.Class")
+    getModifiersC <- clazz `bindMethod` "getModifiers"
+        ::= int
+    getModifiersM <- cMethod `bindMethod` "getModifiers"
+        ::= int
+    getModifiersF <- cField `bindMethod` "getModifiers"
+        ::= int
+    getConstructors <- clazz `bindMethod` "getConstructors"
+        ::= array (object "java.lang.reflect.Constructor")
+    getComponentType <- clazz `bindMethod` "getComponentType"
+        ::= object "java.lang.Class"
+    getEnumConstants <- clazz `bindMethod` "getEnumConstants"
+        ::= array (object "java.lang.Object")
+    getTypeParameters <- clazz `bindMethod` "getTypeParameters"
+        ::= array (object "java.lang.reflect.TypeVariable")
+    getTypeParametersC <- cConstr `bindMethod` "getTypeParameters"
+        ::= array (object "java.lang.reflect.TypeVariable")
+    getTypeParametersM <- cMethod `bindMethod` "getTypeParameters"
+        ::= array (object "java.lang.reflect.TypeVariable")
+
+    -- reflect TypeVariables
+    getTypeVariableName <- cTypeV `bindMethod` "getName"
+        ::= string
+    getTypeVariableBounds <- cTypeV `bindMethod` "getBounds"
+        ::= array (object "java.lang.reflect.Type")
+
+    -- reflect ParameterizedTypes
+    getActualTypeArguments <- cParamT `bindMethod` "getActualTypeArguments"
+        ::= array (object "java.lang.reflect.Type")
+    getRawType <- cParamT `bindMethod` "getRawType"
+        ::= object "java.lang.reflect.Type"
+    
+    -- reflect WildcardTypes
+    getLowerBounds <- cWildT `bindMethod` "getLowerBounds"
+        ::= array (object "java.lang.reflect.Type")
+    getUpperBounds <- cWildT `bindMethod` "getUpperBounds"
+        ::= array (object "java.lang.reflect.Type")
+
+    -- reflect GenericArrayTypes
+    getGenericComponentType <- cGenArrT `bindMethod` "getGenericComponentType"
+        ::= object "java.lang.reflect.Type"
+
+    -- reflect Enum types
+    getEnumName <- cEnum `bindMethod` "name"
+        ::= string
+    getEnumOrdinal <- cEnum `bindMethod` "ordinal"
+        ::= int
+
+    isAnnotation <- clazz `bindMethod` "isAnnotation"
+        ::= boolean
+    isArray <- clazz `bindMethod` "isArray"
+        ::= boolean
+    isEnum <- clazz `bindMethod` "isEnum"
+        ::= boolean
+    isInterface <- clazz `bindMethod` "isInterface"
+        ::= boolean
+    isPrimitive <- clazz `bindMethod` "isPrimitive"
+        ::= boolean
+
+    isStatic <- modifiers `bindStaticMethod` "isStatic"
+        ::= int --> boolean
+    isAbstract <- modifiers `bindStaticMethod` "isAbstract"
+        ::= int --> boolean
+    isFinal <- modifiers `bindStaticMethod` "isFinal"
+        ::= int --> boolean
+    isNative <- modifiers `bindStaticMethod` "isNative"
+        ::= int --> boolean
+    isSynchronized <- modifiers `bindStaticMethod` "isSynchronized"
+        ::= int --> boolean
+
+    (Just classLoader) <- getClass "java.lang.ClassLoader"
+    getSystemClassLoader <- classLoader `bindStaticMethod` "getSystemClassLoader"
+        ::= object "java.lang.ClassLoader"
+    (Just systemClassLoader) <- getSystemClassLoader
+    (Just loadClass) <- classLoader `getMethod` "loadClass"
+        ::= string --> boolean --> object "java.lang.Class"
+
+    let findParentClasses :: JObject -- of type java.lang.Class
+                          -> Java [JObject]
+        findParentClasses clazz = do
+            parent <- getSuperclass clazz
+            case parent of
+                (Just parent) -> do
+                    parents <- findParentClasses parent
+                    return $ parent : parents
+                _ -> return []
+        
+        reflectType :: JObject -- of type java.lang.Class
+                    -> Java (Maybe JavaType)
+        reflectType javatype = do
+
+            isActuallyPrimitive <- isPrimitive javatype
+            isActuallyAnArray   <- isArray javatype
+            
+            case undefined of
+                _ | isActuallyPrimitive -> do
+                    stringRepresentation <- toString javatype
+                    return $ case stringRepresentation of
+                        "boolean" -> Just JBoolean 
+                        "char"    -> Just JChar
+                        "byte"    -> Just JByte
+                        "short"   -> Just JShort
+                        "int"     -> Just JInt
+                        "long"    -> Just JLong
+                        "float"   -> Just JFloat
+                        "double"  -> Just JDouble
+                        "void"    -> Nothing
+                        x -> error ("can't be: " ++ show x)  -- these are all primitive types
+
+                _ | isActuallyAnArray -> do
+                    (Just componentType) <- getComponentType javatype
+                    reflectType componentType >>= return . Just . JArr . fromJust
+
+                _otherwiseItsAnObjectType -> do
+                    (Just name) <- getName javatype
+
+                    return $ Just $ JObj {
+                        typeName = name
+                    }
+
+        reflectTypeParameter :: JObject -- of type java.lang.reflect.TypeVariable<?>
+                             -> Java JavaTypeParam
+        reflectTypeParameter typeParameter = do
+            
+            (Just name) <- getTypeVariableName typeParameter
+            (Just bounds) <- getTypeVariableBounds typeParameter
+
+            bounds' <- toList bounds
+                >>= mapM (reflectGenericType . fromJust)
+
+            return $ JavaTypeParam {
+                paramName = (TyVar name),
+                paramBounds = bounds'
+            }
+
+        reflectGenericType :: JObject -- of type java.lang.reflect.Type
+                           -> Java JavaGenericType
+        reflectGenericType genericType = do
+
+            isGenericArrayType  <- genericType `isInstanceOf` cGenArrT
+            isParameterizedType <- genericType `isInstanceOf` cParamT
+            isTypeVariable      <- genericType `isInstanceOf` cTypeV
+            isWildcardType      <- genericType `isInstanceOf` cWildT
+
+            case undefined of
+                _ | isGenericArrayType -> do
+                    (Just basetype) <- getGenericComponentType genericType
+                    reflectedType <- reflectGenericType basetype
+
+                    return $ GenericArray {
+                        jgtComponentType = reflectedType
+                    }
+
+                _ | isParameterizedType -> do
+                    (Just typeargs) <- getActualTypeArguments genericType
+                    (Just basetype) <- getRawType genericType
+                    isClass <- basetype `isInstanceOf` clazz
+                    basetypeName <- if isClass
+                        then getName basetype >>= return . fromJust
+                        else fail "Type parameterized on a type variable. That was not possible <= Java 8."
+
+                    parameters <- toList typeargs >>= mapM (reflectGenericType . fromJust)
+
+                    return $ Parameterized {
+                        jgtBasetype = basetypeName,
+                        jgtParameters = parameters
+                    }
+
+                _ | isTypeVariable -> do
+                    (Just name) <- getTypeVariableName genericType
+                    
+                    return $ TypeVarReference {
+                        jgtName = (TyVar name)
+                    }
+
+                _ | isWildcardType -> do
+                    (Just lowerBounds) <- getLowerBounds genericType
+                    (Just bounds) <- getUpperBounds genericType
+
+                    lowerBounds' <- toList lowerBounds
+                        >>= mapM (reflectGenericType . fromJust)
+                    bounds' <- toList bounds
+                        >>= mapM (reflectGenericType . fromJust)
+                    
+                    return $ Wildcard {
+                        jgtBounds = bounds',
+                        jgtLowerBounds = lowerBounds'
+                    }
+
+                _ -> getName genericType >>= return . NotSoGeneric . fromJust
+                    
+
+        reflectEnumConstant :: JObject -- of type java.lang.Enum
+                            -> Java (Int32, String)
+        reflectEnumConstant enumConstant = do
+            (Just name) <- getEnumName enumConstant
+            ordinal     <- getEnumOrdinal enumConstant
+            return (ordinal, name)
+
+        reflectConstructor :: JObject -- of type java.lang.reflect.Constructor
+                           -> Java JavaConstructor
+        reflectConstructor constructor = do
+
+            parameters <- getParameters' constructor
+                >>= maybe (return []) toList
+                >>= mapM (fmap fromJust . reflectType . fromJust)
+
+            genericParams <- getGenericParametersC constructor
+                >>= maybe (return []) toList
+                >>= mapM (reflectGenericType . fromJust)
+
+            typeParams <- getTypeParametersC constructor
+                >>= maybe (return []) toList
+                >>= mapM (reflectTypeParameter . fromJust)
+
+            return $ JavaConstructor {
+                constructorParams = zip parameters genericParams,
+                constructorTypeParams = typeParams,
+                constructorExceptions = []
+            }
+
+        reflectField :: JObject -- of type java.lang.reflect.Field
+                     -> Java JavaField
+        reflectField field = do
+
+            (Just name) <- getFieldName field
+            modifiers <- getModifiersF field
+
+            fieldType <- getFieldType field
+                >>= definitely reflectType
+                >>= definitely return
+
+            genericType <- getGenericType field
+                >>= definitely reflectGenericType
+
+            isActuallyStatic <- isStatic modifiers
+            isActuallyFinal  <- isStatic modifiers
+
+            return $ JavaField {
+                fieldName = name,
+                fieldType = (fieldType, genericType),
+                fieldFinal = isActuallyFinal,
+                fieldStatic = isActuallyStatic
+            }
+
+        reflectMethod :: JObject -- of type java.lang.reflect.Method
+                      -> Java JavaMethod
+        reflectMethod method = do
+
+            (Just name) <- getMethodName method
+            modifiers <- getModifiersM method
+
+            returnType <- getReturnType method
+                >>= maybe (return Nothing) reflectType
+
+            parameters <- getParameters method
+                >>= maybe (return []) toList
+                >>= mapM (fmap fromJust . reflectType . fromJust)
+
+            genericParams <- getGenericParametersM method
+                >>= maybe (return []) toList
+                >>= mapM (reflectGenericType . fromJust)
+
+            genericReturnType <- getGenericReturnType method
+                >>= reflectGenericType . fromJust
+                            
+            typeParams <- getTypeParametersM method
+                >>= maybe (return []) toList
+                >>= mapM (reflectTypeParameter . fromJust)
+
+            isActuallyStatic   <- isStatic modifiers
+            isActuallyAbstract <- isAbstract modifiers
+            isActuallyFinal    <- isFinal modifiers
+            isActuallyNative   <- isNative modifiers
+            isActuallySynchronized <- isSynchronized modifiers
+
+            return $ JavaMethod {
+                methodName = name,
+                methodName' = "", -- filled in later on
+                methodParams = zip parameters genericParams,
+                methodReturnType = (returnType, genericReturnType),
+                methodTypeParams = typeParams,
+                methodExceptions = [],
+                methodStatic = isActuallyStatic,
+                methodAbstract = isActuallyAbstract,
+                methodFinal = isActuallyFinal,
+                methodNative = isActuallyNative,
+                methodSynchronized = isActuallySynchronized
+            }
+
+        reflectClass :: String -> Java JavaClass
+        reflectClass className = do
+            
+            (Just clazz) <- callMethod loadClass systemClassLoader className False
+            modifiers <- getModifiersC clazz
+
+            isActuallyAbstract <- isAbstract modifiers
+            isActuallyFinal <- isFinal modifiers
+
+            let name        = takeClassName   className
+                packageName = takePackageName className
+            
+            parents <- asObject clazz
+                >>= findParentClasses
+                >>= mapM (fmap fromJust . getName)
+
+            interfaces <- asObject clazz
+                >>= getInterfaces
+                >>= maybe (return []) toList
+                >>= mapM (getName . maybe undefined id)
+                >>= mapM (maybe undefined return)
+
+            fields <- asObject clazz
+                >>= getFields
+                >>= maybe (return []) toList
+                >>= mapM (maybe undefined reflectField)
+
+            methods <- asObject clazz
+                >>= getMethods
+                >>= maybe (return []) toList
+                >>= mapM (maybe undefined reflectMethod)
+
+            constructors <- asObject clazz
+                >>= getConstructors
+                >>= maybe (return []) toList
+                >>= mapM (maybe undefined reflectConstructor)
+
+            parameters <- asObject clazz
+                >>= getTypeParameters
+                >>= maybe (return []) toList
+                >>= mapM (maybe undefined reflectTypeParameter)
+
+            enumConstants <- asObject clazz
+                >>= getEnumConstants
+                >>= maybe (return []) toList
+                >>= mapM (maybe undefined reflectEnumConstant)
+
+            isActuallyEnum  <- asObject clazz >>= isEnum
+            isActuallyIface <- asObject clazz >>= isInterface
+            isActuallyAnn   <- asObject clazz >>= isAnnotation
+
+            return $ JavaClass {
+                className = name,
+                classPackage = packageName,
+                classModName = "", -- is filled in later
+                classFields = fields,
+                classMethods = methods,
+                classParents = parents,
+                classIfaces = interfaces,
+                classConstructors = constructors,
+                classTypeParams = parameters,
+                classEnum = isActuallyEnum,
+                classEnumConstants = enumConstants,
+                classIface = isActuallyIface,
+                classAnnotation = isActuallyAnn,
+                classAbstract = isActuallyAbstract,
+                classFinal = isActuallyFinal
+            }
+
+    mapM reflectClass classes
+
diff --git a/src/Language/Java/Reflect/Types.hs b/src/Language/Java/Reflect/Types.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Java/Reflect/Types.hs
@@ -0,0 +1,223 @@
+{-# LANGUAGE Haskell2010
+    , DeriveDataTypeable
+ #-}
+{-# OPTIONS -Wall #-}
+
+-- |
+-- Module       : Foreign.Java.Bindings.JavaTypes
+-- Copyright    : (c) Julian Fleischer 2013
+-- License      : MIT (See LICENSE file in cabal package)
+--
+-- Maintainer   : julian.fleischer@fu-berlin.de
+-- Stability    : provisional
+-- Portability  : non-portable (DeriveDataTypeable)
+--
+-- Data structures that describe the interface of
+-- Java structures such as classes, generic types,
+-- their methods, etc.
+--
+-- All types are instances of 'Data' and 'Typeable' and
+-- can therefor be used with /Scrap Your Boilerplate/
+-- combinators (see "Data.Generics").
+module Language.Java.Reflect.Types where
+
+import Foreign.Java.Utils
+import Data.Int
+import Data.Data
+
+-- type JavaClassCache = Map (String, [JavaType]) JavaClass
+
+-- | A JavaType is either a Primitive Type, an Array, or an Object.
+data JavaType
+    = JBoolean
+    | JChar
+    | JByte
+    | JShort
+    | JInt
+    | JLong
+    | JFloat
+    | JDouble
+    | JObj {
+        typeName :: String
+      }
+    | JArr {
+        componentType :: JavaType
+      }
+  deriving (Eq, Ord, Show, Read, Data, Typeable)
+
+
+printJavaType :: JavaType -> String
+printJavaType t = case t of
+    JBoolean -> "boolean"
+    JChar -> "char"
+    JByte -> "byte"
+    JShort -> "short"
+    JInt -> "int"
+    JLong -> "long"
+    JFloat -> "float"
+    JDouble -> "double"
+    JObj n -> n
+    JArr c -> printJavaType c ++ "[]"
+
+-- | The interface of a Java class.
+data JavaClass = JavaClass {
+    className :: String,
+    classPackage :: Maybe String,
+    classModName :: String,
+    classParents :: [String],
+    classIfaces :: [String],
+    classConstructors :: [JavaConstructor],
+    classMethods :: [JavaMethod],
+    classFields :: [JavaField],
+    classTypeParams :: [JavaTypeParam],
+    classEnum :: Bool,
+    classEnumConstants :: [(Int32, String)],
+    classIface :: Bool,
+    classAnnotation :: Bool,
+    classAbstract :: Bool,
+    classFinal :: Bool
+  } deriving (Eq, Show, Read, Data, Typeable)
+
+data JavaClassType = Annotation | Interface | Enum | Class | Exception | Error
+    deriving (Eq, Ord, Show, Read, Data, Typeable)
+
+
+classType :: JavaClass -> JavaClassType
+-- ^ Determines the 'JavaClassType' of a 'JavaClass'.
+classType clazz
+    | "java.lang.Error"     `elem` classParents clazz = Error
+    | "java.lang.Exception" `elem` classParents clazz = Exception
+    | classAnnotation clazz = Annotation
+    | classIface clazz      = Interface
+    | classEnum clazz       = Enum
+    | otherwise             = Class
+
+
+classDependencies :: JavaClass -> [String]
+-- ^ Calculate all classes that are referenced in any way by this class.
+classDependencies clazz = concat [
+    classParents clazz,
+    classIfaces clazz,
+    concatMap fieldDependencies (classFields clazz),
+    concatMap methodDependencies (classMethods clazz),
+    concatMap constructorDependencies (classConstructors clazz) ]
+
+classFullName :: JavaClass -> String
+-- ^ Derive the full name from a class definition. See also 'makeName'.
+classFullName clazz = makeName (classPackage clazz) (className clazz)
+    
+
+-- | A Type variable declaration.
+data JavaTypeParam = JavaTypeParam {
+    paramName :: TyVar,
+    paramBounds :: [JavaGenericType]
+  } deriving (Eq, Ord, Show, Read, Data, Typeable)
+
+-- | A Type variable. This is merely a name.
+newtype TyVar = TyVar { tyVarName :: String }
+    deriving (Eq, Ord, Show, Read, Data, Typeable)
+
+data JavaGenericType
+    = -- | @<? super X>@, @<? extends X>@
+      Wildcard {
+        jgtBounds :: [JavaGenericType],
+        jgtLowerBounds :: [JavaGenericType]
+    }
+    | -- | @java.util.List<X>@
+      Parameterized {
+        -- | The full name of the base type, e.g. @java.lang.Class@.
+        jgtBasetype :: String,
+        -- | The parameters.
+        jgtParameters :: [JavaGenericType]
+    }
+    | -- | @X[]@
+      GenericArray {
+        -- | The base type of the generic array, e.g. @java.lang.Number@.
+        jgtComponentType :: JavaGenericType
+    }
+    | -- | @<X>@
+      TypeVarReference {
+        -- | The name of the type variable, e.g. @E@ or @X@.
+        jgtName :: TyVar
+    }
+    | -- java.lang.Object
+      NotSoGeneric {
+        -- | A plain type, full name. Used for example in a 'Parameterized'
+        -- type, which may be parameterized by a plain type (like
+        -- @Class<Number>@.
+        jgtBasetype :: String
+    } deriving (Eq, Ord, Show, Read, Data, Typeable)
+
+-- | The type of a generic type.
+data JavaGenericTypeType = WildcardT
+                         | ParameterizedT
+                         | GenericArrayT
+                         | TypeVarReferenceT
+                         | NotSoGenericT
+
+jgtType :: JavaGenericType -> JavaGenericTypeType
+-- ^ Get the type of a generic type.
+jgtType t = case t of
+    (Wildcard _ _)       -> WildcardT
+    (Parameterized _ _)  -> ParameterizedT
+    (GenericArray _)     -> GenericArrayT
+    (TypeVarReference _) -> TypeVarReferenceT
+    (NotSoGeneric _)     -> NotSoGenericT
+
+-- | The interface to a field in the Java language.
+data JavaField = JavaField {
+    fieldName :: String,
+    fieldType :: (JavaType, JavaGenericType),
+    fieldFinal :: Bool,
+    fieldStatic :: Bool
+  } deriving (Eq, Show, Read, Data, Typeable)
+
+fieldDependencies :: JavaField -> [String]
+fieldDependencies field = case fst (fieldType field) of
+    JObj n -> [n]
+    _ -> []
+
+-- | The interface to a method in the Java language.
+data JavaMethod = JavaMethod {
+    methodName :: String,
+    methodName' :: String,
+    methodParams :: [(JavaType, JavaGenericType)],
+    methodReturnType :: (Maybe JavaType, JavaGenericType),
+    methodExceptions :: [String],
+    methodTypeParams :: [JavaTypeParam],
+    methodStatic :: Bool,
+    methodAbstract :: Bool,
+    methodFinal :: Bool,
+    methodNative :: Bool,
+    methodSynchronized :: Bool
+  } deriving (Eq, Show, Read, Data, Typeable)
+
+methodDependencies :: JavaMethod -> [String]
+-- ^ Return the full names of all classes that this method
+-- references in its definition.
+methodDependencies method = foldl classReference [] referenced
+  where
+    referenced = maybe paramTypes (: paramTypes) (fst $ methodReturnType method)
+    paramTypes = map fst $ methodParams method
+    classReference r c = case c of
+        JObj n -> n : r
+        _ -> r
+
+-- | A Constructor in the Java language.
+data JavaConstructor = JavaConstructor {
+    constructorParams :: [(JavaType, JavaGenericType)],
+    constructorExceptions :: [String],
+    constructorTypeParams :: [JavaTypeParam]
+  } deriving (Eq, Show, Read, Data, Typeable)
+
+constructorDependencies :: JavaConstructor -> [String]
+-- ^ Retrieve all classes that this constructor definition
+-- references in its parameters or generic declaration.
+constructorDependencies constr = foldl classReference []
+                              $ map fst $ constructorParams constr
+  where
+    classReference r c = case c of
+        JObj n -> n : r
+        _ -> r
+
+
