PageRenderTime 56ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/core/src/java/com/robonobo/core/RobonoboInstance.java

https://github.com/coltnz/robonobo
Java | 409 lines | 339 code | 49 blank | 21 comment | 22 complexity | e5a8c07c98bec4a996df1d49e6b9551d MD5 | raw file
  1. package com.robonobo.core;
  2. import java.io.*;
  3. import java.util.*;
  4. import java.util.concurrent.ScheduledThreadPoolExecutor;
  5. import java.util.regex.Matcher;
  6. import java.util.regex.Pattern;
  7. import org.apache.commons.logging.Log;
  8. import org.apache.commons.logging.LogFactory;
  9. import org.apache.log4j.PropertyConfigurator;
  10. import com.robonobo.common.concurrent.SafetyNet;
  11. import com.robonobo.common.serialization.ConfigBeanSerializer;
  12. import com.robonobo.common.util.*;
  13. import com.robonobo.core.api.*;
  14. import com.robonobo.core.api.config.RobonoboConfig;
  15. import com.robonobo.core.itunes.ITunesService;
  16. import com.robonobo.core.metadata.AbstractMetadataService;
  17. import com.robonobo.core.mina.MinaService;
  18. import com.robonobo.core.service.*;
  19. import com.robonobo.core.storage.StorageService;
  20. import com.robonobo.core.update.Updater;
  21. import com.robonobo.core.wang.WangService;
  22. import com.robonobo.mina.external.Application;
  23. import com.robonobo.mina.external.MinaControl;
  24. import com.robonobo.spi.RuntimeService;
  25. /** Central class that controls a robonobo instance; handles startup, and holds references to services that do the actual
  26. * work
  27. *
  28. * @author macavity */
  29. public class RobonoboInstance implements Robonobo {
  30. protected String version = "dev-unknown";
  31. protected Log log;
  32. ScheduledThreadPoolExecutor executor;
  33. Map<String, Object> configs = new HashMap<String, Object>();
  34. ServiceManager serviceMgr;
  35. Application thisApplication;
  36. private File homeDir;
  37. private RobonoboStatus status = RobonoboStatus.Stopped;
  38. public RobonoboInstance(String[] args) throws Exception {
  39. loadVersion();
  40. setHomeDir();
  41. initLogging();
  42. updateHomeDir();
  43. loadApplicationDetails();
  44. loadConfig();
  45. overrideConfigWithEnv();
  46. registerServices();
  47. startExecutor();
  48. Platform.getPlatform().initRobonobo(this);
  49. }
  50. public void start() throws RobonoboException {
  51. setStatus(RobonoboStatus.Starting);
  52. serviceMgr.startup();
  53. }
  54. protected void startExecutor() {
  55. if (executor == null) {
  56. int poolSz = getConfig().getGeneralThreadPoolSize();
  57. log.info("Starting thread pool with " + poolSz + " threads");
  58. executor = new ScheduledThreadPoolExecutor(poolSz);
  59. }
  60. }
  61. protected void registerServices() {
  62. serviceMgr = new ServiceManager(RobonoboInstance.this);
  63. serviceMgr.registerService(new EventService());
  64. serviceMgr.registerService(new DbService());
  65. serviceMgr.registerService(new FormatService());
  66. serviceMgr.registerService(new SearchService());
  67. serviceMgr.registerService(new StorageService());
  68. serviceMgr.registerService(new MinaService());
  69. serviceMgr.registerService(new GatewayService());
  70. serviceMgr.registerService(new ShareService());
  71. serviceMgr.registerService(new DownloadService());
  72. serviceMgr.registerService(new TrackService());
  73. serviceMgr.registerService(new PlaybackService());
  74. serviceMgr.registerService(new UserService());
  75. serviceMgr.registerService(new PlaylistService());
  76. serviceMgr.registerService(new TaskService());
  77. serviceMgr.registerService(new LibraryService());
  78. serviceMgr.registerService(new CommentService());
  79. serviceMgr.registerService(new StreamService());
  80. serviceMgr.registerService(new HttpService());
  81. // Register our metadata service as defined in config
  82. String metadataServiceClass = getConfig().getMetadataServiceClass();
  83. try {
  84. Class<?> cl = Class.forName(metadataServiceClass);
  85. AbstractMetadataService svc = (AbstractMetadataService) cl.newInstance();
  86. serviceMgr.registerService(svc);
  87. } catch (ClassNotFoundException e) {
  88. throw new RuntimeException("Could not find metadata service class '" + metadataServiceClass + "'", e);
  89. } catch (InstantiationException e) {
  90. throw new RuntimeException("Error instantiating metadata service class '" + metadataServiceClass + "'", e);
  91. } catch (IllegalAccessException e) {
  92. throw new RuntimeException("Error instantiating metadata service class '" + metadataServiceClass + "'", e);
  93. } catch (ClassCastException e) {
  94. throw new RuntimeException("Metadata service class '" + metadataServiceClass
  95. + "' defined in config does not extend com.robonobo.core.metadata.AbstractMetadataServicew", e);
  96. }
  97. if (getConfig().isAgoric())
  98. serviceMgr.registerService(new WangService());
  99. if (Platform.getPlatform().iTunesAvailable())
  100. serviceMgr.registerService(Platform.getPlatform().getITunesService());
  101. // Extra services defined in config
  102. String[] extraServices = getConfig().getExtraServices().split(",");
  103. for (String serviceClass : extraServices) {
  104. if (serviceClass.trim().length() > 0) {
  105. log.info("Instantiating extra service " + serviceClass);
  106. try {
  107. Class<?> cl = Class.forName(serviceClass);
  108. serviceMgr.registerService((RuntimeService) cl.newInstance());
  109. } catch (ClassNotFoundException e) {
  110. throw new RuntimeException(e);
  111. } catch (InstantiationException e) {
  112. throw new RuntimeException(e);
  113. } catch (IllegalAccessException e) {
  114. throw new RuntimeException(e);
  115. }
  116. }
  117. }
  118. }
  119. protected void loadVersion() throws IOException {
  120. InputStream is = getClass().getResourceAsStream("/robonobo-build.properties");
  121. if (is != null) {
  122. Properties props = new Properties();
  123. props.load(is);
  124. version = props.getProperty("version");
  125. is.close();
  126. }
  127. }
  128. protected void loadConfig() throws IOException {
  129. // Load our core configs
  130. Map<String, String> cfgClasses = new HashMap<String, String>();
  131. cfgClasses.put("robo", "com.robonobo.core.api.config.RobonoboConfig");
  132. cfgClasses.put("mina", "com.robonobo.mina.external.MinaConfig");
  133. cfgClasses.put("wang", "com.robonobo.core.wang.RobonoboWangConfig");
  134. cfgClasses.put("gui", "com.robonobo.gui.GuiConfig");
  135. // Load base robonobo config, that contains class names of any other
  136. // configs we have
  137. File cfgDir = new File(homeDir, "config");
  138. if (!cfgDir.exists())
  139. cfgDir.mkdirs();
  140. for (String cfgName : cfgClasses.keySet()) {
  141. String cfgClassName = cfgClasses.get(cfgName);
  142. loadConfig(cfgName, cfgClassName, cfgDir);
  143. }
  144. String extraCfgStr = getConfig().getExtraConfigs();
  145. if (extraCfgStr.length() > 0) {
  146. String[] extraCfgs = extraCfgStr.split(",");
  147. Pattern cfgPat = Pattern.compile("^(.+):(.+)$");
  148. for (String cfgStr : extraCfgs) {
  149. Matcher m = cfgPat.matcher(cfgStr);
  150. if (!m.matches())
  151. throw new IOException("Invalid config string: " + cfgStr);
  152. String cfgName = m.group(1);
  153. String cfgClassName = m.group(2);
  154. loadConfig(cfgName, cfgClassName, cfgDir);
  155. }
  156. }
  157. // First time through, set the default download dir
  158. if (getConfig().getFinishedDownloadsDirectory() == null) {
  159. File dd = Platform.getPlatform().getDefaultDownloadDirectory();
  160. dd.mkdirs();
  161. String ddPath = dd.getAbsolutePath();
  162. getConfig().setFinishedDownloadsDirectory(ddPath);
  163. }
  164. saveConfig();
  165. }
  166. private void loadConfig(String cfgName, String cfgClassName, File cfgDir) {
  167. ConfigBeanSerializer cbs = new ConfigBeanSerializer();
  168. try {
  169. Class<?> cfgClass = Class.forName(cfgClassName);
  170. File cfgFile = new File(cfgDir, cfgName + ".cfg");
  171. if (cfgFile.exists()) {
  172. log.warn("Loading config from " + cfgFile.getAbsolutePath());
  173. configs.put(cfgName, cbs.deserializeConfig(cfgClass, cfgFile));
  174. } else {
  175. log.warn("Config file " + cfgFile.getAbsolutePath() + " not found - creating new config");
  176. configs.put(cfgName, cfgClass.newInstance());
  177. }
  178. } catch (Exception e) {
  179. log.error("Caught exception loading cfg " + cfgName + ":" + cfgClassName, e);
  180. }
  181. }
  182. private void setHomeDir() {
  183. if (System.getenv().containsKey("RBNB_HOME"))
  184. homeDir = new File(System.getenv("RBNB_HOME"));
  185. else
  186. homeDir = Platform.getPlatform().getDefaultHomeDirectory();
  187. homeDir.mkdirs();
  188. }
  189. public File getHomeDir() {
  190. return homeDir;
  191. }
  192. /** Overrides config properties with values specified in 'cfg_<cfgName>_<propName>' environment vars */
  193. protected void overrideConfigWithEnv() {
  194. ConfigBeanSerializer cbs = new ConfigBeanSerializer();
  195. try {
  196. for (String cfgName : configs.keySet()) {
  197. cbs.overrideCfgFromEnv(configs.get(cfgName), cfgName);
  198. }
  199. } catch (Exception e) {
  200. throw new RuntimeException(e);
  201. }
  202. }
  203. public void shutdown() {
  204. setStatus(RobonoboStatus.Stopping);
  205. serviceMgr.shutdown();
  206. setStatus(RobonoboStatus.Stopped);
  207. }
  208. protected void loadApplicationDetails() {
  209. thisApplication = new Application();
  210. thisApplication.setVersion(version);
  211. thisApplication.setName("robonobo");
  212. thisApplication.setPublisher("The robonobo project");
  213. thisApplication.setHomeUri("http://robonobo.com");
  214. log.info(thisApplication.getName() + "/" + thisApplication.getVersion() + " (" + thisApplication.getPublisher() + ") " + thisApplication.getHomeUri());
  215. }
  216. public Application getApplication() {
  217. return thisApplication;
  218. }
  219. public ShareService getShareService() {
  220. return (ShareService) serviceMgr.getService("core.shares");
  221. }
  222. public TrackService getTrackService() {
  223. return (TrackService) serviceMgr.getService("core.tracks");
  224. }
  225. public TaskService getTaskService() {
  226. return (TaskService) serviceMgr.getService("core.tasks");
  227. }
  228. public LibraryService getLibraryService() {
  229. return (LibraryService) serviceMgr.getService("core.libraries");
  230. }
  231. public ITunesService getITunesService() {
  232. return (ITunesService) serviceMgr.getService("core.itunes");
  233. }
  234. public UserService getUserService() {
  235. return (UserService) serviceMgr.getService("core.users");
  236. }
  237. public PlaylistService getPlaylistService() {
  238. return (PlaylistService) serviceMgr.getService("core.playlists");
  239. }
  240. public CommentService getCommentService() {
  241. return (CommentService) serviceMgr.getService("core.comments");
  242. }
  243. public PlaybackService getPlaybackService() {
  244. return (PlaybackService) serviceMgr.getService("core.playback");
  245. }
  246. public DownloadService getDownloadService() {
  247. return (DownloadService) serviceMgr.getService("core.downloads");
  248. }
  249. public WangService getWangService() {
  250. return (WangService) serviceMgr.getService("core.wang");
  251. }
  252. public RobonoboConfig getConfig() {
  253. return (RobonoboConfig) getConfig("robo");
  254. }
  255. public Object getConfig(String cfgName) {
  256. return configs.get(cfgName);
  257. }
  258. public ScheduledThreadPoolExecutor getExecutor() {
  259. return executor;
  260. }
  261. public DbService getDbService() {
  262. return (DbService) serviceMgr.getService("core.db");
  263. }
  264. // public MetadataService getMetadataService() {
  265. // return (MetadataService) serviceMgr.getService("core.metadata");
  266. // }
  267. public AbstractMetadataService getMetadataService() {
  268. return (AbstractMetadataService) serviceMgr.getService("core.metadata");
  269. }
  270. public HttpService getHttpService() {
  271. return (HttpService) serviceMgr.getService("core.http");
  272. }
  273. public StreamService getStreamService() {
  274. return (StreamService) serviceMgr.getService("core.streams");
  275. }
  276. public MinaControl getMina() {
  277. return ((MinaService) getServiceMgr().getService("core.mina")).getMina();
  278. }
  279. public ServiceManager getServiceMgr() {
  280. return serviceMgr;
  281. }
  282. public StorageService getStorageService() {
  283. return (StorageService) serviceMgr.getService("core.storage");
  284. }
  285. public void addConfig(String name, Object cfg) {
  286. configs.put(name, cfg);
  287. saveConfig();
  288. }
  289. public void saveConfig() {
  290. File configDir = new File(homeDir, "config");
  291. ConfigBeanSerializer cbs = new ConfigBeanSerializer();
  292. for (String cfgName : configs.keySet()) {
  293. File configFile = new File(configDir, cfgName + ".cfg");
  294. try {
  295. log.info("Saving config '" + cfgName + "' to " + configFile.getAbsolutePath());
  296. cbs.serializeConfig(configs.get(cfgName), configFile);
  297. } catch (Exception e) {
  298. log.warn("NOT saving config back to filesystem: " + e.getMessage());
  299. }
  300. }
  301. }
  302. public void setExecutor(ScheduledThreadPoolExecutor executor) {
  303. this.executor = executor;
  304. }
  305. protected void initLogging() {
  306. // This property gets picked up by the log4j config
  307. File logDir = new File(homeDir, "logs");
  308. if (!logDir.exists())
  309. logDir.mkdir();
  310. // Add the old property as well for updating
  311. System.setProperty("robo.log.dir", logDir.getAbsolutePath());
  312. System.setProperty("rbnb.log.dir", logDir.getAbsolutePath());
  313. // If there isn't a log4j properties file in our homedir, copy one from
  314. // the jar
  315. try {
  316. File log4jCfgFile = new File(homeDir, "log4j.properties");
  317. if (!log4jCfgFile.exists()) {
  318. // Note, if we call the props file in the jar "log4j.properties", then log4j will detect and use it,
  319. // ignoring what we have on the filesystem
  320. InputStream is = getClass().getResourceAsStream("/log4j.props.skel");
  321. OutputStream os = new FileOutputStream(log4jCfgFile);
  322. ByteUtil.streamDump(is, os);
  323. }
  324. PropertyConfigurator.configureAndWatch(log4jCfgFile.getAbsolutePath());
  325. log = LogFactory.getLog(getClass());
  326. log.fatal("O HAI! robonobo starting using homedir " + homeDir.getAbsolutePath());
  327. // Log uncaught exceptions in other threads
  328. SafetyNet.addListener(new ExceptionListener() {
  329. public void onException(ExceptionEvent e) {
  330. log.error("Uncaught exception", e.getException());
  331. }
  332. });
  333. } catch (Exception e) {
  334. System.err.println("Error: Unable to initialize log4j logging (caught " + e.getClass().getName() + ": " + e.getMessage() + ")");
  335. }
  336. }
  337. protected void updateHomeDir() throws IOException {
  338. Updater updater = new Updater(homeDir);
  339. updater.runUpdate();
  340. }
  341. public FormatService getFormatService() {
  342. return (FormatService) serviceMgr.getService("core.format");
  343. }
  344. public SearchService getSearchService() {
  345. return (SearchService) serviceMgr.getService("core.search");
  346. }
  347. public String getVersion() {
  348. return version;
  349. }
  350. public EventService getEventService() {
  351. return (EventService) serviceMgr.getService("core.events");
  352. }
  353. public RobonoboStatus getStatus() {
  354. return status;
  355. }
  356. public void setStatus(RobonoboStatus status) {
  357. log.debug("New status: " + status);
  358. this.status = status;
  359. }
  360. }