byteString
) where
-import Codec.Binary.UTF8.String hiding (encode, decode)
import Data.Binary
import Data.Binary.Put
import qualified Data.ByteString.Lazy as B
-import Data.Char
-import Data.String
import qualified Data.Map as M
import Data.Default
instance Default Word16 where
def = 0
-instance IsString B.ByteString where
- fromString s = B.pack $ map (fromIntegral . ord) $ encodeString s
-
toCharList :: B.ByteString -> [Int]
toCharList bstr = map fromIntegral $ B.unpack bstr
import Data.Binary
import Data.Default () -- import instances only
import qualified Data.ByteString.Lazy as B
+import qualified Data.ByteString.Lazy.Char8 ()
import qualified Data.Set as S
import qualified Data.Map as M
--- /dev/null
+
+module Java.JAR
+ (readManifest,
+ readJAR,
+ addJAR
+ ) where
+
+import Control.Monad.Trans (liftIO)
+import qualified Control.Monad.State as St
+import Data.List
+import qualified Codec.Archive.LibZip as Zip
+
+import Java.ClassPath
+import Java.JAR.Archive
+import Java.META
+
+readManifest :: Zip.Archive (Maybe Manifest)
+readManifest = do
+ let manifestPath = "META-INF/MANIFEST.MF"
+ files <- Zip.fileNames []
+ if manifestPath `elem` files
+ then do
+ content <- Zip.fileContents [] manifestPath
+ case parseMeta content of
+ Left e -> fail $ show e
+ Right meta -> return $ Just (loadSpec meta)
+ else return Nothing
+
+readOne :: FilePath -> String -> Zip.Archive [Tree CPEntry]
+readOne jarfile str = do
+ files <- Zip.fileNames []
+ return $ mapF (NotLoadedJAR jarfile) (buildTree $ filter good files)
+ where
+ good name = str `isPrefixOf` name
+
+-- | Read entries from JAR file, using MANIFEST.MF if it exists.
+readJAR :: FilePath -> IO [Tree CPEntry]
+readJAR jarfile = do
+ r <- Zip.withArchive [] jarfile $ do
+ m <- readManifest
+ case m of
+ Nothing -> return Nothing
+ Just mf -> do
+ trees <- mapM (readOne jarfile) (map meName $ manifestEntries mf)
+ let forest = merge (concat trees)
+ return (Just forest)
+ case r of
+ Nothing -> readAllJAR jarfile
+ Just f -> return f
+
+-- | Add given JAR file to ClassPath
+addJAR :: FilePath -> ClassPath ()
+addJAR jarfile = do
+ classes <- liftIO $ readJAR jarfile
+ cp <- St.get
+ let cp' = merge $ cp ++ classes
+ St.put cp'
+
-- | This module defines functions to read Java JAR files.
module Java.JAR.Archive where
-import Control.Monad.Trans
-import qualified Control.Monad.State as St
import qualified Codec.Archive.LibZip as Zip
import Data.Binary
import qualified Data.ByteString.Lazy as B
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)
+
-- | Read all entires from JAR file
-readJAR :: FilePath -> IO [Tree CPEntry]
-readJAR jarfile = do
+readAllJAR :: FilePath -> IO [Tree CPEntry]
+readAllJAR jarfile = do
files <- Zip.withArchive [] jarfile $ Zip.fileNames []
return $ mapF (NotLoadedJAR jarfile) (buildTree files)
let bstr = B.pack content
return $ classFile2Direct (decode bstr)
--- | Add given JAR file to ClassPath
-addJAR :: FilePath -> ClassPath ()
-addJAR jarfile = do
- classes <- liftIO $ readJAR jarfile
- cp <- St.get
- let cp' = merge $ cp ++ classes
- St.put cp'
-
+++ /dev/null
-
-module JAR.Tree where
-
module Java.META
(module Java.META.Types,
module Java.META.Parser,
- module Java.META.Spec)
+ module Java.META.Spec,
+ Manifest (..),
+ ManifestEntry (..))
where
+import qualified Data.Map as M
+import Data.Map ((!))
+
import Java.META.Types
import Java.META.Parser
import Java.META.Spec
module Java.META.Parser
- (parseMetaFile) where
+ (parseMeta,
+ parseMetaFile) where
import qualified Data.Map as M
import Text.Parsec
parseMetaFile path = do
str <- readFile path
return $ parse pMETA path (str ++ "\n\n")
+
+parseMeta :: String -> Either ParseError META
+parseMeta str = parse pMETA "<META>" (str ++ "\n\n")
+
module Java.META.Spec where
-import Control.Monad
-import Control.Monad.Error
-import qualified Data.Map as M
-import Data.Map ((!))
import Data.Char (toLower)
import Java.META.Types
module Java.META.Types where
import qualified Data.Map as M
-import Text.Parsec
-import Text.Parsec.String
type Section = M.Map String String
type META = [Section]
Java.ClassPath
Java.ClassPath.Types
Java.ClassPath.Common
+ Java.JAR
Java.JAR.Archive
+ Java.META
+ Java.META.Types
+ Java.META.Spec
+ Java.META.Parser
Build-Depends: base >= 3 && <= 5, containers, binary,
mtl, directory, filepath, utf8-string, array,
bytestring, data-binary-ieee754, binary-state,
control-monad-exception, data-default, MissingH,
- LibZip, Glob
+ LibZip, Glob, parsec >= 3 && <4
ghc-options: -fwarn-unused-imports