001/* 002 * Copyright 2002-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.core.env; 018 019import java.util.ArrayList; 020import java.util.Collections; 021import java.util.List; 022 023import joptsimple.OptionSet; 024import joptsimple.OptionSpec; 025 026import org.springframework.lang.Nullable; 027import org.springframework.util.CollectionUtils; 028import org.springframework.util.StringUtils; 029 030/** 031 * {@link CommandLinePropertySource} implementation backed by a JOpt {@link OptionSet}. 032 * 033 * <h2>Typical usage</h2> 034 * 035 * Configure and execute an {@code OptionParser} against the {@code String[]} of arguments 036 * supplied to the {@code main} method, and create a {@link JOptCommandLinePropertySource} 037 * using the resulting {@code OptionSet} object: 038 * 039 * <pre class="code"> 040 * public static void main(String[] args) { 041 * OptionParser parser = new OptionParser(); 042 * parser.accepts("option1"); 043 * parser.accepts("option2").withRequiredArg(); 044 * OptionSet options = parser.parse(args); 045 * PropertySource<?> ps = new JOptCommandLinePropertySource(options); 046 * // ... 047 * }</pre> 048 * 049 * See {@link CommandLinePropertySource} for complete general usage examples. 050 * 051 * <p>Requires JOpt Simple version 4.3 or higher. Tested against JOpt up until 5.0. 052 * 053 * @author Chris Beams 054 * @author Juergen Hoeller 055 * @author Dave Syer 056 * @since 3.1 057 * @see CommandLinePropertySource 058 * @see joptsimple.OptionParser 059 * @see joptsimple.OptionSet 060 */ 061public class JOptCommandLinePropertySource extends CommandLinePropertySource<OptionSet> { 062 063 /** 064 * Create a new {@code JOptCommandLinePropertySource} having the default name 065 * and backed by the given {@code OptionSet}. 066 * @see CommandLinePropertySource#COMMAND_LINE_PROPERTY_SOURCE_NAME 067 * @see CommandLinePropertySource#CommandLinePropertySource(Object) 068 */ 069 public JOptCommandLinePropertySource(OptionSet options) { 070 super(options); 071 } 072 073 /** 074 * Create a new {@code JOptCommandLinePropertySource} having the given name 075 * and backed by the given {@code OptionSet}. 076 */ 077 public JOptCommandLinePropertySource(String name, OptionSet options) { 078 super(name, options); 079 } 080 081 082 @Override 083 protected boolean containsOption(String name) { 084 return this.source.has(name); 085 } 086 087 @Override 088 public String[] getPropertyNames() { 089 List<String> names = new ArrayList<>(); 090 for (OptionSpec<?> spec : this.source.specs()) { 091 String lastOption = CollectionUtils.lastElement(spec.options()); 092 if (lastOption != null) { 093 // Only the longest name is used for enumerating 094 names.add(lastOption); 095 } 096 } 097 return StringUtils.toStringArray(names); 098 } 099 100 @Override 101 @Nullable 102 public List<String> getOptionValues(String name) { 103 List<?> argValues = this.source.valuesOf(name); 104 List<String> stringArgValues = new ArrayList<>(); 105 for (Object argValue : argValues) { 106 stringArgValues.add(argValue.toString()); 107 } 108 if (stringArgValues.isEmpty()) { 109 return (this.source.has(name) ? Collections.emptyList() : null); 110 } 111 return Collections.unmodifiableList(stringArgValues); 112 } 113 114 @Override 115 protected List<String> getNonOptionArgs() { 116 List<?> argValues = this.source.nonOptionArguments(); 117 List<String> stringArgValues = new ArrayList<>(); 118 for (Object argValue : argValues) { 119 stringArgValues.add(argValue.toString()); 120 } 121 return (stringArgValues.isEmpty() ? Collections.emptyList() : 122 Collections.unmodifiableList(stringArgValues)); 123 } 124 125}