com.blackducksoftware.integration.email.EmailEngine.java Source code

Java tutorial

Introduction

Here is the source code for com.blackducksoftware.integration.email.EmailEngine.java

Source

/*******************************************************************************
 * Copyright (C) 2016 Black Duck Software, Inc.
 * http://www.blackducksoftware.com/
 *
 * 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 com.blackducksoftware.integration.email;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Optional;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;

import org.apache.commons.lang3.StringUtils;
import org.restlet.Server;
import org.restlet.data.Parameter;
import org.restlet.data.Protocol;
import org.restlet.util.Series;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.blackducksoftware.integration.email.extension.config.ExtensionConfigManager;
import com.blackducksoftware.integration.email.extension.config.ExtensionInfo;
import com.blackducksoftware.integration.email.extension.server.EmailExtensionApplication;
import com.blackducksoftware.integration.email.extension.server.oauth.ExtensionTokenManager;
import com.blackducksoftware.integration.email.extension.server.oauth.OAuthEndpoint;
import com.blackducksoftware.integration.email.extension.server.oauth.listeners.IAuthorizedListener;
import com.blackducksoftware.integration.email.model.ExtensionProperties;
import com.blackducksoftware.integration.email.model.JavaMailWrapper;
import com.blackducksoftware.integration.email.notifier.CustomDigestNotifier;
import com.blackducksoftware.integration.email.notifier.DailyDigestNotifier;
import com.blackducksoftware.integration.email.notifier.NotifierManager;
import com.blackducksoftware.integration.email.notifier.RealTimeDigestNotifier;
import com.blackducksoftware.integration.email.notifier.TestEmailNotifier;
import com.blackducksoftware.integration.email.service.EmailMessagingService;
import com.blackducksoftware.integration.hub.builder.HubServerConfigBuilder;
import com.blackducksoftware.integration.hub.dataservice.extension.ExtensionConfigDataService;
import com.blackducksoftware.integration.hub.dataservice.notification.NotificationDataService;
import com.blackducksoftware.integration.hub.global.HubServerConfig;
import com.blackducksoftware.integration.hub.proxy.ProxyInfo;
import com.blackducksoftware.integration.hub.proxy.ProxyInfoBuilder;
import com.blackducksoftware.integration.hub.rest.RestConnection;
import com.blackducksoftware.integration.hub.rest.oauth.AccessType;
import com.blackducksoftware.integration.hub.rest.oauth.OAuthRestConnectionBuilder;
import com.blackducksoftware.integration.hub.service.HubServicesFactory;
import com.blackducksoftware.integration.hub.util.HostnameHelper;
import com.blackducksoftware.integration.log.IntLogger;
import com.google.gson.JsonParser;

import freemarker.template.Configuration;
import freemarker.template.TemplateExceptionHandler;

public class EmailEngine implements IAuthorizedListener {
    private final Logger logger = LoggerFactory.getLogger(EmailEngine.class);

    private final Configuration configuration;

    private JavaMailWrapper javaMailWrapper;

    private EmailMessagingService emailMessagingService;

    private HubServerConfig hubServerConfig;

    private RestConnection restConnection;

    private final Properties appProperties;

    private final ExtensionProperties extensionProperties;

    private NotificationDataService notificationDataService;

    private NotifierManager notifierManager;

    private final ExtensionTokenManager tokenManager;

    private final OAuthEndpoint restletComponent;

    private final ExtensionInfo extensionInfoData;

    private final ExtensionConfigManager extConfigManager;

    private ExtensionConfigDataService extConfigDataService;

    private HubServicesFactory hubServicesFactory;

    private EmailExtensionApplication emailExtensionApplication;
    private final boolean alwaysTrustServerCertificate;

    public EmailEngine() throws FileNotFoundException, IOException {
        alwaysTrustServerCertificate = getAlwaysTrustServerCertificates();
        appProperties = createAppProperties();
        extensionProperties = createExtensionProperties();
        configuration = createFreemarkerConfig();
        extensionInfoData = createExtensionInfoData();
        tokenManager = createTokenManager();
        extConfigManager = createExtensionConfigManager();
        restletComponent = createRestletComponent();
    }

    public boolean getAlwaysTrustServerCertificates() {
        boolean alwaysTrustServerCertificate = false;
        final String alwaysTrust = System.getenv("EXTENSION_ALWAYS_TRUST_SERVER_CERTIFICATE");
        if (StringUtils.isNotBlank(alwaysTrust)) {
            alwaysTrustServerCertificate = Boolean.parseBoolean(alwaysTrust);
            if (alwaysTrustServerCertificate) {
                logger.warn("Always trust server certificates option enabled");
            }
        }
        return alwaysTrustServerCertificate;
    }

    public Logger getLogger() {
        return logger;
    }

    public Configuration getConfiguration() {
        return configuration;
    }

    public JavaMailWrapper getJavaMailWrapper() {
        return javaMailWrapper;
    }

    public EmailMessagingService getEmailMessagingService() {
        return emailMessagingService;
    }

    public HubServerConfig getHubServerConfig() {
        return hubServerConfig;
    }

    public RestConnection getRestConnection() {
        return restConnection;
    }

    public Properties getAppProperties() {
        return appProperties;
    }

    public ExtensionProperties getExtensionProperties() {
        return extensionProperties;
    }

    public NotificationDataService getNotificationDataService() {
        return notificationDataService;
    }

    public NotifierManager getNotifierManager() {
        return notifierManager;
    }

    public ExtensionTokenManager getTokenManager() {
        return tokenManager;
    }

    public OAuthEndpoint getRestletComponent() {
        return restletComponent;
    }

    public ExtensionInfo getExtensionInfoData() {
        return extensionInfoData;
    }

    public ExtensionConfigManager getExtConfigManager() {
        return extConfigManager;
    }

    public ExtensionConfigDataService getExtConfigDataService() {
        return extConfigDataService;
    }

    public HubServicesFactory getHubServicesFactory() {
        return hubServicesFactory;
    }

    public void start() {
        try {
            restletComponent.start();
            tokenManager.refreshToken(AccessType.USER);
        } catch (final Exception e) {
            logger.error("Error Starting Email Engine", e);
        }
    }

    public void shutDown() {
        try {
            notifierManager.stop();
            restletComponent.stop();
        } catch (final Exception e) {
            logger.error("Error stopping Email Engine", e);
        }
    }

    public Properties createAppProperties() throws FileNotFoundException, IOException {
        final Properties appProperties = new Properties();
        final String configLocation = System.getProperty(ExtensionConfigManager.PROPERTY_KEY_CONFIG_LOCATION_PATH);
        final File customerPropertiesFile = new File(configLocation, "extension.properties");
        try (FileInputStream fileInputStream = new FileInputStream(customerPropertiesFile)) {
            appProperties.load(fileInputStream);
        }

        return appProperties;
    }

    public Configuration createFreemarkerConfig() throws IOException {
        final Configuration cfg = new Configuration(Configuration.VERSION_2_3_25);
        final File templateDirectory = findTemplateDirectory();
        cfg.setDirectoryForTemplateLoading(templateDirectory);
        cfg.setDefaultEncoding("UTF-8");
        cfg.setTemplateExceptionHandler(TemplateExceptionHandler.HTML_DEBUG_HANDLER);
        cfg.setLogTemplateExceptions(false);

        return cfg;
    }

    private File findTemplateDirectory() {
        try {
            File templateDir = null;
            final String appHomeDir = System.getProperty(EmailExtensionConstants.SYSTEM_PROPERTY_KEY_APP_HOME);
            if (StringUtils.isNotBlank(appHomeDir)) {
                templateDir = new File(appHomeDir, "templates");
            }

            final String templateDirProperty = extensionProperties.getEmailTemplateDirectory();
            if (StringUtils.isNotBlank(templateDirProperty)) {
                templateDir = new File(templateDirProperty);
            }

            return templateDir;
        } catch (final Exception e) {
            logger.error("Error finding the template directory", e);
            return null;
        }
    }

    public DateFormat createNotificationDateFormat() {
        final DateFormat dateFormat = new SimpleDateFormat(RestConnection.JSON_DATE_FORMAT);
        dateFormat.setTimeZone(java.util.TimeZone.getTimeZone("Zulu"));
        return dateFormat;
    }

    public Date createApplicationStartDate() {
        return new Date();
    }

    public ExecutorService createExecutorService() {
        final ThreadFactory threadFactory = Executors.defaultThreadFactory();
        return Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors(), threadFactory);
    }

    public ExtensionProperties createExtensionProperties() {
        return new ExtensionProperties(appProperties);
    }

    public JavaMailWrapper createJavaMailWrapper() {
        return new JavaMailWrapper();
    }

    public EmailMessagingService createEmailMessagingService() {
        return new EmailMessagingService(extensionProperties, configuration, javaMailWrapper);
    }

    public HubServerConfig createHubConfig(final String hubUri) {
        try {
            final HubServerConfigBuilder configBuilder = new HubServerConfigBuilder();
            configBuilder.setHubUrl(hubUri);
            // using oauth the username and password aren't used but need to be set
            // for the builder
            configBuilder.setUsername("auser");
            configBuilder.setPassword("apassword");
            configBuilder.setTimeout(extensionProperties.getHubServerTimeout());
            configBuilder.setProxyHost(extensionProperties.getHubProxyHost());
            configBuilder.setProxyPort(extensionProperties.getHubProxyPort());
            configBuilder.setIgnoredProxyHosts(extensionProperties.getHubProxyNoHost());
            configBuilder.setProxyUsername(extensionProperties.getHubProxyUser());
            configBuilder.setProxyPassword(extensionProperties.getHubProxyPassword());
            configBuilder.setAlwaysTrustServerCertificate(alwaysTrustServerCertificate);

            final HubServerConfig config = configBuilder.build();
            // output the configuration details
            logger.info("Hub Server URL          = " + config.getHubUrl());
            logger.info("Hub Timeout             = " + config.getTimeout());

            return config;
        } catch (final IllegalStateException ex) {
            logger.error("Error with the hub configuration", ex);
        }

        return null;
    }

    public RestConnection createRestConnection(final String hubUri) {
        final RestConnection restConnection = initRestConnection(hubUri);
        return restConnection;
    }

    public NotificationDataService createNotificationDataService() {
        final NotificationDataService notificationDataService = hubServicesFactory.createNotificationDataService();
        return notificationDataService;
    }

    public RestConnection initRestConnection(final String hubUri) {
        final IntLogger extLogger = new ExtensionLogger(logger);
        final OAuthRestConnectionBuilder builder = new OAuthRestConnectionBuilder();
        builder.setLogger(extLogger);
        builder.setBaseUrl(hubServerConfig.getHubUrl().toString());
        builder.setTimeout(hubServerConfig.getTimeout());
        builder.setTokenManager(tokenManager);
        builder.setAccessType(AccessType.USER);
        builder.setAlwaysTrustServerCertificate(alwaysTrustServerCertificate);
        final RestConnection restConnection = builder.build();
        return restConnection;
    }

    public NotifierManager createNotifierManager() {
        final NotifierManager manager = new NotifierManager();

        final DailyDigestNotifier dailyNotifier = new DailyDigestNotifier(extensionProperties,
                emailMessagingService, hubServicesFactory, getExtensionInfoData());
        final TestEmailNotifier testNotifier = new TestEmailNotifier(extensionProperties, emailMessagingService,
                hubServicesFactory, getExtensionInfoData());
        final RealTimeDigestNotifier realTimeNotifier = new RealTimeDigestNotifier(extensionProperties,
                emailMessagingService, hubServicesFactory, getExtensionInfoData());
        final CustomDigestNotifier customNotifier = new CustomDigestNotifier(extensionProperties,
                emailMessagingService, hubServicesFactory, getExtensionInfoData());
        manager.attach(dailyNotifier);
        manager.attach(realTimeNotifier);
        manager.attach(testNotifier);
        manager.attach(customNotifier);
        emailExtensionApplication.getContext().getAttributes()
                .put(EmailExtensionConstants.CONTEXT_ATTRIBUTE_KEY_TEST_NOTIFIER, testNotifier);
        return manager;
    }

    public ExtensionInfo createExtensionInfoData() {
        final String id = generateExtensionId();
        final String name = extensionProperties.getExtensionName();
        final String description = extensionProperties.getExtensionDescription();
        String baseUrl = extensionProperties.getExtensionBaseUrl();
        URL extensionUrl;
        try {
            extensionUrl = new URL(baseUrl);
            if (extensionUrl.getHost().equals("localhost")) {
                final String hostName = Optional.ofNullable(System.getenv("PUBLIC_HUB_WEBSERVER_HOST"))
                        .orElseGet(() -> HostnameHelper.getMyHostname());
                final URL url = new URL(extensionUrl.getProtocol(), hostName, extensionUrl.getPort(),
                        extensionUrl.getFile());
                baseUrl = url.toString();
            }
        } catch (final MalformedURLException e) {
            baseUrl = extensionProperties.getExtensionBaseUrl();
        }
        logger.info("Extension Base URL: {}", baseUrl);
        return new ExtensionInfo(id, name, description, baseUrl);
    }

    public String generateExtensionId() {
        final Class<? extends EmailEngine> engineClass = this.getClass();
        final Package enginePackage = engineClass.getPackage();

        final String name = enginePackage.getName();
        final String version = extensionProperties.getExtensionVersion();
        final String id = name + ".email-extension." + version;
        logger.info("Extension ID - {}", id);
        return id;
    }

    public OAuthEndpoint createRestletComponent() {
        emailExtensionApplication = new EmailExtensionApplication(tokenManager, extConfigManager);
        final OAuthEndpoint endpoint = new OAuthEndpoint(emailExtensionApplication);
        try {
            final URL url = new URL(extensionInfoData.getBaseUrl());
            final int port = url.getPort();
            if (Protocol.HTTP.getSchemeName().equals(url.getProtocol())) {
                if (port > 0) {
                    endpoint.getServers().add(Protocol.HTTP, port);
                } else {
                    endpoint.getServers().add(Protocol.HTTP);
                }
            } else if (Protocol.HTTPS.getSchemeName().equals(url.getProtocol())) {
                Server server;
                if (port > 0) {
                    server = endpoint.getServers().add(Protocol.HTTPS, port);
                } else {
                    server = endpoint.getServers().add(Protocol.HTTPS);
                }
                final Series<Parameter> parameters = server.getContext().getParameters();
                parameters.add("sslContextFactory", "org.restlet.engine.ssl.DefaultSslContextFactory");
                parameters.add("keyStorePath", extensionProperties.getSSLKeyStorePath());
                parameters.add("keyStorePassword", extensionProperties.getSSLKeyStorePassword());
                parameters.add("keyPassword", extensionProperties.getSSLKeyPassword());
                parameters.add("keyStoreType", extensionProperties.getSSLKeyStoreType());
            } else {
                logger.error("URL scheme {} not supported.  Not starting the email extension. ", url.getProtocol());
            }
        } catch (final MalformedURLException e) {
            logger.error("createRestletComponent error with base URL", e);
        }

        return endpoint;
    }

    public ExtensionTokenManager createTokenManager() {
        final Logger tokenManagerLogger = LoggerFactory.getLogger(ExtensionTokenManager.class);
        final ExtensionLogger serviceLogger = new ExtensionLogger(tokenManagerLogger);
        final String timeoutString = extensionProperties.getHubServerTimeout();
        final int timeout = Integer.parseInt(timeoutString);
        final ExtensionTokenManager tokenManager = new ExtensionTokenManager(serviceLogger, timeout,
                extensionInfoData);
        final ProxyInfoBuilder proxyInfoBuilder = new ProxyInfoBuilder();
        final String proxyHost = extensionProperties.getHubProxyHost();
        final String proxyPort = extensionProperties.getHubProxyPort();
        final String proxyIgnoredHosts = extensionProperties.getHubProxyNoHost();
        final String proxyUser = extensionProperties.getHubProxyUser();
        final String proxyPassword = extensionProperties.getHubProxyPassword();
        proxyInfoBuilder.setHost(proxyHost);
        proxyInfoBuilder.setPort(proxyPort);
        proxyInfoBuilder.setIgnoredProxyHosts(proxyIgnoredHosts);
        proxyInfoBuilder.setUsername(proxyUser);
        proxyInfoBuilder.setPassword(proxyPassword);
        final ProxyInfo proxyInfo = proxyInfoBuilder.build();
        tokenManager.setProxyInfo(proxyInfo);
        tokenManager.setAlwaysTrustServerCertificate(alwaysTrustServerCertificate);
        tokenManager.addAuthorizedListener(this);
        logger.info("Proxy Host          = " + proxyHost);
        logger.info("Proxy Port          = " + proxyPort);
        logger.info("Ignored Proxy Hosts = " + proxyIgnoredHosts);
        return tokenManager;
    }

    public ExtensionConfigManager createExtensionConfigManager() {
        // has to be separate from the dataservicesfactory otherwise we have a
        // chicken and egg problem
        final ExtensionConfigManager extConfigManager = new ExtensionConfigManager(extensionInfoData,
                new JsonParser());
        return extConfigManager;
    }

    public ExtensionConfigDataService createExtensionConfigDataService() {
        final ExtensionConfigDataService extConfigDataService = hubServicesFactory
                .createExtensionConfigDataService();
        return extConfigDataService;
    }

    @Override
    public void onAuthorized() {
        try {
            String hubUri;
            hubUri = createHubBaseUrl(tokenManager.getConfiguration().hubUri);
            hubServerConfig = createHubConfig(hubUri);
            restConnection = createRestConnection(hubUri);
            javaMailWrapper = createJavaMailWrapper();
            hubServicesFactory = new HubServicesFactory(restConnection);
            emailMessagingService = createEmailMessagingService();
            notificationDataService = createNotificationDataService();
            extConfigDataService = createExtensionConfigDataService();
            notifierManager = createNotifierManager();
            notifierManager.updateHubExtensionUri(tokenManager.getConfiguration().extensionUri);
            notifierManager.start();
        } catch (final MalformedURLException e) {
            logger.error("Error completing extension initialization", e);
        } finally {
            tokenManager.removeAuthorizedListener(this);
        }
    }

    // TODO file a ticket against the hub to give me the root URL not with a
    // path
    private String createHubBaseUrl(final String hubUri) throws MalformedURLException {
        final URL original = new URL(hubUri);
        final URL baseUrl = new URL(original.getProtocol(), original.getHost(), original.getPort(), "");
        return baseUrl.toString();
    }
}