module Java.JAR.Archive where
import qualified Codec.Archive.LibZip as Zip
import Data.Binary
import Data.List
import qualified Data.ByteString.Lazy as B
import System.FilePath
import Java.ClassPath.Types
import Java.ClassPath.Common
import JVM.ClassFile
import JVM.Converter
readJAREntry :: (Enum a) => FilePath -> String -> IO (Maybe [a])
readJAREntry jarfile path = do
Zip.catchZipError (Just `fmap` (Zip.withArchive [] jarfile $ Zip.fileContents [] path))
(\_ -> return Nothing)
readAllJAR :: FilePath -> IO [Tree CPEntry]
readAllJAR jarfile = do
files <- Zip.withArchive [] jarfile $ Zip.fileNames []
return $ mapF (NotLoadedJAR jarfile) (buildTree $ filter good files)
where
good file = ".class" `isSuffixOf` file
readFromJAR :: FilePath -> FilePath -> IO (Class Direct)
readFromJAR jarfile path = do
content <- Zip.withArchive [] jarfile $ Zip.fileContents [] path
let bstr = B.pack content
return $ classFile2Direct (decode bstr)
checkClassTree :: [Tree CPEntry] -> IO [Tree (FilePath, Class Direct)]
checkClassTree forest = mapFMF check forest
where
check _ (NotLoaded path) = do
cls <- parseClassFile path
return (path, cls)
check a (Loaded path cls) = return (a </> path, cls)
check a (NotLoadedJAR jar path) = do
cls <- readFromJAR jar (a </> path)
return (a </> path, cls)
check a (LoadedJAR _ cls) =
return (a </> show (thisClass cls), cls)
zipJAR :: [Tree (FilePath, Class Direct)] -> Zip.Archive ()
zipJAR forest = do
mapFM go forest
return ()
where
go (path, cls) = Zip.addFile path =<< Zip.sourceBuffer (B.unpack $ encodeClass cls)