blob: 6c70d1b0a1642c1bd42007637fe78fff073d3a68 [file] [log] [blame]
/*
* 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.apache.calcite.avatica.server;
import org.apache.calcite.avatica.metrics.MetricsSystem;
import org.apache.calcite.avatica.metrics.MetricsSystemConfiguration;
import org.apache.calcite.avatica.metrics.MetricsSystemFactory;
import org.apache.calcite.avatica.metrics.MetricsSystemLoader;
import org.apache.calcite.avatica.metrics.noop.NoopMetricsSystem;
import org.apache.calcite.avatica.metrics.noop.NoopMetricsSystemConfiguration;
import org.apache.calcite.avatica.remote.Driver;
import org.apache.calcite.avatica.remote.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.ServiceLoader;
/**
* Factory that instantiates the desired implementation, typically differing on the method
* used to serialize messages, for use in the Avatica server.
*/
public class HandlerFactory {
private static final Logger LOG = LoggerFactory.getLogger(HandlerFactory.class);
/**
* Constructs the desired implementation for the given serialization method with metrics.
*
* @param service The underlying {@link Service}.
* @param serialization The desired message serialization.
* @return The {@link AvaticaHandler}.
*/
public AvaticaHandler getHandler(Service service, Driver.Serialization serialization) {
return getHandler(service, serialization, NoopMetricsSystemConfiguration.getInstance());
}
/**
* Constructs the desired implementation for the given serialization method and server
* configuration with metrics.
*
* @param service The underlying {@link Service}.
* @param serialization The desired message serialization.
* @param serverConfig Avatica server configuration or null.
* @return The {@link AvaticaHandler}.
*/
public AvaticaHandler getHandler(Service service, Driver.Serialization serialization,
AvaticaServerConfiguration serverConfig) {
return getHandler(service, serialization, NoopMetricsSystemConfiguration.getInstance(),
serverConfig);
}
/**
* Constructs the desired implementation for the given serialization method with metrics.
*
* @param service The underlying {@link Service}.
* @param serialization The desired message serialization.
* @param metricsConfig Configuration for the {@link MetricsSystem}.
* @return The {@link AvaticaHandler}.
*/
public AvaticaHandler getHandler(Service service, Driver.Serialization serialization,
MetricsSystemConfiguration<?> metricsConfig) {
return getHandler(service, serialization, metricsConfig, null);
}
/**
* Constructs the desired implementation for the given serialization method and server
* configuration with metrics.
*
* @param service The underlying {@link Service}
* @param serialization The serializatio mechanism to use
* @param metricsConfig Configuration for the {@link MetricsSystem}.
* @param serverConfig Avatica server configuration or null
* @return An {@link AvaticaHandler}
*/
public AvaticaHandler getHandler(Service service, Driver.Serialization serialization,
MetricsSystemConfiguration<?> metricsConfig, AvaticaServerConfiguration serverConfig) {
if (null == metricsConfig) {
metricsConfig = NoopMetricsSystemConfiguration.getInstance();
}
MetricsSystem metrics = MetricsSystemLoader.load(metricsConfig);
switch (serialization) {
case JSON:
return new AvaticaJsonHandler(service, metrics, serverConfig);
case PROTOBUF:
return new AvaticaProtobufHandler(service, metrics, serverConfig);
default:
throw new IllegalArgumentException("Unknown Avatica handler for " + serialization.name());
}
}
/**
* Load a {@link MetricsSystem} using ServiceLoader to create a {@link MetricsSystemFactory}.
*
* @param config State to pass to the factory for initialization.
* @return A {@link MetricsSystem} instance.
*/
MetricsSystem loadMetricsSystem(MetricsSystemConfiguration<?> config) {
ServiceLoader<MetricsSystemFactory> loader = ServiceLoader.load(MetricsSystemFactory.class);
List<MetricsSystemFactory> availableFactories = new ArrayList<>();
for (MetricsSystemFactory factory : loader) {
availableFactories.add(factory);
}
if (1 == availableFactories.size()) {
// One and only one instance -- what we want
MetricsSystemFactory factory = availableFactories.get(0);
LOG.info("Loaded MetricsSystem {}", factory.getClass());
return factory.create(config);
} else if (availableFactories.isEmpty()) {
// None-provided default to no metrics
LOG.info("No metrics implementation available on classpath. Using No-op implementation");
return NoopMetricsSystem.getInstance();
} else {
// Tell the user they're doing something wrong, and choose the first impl.
StringBuilder sb = new StringBuilder();
for (MetricsSystemFactory factory : availableFactories) {
if (sb.length() > 0) {
sb.append(", ");
}
sb.append(factory.getClass());
}
LOG.warn("Found multiple MetricsSystemFactory implementations: {}."
+ " Using No-op implementation", sb);
return NoopMetricsSystem.getInstance();
}
}
}
// End HandlerFactory.java