@@ -40,7 +40,6 @@ import org.springframework.shell2.standard.StandardParameterResolver;
|
||||
* @author Camilo Gonzalez
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@ComponentScan(basePackageClasses = Bootstrap.class)
|
||||
public class Bootstrap {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
@@ -53,18 +52,9 @@ public class Bootstrap {
|
||||
return new DefaultConversionService();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ParameterResolver parameterResolver(ConversionService conversionService) {
|
||||
return new StandardParameterResolver(conversionService);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Terminal terminal() throws IOException {
|
||||
return TerminalBuilder.builder().build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public EnumValueProvider enumValueProvider() {
|
||||
return new EnumValueProvider();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,8 +46,10 @@ import org.jline.utils.AttributedStringBuilder;
|
||||
import org.jline.utils.AttributedStyle;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.shell2.result.TypeHierarchyResultHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
@@ -64,7 +66,8 @@ import org.springframework.util.ReflectionUtils;
|
||||
public class JLineShell implements Shell {
|
||||
|
||||
@Autowired
|
||||
ResultHandlers resultHandlers = new ResultHandlers();
|
||||
@Qualifier("main")
|
||||
ResultHandler resultHandler;
|
||||
|
||||
@Autowired
|
||||
private ApplicationContext applicationContext;
|
||||
@@ -133,7 +136,7 @@ public class JLineShell implements Shell {
|
||||
}
|
||||
catch (UserInterruptException e) {
|
||||
if (e.getPartialLine().isEmpty()) {
|
||||
resultHandlers.handleResult(new ExitRequest(1));
|
||||
resultHandler.handleResult(new ExitRequest(1));
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
@@ -171,7 +174,7 @@ public class JLineShell implements Shell {
|
||||
result = e;
|
||||
}
|
||||
|
||||
resultHandlers.handleResult(result);
|
||||
resultHandler.handleResult(result);
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.shell2.result;
|
||||
package org.springframework.shell2;
|
||||
|
||||
/**
|
||||
* Implementations know how to deal with results of method invocations, whether normal results or exceptions thrown.
|
||||
@@ -20,6 +20,7 @@ import org.jline.terminal.Terminal;
|
||||
import org.jline.utils.AttributedCharSequence;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.shell2.ResultHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.shell2.result;
|
||||
|
||||
import org.springframework.shell2.ResultHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.io.IOException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.shell2.ExitRequest;
|
||||
import org.springframework.shell2.ResultHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,29 +17,29 @@
|
||||
package org.springframework.shell2.result;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.shell2.ResultHandlers;
|
||||
import org.springframework.shell2.ResultHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* A {@link ResultHandler} that deals with {@link Iterable}s and delegates to
|
||||
* {@link ResultHandlers} for each element in turn.
|
||||
* {@link TypeHierarchyResultHandler} for each element in turn.
|
||||
*
|
||||
* @author Eric Bottard
|
||||
*/
|
||||
@Component
|
||||
public class IterableResultHandler implements ResultHandler<Iterable> {
|
||||
|
||||
private ResultHandlers resultHandlers;
|
||||
private ResultHandler delegate;
|
||||
|
||||
@Autowired
|
||||
public void setResultHandlers(ResultHandlers resultHandlers) {
|
||||
this.resultHandlers = resultHandlers;
|
||||
// Setter injection to avoid circular dependency at creation time
|
||||
public void setDelegate(ResultHandler delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleResult(Iterable result) {
|
||||
for (Object o : result) {
|
||||
resultHandlers.handleResult(o);
|
||||
delegate.handleResult(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.shell2.result;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.shell2.ResultHandler;
|
||||
|
||||
/**
|
||||
* Used for explicit configuration of {@link org.springframework.shell2.ResultHandler}s.
|
||||
*
|
||||
* @author Eric Bottard
|
||||
*/
|
||||
@Configuration
|
||||
public class ResultHandlerConfig {
|
||||
|
||||
@Bean
|
||||
@Qualifier("main")
|
||||
public ResultHandler<?> mainResultHandler() {
|
||||
return new TypeHierarchyResultHandler();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public IterableResultHandler iterableResultHandler() {
|
||||
return new IterableResultHandler();
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void wireIterableResultHandler() {
|
||||
iterableResultHandler().setDelegate(mainResultHandler());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,6 +19,7 @@ package org.springframework.shell2.result;
|
||||
import org.jline.utils.AttributedString;
|
||||
import org.jline.utils.AttributedStyle;
|
||||
|
||||
import org.springframework.shell2.ResultHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.shell2;
|
||||
package org.springframework.shell2.result;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
@@ -23,17 +23,20 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.shell2.result.ResultHandler;
|
||||
import org.springframework.shell2.ResultHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* A unique entry point delegating to the most appropriate {@link ResultHandler},
|
||||
* according to the type of result to handle.
|
||||
* A delegating {@link ResultHandler} that dispatches handling based on the type of the result.
|
||||
* <p>
|
||||
* If no direct match is found, the type hierarchy of the result is considered, including implemented interfaces.
|
||||
* Auto-populates the handler map based on Generics type declaration of each discovered {@link ResultHandler} in the
|
||||
* ApplicationContext.
|
||||
* </p>
|
||||
*
|
||||
* @author Eric Bottard
|
||||
*/
|
||||
@Component
|
||||
public class ResultHandlers {
|
||||
public class TypeHierarchyResultHandler implements ResultHandler<Object> {
|
||||
|
||||
private Map<Class<?>, ResultHandler<?>> resultHandlers = new HashMap<>();
|
||||
|
||||
@@ -67,7 +70,14 @@ public class ResultHandlers {
|
||||
public void setResultHandlers(Set<ResultHandler<?>> resultHandlers) {
|
||||
for (ResultHandler<?> resultHandler : resultHandlers) {
|
||||
Type type = ((ParameterizedType) resultHandler.getClass().getGenericInterfaces()[0]).getActualTypeArguments()[0];
|
||||
this.resultHandlers.put((Class<?>) type, resultHandler);
|
||||
registerHandler((Class<?>) type, resultHandler);
|
||||
}
|
||||
}
|
||||
|
||||
private void registerHandler(Class<?> type, ResultHandler<?> resultHandler) {
|
||||
ResultHandler<?> previous = this.resultHandlers.put(type, resultHandler);
|
||||
if (previous != null) {
|
||||
throw new IllegalArgumentException(String.format("Multiple ResultHandlers configured for %s: both %s and %s", type, previous, resultHandler));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,11 +22,13 @@ import java.util.List;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.shell2.CompletionContext;
|
||||
import org.springframework.shell2.CompletionProposal;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* A {@link ValueProvider} that knows how to complete values for {@link Enum} typed parameters.
|
||||
* @author Eric Bottard
|
||||
*/
|
||||
@Component
|
||||
public class EnumValueProvider implements ValueProvider {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -45,6 +45,7 @@ import org.springframework.shell2.ParameterMissingResolutionException;
|
||||
import org.springframework.shell2.ParameterResolver;
|
||||
import org.springframework.shell2.UnfinishedParameterResolutionException;
|
||||
import org.springframework.shell2.Utils;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ConcurrentReferenceHashMap;
|
||||
|
||||
@@ -71,6 +72,7 @@ import org.springframework.util.ConcurrentReferenceHashMap;
|
||||
* @author Eric Bottard
|
||||
* @author Florent Biville
|
||||
*/
|
||||
@Component
|
||||
public class StandardParameterResolver implements ParameterResolver {
|
||||
|
||||
private final ConversionService conversionService;
|
||||
@@ -84,6 +86,7 @@ public class StandardParameterResolver implements ParameterResolver {
|
||||
*/
|
||||
private final Map<CacheKey, Map<Parameter, ParameterRawValue>> parameterCache = new ConcurrentReferenceHashMap<>();
|
||||
|
||||
@Autowired
|
||||
public StandardParameterResolver(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
@@ -23,13 +23,13 @@ import org.jline.reader.UserInterruptException;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import org.springframework.shell2.result.ResultHandler;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.springframework.shell2.result.TypeHierarchyResultHandler;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link JLineShell}.
|
||||
*
|
||||
@@ -43,7 +43,7 @@ public class JLineShellTest {
|
||||
public void testCtrlCInterception() throws Exception {
|
||||
shell.lineReader = mock(LineReader.class);
|
||||
AssertingExitRequestResultHandler resultHandler = new AssertingExitRequestResultHandler();
|
||||
shell.resultHandlers.setResultHandlers(Collections.singleton(resultHandler));
|
||||
shell.resultHandler = resultHandler;
|
||||
when(shell.lineReader.readLine(Mockito.<String>any())).thenThrow(
|
||||
new UserInterruptException("some input"),
|
||||
new UserInterruptException("")
|
||||
|
||||
Reference in New Issue
Block a user