-- | Generic .class file format
data Class stage = Class {
- magic :: Word32, -- ^ Magic value: 0xCAFEBABE
+ magic :: Word32, -- ^ Magic value: 0xCAFEBABE
minorVersion :: Word16,
majorVersion :: Word16,
- constsPoolSize :: Word16, -- ^ Number of items in constants pool
- constsPool :: Pool stage, -- ^ Constants pool itself
- accessFlags :: AccessFlags stage, -- ^ See @JVM.Types.AccessFlag@
- thisClass :: Link stage B.ByteString, -- ^ Constants pool item index for this class
- superClass :: Link stage B.ByteString, -- ^ --/-- for super class, zero for java.lang.Object
- interfacesCount :: Word16, -- ^ Number of implemented interfaces
- interfaces :: [Link stage B.ByteString], -- ^ Constants pool item indexes for implemented interfaces
- classFieldsCount :: Word16, -- ^ Number of class fileds
- classFields :: [Field stage], -- ^ Class fields
- classMethodsCount :: Word16, -- ^ Number of class methods
- classMethods :: [Method stage], -- ^ Class methods
- classAttributesCount :: Word16, -- ^ Number of class attributes
- classAttributes :: Attributes stage -- ^ Class attributes
+ constsPoolSize :: Word16, -- ^ Number of items in constants pool
+ constsPool :: Pool stage, -- ^ Constants pool itself
+ accessFlags :: AccessFlags stage, -- ^ See @JVM.Types.AccessFlag@
+ thisClass :: Link stage B.ByteString, -- ^ Constants pool item index for this class
+ superClass :: Link stage B.ByteString, -- ^ --/-- for super class, zero for java.lang.Object
+ interfacesCount :: Word16, -- ^ Number of implemented interfaces
+ interfaces :: [Link stage B.ByteString], -- ^ Constants pool item indexes for implemented interfaces
+ classFieldsCount :: Word16, -- ^ Number of class fileds
+ classFields :: [Field stage], -- ^ Class fields
+ classMethodsCount :: Word16, -- ^ Number of class methods
+ classMethods :: [Method stage], -- ^ Class methods
+ classAttributesCount :: Word16, -- ^ Number of class attributes
+ classAttributes :: Attributes stage -- ^ Class attributes
}
deriving instance Eq (Class File)
import Data.List
import Data.String.Utils (split)
+import System.FilePath
import Java.ClassPath.Types
mapTM fn (Directory dir forest) = Directory dir `fmap` mapFM fn forest
mapTM fn (File a) = File `fmap` fn a
+mapFMF :: (Monad m, Functor m) => (FilePath -> t -> m a) -> [Tree t] -> m [Tree a]
+mapFMF fn forest = mapM (mapTMF fn) forest
+
+mapTMF :: (Monad m, Functor m) => (FilePath -> t -> m a) -> Tree t -> m (Tree a)
+mapTMF fn t = go "" t
+ where
+ go path (Directory dir forest) = Directory dir `fmap` mapM (go $ path </> dir) forest
+ go path (File a) = File `fmap` fn path a
+
-- | map on tree
mapT :: (t -> a) -> Tree t -> Tree a
mapT fn (Directory dir forest) = Directory dir (mapF fn forest)
-- | This module defines functions to read Java JAR files.
module Java.JAR.Archive where
+import Control.Monad.Trans
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
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)
+