001/* 002 * Copyright 2012-2016 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 * http://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.boot.cli.command.options; 018 019import java.io.File; 020import java.util.ArrayList; 021import java.util.Collections; 022import java.util.List; 023 024import joptsimple.OptionSet; 025 026import org.springframework.boot.cli.util.ResourceUtils; 027import org.springframework.util.Assert; 028 029/** 030 * Extract source file options (anything following '--' in an {@link OptionSet}). 031 * 032 * @author Phillip Webb 033 * @author Dave Syer 034 * @author Greg Turnquist 035 * @author Andy Wilkinson 036 */ 037public class SourceOptions { 038 039 private final List<String> sources; 040 041 private final List<?> args; 042 043 /** 044 * Create a new {@link SourceOptions} instance. 045 * @param options the source option set 046 */ 047 public SourceOptions(OptionSet options) { 048 this(options, null); 049 } 050 051 /** 052 * Create a new {@link SourceOptions} instance. 053 * @param arguments the source arguments 054 */ 055 public SourceOptions(List<?> arguments) { 056 this(arguments, null); 057 } 058 059 /** 060 * Create a new {@link SourceOptions} instance. If it is an error to pass options that 061 * specify non-existent sources, but the default paths are allowed not to exist (the 062 * paths are tested before use). If default paths are provided and the option set 063 * contains no source file arguments it is not an error even if none of the default 064 * paths exist). 065 * @param optionSet the source option set 066 * @param classLoader an optional classloader used to try and load files that are not 067 * found in the local filesystem 068 */ 069 public SourceOptions(OptionSet optionSet, ClassLoader classLoader) { 070 this(optionSet.nonOptionArguments(), classLoader); 071 } 072 073 private SourceOptions(List<?> nonOptionArguments, ClassLoader classLoader) { 074 List<String> sources = new ArrayList<String>(); 075 int sourceArgCount = 0; 076 for (Object option : nonOptionArguments) { 077 if (option instanceof String) { 078 String filename = (String) option; 079 if ("--".equals(filename)) { 080 break; 081 } 082 List<String> urls = new ArrayList<String>(); 083 File fileCandidate = new File(filename); 084 if (fileCandidate.isFile()) { 085 urls.add(fileCandidate.getAbsoluteFile().toURI().toString()); 086 } 087 else if (!isAbsoluteWindowsFile(fileCandidate)) { 088 urls.addAll(ResourceUtils.getUrls(filename, classLoader)); 089 } 090 for (String url : urls) { 091 if (isSource(url)) { 092 sources.add(url); 093 } 094 } 095 if (isSource(filename)) { 096 if (urls.isEmpty()) { 097 throw new IllegalArgumentException("Can't find " + filename); 098 } 099 else { 100 sourceArgCount++; 101 } 102 } 103 } 104 } 105 this.args = Collections.unmodifiableList( 106 nonOptionArguments.subList(sourceArgCount, nonOptionArguments.size())); 107 Assert.isTrue(!sources.isEmpty(), "Please specify at least one file"); 108 this.sources = Collections.unmodifiableList(sources); 109 } 110 111 private boolean isAbsoluteWindowsFile(File file) { 112 return isWindows() && file.isAbsolute(); 113 } 114 115 private boolean isWindows() { 116 return File.separatorChar == '\\'; 117 } 118 119 private boolean isSource(String name) { 120 return name.endsWith(".java") || name.endsWith(".groovy"); 121 } 122 123 public List<?> getArgs() { 124 return this.args; 125 } 126 127 public String[] getArgsArray() { 128 return this.args.toArray(new String[this.args.size()]); 129 } 130 131 public List<String> getSources() { 132 return this.sources; 133 } 134 135 public String[] getSourcesArray() { 136 return this.sources.toArray(new String[this.sources.size()]); 137 } 138 139}