Java tutorial
/* * Copyright 2015-2018 Jeeva Kandasamy (jkandasa@gmail.com) * and other contributors as indicated by the @author tags. * * Licensed 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.mycontroller.standalone; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.net.URISyntaxException; import java.sql.SQLException; import java.util.ArrayList; import java.util.Properties; import org.apache.commons.io.FileUtils; import org.jboss.resteasy.plugins.server.tjws.TJWSEmbeddedJaxrsServer; import org.jboss.resteasy.spi.ResteasyDeployment; import org.mycontroller.standalone.AppProperties.MC_LANGUAGE; import org.mycontroller.standalone.api.jaxrs.AuthenticationHandler; import org.mycontroller.standalone.api.jaxrs.BackupHandler; import org.mycontroller.standalone.api.jaxrs.DashboardHandler; import org.mycontroller.standalone.api.jaxrs.ExternalServerHandler; import org.mycontroller.standalone.api.jaxrs.FirmwareHandler; import org.mycontroller.standalone.api.jaxrs.ForwardPayloadHandler; import org.mycontroller.standalone.api.jaxrs.GatewayHandler; import org.mycontroller.standalone.api.jaxrs.MetricsHandler; import org.mycontroller.standalone.api.jaxrs.MyControllerHandler; import org.mycontroller.standalone.api.jaxrs.NodeHandler; import org.mycontroller.standalone.api.jaxrs.OSCommandExecuterHandler; import org.mycontroller.standalone.api.jaxrs.OperationHandler; import org.mycontroller.standalone.api.jaxrs.OptionsHandler; import org.mycontroller.standalone.api.jaxrs.ResourcesDataHandler; import org.mycontroller.standalone.api.jaxrs.ResourcesGroupHandler; import org.mycontroller.standalone.api.jaxrs.ResourcesLogsHandler; import org.mycontroller.standalone.api.jaxrs.RoomHandler; import org.mycontroller.standalone.api.jaxrs.RuleHandler; import org.mycontroller.standalone.api.jaxrs.ScriptsHandler; import org.mycontroller.standalone.api.jaxrs.SecurityHandler; import org.mycontroller.standalone.api.jaxrs.SensorHandler; import org.mycontroller.standalone.api.jaxrs.SettingsHandler; import org.mycontroller.standalone.api.jaxrs.TemplatesHandler; import org.mycontroller.standalone.api.jaxrs.TimerHandler; import org.mycontroller.standalone.api.jaxrs.TypesHandler; import org.mycontroller.standalone.api.jaxrs.UidTagHandler; import org.mycontroller.standalone.api.jaxrs.VariablesHandler; import org.mycontroller.standalone.api.jaxrs.exception.mappers.ApplicationExceptionMapper; import org.mycontroller.standalone.api.jaxrs.exception.mappers.BadRequestExceptionMapper; import org.mycontroller.standalone.api.jaxrs.exception.mappers.DefaultOptionsMethodExceptionMapper; import org.mycontroller.standalone.api.jaxrs.exception.mappers.ForbiddenExceptionMapper; import org.mycontroller.standalone.api.jaxrs.exception.mappers.NotAcceptableExceptionMapper; import org.mycontroller.standalone.api.jaxrs.exception.mappers.NotAllowedExceptionMapper; import org.mycontroller.standalone.api.jaxrs.exception.mappers.NotAuthorizedExceptionMapper; import org.mycontroller.standalone.api.jaxrs.exception.mappers.NotFoundExceptionMapper; import org.mycontroller.standalone.api.jaxrs.exception.mappers.NotSupportedExceptionMapper; import org.mycontroller.standalone.api.jaxrs.mixins.McJacksonJson2Provider; import org.mycontroller.standalone.auth.BasicAthenticationSecurityDomain; import org.mycontroller.standalone.auth.McContainerRequestFilter; import org.mycontroller.standalone.db.DataBaseUtils; import org.mycontroller.standalone.externalserver.ExternalServerFactory; import org.mycontroller.standalone.gateway.GatewayUtils; import org.mycontroller.standalone.mdns.McmDNSFactory; import org.mycontroller.standalone.metrics.MetricsUtils; import org.mycontroller.standalone.mqttbroker.MoquetteMqttBroker; import org.mycontroller.standalone.offheap.OffHeapFactory; import org.mycontroller.standalone.scheduler.SchedulerUtils; import org.mycontroller.standalone.scripts.McScriptEngineUtils; import org.mycontroller.standalone.settings.SettingsUtils; import org.mycontroller.standalone.timer.TimerUtils; import org.mycontroller.standalone.utils.McServerFileUtils; import org.mycontroller.standalone.utils.McUtils; import lombok.extern.slf4j.Slf4j; /** * @author Jeeva Kandasamy (jkandasa) * @since 0.0.1 */ @Slf4j public class StartApp { //TJWS Server instance private static final TJWSEmbeddedJaxrsServer server = new TJWSEmbeddedJaxrsServer(); static ResteasyDeployment deployment; static long start; public static void main(String[] args) { try { startMycontroller(); } catch (Exception ex) { _logger.error("Unable to start application, refer error log,", ex); System.exit(1);//Terminate jvm, with non zero } } public static synchronized void startMycontroller() throws ClassNotFoundException, SQLException, URISyntaxException { start = System.currentTimeMillis(); loadInitialProperties(System.getProperty("mc.conf.file")); _logger.debug("App Properties: {}", AppProperties.getInstance().toString()); _logger.debug("Operating System detail:[os:{},arch:{},version:{}]", AppProperties.getOsName(), AppProperties.getOsArch(), AppProperties.getOsVersion()); startServices(); _logger.info("MyController.org server started in [{}] ms", System.currentTimeMillis() - start); } private static void loadStartingValues() { try { // update log file location McServerFileUtils.updateApplicationLogLocation(); // update sunrise/sunset time TimerUtils.updateSunriseSunset(); _logger.debug("Sunrise[{}], Sunset[{}] time updated", TimerUtils.getSunriseTime(), TimerUtils.getSunsetTime()); } catch (Exception ex) { _logger.error("Failed to update sunrise/sunset time", ex); } } //ResteasyDeployment for TJWS server. private static ResteasyDeployment getResteasyDeployment() { if (deployment == null) { deployment = new ResteasyDeployment(); } ArrayList<String> resources = new ArrayList<String>(); resources.add(AuthenticationHandler.class.getName()); resources.add(BackupHandler.class.getName()); resources.add(DashboardHandler.class.getName()); resources.add(ExternalServerHandler.class.getName()); resources.add(FirmwareHandler.class.getName()); resources.add(ForwardPayloadHandler.class.getName()); resources.add(GatewayHandler.class.getName()); resources.add(MetricsHandler.class.getName()); resources.add(MyControllerHandler.class.getName()); resources.add(NodeHandler.class.getName()); resources.add(OperationHandler.class.getName()); resources.add(OSCommandExecuterHandler.class.getName()); resources.add(ResourcesDataHandler.class.getName()); resources.add(ResourcesGroupHandler.class.getName()); resources.add(ResourcesLogsHandler.class.getName()); resources.add(RoomHandler.class.getName()); resources.add(RuleHandler.class.getName()); resources.add(ScriptsHandler.class.getName()); resources.add(SecurityHandler.class.getName()); resources.add(SensorHandler.class.getName()); resources.add(SettingsHandler.class.getName()); resources.add(TemplatesHandler.class.getName()); resources.add(TimerHandler.class.getName()); resources.add(TypesHandler.class.getName()); resources.add(UidTagHandler.class.getName()); resources.add(VariablesHandler.class.getName()); //Add PreFlight handler resources.add(OptionsHandler.class.getName()); //Add Exception mapper(providers) ArrayList<Object> providers = new ArrayList<Object>(); providers.add(new ApplicationExceptionMapper()); providers.add(new BadRequestExceptionMapper()); providers.add(new DefaultOptionsMethodExceptionMapper()); providers.add(new ForbiddenExceptionMapper()); providers.add(new McContainerRequestFilter());//SecurityInterceptor providers.add(new McJacksonJson2Provider()); //Mixin provider providers.add(new NotAcceptableExceptionMapper()); providers.add(new NotAllowedExceptionMapper()); providers.add(new NotAuthorizedExceptionMapper()); providers.add(new NotFoundExceptionMapper()); providers.add(new NotSupportedExceptionMapper()); //Add all resourceClasses deployment.setResourceClasses(resources); //Add all providers deployment.setProviders(providers); return deployment; } private static void startHTTPWebServer() { //Check HTTPS enabled? if (AppProperties.getInstance().isWebHttpsEnabled()) { // Set up SSL connections on server server.setSSLPort(AppProperties.getInstance().getWebHttpPort()); server.setSSLKeyStoreFile(AppProperties.getInstance().getWebSslKeystoreFile()); server.setSSLKeyStorePass(AppProperties.getInstance().getWebSslKeystorePassword()); server.setSSLKeyStoreType(AppProperties.getInstance().getWebSslKeystoreType()); } else { //Set http communication port server.setPort(AppProperties.getInstance().getWebHttpPort()); } if (AppProperties.getInstance().getWebBindAddress() != null) { server.setBindAddress(AppProperties.getInstance().getWebBindAddress()); } //Deploy RestEasy with TJWS server.setDeployment(getResteasyDeployment()); server.addFileMapping("/", new File(AppProperties.getInstance().getWebFileLocation())); //Enable Authentication server.setSecurityDomain(new BasicAthenticationSecurityDomain()); server.getDeployment().setSecurityEnabled(true); server.setRootResourcePath("/mc"); // Start TJWS server server.start(); _logger.info("TJWS server started successfully, HTTPS Enabled?:{}, HTTP(S) Port: [{}]", AppProperties.getInstance().isWebHttpsEnabled(), AppProperties.getInstance().getWebHttpPort()); if (AppProperties.getInstance().isMDNSserviceEnabled()) { McmDNSFactory.updateHttpService(true); } } private static void stopHTTPWebServer() { if (server != null) { server.stop(); _logger.debug("Web server stopped."); } else { _logger.debug("Web server is not running."); } } private static boolean startServices() throws ClassNotFoundException, SQLException, URISyntaxException { //Start order.. // - set to default locale // - Add Shutdown hook // - Start DB service // - Cleanup services // - Initialize MapDB store // - Set to locale actual // - Check password reset file // - Start message Monitor Thread // - Load starting values // - Start MQTT Broker // - Start gateway listener // - Start scheduler // - Start Web Server //Set to default locale McUtils.updateLocale(MC_LANGUAGE.EN_US); //Add Shutdown hook new AppShutdownHook().attachShutDownHook(); //Start DB migration service DataBaseUtils.runDatabaseMigration(); //cleanup services cleanUpServices(); //Load Metric engine factory MetricsUtils.loadEngine(); //Initialize MapDB store //MapDbFactory.init(); OffHeapFactory.init(); //Create or update static json file used for GUI before login SettingsUtils.updateStaticJsonInformationFile(); //Set to locale actual McUtils.updateLocale( MC_LANGUAGE.fromString(AppProperties.getInstance().getControllerSettings().getLanguage())); //List available script engines information McScriptEngineUtils.listAvailableEngines(); //Check password reset file ResetPassword.executeResetPassword(); //Start message Monitor Thread //Create new thread to monitor received logs //MessageMonitorThread messageMonitorThread = new MessageMonitorThread(); //Thread thread = new Thread(messageMonitorThread); //thread.start(); // - Load starting values loadStartingValues(); // - Start MQTT Broker MoquetteMqttBroker.start(); //Start all the gateways GatewayUtils.loadEngineAll(); // - Start scheduler SchedulerUtils.startScheduler(); // - Start Web Server startHTTPWebServer(); return true; } private static void cleanUpServices() { // clean the services // - MQTT client location // - MQTT broker location try { File mqttClientDir = new File(AppProperties.getInstance().getMqttClientPersistentStoresLocation()); if (mqttClientDir.exists()) { FileUtils.cleanDirectory(mqttClientDir); _logger.debug("MQTT Client persistent store cleared. [{}]", mqttClientDir.getCanonicalFile()); } File mqttBrokerDir = new File(AppProperties.getInstance().getMqttBrokerPersistentStore()) .getParentFile(); if (mqttBrokerDir.exists()) { FileUtils.cleanDirectory(mqttBrokerDir); _logger.debug("MQTT broker persistent store cleared. [{}]", mqttBrokerDir.getCanonicalFile()); } } catch (IOException ex) { _logger.error("Exception,", ex); } } public static synchronized void stopServices() { //Stop order.. // - stop web server // - clear external servers // - Stop scheduler // - Stop GatewayTable Listener // - Stop MQTT broker // - Stop message Monitor Thread // - Clear Raw Message Queue (Optional) // - Stop DB service // - Stop metric engine stopHTTPWebServer(); ExternalServerFactory.clearDrivers(); SchedulerUtils.stop(); GatewayUtils.unloadEngineAll(); MoquetteMqttBroker.stop(); DataBaseUtils.stop(); MetricsUtils.shutdownEngine(); OffHeapFactory.close(); McThreadPoolFactory.shutdownNow(); _logger.debug("All services stopped."); //Remove references McObjectManager.clearAllReferences(); } public static boolean loadInitialProperties(String propertiesFile) { try { Properties properties = new Properties(); if (propertiesFile == null) { properties.load(ClassLoader.getSystemClassLoader().getResourceAsStream("mycontroller.properties")); } else { FileReader fileReader = new FileReader(propertiesFile); properties.load(fileReader); fileReader.close(); } AppProperties.getInstance().loadProperties(properties); _logger.debug("Properties are loaded successfuly..."); return true; } catch (IOException ex) { _logger.error("Exception while loading properties file, ", ex); return false; } } }