class HugeFactory {

    private static final Logger LOG = Log.logger(HugeFactory.class);

    private static final Thread SHUT_DOWN_HOOK = new Thread(() -> {
        LOG.info("HugeGraph is shutting down");
        HugeFactory.shutdown(30L, true);
    }, "hugegraph-shutdown");

    static {
        SerialEnum.registerInternalEnums();
        HugeGraph.registerTraversalStrategies(StandardHugeGraph.class);

        Runtime.getRuntime().addShutdownHook(SHUT_DOWN_HOOK);
    }

    private static final String NAME_REGEX = "^[A-Za-z][A-Za-z0-9_]{0,47}$";

    private static final Map<String, HugeGraph> GRAPHS = new HashMap<>();

    private static final AtomicBoolean SHUT_DOWN = new AtomicBoolean(false);

    public static synchronized HugeGraph open(Configuration config) {
        HugeConfig conf = config instanceof HugeConfig ?
                          (HugeConfig) config : new HugeConfig(config);
        return open(conf);
    }

    public static synchronized HugeGraph open(HugeConfig config) {<FILL_FUNCTION_BODY>}

    public static HugeGraph open(String path) {
        return open(getLocalConfig(path));
    }

    public static HugeGraph open(URL url) {
        return open(getRemoteConfig(url));
    }

    public static void remove(HugeGraph graph) {
        String name = graph.option(CoreOptions.STORE);
        GRAPHS.remove(name);
    }

    public static void checkGraphName(String name, String configFile) {
        E.checkArgument(name.matches(NAME_REGEX),
                        "Invalid graph name '%s' in %s, " +
                        "valid graph name is up to 48 alpha-numeric " +
                        "characters and underscores and only letters are " +
                        "supported as first letter. " +
                        "Note: letter is case insensitive", name, configFile);
    }

    public static PropertiesConfiguration getLocalConfig(String path) {
        File file = new File(path);
        E.checkArgument(file.exists() && file.isFile() && file.canRead(),
                        "Please specify a proper config file rather than: %s",
                        file.toString());
        try {
            return new Configurations().properties(file);
        } catch (ConfigurationException e) {
            throw new HugeException("Unable to load config file: %s", e, path);
        }
    }

    public static PropertiesConfiguration getRemoteConfig(URL url) {
        try {
            return new Configurations().properties(url);
        } catch (ConfigurationException e) {
            throw new HugeException("Unable to load remote config file: %s",
                                    e, url);
        }
    }

    public static void shutdown(long timeout) {
        shutdown(timeout, false);
    }

    /**
     * Stop all the daemon threads
     *
     * @param timeout         wait in seconds
     * @param ignoreException don't throw exception if true
     */
    public static void shutdown(long timeout, boolean ignoreException) {
        if (!SHUT_DOWN.compareAndSet(false, true)) {
            return;
        }
        try {
            if (!EventHub.destroy(timeout)) {
                throw new TimeoutException(timeout + "s");
            }
            TaskManager.instance().shutdown(timeout);
            OltpTraverser.destroy();
        } catch (Throwable e) {
            LOG.error("Error while shutdown", e);
            SHUT_DOWN.compareAndSet(true, false);
            if (ignoreException) {
                return;
            } else {
                throw new HugeException("Failed to shutdown", e);
            }
        }

        LOG.info("HugeFactory shutdown");
    }

    public static void removeShutdownHook() {
        Runtime.getRuntime().removeShutdownHook(SHUT_DOWN_HOOK);
    }
}

        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            // Not allowed to read file via Gremlin when SecurityManager enabled
            String configFileName;
            File configFile = config.file();
            if (configFile == null) {
                configFileName = config.toString();
            } else {
                configFileName = configFile.getName();
            }
            sm.checkRead(configFileName);
        }

        String name = config.get(CoreOptions.STORE);
        checkGraphName(name, "graph config(like hugegraph.properties)");
        name = name.toLowerCase();
        HugeGraph graph = GRAPHS.get(name);
        if (graph == null || graph.closed()) {
            graph = new StandardHugeGraph(config);
            GRAPHS.put(name, graph);
        } else {
            String backend = config.get(CoreOptions.BACKEND);
            E.checkState(backend.equalsIgnoreCase(graph.backend()),
                         "Graph name '%s' has been used by backend '%s'",
                         name, graph.backend());
        }
        return graph;
    
<no_super_class>