Search in sources :

Example 1 with ATTRIBUTE_KEY_SAFE_MODE

use of org.pepsoft.worldpainter.Constants.ATTRIBUTE_KEY_SAFE_MODE in project WorldPainter by Captain-Chaos.

the class Main method main.

/**
 * @param args the command line arguments
 */
public static void main(String[] args) throws IOException {
    // Force language to English for now. TODO: remove this once the first
    // translations are implemented
    Locale.setDefault(Locale.US);
    System.setProperty("sun.awt.exception.handler", ExceptionHandler.class.getName());
    Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler());
    // Configure logging
    String logLevel;
    if ("true".equalsIgnoreCase(System.getProperty("org.pepsoft.worldpainter.debugLogging"))) {
        logLevel = "DEBUG";
    } else if ("extra".equalsIgnoreCase(System.getProperty("org.pepsoft.worldpainter.debugLogging"))) {
        logLevel = "TRACE";
    } else {
        logLevel = "INFO";
    }
    File configDir = Configuration.getConfigDir();
    if (!configDir.isDirectory()) {
        configDir.mkdirs();
    }
    LoggerContext logContext = (LoggerContext) LoggerFactory.getILoggerFactory();
    try {
        JoranConfigurator configurator = new JoranConfigurator();
        configurator.setContext(logContext);
        logContext.reset();
        System.setProperty("org.pepsoft.worldpainter.configDir", configDir.getAbsolutePath());
        System.setProperty("org.pepsoft.worldpainter.logLevel", logLevel);
        configurator.doConfigure(ClassLoader.getSystemResourceAsStream("logback-main.xml"));
    } catch (JoranException e) {
    // StatusPrinter will handle this
    }
    StatusPrinter.printInCaseOfErrorsOrWarnings(logContext);
    SLF4JBridgeHandler.removeHandlersForRootLogger();
    SLF4JBridgeHandler.install();
    logger.info("Starting WorldPainter " + Version.VERSION + " (" + Version.BUILD + ")");
    // Parse the command line
    File myFile = null;
    boolean mySafeMode = false;
    for (String arg : args) {
        if (arg.trim().toLowerCase().equals("--safe")) {
            mySafeMode = true;
            logger.info("WorldPainter running in safe mode");
        } else if (new File(arg).isFile()) {
            myFile = new File(args[0]);
        }
    }
    final File file = myFile;
    boolean safeMode = mySafeMode;
    // Set the acceleration mode. For some reason we don't fully understand,
    // loading the Configuration from disk initialises Java2D, so we have to
    // do this *before* then.
    // But only do this if a config file exists. If it does not, someone may
    // be trying to reset the configuration, so make sure that the
    // acceleration type setting is reset too in that case.
    AccelerationType accelerationType;
    if (Configuration.getConfigFile().isFile()) {
        String accelTypeName = Preferences.userNodeForPackage(Main.class).get("accelerationType", null);
        if (accelTypeName != null) {
            accelerationType = AccelerationType.valueOf(accelTypeName);
        } else {
            accelerationType = AccelerationType.DEFAULT;
        // TODO: Experiment with which ones work well and use them by default!
        }
        if (!safeMode) {
            switch(accelerationType) {
                case UNACCELERATED:
                    // Try to disable all accelerated pipelines we know of:
                    System.setProperty("sun.java2d.d3d", "false");
                    System.setProperty("sun.java2d.opengl", "false");
                    System.setProperty("sun.java2d.xrender", "false");
                    System.setProperty("apple.awt.graphics.UseQuartz", "false");
                    logger.info("Hardware acceleration method: unaccelerated");
                    break;
                case DIRECT3D:
                    // Direct3D should already be the default on Windows, but
                    // enable a few things which are off by default:
                    System.setProperty("sun.java2d.translaccel", "true");
                    System.setProperty("sun.java2d.ddscale", "true");
                    logger.info("Hardware acceleration method: Direct3D");
                    break;
                case OPENGL:
                    System.setProperty("sun.java2d.opengl", "True");
                    logger.info("Hardware acceleration method: OpenGL");
                    break;
                case XRENDER:
                    System.setProperty("sun.java2d.xrender", "True");
                    logger.info("Hardware acceleration method: XRender");
                    break;
                case QUARTZ:
                    System.setProperty("apple.awt.graphics.UseQuartz", "true");
                    logger.info("Hardware acceleration method: Quartz");
                    break;
                default:
                    logger.info("Hardware acceleration method: default");
                    break;
            }
        }
    } else {
        accelerationType = AccelerationType.DEFAULT;
        if (!safeMode) {
            logger.info("Hardware acceleration method: default");
        }
    }
    if (safeMode) {
        logger.info("[SAFE MODE] Hardware acceleration method: default");
    }
    // Load or initialise configuration
    Configuration config = null;
    try {
        // This will migrate the configuration directory if necessary
        config = Configuration.load();
    } catch (IOException | Error | RuntimeException | ClassNotFoundException e) {
        configError(e);
    }
    if (config == null) {
        if (!logger.isDebugEnabled()) {
            // If debug logging is on, the Configuration constructor will
            // already log this
            logger.info("Creating new configuration");
        }
        config = new Configuration();
    }
    Configuration.setInstance(config);
    logger.info("Installation ID: " + config.getUuid());
    // Store the acceleration type in the config object so the Preferences
    // dialog can edit it
    config.setAccelerationType(accelerationType);
    // Start background scan for Minecraft jars
    BiomeSchemeManager.initialiseInBackground();
    // Load and install trusted WorldPainter root certificate
    X509Certificate trustedCert = null;
    try {
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        trustedCert = (X509Certificate) certificateFactory.generateCertificate(Main.class.getResourceAsStream("/wproot.pem"));
        WPTrustManager trustManager = new WPTrustManager(trustedCert);
        SSLContext sslContext = SSLContext.getInstance("SSL");
        sslContext.init(null, new TrustManager[] { trustManager }, new SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
    } catch (CertificateException e) {
        logger.error("Certificate exception while loading trusted root certificate", e);
    } catch (NoSuchAlgorithmException e) {
        logger.error("No such algorithm exception while loading trusted root certificate", e);
    } catch (KeyManagementException e) {
        logger.error("Key management exception while loading trusted root certificate", e);
    }
    // Load the plugins
    if (!safeMode) {
        if (trustedCert != null) {
            PluginManager.loadPlugins(new File(configDir, "plugins"), trustedCert.getPublicKey());
        } else {
            logger.error("Trusted root certificate not available; not loading plugins");
        }
    } else {
        logger.info("[SAFE MODE] Not loading plugins");
    }
    WPPluginManager.initialise(config.getUuid());
    String httpAgent = "WorldPainter " + Version.VERSION + "; " + System.getProperty("os.name") + " " + System.getProperty("os.version") + " " + System.getProperty("os.arch") + ";";
    System.setProperty("http.agent", httpAgent);
    // WorldPainter to perform, such as check for updates and submit usage data
    for (PrivateContext aPrivateContextLoader : ServiceLoader.load(PrivateContext.class)) {
        if (privateContext == null) {
            privateContext = aPrivateContextLoader;
        } else {
            throw new IllegalStateException("More than one private context found on classpath");
        }
    }
    if (privateContext == null) {
        logger.debug("No private context found on classpath; update checks and usage data submission disabled");
        config.setPingAllowed(false);
    }
    // Check for updates (if update checker is available)
    if (privateContext != null) {
        privateContext.checkForUpdates();
    }
    final long start = System.currentTimeMillis();
    config.setLaunchCount(config.getLaunchCount() + 1);
    Runtime.getRuntime().addShutdownHook(new Thread("Configuration Saver") {

        @Override
        public void run() {
            try {
                Configuration config = Configuration.getInstance();
                MouseOrTabletOperation.flushEvents(config);
                BetterAction.flushEvents(config);
                EventVO sessionEvent = new EventVO("worldpainter.session").setAttribute(EventVO.ATTRIBUTE_TIMESTAMP, new Date(start)).duration(System.currentTimeMillis() - start);
                StringBuilder sb = new StringBuilder();
                List<Plugin> plugins = WPPluginManager.getInstance().getAllPlugins();
                plugins.stream().filter(plugin -> !(plugin.getName().equals("Default") || plugin.getName().equals("DefaultPlatforms") || plugin.getName().equals("DefaultCustomObjects") || plugin.getName().equals("DefaultLayerEditorProvider"))).forEach(plugin -> {
                    if (sb.length() > 0) {
                        sb.append(',');
                    }
                    sb.append("{name=");
                    sb.append(plugin.getName().replaceAll("[ \\t\\n\\x0B\\f\\r\\.]", ""));
                    sb.append(",version=");
                    sb.append(plugin.getVersion());
                    sb.append('}');
                });
                if (sb.length() > 0) {
                    sessionEvent.setAttribute(ATTRIBUTE_KEY_PLUGINS, sb.toString());
                }
                sessionEvent.setAttribute(ATTRIBUTE_KEY_SAFE_MODE, safeMode);
                config.logEvent(sessionEvent);
                config.save();
                // Store the acceleration type separately, because we need
                // it before we can load the config:
                Preferences prefs = Preferences.userNodeForPackage(Main.class);
                prefs.put("accelerationType", config.getAccelerationType().name());
                prefs.flush();
            } catch (IOException e) {
                logger.error("I/O error saving configuration", e);
            } catch (BackingStoreException e) {
                logger.error("Backing store exception saving acceleration type", e);
            }
            logger.info("Shutting down WorldPainter");
        }
    });
    // Make the "action:" and "bitcoin:" URLs used in various places work:
    URL.setURLStreamHandlerFactory(protocol -> {
        switch(protocol) {
            case "action":
                return new URLStreamHandler() {

                    @Override
                    protected URLConnection openConnection(URL u) throws IOException {
                        throw new UnsupportedOperationException("Not supported");
                    }
                };
            case "bitcoin":
                return new URLStreamHandler() {

                    @Override
                    protected URLConnection openConnection(URL u) throws IOException {
                        throw new UnsupportedOperationException("Not supported");
                    }
                };
            default:
                return null;
        }
    });
    final World2 world;
    if (file == null) {
        world = WorldFactory.createDefaultWorld(config, new Random().nextLong());
    // world = WorldFactory.createFancyWorld(config, new Random().nextLong());
    } else {
        world = null;
    }
    // Install JIDE licence, if present
    InputStream in = ClassLoader.getSystemResourceAsStream("jide_licence.properties");
    if (in != null) {
        try {
            Properties jideLicenceProps = new Properties();
            jideLicenceProps.load(in);
            Lm.verifyLicense(jideLicenceProps.getProperty("companyName"), jideLicenceProps.getProperty("projectName"), jideLicenceProps.getProperty("licenceKey"));
        } finally {
            in.close();
        }
    }
    final Configuration.LookAndFeel lookAndFeel = (config.getLookAndFeel() != null) ? config.getLookAndFeel() : Configuration.LookAndFeel.SYSTEM;
    SwingUtilities.invokeLater(() -> {
        // Install configured look and feel
        try {
            String laf;
            if ((GUIUtils.UI_SCALE > 1) || safeMode) {
                laf = UIManager.getSystemLookAndFeelClassName();
            } else {
                switch(lookAndFeel) {
                    case SYSTEM:
                        laf = UIManager.getSystemLookAndFeelClassName();
                        break;
                    case METAL:
                        laf = "javax.swing.plaf.metal.MetalLookAndFeel";
                        break;
                    case NIMBUS:
                        laf = "javax.swing.plaf.nimbus.NimbusLookAndFeel";
                        break;
                    case DARK_METAL:
                        laf = "org.netbeans.swing.laf.dark.DarkMetalLookAndFeel";
                        break;
                    case DARK_NIMBUS:
                        laf = "org.netbeans.swing.laf.dark.DarkNimbusLookAndFeel";
                        break;
                    default:
                        throw new InternalError();
                }
            }
            if (safeMode) {
                logger.info("[SAFE MODE] Installing system visual theme");
            }
            logger.debug("Installing look and feel: " + laf);
            UIManager.setLookAndFeel(laf);
            LookAndFeelFactory.installJideExtension();
            if ((GUIUtils.UI_SCALE == 1) && ((lookAndFeel == Configuration.LookAndFeel.DARK_METAL) || (lookAndFeel == Configuration.LookAndFeel.DARK_NIMBUS)) && (!safeMode)) {
                // Patch some things to make dark themes look better
                VoidRenderer.setColour(UIManager.getColor("Panel.background").getRGB());
                if (lookAndFeel == Configuration.LookAndFeel.DARK_METAL) {
                    UIManager.put("ContentContainer.background", UIManager.getColor("desktop"));
                    UIManager.put("JideTabbedPane.foreground", new Color(222, 222, 222));
                }
            }
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {
            logger.warn("Could not install selected look and feel", e);
        }
        // Don't paint values above sliders in GTK look and feel
        UIManager.put("Slider.paintValue", Boolean.FALSE);
        final App app = App.getInstance();
        app.setVisible(true);
        // Swing quirk:
        if (Configuration.getInstance().isMaximised() && (System.getProperty("org.pepsoft.worldpainter.size") == null)) {
            app.setExtendedState(Frame.MAXIMIZED_BOTH);
        }
        // Do this later to give the app the chance to properly set
        // itself up
        SwingUtilities.invokeLater(() -> {
            if (world != null) {
                // On a Mac we may be doing this unnecessarily because we
                // may be opening a .world file, but it has proven difficult
                // to detect that. TODO
                app.setWorld(world);
            } else {
                app.open(file);
            }
            DonationDialog.maybeShowDonationDialog(app);
        });
    });
}
Also used : X509Certificate(java.security.cert.X509Certificate) SSLContext(javax.net.ssl.SSLContext) java.util(java.util) JoranConfigurator(ch.qos.logback.classic.joran.JoranConfigurator) PluginManager(org.pepsoft.util.PluginManager) CertificateFactory(java.security.cert.CertificateFactory) URL(java.net.URL) EventVO(org.pepsoft.worldpainter.vo.EventVO) LoggerFactory(org.slf4j.LoggerFactory) TrustManager(javax.net.ssl.TrustManager) BackingStoreException(java.util.prefs.BackingStoreException) LoggerContext(ch.qos.logback.classic.LoggerContext) SLF4JBridgeHandler(org.slf4j.bridge.SLF4JBridgeHandler) Lm(com.jidesoft.utils.Lm) VoidRenderer(org.pepsoft.worldpainter.layers.renderers.VoidRenderer) SecureRandom(java.security.SecureRandom) URLConnection(java.net.URLConnection) GUIUtils(org.pepsoft.util.GUIUtils) ATTRIBUTE_KEY_PLUGINS(org.pepsoft.worldpainter.Constants.ATTRIBUTE_KEY_PLUGINS) BetterAction(org.pepsoft.worldpainter.util.BetterAction) BiomeSchemeManager(org.pepsoft.worldpainter.biomeschemes.BiomeSchemeManager) HttpsURLConnection(javax.net.ssl.HttpsURLConnection) ATTRIBUTE_KEY_SAFE_MODE(org.pepsoft.worldpainter.Constants.ATTRIBUTE_KEY_SAFE_MODE) WPTrustManager(org.pepsoft.worldpainter.browser.WPTrustManager) MouseOrTabletOperation(org.pepsoft.worldpainter.operations.MouseOrTabletOperation) IOException(java.io.IOException) KeyManagementException(java.security.KeyManagementException) CertificateException(java.security.cert.CertificateException) StatusPrinter(ch.qos.logback.core.util.StatusPrinter) File(java.io.File) Preferences(java.util.prefs.Preferences) java.awt(java.awt) LookAndFeelFactory(com.jidesoft.plaf.LookAndFeelFactory) URLStreamHandler(java.net.URLStreamHandler) List(java.util.List) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) JoranException(ch.qos.logback.core.joran.spi.JoranException) Plugin(org.pepsoft.worldpainter.plugins.Plugin) WPPluginManager(org.pepsoft.worldpainter.plugins.WPPluginManager) javax.swing(javax.swing) InputStream(java.io.InputStream) CertificateException(java.security.cert.CertificateException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) SecureRandom(java.security.SecureRandom) JoranConfigurator(ch.qos.logback.classic.joran.JoranConfigurator) List(java.util.List) EventVO(org.pepsoft.worldpainter.vo.EventVO) SecureRandom(java.security.SecureRandom) X509Certificate(java.security.cert.X509Certificate) URLStreamHandler(java.net.URLStreamHandler) File(java.io.File) CertificateFactory(java.security.cert.CertificateFactory) KeyManagementException(java.security.KeyManagementException) URL(java.net.URL) JoranException(ch.qos.logback.core.joran.spi.JoranException) Preferences(java.util.prefs.Preferences) WPTrustManager(org.pepsoft.worldpainter.browser.WPTrustManager) InputStream(java.io.InputStream) BackingStoreException(java.util.prefs.BackingStoreException) IOException(java.io.IOException) SSLContext(javax.net.ssl.SSLContext) LoggerContext(ch.qos.logback.classic.LoggerContext)

Aggregations

LoggerContext (ch.qos.logback.classic.LoggerContext)1 JoranConfigurator (ch.qos.logback.classic.joran.JoranConfigurator)1 JoranException (ch.qos.logback.core.joran.spi.JoranException)1 StatusPrinter (ch.qos.logback.core.util.StatusPrinter)1 LookAndFeelFactory (com.jidesoft.plaf.LookAndFeelFactory)1 Lm (com.jidesoft.utils.Lm)1 java.awt (java.awt)1 File (java.io.File)1 IOException (java.io.IOException)1 InputStream (java.io.InputStream)1 URL (java.net.URL)1 URLConnection (java.net.URLConnection)1 URLStreamHandler (java.net.URLStreamHandler)1 KeyManagementException (java.security.KeyManagementException)1 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)1 SecureRandom (java.security.SecureRandom)1 CertificateException (java.security.cert.CertificateException)1 CertificateFactory (java.security.cert.CertificateFactory)1 X509Certificate (java.security.cert.X509Certificate)1 java.util (java.util)1