+ St.put cp'
+
+runClassPath :: ClassPath a -> IO a
+runClassPath m = St.evalStateT m []
+
+execClassPath :: ClassPath () -> IO [Tree CPEntry]
+execClassPath m = St.execStateT m []
+
+loadClass :: String -> ClassPath ()
+loadClass path = do
+ cp <- St.get
+ cp' <- liftIO $ mapM (load xs) cp
+ St.put cp'
+ where
+ xs = split "/" path
+
+ load :: [String] -> Tree CPEntry -> IO (Tree CPEntry)
+ load [] t = return t
+ load (p:ps) t@(Directory dir forest)
+ | p == dir = Directory dir `fmap` mapM (load ps) forest
+ | otherwise = return t
+ load [p] t@(File (NotLoaded f))
+ | (p ++ ".class") == f = do
+ cls <- parseClassFile (path ++ ".class")
+ return (File $ Loaded path cls)
+ | otherwise = return t
+ load [p] t@(File (NotLoadedJAR jarfile f))
+ | (p ++ ".class") == f = do
+ cls <- readFromJAR jarfile (path ++ ".class")
+ return (File $ LoadedJAR jarfile cls)
+ | otherwise = return t
+ load ps (File _) = fail $ "Found file when expecting directory! " ++ show ps
+
+getEntry :: [Tree CPEntry] -> String -> IO (Maybe CPEntry)
+getEntry cp path = get cp (split "/" path)
+ where
+ get :: [Tree CPEntry] -> [String] -> IO (Maybe CPEntry)
+ get _ [] = fail "Empty path for ClassPath.getEntry.get!"
+ get [] _ = return Nothing
+ get (Directory dir forest: es) (p:ps)
+ | dir == p = get forest ps
+ | otherwise = get es (p:ps)
+ get (File i@(NotLoaded f): es) [p]
+ | (p ++ ".class" == f) = do
+ cls <- parseClassFile (path ++ ".class")
+ return $ Just (Loaded path cls)
+ | otherwise = get es [p]
+ get (File i@(NotLoadedJAR jarfile r): es) [p]
+ | (p ++ ".class" == r) = do
+ cls <- readFromJAR jarfile (path ++ ".class")
+ return $ Just (LoadedJAR jarfile cls)
+ | otherwise = get es [p]
+ get (File i@(Loaded f c):es) [p]
+ | f == p = return (Just i)
+ | otherwise = get es [p]
+ get (File i@(LoadedJAR f c):es) [p]
+ | toString (thisClass c) == path = return (Just i)
+ | otherwise = get es [p]
+ get x y = fail $ "Unexpected arguments for ClassPath.getEntry.get: " ++ show x ++ ", " ++ show y