package org.apache.helix.ui.util;
/*
* 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.
*/
import com.codahale.metrics.MetricRegistry;
import io.dropwizard.Application;
import io.dropwizard.Configuration;
import io.dropwizard.cli.ServerCommand;
import io.dropwizard.configuration.ConfigurationFactory;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;
import org.apache.helix.ui.HelixUIApplication;
import org.apache.helix.ui.HelixUIApplicationConfiguration;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.component.LifeCycle;
import java.io.File;
import java.lang.reflect.Field;
import java.util.List;
/**
* A utility to run DropWizard (http://dropwizard.io/) applications in-process.
*/
public class DropWizardApplicationRunner {
/**
* Creates a Jetty server for an application that can be started / stopped in-process
*
* @param config An application configuration instance (with properties set)
* @param applicationClass The {@link io.dropwizard.Application} implementation class
* @param <T> The configuration class
* @return A DropWizard server startable in-process
*/
@SuppressWarnings("unchecked")
public static <T extends Configuration>
DropWizardServer<T> createServer(T config, Class<? extends Application<T>> applicationClass) throws Exception {
// Create application
final Application<T> application = applicationClass.getConstructor().newInstance();
// Create bootstrap
final ServerCommand<T> serverCommand = new ServerCommand<T>(application);
final Bootstrap<T> bootstrap = new Bootstrap<T>(application);
bootstrap.addCommand(serverCommand);
// Write a temporary config file
File tmpConfigFile = new File(
System.getProperty("java.io.tmpdir"),
config.getClass().getCanonicalName() + "_" + System.currentTimeMillis());
tmpConfigFile.deleteOnExit();
bootstrap.getObjectMapper().writeValue(tmpConfigFile, config);
// Parse configuration
ConfigurationFactory<T> configurationFactory
= bootstrap.getConfigurationFactoryFactory()
.create((Class<T>) config.getClass(),
bootstrap.getValidatorFactory().getValidator(),
bootstrap.getObjectMapper(),
"dw");
final T builtConfig = configurationFactory.build(
bootstrap.getConfigurationSourceProvider(), tmpConfigFile.getAbsolutePath());
// Configure logging
builtConfig.getLoggingFactory()
.configure(bootstrap.getMetricRegistry(),
bootstrap.getApplication().getName());
// Environment
final Environment environment = new Environment(bootstrap.getApplication().getName(),
bootstrap.getObjectMapper(),
bootstrap.getValidatorFactory().getValidator(),
bootstrap.getMetricRegistry(),
bootstrap.getClassLoader());
// Initialize environment
builtConfig.getMetricsFactory().configure(environment.lifecycle(), bootstrap.getMetricRegistry());
// Server
final Server server = builtConfig.getServerFactory().build(environment);
server.addLifeCycleListener(new AbstractLifeCycle.AbstractLifeCycleListener() {
@Override
public void lifeCycleStopped(LifeCycle event) {
builtConfig.getLoggingFactory().stop();
}
});
return new DropWizardServer(builtConfig, bootstrap, application, environment, server, environment.metrics());
}
public static class DropWizardServer<T extends Configuration> {
private final T builtConfig;
private final Bootstrap<T> bootstrap;
private final Application<T> application;
private final Environment environment;
private final Server jettyServer;
private final MetricRegistry metricRegistry;
DropWizardServer(T builtConfig,
Bootstrap<T> bootstrap,
Application<T> application,
Environment environment,
Server jettyServer,
MetricRegistry metricRegistry) {
this.builtConfig = builtConfig;
this.bootstrap = bootstrap;
this.application = application;
this.environment = environment;
this.jettyServer = jettyServer;
this.metricRegistry = metricRegistry;
}
public MetricRegistry getMetricRegistry() {
return metricRegistry;
}
public void start() throws Exception {
application.initialize(bootstrap);
bootstrap.run(builtConfig, environment);
application.run(builtConfig, environment);
toggleManagedObjects(true);
jettyServer.start();
}
public void stop() throws Exception {
jettyServer.stop();
toggleManagedObjects(false);
}
@SuppressWarnings("unchecked")
private void toggleManagedObjects(boolean start) throws Exception {
Field managedObjectsField = environment.lifecycle().getClass().getDeclaredField("managedObjects");
managedObjectsField.setAccessible(true);
List<LifeCycle> managedObjects = (List<LifeCycle>) managedObjectsField.get(environment.lifecycle());
for (LifeCycle managedObject : managedObjects) {
if (start) {
managedObject.start();
} else {
managedObject.stop();
}
}
}
}
public static void main(String[] args) throws Exception {
HelixUIApplicationConfiguration config
= new HelixUIApplicationConfiguration();
DropWizardServer<HelixUIApplicationConfiguration> server
= DropWizardApplicationRunner.createServer(config, HelixUIApplication.class);
server.start();
}
}