001/* 002 * Forge Mod Loader 003 * Copyright (c) 2012-2013 cpw. 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser Public License v2.1 006 * which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html 008 * 009 * Contributors: 010 * cpw - implementation 011 */ 012 013package cpw.mods.fml.common.discovery; 014 015import java.util.Collections; 016import java.util.List; 017import java.util.logging.Level; 018import java.util.regex.Matcher; 019import java.util.zip.ZipEntry; 020import java.util.zip.ZipFile; 021 022import com.google.common.collect.Lists; 023 024import cpw.mods.fml.common.FMLLog; 025import cpw.mods.fml.common.LoaderException; 026import cpw.mods.fml.common.MetadataCollection; 027import cpw.mods.fml.common.ModContainer; 028import cpw.mods.fml.common.ModContainerFactory; 029import cpw.mods.fml.common.discovery.asm.ASMModParser; 030 031public class JarDiscoverer implements ITypeDiscoverer 032{ 033 @Override 034 public List<ModContainer> discover(ModCandidate candidate, ASMDataTable table) 035 { 036 List<ModContainer> foundMods = Lists.newArrayList(); 037 FMLLog.fine("Examining file %s for potential mods", candidate.getModContainer().getName()); 038 ZipFile jar = null; 039 try 040 { 041 jar = new ZipFile(candidate.getModContainer()); 042 043 ZipEntry modInfo = jar.getEntry("mcmod.info"); 044 MetadataCollection mc = null; 045 if (modInfo != null) 046 { 047 FMLLog.finer("Located mcmod.info file in file %s", candidate.getModContainer().getName()); 048 mc = MetadataCollection.from(jar.getInputStream(modInfo), candidate.getModContainer().getName()); 049 } 050 else 051 { 052 FMLLog.fine("The mod container %s appears to be missing an mcmod.info file", candidate.getModContainer().getName()); 053 mc = MetadataCollection.from(null, ""); 054 } 055 for (ZipEntry ze : Collections.list(jar.entries())) 056 { 057 if (ze.getName()!=null && ze.getName().startsWith("__MACOSX")) 058 { 059 continue; 060 } 061 Matcher match = classFile.matcher(ze.getName()); 062 if (match.matches()) 063 { 064 ASMModParser modParser; 065 try 066 { 067 modParser = new ASMModParser(jar.getInputStream(ze)); 068 } 069 catch (LoaderException e) 070 { 071 FMLLog.log(Level.SEVERE, e, "There was a problem reading the entry %s in the jar %s - probably a corrupt zip", ze.getName(), candidate.getModContainer().getPath()); 072 jar.close(); 073 throw e; 074 } 075 modParser.validate(); 076 modParser.sendToTable(table, candidate); 077 ModContainer container = ModContainerFactory.instance().build(modParser, candidate.getModContainer(), candidate); 078 if (container!=null) 079 { 080 table.addContainer(container); 081 foundMods.add(container); 082 container.bindMetadata(mc); 083 } 084 } 085 } 086 } 087 catch (Exception e) 088 { 089 FMLLog.log(Level.WARNING, e, "Zip file %s failed to read properly, it will be ignored", candidate.getModContainer().getName()); 090 } 091 finally 092 { 093 if (jar != null) 094 { 095 try 096 { 097 jar.close(); 098 } 099 catch (Exception e) 100 { 101 } 102 } 103 } 104 return foundMods; 105 } 106 107}