Java tutorial
/** * 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.whirr.command; import static org.apache.whirr.ClusterSpec.Property.CLUSTER_NAME; import static org.apache.whirr.ClusterSpec.Property.CREDENTIAL; import static org.apache.whirr.ClusterSpec.Property.IDENTITY; import static org.apache.whirr.ClusterSpec.Property.INSTANCE_TEMPLATES; import static org.apache.whirr.ClusterSpec.Property.PRIVATE_KEY_FILE; import static org.apache.whirr.ClusterSpec.Property.PROVIDER; import java.io.IOException; import java.io.PrintStream; import java.util.EnumSet; import java.util.Map; import joptsimple.ArgumentAcceptingOptionSpec; import joptsimple.OptionParser; import joptsimple.OptionSet; import joptsimple.OptionSpec; import org.apache.commons.configuration.CompositeConfiguration; import org.apache.commons.configuration.Configuration; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.PropertiesConfiguration; import org.apache.whirr.Cluster; import org.apache.whirr.ClusterController; import org.apache.whirr.ClusterControllerFactory; import org.apache.whirr.ClusterSpec; import org.apache.whirr.ClusterSpec.Property; import org.apache.whirr.state.ClusterStateStore; import org.apache.whirr.state.ClusterStateStoreFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.collect.Maps; /** * An abstract command for interacting with clusters. */ public abstract class AbstractClusterCommand extends Command { private static final Logger LOG = LoggerFactory.getLogger(AbstractClusterCommand.class); protected ClusterControllerFactory factory; protected ClusterStateStoreFactory stateStoreFactory; protected OptionParser parser = new OptionParser(); private Map<Property, OptionSpec<?>> optionSpecs; private OptionSpec<String> configOption; public AbstractClusterCommand(String name, String description, ClusterControllerFactory factory) { this(name, description, factory, new ClusterStateStoreFactory()); } public AbstractClusterCommand(String name, String description, ClusterControllerFactory factory, ClusterStateStoreFactory stateStoreFactory) { super(name, description); configOption = parser .accepts("config", "Note that Whirr properties specified in " + "this file should all have a whirr. prefix.") .withRequiredArg().describedAs("config.properties").ofType(String.class); parser.accepts("quiet", "Be less verbose"); this.factory = factory; this.stateStoreFactory = stateStoreFactory; optionSpecs = Maps.newHashMap(); for (Property property : EnumSet.allOf(Property.class)) { ArgumentAcceptingOptionSpec<?> spec = parser .accepts(property.getSimpleName(), property.getDescription()).withRequiredArg() .ofType(property.getType()); if (property.hasMultipleArguments()) { spec.withValuesSeparatedBy(','); } optionSpecs.put(property, spec); } } /** * Load the cluster spec by parsing the command line option set */ protected ClusterSpec getClusterSpec(OptionSet optionSet) throws ConfigurationException { Configuration optionsConfig = new PropertiesConfiguration(); for (Map.Entry<Property, OptionSpec<?>> entry : optionSpecs.entrySet()) { Property property = entry.getKey(); OptionSpec<?> option = entry.getValue(); Object value; if (property.hasMultipleArguments()) { value = optionSet.valuesOf(option); } else { value = optionSet.valueOf(option); } if (value != null) { optionsConfig.setProperty(property.getConfigName(), value); } } CompositeConfiguration config = new CompositeConfiguration(); config.addConfiguration(optionsConfig); if (optionSet.has(configOption)) { Configuration defaults = new PropertiesConfiguration(optionSet.valueOf(configOption)); config.addConfiguration(defaults); } ClusterSpec clusterSpec = new ClusterSpec(config); for (Property required : EnumSet.of(CLUSTER_NAME, PROVIDER, IDENTITY, CREDENTIAL, INSTANCE_TEMPLATES, PRIVATE_KEY_FILE)) { if (clusterSpec.getConfiguration().getString(required.getConfigName()) == null) { throw new IllegalArgumentException(String.format("Option '%s' not set.", required.getSimpleName())); } } return clusterSpec; } /** * Get the cluster instance together with NodeMetadata (through API calls) */ protected Cluster getCluster(ClusterSpec clusterSpec, ClusterController controller) throws IOException, InterruptedException { return new Cluster(controller.getInstances(clusterSpec, createClusterStateStore(clusterSpec))); } /** * Create the specified service */ protected ClusterController createClusterController(String serviceName) { ClusterController controller = factory.create(serviceName); if (controller == null) { LOG.warn("Unable to find service {}, using default.", serviceName); controller = factory.create(null); } return controller; } /** * Create the cluster state store object */ protected ClusterStateStore createClusterStateStore(ClusterSpec spec) { return stateStoreFactory.create(spec); } protected void printProviderInfo(PrintStream out, PrintStream err, ClusterSpec clusterSpec, OptionSet optionSet) { if (!optionSet.has("quiet")) { out.println(String.format("Running on provider %s using identity %s", clusterSpec.getProvider(), clusterSpec.getIdentity())); } } /** * Print command execution error and a hint to help the user get more help */ protected void printErrorAndHelpHint(PrintStream stream, Throwable e) { stream.println(e.getMessage()); stream.println("Help: whirr help " + getName()); } /** * Print a generic usage indication for commands */ @Override public void printUsage(PrintStream stream) throws IOException { stream.println("Usage: whirr " + getName() + " [OPTIONS]"); stream.println(); parser.printHelpOn(stream); } }