Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.grouter.core; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.apache.log4j.NDC; import org.grouter.common.config.XmlConfigHandler; import org.grouter.core.config.ConfigFactory; import org.grouter.core.util.SchedulerService; import org.grouter.core.util.file.FileUtils; import org.grouter.domain.RouterCache; import org.grouter.domain.entities.*; import org.grouter.domain.service.RouterService; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.remoting.rmi.RmiServiceExporter; import java.io.File; import java.io.IOException; import java.rmi.RemoteException; import java.util.Date; /** * Main class for grouter - parses config file, updates database, exposes remote interface, * fires of jobs, schedules nodes etc. * <p/> * Implements an interface exposed for remote clients. * <p/> * Adds shutdown hook to vm so that we get to write an email when we close down gracefully * using ctrl+c (win) or kill -15 (*nix). * * @author Georges Polyzois */ final public class RouterServerImpl implements Runnable, RemoteRouterService { private static Logger logger = Logger.getLogger(RouterServerImpl.class); // spring context ApplicationContext context; // handler for configuration file private XmlConfigHandler xmlConfigHandler; private Router router; // scheduler service handles start / stop etc of nodes private static SchedulerService schedulerService; // operation against database are handled through this service static RouterService routerService; private static final String ROUTER_SERVICE = "routerService"; private static final String RMI_SERVICE_EXPORTER_FACTORY_BEAN = "rmiServiceExporterFactoryBean"; public RouterServerImpl() { } /** * Constructor with a config path parameter. * * @param configPath * @throws IllegalArgumentException if configPath == null */ public RouterServerImpl(String configPath) { if (!FileUtils.isValidFile(configPath)) { throw new IllegalArgumentException("Invalid path given to config file!!! Path was " + configPath); } try { logger.info("Using config path : " + configPath); readConfiguration(configPath); overrideContext(); initApplicationContext(); forceMakeDirectories(); RouterCache.init(router); updatePersistentState(); // initRmi(); logger.info(router.printNodes()); logStatus(); } catch (Exception ex) { logger.error("Failed setup - exiting", ex); System.exit(0); } } private void readConfiguration(final String configPath) { logger.info("Parsing config xml for router"); xmlConfigHandler = new XmlConfigHandler(configPath, null); router = ConfigFactory.createRouter(xmlConfigHandler.getGrouterConfigDocument().getGrouter()); logger.info("Parsing completed. Router config was read."); } /** * Load config file and store reference for further processing of config data. */ private void initApplicationContext() throws Exception { logger.info("Initializing router context"); context = new ClassPathXmlApplicationContext(getConfigLocations()); routerService = (RouterService) context.getBean(ROUTER_SERVICE); schedulerService = new SchedulerService(router.getNodes()); } /** * Override properties set in Spring context files. */ private void overrideContext() { String driverClassName = (String) router.getSettings().getSettingsContext() .get(SettingsContext.KEY_SETTINGS_DATASOURCE_DRIVERCLASSNAME); String url = (String) router.getSettings().getSettingsContext() .get(SettingsContext.KEY_SETTINGS_DATASOURCE_URL); String userName = (String) router.getSettings().getSettingsContext() .get(SettingsContext.KEY_SETTINGS_DATASOURCE_USERNAME); String password = (String) router.getSettings().getSettingsContext() .get(SettingsContext.KEY_SETTINGS_DATASOURCE_PASSWORD); if (StringUtils.isNotEmpty(driverClassName) && StringUtils.isNotEmpty(url) && StringUtils.isNotEmpty(userName) && StringUtils.isNotEmpty(password)) { logger.info("Overriding datasource context from router config file"); logger.info( "Overriding datasource context from router config file: grouter.db.driver=" + driverClassName); System.setProperty("grouter.db.driver", driverClassName); logger.info("Overriding datasource context from router config file: grouter.db.url=" + url); System.setProperty("grouter.db.url", url); logger.info("Overriding datasource context from router config file: grouter.db.username=" + userName); System.setProperty("grouter.db.username", userName); logger.info("Overriding datasource context from router config file: grouter.db.password=" + password); System.setProperty("grouter.db.password", password); } final String registryPort = Integer.toString(router.getRmiRegistryPort()); final String rmiSericePort = Integer.toString(router.getRmiServicePort()); if (StringUtils.isNotEmpty(rmiSericePort) && StringUtils.isNotEmpty(registryPort)) { logger.info("Overriding rmi properties in context files from grouter config"); logger.info("grouter.rmi.registryPort:" + registryPort); System.setProperty("grouter.rmi.registryPort", registryPort); logger.info("grouter.rmi.servicePort:" + rmiSericePort); System.setProperty("grouter.rmi.servicePort", rmiSericePort); } } /** * Save configuration of raouter in database and also update any nodes that do not have * a parent. */ private void updatePersistentState() { logger.info("Saving router state in database"); AuditInfo auditInfo = new AuditInfo(); auditInfo.setModifiedOn(new Date()); auditInfo.setModifiedBy(User.ADMIN.getId()); router.setAuditInfo(auditInfo); routerService.saveRouter(router); routerService.updateStateForNotConfiguredNodes(router.getId(), router.getNodes()); logger.info("Router state saved in database"); } private void forceCreateHomePathOnStartUp() { } /** * If there is a rmi port configured then we register the router in jndi. * <p/> * Lookup up bean in context and use our config files parameters to set * port etc and finally call prepare to fire things up. */ private void initRmi() { logger.info("Check if we are to register as RMI service"); if (router.getRmiRegistryPort() > 0 || router.getRmiServicePort() > 0) { try { logger.info("Trying to register in router as RMI service jndi"); logger.info("Rmiregistryport :" + router.getRmiRegistryPort()); logger.info("Rmiserviceport :" + router.getRmiServicePort()); logger.debug("Get rmi exporter bean from context :" + RMI_SERVICE_EXPORTER_FACTORY_BEAN); RmiServiceExporter rmiServiceExporter = (RmiServiceExporter) context .getBean(RMI_SERVICE_EXPORTER_FACTORY_BEAN); rmiServiceExporter.setRegistryPort(router.getRmiRegistryPort()); rmiServiceExporter.setServicePort(router.getRmiServicePort()); logger.debug("Calling prepare on rmi exporter"); rmiServiceExporter.prepare(); logger.info("Registered ok as RMI service jndi"); } catch (RemoteException e) { logger.error("Failed to register router as RMI service in JNDI", e); } } else { logger.info("Router was no tconfigured to use RMI - rmi ports missing in config file"); } } private void logStatus() { logger.info("Startup statistics"); logger.info("Number of nodes in conf file :" + router.getNodes().size()); for (Node node : router.getNodes()) { logger.info("{id=" + node.getId() + ",name=" + node.getDisplayName() + "}"); } } /** * Start up all nodes and add shutdown hook in JVM. * * @throws Exception */ public void start() throws Exception { schedulerService.startAllNodes(); // update the status of the nodes routerService.saveRouter(router); Thread thr = new Thread(this); logger.info("Adding shutdown hook"); // Runtime.getRuntime().addShutdownHook( thr ); thr.start(); } /** * Called by vm when when we get a controlled exit. */ public void onExit() { logger.debug("Exiting grouter..."); NDC.remove(); // sendEmail(); } /** * Called by vm when when we get a controlled exit. */ public void run() { logger.info("In run"); while (true) { try { Thread.sleep(2000); } catch (Exception e) { logger.warn("Thread got an exception : " + e.getMessage()); } } //onExit(); } // todo do checks ofr other endpoint types - if a ftp type try to ping it ,.... private void forceMakeDirectories() { String homePath = router.getHomePath(); for (Node node : router.getNodes()) { if (node.getCreateDirectories().booleanValue() == true) { logger.info("Trying to create node directories. Path for this node:" + homePath + node.getId()); String pathInternalIn = null; try { // Internal in directories pathInternalIn = homePath + File.separator + "nodes" + File.separator + node.getId() + File.separator + "internal" + File.separator + "in"; org.apache.commons.io.FileUtils.forceMkdir(new File(pathInternalIn)); logger.info("Created node path:" + homePath + node.getId()); } catch (IOException e) { logger.error("Could not create directory for :" + pathInternalIn); } String pathInternalOut = null; try { //Internal out pathInternalOut = homePath + File.separator + "nodes" + File.separator + node.getId() + File.separator + "internal" + File.separator + "out"; org.apache.commons.io.FileUtils.forceMkdir(new File(pathInternalOut)); logger.info("Created node path:" + homePath + node.getId()); } catch (IOException ex) { logger.error("Could not create directory for :" + pathInternalOut); } if (node.getInBound().getEndPointType().equals(EndPointType.FILE_READER)) { String internalInPath = null; try { internalInPath = homePath + File.separator + "nodes" + File.separator + node.getId() + File.separator + "in"; org.apache.commons.io.FileUtils.forceMkdir(new File(internalInPath)); logger.info("Created node path:" + homePath + node.getId()); } catch (IOException e) { logger.error("Could not create directory for :" + internalInPath); } } } else { logger.info("Not creating directories for node:" + node.getId()); } } } /** * Context files which will be loaded be the grouter on startup. * * @return */ protected String[] getConfigLocations() { return new String[] { "context-domain-aop.xml", "context-domain-datasource.xml", "context-domain-service.xml", "context-domain-dao.xml", "context-domain-sessionfactory.xml", "context-router.xml"//, "context-router-rmi.xml" }; } /** * Delegates to scheduler service for stopping a node after looking up a node in db. * * @param nodeId id of node to stop * @throws RemoteException if we encounter som exception trying to stop a node */ public void stopNode(String nodeId) throws RemoteException { Node node = routerService.findNodeById(nodeId); logger.info("Stopping node :" + node.getId()); try { schedulerService.stop(node); } catch (Exception e) { throw new RemoteException("Could not stop the node :" + nodeId + " Got exception :" + e.getMessage()); } } public static void main(String[] args) { try { String configPath = System.getProperty("grouter.configfile"); File configFile = new File(configPath); RouterServerImpl router = new RouterServerImpl(configFile.getPath()); router.start(); } catch (Exception e) { e.printStackTrace(); } } }