/* * Galaxy * Copyright (c) 2012-2014, Parallel Universe Software Co. All rights reserved. * * This program and the accompanying materials are dual-licensed under * either the terms of the Eclipse Public License v1.0 as published by * the Eclipse Foundation * * or (per the licensee's choosing) * * under the terms of the GNU Lesser General Public License version 3.0 * as published by the Free Software Foundation. */ package co.paralleluniverse.galaxy; import co.paralleluniverse.common.spring.Service; import co.paralleluniverse.common.spring.SpringContainerHelper; import co.paralleluniverse.galaxy.core.*; import co.paralleluniverse.galaxy.core.Cache; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.Resource; import org.springframework.core.io.UrlResource; import java.net.URL; import java.util.Properties; /** * The central access point to the grid's services (the word <i>grid</i> describes the collection distributed of software provided * in the physical node <i>cluster</i>). */ public class Grid { private static Grid instance = null; private final static Object lock = new Object(); /** * Retrieves the named grid instance, as specified in the default configuration file. * * @return The grid instance. */ public static Grid getInstance() throws InterruptedException { return getInstance(null, (Object) null); } /** * Retrieves the grid instance, as defined in the given configuration file. * * @param configFile The name of the configuration file containing the grid definition. * @param propertiesFile The name of the properties file containing the grid's properties. You may, of course use Spring's {@code <context:property-placeholder location="classpath:com/foo/bar.properties"/>} * but this parameter is helpful when you want to use the same xml configuration with different properties for different * instances. * @return The grid instance. */ public static Grid getInstance(String configFile, String propertiesFile) throws InterruptedException { return getInstance(configFile == null ? null : new FileSystemResource(configFile), propertiesFile); } /** * Retrieves the grid instance, as defined in the given configuration file. * * @param configFile The name of the configuration file containing the grid definition. * @param properties A {@link Properties Properties} object containing the grid's properties to be injected into placeholders * in the configuration file. * This parameter is helpful when you want to use the same xml configuration with different properties for different * instances. * @return The grid instance. */ public static Grid getInstance(String configFile, Properties properties) throws InterruptedException { return getInstance(configFile == null ? null : new FileSystemResource(configFile), (Object) properties); } /** * Retrieves the grid instance, as defined in the given configuration file. * * @param configFile The name of the configuration file containing the grid definition. * @param propertiesFile The name of the properties file containing the grid's properties. You may, of course use Spring's {@code <context:property-placeholder location="classpath:com/foo/bar.properties"/>} * but this parameter is helpful when you want to use the same xml configuration with different properties for different * instances. * @return The grid instance. */ public static Grid getInstance(URL configFile, URL propertiesFile) throws InterruptedException { return getInstance(new UrlResource(configFile), propertiesFile); } /** * Retrieves the grid instance, as defined in the given configuration file. * * @param configFile The name of the configuration file containing the grid definition. * @param properties A {@link Properties Properties} object containing the grid's properties to be injected into placeholders * in the configuration file. * This parameter is helpful when you want to use the same xml configuration with different properties for different * instances. * @return The grid instance. */ public static Grid getInstance(URL configFile, Properties properties) throws InterruptedException { return getInstance(new UrlResource(configFile), properties); } private static Grid getInstance(Resource configFile, Object properties) throws InterruptedException { synchronized (lock) { Grid _instance = instance; if (_instance == null) { _instance = new Grid(configFile, properties); if (_instance == null) throw new RuntimeException("Error while creating a grid instance from configuration file " + configFile + "!"); instance = _instance; if (Boolean.getBoolean("co.paralleluniverse.galaxy.autoGoOnline")) instance.goOnline(); } return _instance; } } ///////////////////////////////////// private final ApplicationContext context; private final Messenger messenger; private final Backup backup; private final Cache cache; private final Store store; private final Cluster cluster; private final ClusterMonitor clusterMonitor; private Grid(Resource configFile, Object properties) throws InterruptedException { if (configFile == null) { String propertyConfigFile = System.getProperty("co.paralleluniverse.galaxy.configFile"); if (propertyConfigFile != null) { configFile = new FileSystemResource(propertyConfigFile); } else { configFile = new ClassPathResource("galaxy.xml"); } } if (properties == null) properties = System.getProperty("co.paralleluniverse.galaxy.propertiesFile"); if (properties instanceof String) properties = new FileSystemResource((String) properties); if (properties instanceof URL) properties = new UrlResource((URL)properties); this.context = SpringContainerHelper.createContext("co.paralleluniverse.galaxy", configFile, properties, new BeanFactoryPostProcessor() { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory1) throws BeansException { final DefaultListableBeanFactory beanFactory = ((DefaultListableBeanFactory) beanFactory1); // messenger // BeanDefinition messengerBeanDefinition = SpringContainerHelper.defineBean( // MessengerImpl.class, // SpringContainerHelper.constructorArgs("messenger", new RuntimeBeanReference("cache")), // null); // messengerBeanDefinition.setDependsOn(new String[]{"cache"}); // beanFactory.registerBeanDefinition("messenger", messengerBeanDefinition); //beanFactory.registerSingleton(name, object); } }); this.cluster = context.getBean("cluster", Cluster.class); this.clusterMonitor = new ClusterMonitor(cluster); this.backup = context.getBean("backup", Backup.class); this.cache = context.getBean("cache", Cache.class); this.store = new StoreImpl(cache); this.messenger = context.getBean("messenger", Messenger.class); // new MessengerImpl(cache); } /** * Returns the grid's distributed data-store service. * * @return The grid's distributed data-store service. */ public Store store() { return store; } /** * Returns the grid's messaging service. * * @return The grid's messaging service. */ public Messenger messenger() { return messenger; } /** * Returns the grid's cluster management and node lifecycle service. * * @return The grid's cluster management and node lifecycle service. */ public Cluster cluster() { return cluster; } /** * Makes this node a full participant in the cluster (rather than just an observer). */ public void goOnline() throws InterruptedException { ((Service) backup).awaitAvailable(); ((AbstractCluster) cluster).goOnline(); cache.awaitAvailable(); } }