    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.relauncher;
    014
    015import java.io.File;
    016import java.io.FileInputStream;
    017import java.io.FileOutputStream;
    018import java.io.FilenameFilter;
    019import java.io.IOException;
    020import java.io.InputStream;
    021import java.io.InterruptedIOException;
    022import java.lang.reflect.Method;
    023import java.net.MalformedURLException;
    024import java.net.URL;
    025import java.net.URLConnection;
    026import java.nio.ByteBuffer;
    027import java.nio.MappedByteBuffer;
    028import java.nio.channels.FileChannel;
    029import java.nio.channels.FileChannel.MapMode;
    030import java.security.MessageDigest;
    031import java.util.ArrayList;
    032import java.util.Arrays;
    033import java.util.HashMap;
    034import java.util.List;
    035import java.util.Map;
    036import java.util.jar.Attributes;
    037import java.util.jar.JarFile;
    038import java.util.logging.Level;
    039
    040import cpw.mods.fml.common.CertificateHelper;
    041import cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion;
    042import cpw.mods.fml.relauncher.IFMLLoadingPlugin.TransformerExclusions;
    043
    044public class RelaunchLibraryManager
    045{
    046    private static String[] rootPlugins =  { "cpw.mods.fml.relauncher.FMLCorePlugin" , "net.minecraftforge.classloading.FMLForgePlugin" };
    047    private static List<String> loadedLibraries = new ArrayList<String>();
    048    private static Map<IFMLLoadingPlugin, File> pluginLocations;
    049    private static List<IFMLLoadingPlugin> loadPlugins;
    050    private static List<ILibrarySet> libraries;
    051    private static boolean deobfuscatedEnvironment;
    052
    053    public static void handleLaunch(File mcDir, RelaunchClassLoader actualClassLoader)
    054    {
    055        try
    056        {
    057            // Are we in a 'decompiled' environment?
    058            byte[] bs = actualClassLoader.getClassBytes("net.minecraft.world.World");
    059            if (bs != null)
    060            {
    061                FMLRelaunchLog.info("Managed to load a deobfuscated Minecraft name- we are in a deobfuscated environment. Skipping runtime deobfuscation");
    062                deobfuscatedEnvironment = true;
    063            }
    064        }
    065        catch (IOException e1)
    066        {
    067        }
    068
    069        if (!deobfuscatedEnvironment)
    070        {
    071            FMLRelaunchLog.fine("Enabling runtime deobfuscation");
    072        }
    073        pluginLocations = new HashMap<IFMLLoadingPlugin, File>();
    074        loadPlugins = new ArrayList<IFMLLoadingPlugin>();
    075        libraries = new ArrayList<ILibrarySet>();
    076        for (String s : rootPlugins)
    077        {
    078            try
    079            {
    080                IFMLLoadingPlugin plugin = (IFMLLoadingPlugin) Class.forName(s, true, actualClassLoader).newInstance();
    081                loadPlugins.add(plugin);
    082                for (String libName : plugin.getLibraryRequestClass())
    083                {
    084                    libraries.add((ILibrarySet) Class.forName(libName, true, actualClassLoader).newInstance());
    085                }
    086            }
    087            catch (Exception e)
    088            {
    089                // HMMM
    090            }
    091        }
    092
    093        if (loadPlugins.isEmpty())
    094        {
    095            throw new RuntimeException("A fatal error has occured - no valid fml load plugin was found - this is a completely corrupt FML installation.");
    096        }
    097
    098        downloadMonitor.updateProgressString("All core mods are successfully located");
    099        // Now that we have the root plugins loaded - lets see what else might be around
    100        String commandLineCoremods = System.getProperty("fml.coreMods.load","");
    101        for (String s : commandLineCoremods.split(","))
    102        {
    103            if (s.isEmpty())
    104            {
    105                continue;
    106            }
    107            FMLRelaunchLog.info("Found a command line coremod : %s", s);
    108            try
    109            {
    110                actualClassLoader.addTransformerExclusion(s);
    111                Class<?> coreModClass = Class.forName(s, true, actualClassLoader);
    112                TransformerExclusions trExclusions = coreModClass.getAnnotation(IFMLLoadingPlugin.TransformerExclusions.class);
    113                if (trExclusions!=null)
    114                {
    115                    for (String st : trExclusions.value())
    116                    {
    117                        actualClassLoader.addTransformerExclusion(st);
    118                    }
    119                }
    120                IFMLLoadingPlugin plugin = (IFMLLoadingPlugin) coreModClass.newInstance();
    121                loadPlugins.add(plugin);
    122                if (plugin.getLibraryRequestClass()!=null)
    123                {
    124                    for (String libName : plugin.getLibraryRequestClass())
    125                    {
    126                        libraries.add((ILibrarySet) Class.forName(libName, true, actualClassLoader).newInstance());
    127                    }
    128                }
    129            }
    130            catch (Throwable e)
    131            {
    132                FMLRelaunchLog.log(Level.SEVERE,e,"Exception occured trying to load coremod %s",s);
    133                throw new RuntimeException(e);
    134            }
    135        }
    136        discoverCoreMods(mcDir, actualClassLoader, loadPlugins, libraries);
    137
    138        List<Throwable> caughtErrors = new ArrayList<Throwable>();
    139        try
    140        {
    141            File libDir;
    142            try
    143            {
    144                libDir = setupLibDir(mcDir);
    145            }
    146            catch (Exception e)
    147            {
    148                caughtErrors.add(e);
    149                return;
    150            }
    151
    152            for (ILibrarySet lib : libraries)
    153            {
    154                for (int i=0; i<lib.getLibraries().length; i++)
    155                {
    156                    boolean download = false;
    157                    String libName = lib.getLibraries()[i];
    158                    String targFileName = libName.lastIndexOf('/')>=0 ? libName.substring(libName.lastIndexOf('/')) : libName;
    159                    String checksum = lib.getHashes()[i];
    160                    File libFile = new File(libDir, targFileName);
    161                    if (!libFile.exists())
    162                    {
    163                        try
    164                        {
    165                            downloadFile(libFile, lib.getRootURL(), libName, checksum);
    166                            download = true;
    167                        }
    168                        catch (Throwable e)
    169                        {
    170                            caughtErrors.add(e);
    171                            continue;
    172                        }
    173                    }
    174
    175                    if (libFile.exists() && !libFile.isFile())
    176                    {
    177                        caughtErrors.add(new RuntimeException(String.format("Found a file %s that is not a normal file - you should clear this out of the way", libName)));
    178                        continue;
    179                    }
    180
    181                    if (!download)
    182                    {
    183                        try
    184                        {
    185                            FileInputStream fis = new FileInputStream(libFile);
    186                            FileChannel chan = fis.getChannel();
    187                            MappedByteBuffer mappedFile = chan.map(MapMode.READ_ONLY, 0, libFile.length());
    188                            String fileChecksum = generateChecksum(mappedFile);
    189                            fis.close();
    190                            // bad checksum and I did not download this file
    191                            if (!checksum.equals(fileChecksum))
    192                            {
    193                                caughtErrors.add(new RuntimeException(String.format("The file %s was found in your lib directory and has an invalid checksum %s (expecting %s) - it is unlikely to be the correct download, please move it out of the way and try again.", libName, fileChecksum, checksum)));
    194                                continue;
    195                            }
    196                        }
    197                        catch (Exception e)
    198                        {
    199                            FMLRelaunchLog.log(Level.SEVERE, e, "The library file %s could not be validated", libFile.getName());
    200                            caughtErrors.add(new RuntimeException(String.format("The library file %s could not be validated", libFile.getName()),e));
    201                            continue;
    202                        }
    203                    }
    204
    205                    if (!download)
    206                    {
    207                        downloadMonitor.updateProgressString("Found library file %s present and correct in lib dir", libName);
    208                    }
    209                    else
    210                    {
    211                        downloadMonitor.updateProgressString("Library file %s was downloaded and verified successfully", libName);
    212                    }
    213
    214                    try
    215                    {
    216                        actualClassLoader.addURL(libFile.toURI().toURL());
    217                        loadedLibraries.add(libName);
    218                    }
    219                    catch (MalformedURLException e)
    220                    {
    221                        caughtErrors.add(new RuntimeException(String.format("Should never happen - %s is broken - probably a somehow corrupted download. Delete it and try again.", libFile.getName()), e));
    222                    }
    223                }
    224            }
    225        }
    226        finally
    227        {
    228            if (downloadMonitor.shouldStopIt())
    229            {
    230                return;
    231            }
    232            if (!caughtErrors.isEmpty())
    233            {
    234                FMLRelaunchLog.severe("There were errors during initial FML setup. " +
    235                        "Some files failed to download or were otherwise corrupted. " +
    236                        "You will need to manually obtain the following files from " +
    237                        "these download links and ensure your lib directory is clean. ");
    238                for (ILibrarySet set : libraries)
    239                {
    240                    for (String file : set.getLibraries())
    241                    {
    242                        FMLRelaunchLog.severe("*** Download "+set.getRootURL(), file);
    243                    }
    244                }
    245                FMLRelaunchLog.severe("<===========>");
    246                FMLRelaunchLog.severe("The following is the errors that caused the setup to fail. " +
    247                        "They may help you diagnose and resolve the issue");
    248                for (Throwable t : caughtErrors)
    249                {
    250                    if (t.getMessage()!=null)
    251                    {
    252                        FMLRelaunchLog.severe(t.getMessage());
    253                    }
    254                }
    255                FMLRelaunchLog.severe("<<< ==== >>>");
    256                FMLRelaunchLog.severe("The following is diagnostic information for developers to review.");
    257                for (Throwable t : caughtErrors)
    258                {
    259                    FMLRelaunchLog.log(Level.SEVERE, t, "Error details");
    260                }
    261                throw new RuntimeException("A fatal error occured and FML cannot continue");
    262            }
    263        }
    264
    265        for (IFMLLoadingPlugin plug : loadPlugins)
    266        {
    267            if (plug.getASMTransformerClass()!=null)
    268            {
    269                for (String xformClass : plug.getASMTransformerClass())
    270                {
    271                    actualClassLoader.registerTransformer(xformClass);
    272                }
    273            }
    274        }
    275        // Deobfuscation transformer, always last
    276        if (!deobfuscatedEnvironment)
    277        {
    278            actualClassLoader.registerTransformer("cpw.mods.fml.common.asm.transformers.DeobfuscationTransformer");
    279        }
    280        downloadMonitor.updateProgressString("Running coremod plugins");
    281        Map<String,Object> data = new HashMap<String,Object>();
    282        data.put("mcLocation", mcDir);
    283        data.put("coremodList", loadPlugins);
    284        data.put("runtimeDeobfuscationEnabled", !deobfuscatedEnvironment);
    285        for (IFMLLoadingPlugin plugin : loadPlugins)
    286        {
    287            downloadMonitor.updateProgressString("Running coremod plugin %s", plugin.getClass().getSimpleName());
    288            data.put("coremodLocation", pluginLocations.get(plugin));
    289            plugin.injectData(data);
    290            String setupClass = plugin.getSetupClass();
    291            if (setupClass != null)
    292            {
    293                try
    294                {
    295                    IFMLCallHook call = (IFMLCallHook) Class.forName(setupClass, true, actualClassLoader).newInstance();
    296                    Map<String,Object> callData = new HashMap<String, Object>();
    297                    callData.put("mcLocation", mcDir);
    298                    callData.put("classLoader", actualClassLoader);
    299                    callData.put("coremodLocation", pluginLocations.get(plugin));
    300                    callData.put("deobfuscationFileName", FMLInjectionData.debfuscationDataName());
    301                    call.injectData(callData);
    302                    call.call();
    303                }
    304                catch (Exception e)
    305                {
    306                    throw new RuntimeException(e);
    307                }
    308            }
    309            downloadMonitor.updateProgressString("Coremod plugin %s run successfully", plugin.getClass().getSimpleName());
    310
    311            String modContainer = plugin.getModContainerClass();
    312            if (modContainer != null)
    313            {
    314                FMLInjectionData.containers.add(modContainer);
    315            }
    316        }
    317        try
    318        {
    319            downloadMonitor.updateProgressString("Validating minecraft");
    320            Class<?> loaderClazz = Class.forName("cpw.mods.fml.common.Loader", true, actualClassLoader);
    321            Method m = loaderClazz.getMethod("injectData", Object[].class);
    322            m.invoke(null, (Object)FMLInjectionData.data());
    323            m = loaderClazz.getMethod("instance");
    324            m.invoke(null);
    325            downloadMonitor.updateProgressString("Minecraft validated, launching...");
    326            downloadBuffer = null;
    327        }
    328        catch (Exception e)
    329        {
    330            // Load in the Loader, make sure he's ready to roll - this will initialize most of the rest of minecraft here
    331            System.out.println("A CRITICAL PROBLEM OCCURED INITIALIZING MINECRAFT - LIKELY YOU HAVE AN INCORRECT VERSION FOR THIS FML");
    332            throw new RuntimeException(e);
    333        }
    334    }
    335
    336    private static void discoverCoreMods(File mcDir, RelaunchClassLoader classLoader, List<IFMLLoadingPlugin> loadPlugins, List<ILibrarySet> libraries)
    337    {
    338        downloadMonitor.updateProgressString("Discovering coremods");
    339        File coreMods = setupCoreModDir(mcDir);
    340        FilenameFilter ff = new FilenameFilter()
    341        {
    342            @Override
    343            public boolean accept(File dir, String name)
    344            {
    345                return name.endsWith(".jar");
    346            }
    347        };
    348        File[] coreModList = coreMods.listFiles(ff);
    349        Arrays.sort(coreModList);
    350
    351        for (File coreMod : coreModList)
    352        {
    353            downloadMonitor.updateProgressString("Found a candidate coremod %s", coreMod.getName());
    354            JarFile jar;
    355            Attributes mfAttributes;
    356            try
    357            {
    358                jar = new JarFile(coreMod);
    359                if (jar.getManifest() == null)
    360                {
    361                    FMLRelaunchLog.warning("Found an un-manifested jar file in the coremods folder : %s, it will be ignored.", coreMod.getName());
    362                    continue;
    363                }
    364                mfAttributes = jar.getManifest().getMainAttributes();
    365            }
    366            catch (IOException ioe)
    367            {
    368                FMLRelaunchLog.log(Level.SEVERE, ioe, "Unable to read the coremod jar file %s - ignoring", coreMod.getName());
    369                continue;
    370            }
    371
    372            String fmlCorePlugin = mfAttributes.getValue("FMLCorePlugin");
    373            if (fmlCorePlugin == null)
    374            {
    375                FMLRelaunchLog.severe("The coremod %s does not contain a valid jar manifest- it will be ignored", coreMod.getName());
    376                continue;
    377            }
    378
    379//            String className = fmlCorePlugin.replace('.', '/').concat(".class");
    380//            JarEntry ent = jar.getJarEntry(className);
    381//            if (ent ==null)
    382//            {
    383//                FMLLog.severe("The coremod %s specified %s as it's loading class but it does not include it - it will be ignored", coreMod.getName(), fmlCorePlugin);
    384//                continue;
    385//            }
    386//            try
    387//            {
    388//                Class<?> coreModClass = Class.forName(fmlCorePlugin, false, classLoader);
    389//                FMLLog.severe("The coremods %s specified a class %s that is already present in the classpath - it will be ignored", coreMod.getName(), fmlCorePlugin);
    390//                continue;
    391//            }
    392//            catch (ClassNotFoundException cnfe)
    393//            {
    394//                // didn't find it, good
    395//            }
    396            try
    397            {
    398                classLoader.addURL(coreMod.toURI().toURL());
    399            }
    400            catch (MalformedURLException e)
    401            {
    402                FMLRelaunchLog.log(Level.SEVERE, e, "Unable to convert file into a URL. weird");
    403                continue;
    404            }
    405            try
    406            {
    407                downloadMonitor.updateProgressString("Loading coremod %s", coreMod.getName());
    408                classLoader.addTransformerExclusion(fmlCorePlugin);
    409                Class<?> coreModClass = Class.forName(fmlCorePlugin, true, classLoader);
    410                MCVersion requiredMCVersion = coreModClass.getAnnotation(IFMLLoadingPlugin.MCVersion.class);
    411                String version = "";
    412                if (requiredMCVersion == null)
    413                {
    414                    FMLRelaunchLog.log(Level.WARNING, "The coremod %s does not have a MCVersion annotation, it may cause issues with this version of Minecraft", fmlCorePlugin);
    415                }
    416                else
    417                {
    418                    version = requiredMCVersion.value();
    419                }
    420                if (!"".equals(version) && !FMLInjectionData.mccversion.equals(version))
    421                {
    422                    FMLRelaunchLog.log(Level.SEVERE, "The coremod %s is requesting minecraft version %s and minecraft is %s. It will be ignored.", fmlCorePlugin, version, FMLInjectionData.mccversion);
    423                    continue;
    424                }
    425                else if (!"".equals(version))
    426                {
    427                    FMLRelaunchLog.log(Level.FINE, "The coremod %s requested minecraft version %s and minecraft is %s. It will be loaded.", fmlCorePlugin, version, FMLInjectionData.mccversion);
    428                }
    429                TransformerExclusions trExclusions = coreModClass.getAnnotation(IFMLLoadingPlugin.TransformerExclusions.class);
    430                if (trExclusions!=null)
    431                {
    432                    for (String st : trExclusions.value())
    433                    {
    434                        classLoader.addTransformerExclusion(st);
    435                    }
    436                }
    437                IFMLLoadingPlugin plugin = (IFMLLoadingPlugin) coreModClass.newInstance();
    438                loadPlugins.add(plugin);
    439                pluginLocations .put(plugin, coreMod);
    440                if (plugin.getLibraryRequestClass()!=null)
    441                {
    442                    for (String libName : plugin.getLibraryRequestClass())
    443                    {
    444                        libraries.add((ILibrarySet) Class.forName(libName, true, classLoader).newInstance());
    445                    }
    446                }
    447                downloadMonitor.updateProgressString("Loaded coremod %s", coreMod.getName());
    448            }
    449            catch (ClassNotFoundException cnfe)
    450            {
    451                FMLRelaunchLog.log(Level.SEVERE, cnfe, "Coremod %s: Unable to class load the plugin %s", coreMod.getName(), fmlCorePlugin);
    452            }
    453            catch (ClassCastException cce)
    454            {
    455                FMLRelaunchLog.log(Level.SEVERE, cce, "Coremod %s: The plugin %s is not an implementor of IFMLLoadingPlugin", coreMod.getName(), fmlCorePlugin);
    456            }
    457            catch (InstantiationException ie)
    458            {
    459                FMLRelaunchLog.log(Level.SEVERE, ie, "Coremod %s: The plugin class %s was not instantiable", coreMod.getName(), fmlCorePlugin);
    460            }
    461            catch (IllegalAccessException iae)
    462            {
    463                FMLRelaunchLog.log(Level.SEVERE, iae, "Coremod %s: The plugin class %s was not accessible", coreMod.getName(), fmlCorePlugin);
    464            }
    465        }
    466    }
    467
    468    /**
    469     * @param mcDir the minecraft home directory
    470     * @return the lib directory
    471     */
    472    private static File setupLibDir(File mcDir)
    473    {
    474        File libDir = new File(mcDir,"lib");
    475        try
    476        {
    477            libDir = libDir.getCanonicalFile();
    478        }
    479        catch (IOException e)
    480        {
    481            throw new RuntimeException(String.format("Unable to canonicalize the lib dir at %s", mcDir.getName()),e);
    482        }
    483        if (!libDir.exists())
    484        {
    485            libDir.mkdir();
    486        }
    487        else if (libDir.exists() && !libDir.isDirectory())
    488        {
    489            throw new RuntimeException(String.format("Found a lib file in %s that's not a directory", mcDir.getName()));
    490        }
    491        return libDir;
    492    }
    493
    494    /**
    495     * @param mcDir the minecraft home directory
    496     * @return the coremod directory
    497     */
    498    private static File setupCoreModDir(File mcDir)
    499    {
    500        File coreModDir = new File(mcDir,"coremods");
    501        try
    502        {
    503            coreModDir = coreModDir.getCanonicalFile();
    504        }
    505        catch (IOException e)
    506        {
    507            throw new RuntimeException(String.format("Unable to canonicalize the coremod dir at %s", mcDir.getName()),e);
    508        }
    509        if (!coreModDir.exists())
    510        {
    511            coreModDir.mkdir();
    512        }
    513        else if (coreModDir.exists() && !coreModDir.isDirectory())
    514        {
    515            throw new RuntimeException(String.format("Found a coremod file in %s that's not a directory", mcDir.getName()));
    516        }
    517        return coreModDir;
    518    }
    519
    520    private static void downloadFile(File libFile, String rootUrl,String realFilePath, String hash)
    521    {
    522        try
    523        {
    524            URL libDownload = new URL(String.format(rootUrl,realFilePath));
    525            downloadMonitor.updateProgressString("Downloading file %s", libDownload.toString());
    526            FMLRelaunchLog.info("Downloading file %s", libDownload.toString());
    527            URLConnection connection = libDownload.openConnection();
    528            connection.setConnectTimeout(5000);
    529            connection.setReadTimeout(5000);
    530            connection.setRequestProperty("User-Agent", "FML Relaunch Downloader");
    531            int sizeGuess = connection.getContentLength();
    532            performDownload(connection.getInputStream(), sizeGuess, hash, libFile);
    533            downloadMonitor.updateProgressString("Download complete");
    534            FMLRelaunchLog.info("Download complete");
    535        }
    536        catch (Exception e)
    537        {
    538            if (downloadMonitor.shouldStopIt())
    539            {
    540                FMLRelaunchLog.warning("You have stopped the downloading operation before it could complete");
    541                return;
    542            }
    543            if (e instanceof RuntimeException) throw (RuntimeException)e;
    544            FMLRelaunchLog.severe("There was a problem downloading the file %s automatically. Perhaps you " +
    545                    "have an environment without internet access. You will need to download " +
    546                    "the file manually or restart and let it try again\n", libFile.getName());
    547            libFile.delete();
    548            throw new RuntimeException("A download error occured", e);
    549        }
    550    }
    551
    552    public static List<String> getLibraries()
    553    {
    554        return loadedLibraries;
    555    }
    556
    557    private static ByteBuffer downloadBuffer = ByteBuffer.allocateDirect(1 << 23);
    558    static IDownloadDisplay downloadMonitor;
    559
    560    private static void performDownload(InputStream is, int sizeGuess, String validationHash, File target)
    561    {
    562        if (sizeGuess > downloadBuffer.capacity())
    563        {
    564            throw new RuntimeException(String.format("The file %s is too large to be downloaded by FML - the coremod is invalid", target.getName()));
    565        }
    566        downloadBuffer.clear();
    567
    568        int bytesRead, fullLength = 0;
    569
    570        downloadMonitor.resetProgress(sizeGuess);
    571        try
    572        {
    573            downloadMonitor.setPokeThread(Thread.currentThread());
    574            byte[] smallBuffer = new byte[1024];
    575            while ((bytesRead = is.read(smallBuffer)) >= 0) {
    576                downloadBuffer.put(smallBuffer, 0, bytesRead);
    577                fullLength += bytesRead;
    578                if (downloadMonitor.shouldStopIt())
    579                {
    580                    break;
    581                }
    582                downloadMonitor.updateProgress(fullLength);
    583            }
    584            is.close();
    585            downloadMonitor.setPokeThread(null);
    586            downloadBuffer.limit(fullLength);
    587            downloadBuffer.position(0);
    588        }
    589        catch (InterruptedIOException e)
    590        {
    591            // We were interrupted by the stop button. We're stopping now.. clear interruption flag.
    592            Thread.interrupted();
    593            return;
    594        }
    595        catch (IOException e)
    596        {
    597            throw new RuntimeException(e);
    598        }
    599
    600
    601        try
    602        {
    603            String cksum = generateChecksum(downloadBuffer);
    604            if (cksum.equals(validationHash))
    605            {
    606                downloadBuffer.position(0);
    607                FileOutputStream fos = new FileOutputStream(target);
    608                fos.getChannel().write(downloadBuffer);
    609                fos.close();
    610            }
    611            else
    612            {
    613                throw new RuntimeException(String.format("The downloaded file %s has an invalid checksum %s (expecting %s). The download did not succeed correctly and the file has been deleted. Please try launching again.", target.getName(), cksum, validationHash));
    614            }
    615        }
    616        catch (Exception e)
    617        {
    618            if (e instanceof RuntimeException) throw (RuntimeException)e;
    619            throw new RuntimeException(e);
    620        }
    621
    622
    623
    624    }
    625
    626    private static String generateChecksum(ByteBuffer buffer)
    627    {
    628        return CertificateHelper.getFingerprint(buffer);
    629    }
    630}