1 -- | This module defines functions to read Java JAR files.
2 module Java.JAR.Archive where
4 import Control.Monad.Trans
5 import qualified Codec.Archive.LibZip as Zip
8 import qualified Data.ByteString.Lazy as B
11 import Java.ClassPath.Types
12 import Java.ClassPath.Common
16 readJAREntry :: (Enum a) => FilePath -> String -> IO (Maybe [a])
17 readJAREntry jarfile path = do
18 Zip.catchZipError (Just `fmap` (Zip.withArchive [] jarfile $ Zip.fileContents [] path))
19 (\_ -> return Nothing)
21 -- | Read all entires from JAR file
22 readAllJAR :: FilePath -> IO [Tree CPEntry]
23 readAllJAR jarfile = do
24 files <- Zip.withArchive [] jarfile $ Zip.fileNames []
25 return $ mapF (NotLoadedJAR jarfile) (buildTree $ filter good files)
27 good file = ".class" `isSuffixOf` file
29 -- | Read one class from JAR file
30 readFromJAR :: FilePath -> FilePath -> IO (Class Direct)
31 readFromJAR jarfile path = do
32 content <- Zip.withArchive [] jarfile $ Zip.fileContents [] path
33 let bstr = B.pack content
34 return $ classFile2Direct (decode bstr)
36 checkClassTree :: [Tree CPEntry] -> IO [Tree (FilePath, Class Direct)]
37 checkClassTree forest = mapFMF check forest
39 check _ (NotLoaded path) = do
40 cls <- parseClassFile path
42 check a (Loaded path cls) = return (a </> path, cls)
43 check a (NotLoadedJAR jar path) = do
44 cls <- readFromJAR jar (a </> path)
45 return (a </> path, cls)
46 check a (LoadedJAR _ cls) =
47 return (a </> show (thisClass cls), cls)
49 zipJAR :: [Tree (FilePath, Class Direct)] -> Zip.Archive ()
54 go (path, cls) = Zip.addFile path =<< Zip.sourceBuffer (B.unpack $ encodeClass cls)