+
+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'
+