parent
c91e83c7d2
commit
38f0cf1ed2
|
@ -1,12 +1,6 @@
|
|||
package org.test
|
||||
|
||||
@GrabResolver(name='spring-milestone', root='http://repo.springframework.org/milestone')
|
||||
@GrabResolver(name='spring-snapshot', root='http://repo.springframework.org/snapshot')
|
||||
@Grab("org.springframework.bootstrap:spring-bootstrap:0.0.1-SNAPSHOT")
|
||||
@Grab("org.springframework:spring-context:4.0.0.BOOTSTRAP-SNAPSHOT")
|
||||
|
||||
@org.springframework.bootstrap.context.annotation.EnableAutoConfiguration
|
||||
@org.springframework.stereotype.Component
|
||||
@Component
|
||||
class Example implements org.springframework.bootstrap.CommandLineRunner {
|
||||
|
||||
@org.springframework.beans.factory.annotation.Autowired
|
||||
|
@ -18,7 +12,7 @@ class Example implements org.springframework.bootstrap.CommandLineRunner {
|
|||
}
|
||||
|
||||
|
||||
@org.springframework.stereotype.Service
|
||||
@Service
|
||||
class MyService {
|
||||
|
||||
public String sayWorld() {
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
package org.test
|
||||
|
||||
@GrabResolver(name='spring-snapshot', root='http://repo.springframework.org/snapshot')
|
||||
@Grab("org.springframework.bootstrap:spring-bootstrap-service:0.0.1-SNAPSHOT")
|
||||
|
||||
@Controller
|
||||
class SampleController {
|
||||
|
||||
@RequestMapping("/")
|
||||
@ResponseBody
|
||||
public def hello() {
|
||||
[message: "Hello World!"]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
@org.springframework.bootstrap.context.annotation.EnableAutoConfiguration
|
||||
@Controller
|
||||
class Example {
|
||||
|
||||
|
|
|
@ -48,7 +48,9 @@ public class RunCommand extends OptionParsingCommand {
|
|||
|
||||
private OptionSpec<Void> verboseOption;
|
||||
|
||||
private OptionSpec<Void> quiteOption;
|
||||
private OptionSpec<Void> quietOption;
|
||||
|
||||
private BootstrapRunner runner;
|
||||
|
||||
public RunCommand() {
|
||||
super("run", "Run a spring groovy script");
|
||||
|
@ -59,6 +61,12 @@ public class RunCommand extends OptionParsingCommand {
|
|||
return "[options] <file>";
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
if (this.runner != null) {
|
||||
this.runner.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected OptionParser createOptionParser() {
|
||||
OptionParser parser = new OptionParser();
|
||||
|
@ -71,7 +79,7 @@ public class RunCommand extends OptionParsingCommand {
|
|||
this.noGuessDependenciesOption = parser.accepts("no-guess-dependencies",
|
||||
"Do not attempt to guess dependencies");
|
||||
this.verboseOption = parser.acceptsAll(asList("verbose", "v"), "Verbose logging");
|
||||
this.quiteOption = parser.acceptsAll(asList("quiet", "q"), "Quiet logging");
|
||||
this.quietOption = parser.acceptsAll(asList("quiet", "q"), "Quiet logging");
|
||||
return parser;
|
||||
}
|
||||
|
||||
|
@ -87,8 +95,9 @@ public class RunCommand extends OptionParsingCommand {
|
|||
|
||||
BootstrapRunnerConfiguration configuration = new BootstrapRunnerConfigurationAdapter(
|
||||
options);
|
||||
new BootstrapRunner(configuration, file, args.toArray(new String[args.size()]))
|
||||
.compileAndRun();
|
||||
this.runner = new BootstrapRunner(configuration, file,
|
||||
args.toArray(new String[args.size()]));
|
||||
this.runner.compileAndRun();
|
||||
}
|
||||
|
||||
private File getFileArgument(List<String> nonOptionArguments) {
|
||||
|
@ -136,7 +145,7 @@ public class RunCommand extends OptionParsingCommand {
|
|||
if (this.options.has(RunCommand.this.verboseOption)) {
|
||||
return Level.FINEST;
|
||||
}
|
||||
if (this.options.has(RunCommand.this.quiteOption)) {
|
||||
if (this.options.has(RunCommand.this.quietOption)) {
|
||||
return Level.OFF;
|
||||
}
|
||||
return Level.INFO;
|
||||
|
|
|
@ -60,12 +60,34 @@ public class DependencyCustomizer {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create a nested {@link DependencyCustomizer} that only applies if the specified
|
||||
* class names are not on the class path.
|
||||
* Create a nested {@link DependencyCustomizer} that only applies if any of the
|
||||
* specified class names are not on the class path.
|
||||
* @param classNames the class names to test
|
||||
* @return a nested {@link DependencyCustomizer}
|
||||
*/
|
||||
public DependencyCustomizer ifMissingClasses(final String... classNames) {
|
||||
public DependencyCustomizer ifAnyMissingClasses(final String... classNames) {
|
||||
return new DependencyCustomizer(this) {
|
||||
@Override
|
||||
protected boolean canAdd() {
|
||||
for (String classname : classNames) {
|
||||
try {
|
||||
DependencyCustomizer.this.loader.loadClass(classname);
|
||||
} catch (Exception e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return DependencyCustomizer.this.canAdd();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a nested {@link DependencyCustomizer} that only applies if all of the
|
||||
* specified class names are not on the class path.
|
||||
* @param classNames the class names to test
|
||||
* @return a nested {@link DependencyCustomizer}
|
||||
*/
|
||||
public DependencyCustomizer ifAllMissingClasses(final String... classNames) {
|
||||
return new DependencyCustomizer(this) {
|
||||
@Override
|
||||
protected boolean canAdd() {
|
||||
|
@ -81,6 +103,86 @@ public class DependencyCustomizer {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a nested {@link DependencyCustomizer} that only applies if the specified
|
||||
* paths are on the class path.
|
||||
* @param paths the paths to test
|
||||
* @return a nested {@link DependencyCustomizer}
|
||||
*/
|
||||
public DependencyCustomizer ifAllResourcesPresent(final String... paths) {
|
||||
return new DependencyCustomizer(this) {
|
||||
@Override
|
||||
protected boolean canAdd() {
|
||||
for (String path : paths) {
|
||||
try {
|
||||
if (DependencyCustomizer.this.loader.getResource(path) == null) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
return DependencyCustomizer.this.canAdd();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a nested {@link DependencyCustomizer} that only applies at least one of the
|
||||
* specified paths is on the class path.
|
||||
* @param paths the paths to test
|
||||
* @return a nested {@link DependencyCustomizer}
|
||||
*/
|
||||
public DependencyCustomizer ifAnyResourcesPresent(final String... paths) {
|
||||
return new DependencyCustomizer(this) {
|
||||
@Override
|
||||
protected boolean canAdd() {
|
||||
for (String path : paths) {
|
||||
try {
|
||||
if (DependencyCustomizer.this.loader.getResource(path) != null) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
return DependencyCustomizer.this.canAdd();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a nested {@link DependencyCustomizer} that only applies the specified one
|
||||
* was not yet added.
|
||||
* @return a nested {@link DependencyCustomizer}
|
||||
*/
|
||||
public DependencyCustomizer ifNotAdded(final String group, final String module) {
|
||||
return new DependencyCustomizer(this) {
|
||||
@Override
|
||||
protected boolean canAdd() {
|
||||
if (DependencyCustomizer.this.contains(group, module)) {
|
||||
return false;
|
||||
}
|
||||
return DependencyCustomizer.this.canAdd();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param group the group ID
|
||||
* @param module the module ID
|
||||
* @return true if this module is already in the dependencies
|
||||
*/
|
||||
protected boolean contains(String group, String module) {
|
||||
for (Map<String, Object> dependency : this.dependencies) {
|
||||
if (group.equals(dependency.get("group"))
|
||||
&& module.equals(dependency.get("module"))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a single dependencies.
|
||||
* @param group the group ID
|
||||
|
@ -113,7 +215,7 @@ public class DependencyCustomizer {
|
|||
|
||||
/**
|
||||
* Strategy called to test if dependencies can be added. Subclasses override as
|
||||
* requred.
|
||||
* required.
|
||||
*/
|
||||
protected boolean canAdd() {
|
||||
return true;
|
||||
|
|
|
@ -37,7 +37,7 @@ public class SpringBatchCompilerAutoConfiguration extends CompilerAutoConfigurat
|
|||
|
||||
@Override
|
||||
public void applyDependencies(DependencyCustomizer dependencies) {
|
||||
dependencies.ifMissingClasses("org.springframework.batch.core.Job").add(
|
||||
dependencies.ifAnyMissingClasses("org.springframework.batch.core.Job").add(
|
||||
"org.springframework.batch", "spring-batch-core", "2.1.9.RELEASE");
|
||||
}
|
||||
|
||||
|
|
|
@ -38,15 +38,27 @@ public class SpringBootstrapCompilerAutoConfiguration extends CompilerAutoConfig
|
|||
|
||||
@Override
|
||||
public void applyDependencies(DependencyCustomizer dependencies) {
|
||||
dependencies.ifMissingClasses("org.springframework.bootstrap.SpringApplication")
|
||||
.add("org.springframework.bootstrap", "spring-bootstrap-application",
|
||||
"0.0.1-SNAPSHOT");
|
||||
DependencyCustomizer customizer = dependencies.ifAnyMissingClasses(
|
||||
"org.springframework.bootstrap.SpringApplication").add(
|
||||
"org.springframework.bootstrap", "spring-bootstrap", "0.0.1-SNAPSHOT");
|
||||
customizer = customizer.ifAnyResourcesPresent("logback.xml").add(
|
||||
"ch.qos.logback", "logback-classic", "1.0.7");
|
||||
customizer = customizer.ifNotAdded("cg.qos.logback", "logback-classic")
|
||||
.ifAnyResourcesPresent("log4j.properties", "log4j.xml")
|
||||
.add("org.slf4j", "slf4j-log4j12", "1.7.1")
|
||||
.add("log4j", "log4j", "1.2.16");
|
||||
customizer = customizer.ifNotAdded("ch.qos.logback", "logback-classic")
|
||||
.ifNotAdded("org.slf4j", "slf4j-log4j12")
|
||||
.add("org.slf4j", "slf4j-jdk14", "1.7.1");
|
||||
// FIXME get the version
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyImports(ImportCustomizer imports) {
|
||||
imports.addImports("javax.sql.DataSource",
|
||||
"org.springframework.stereotype.Controller",
|
||||
"org.springframework.stereotype.Service",
|
||||
"org.springframework.stereotype.Component",
|
||||
"org.springframework.beans.factory.annotation.Autowired",
|
||||
"org.springframework.beans.factory.annotation.Value",
|
||||
"org.springframework.context.annotation.Import",
|
||||
|
|
|
@ -32,10 +32,10 @@ public class SpringMvcCompilerAutoConfiguration extends CompilerAutoConfiguratio
|
|||
|
||||
@Override
|
||||
public void applyDependencies(DependencyCustomizer dependencies) {
|
||||
dependencies.ifMissingClasses("org.springframework.web.servlet.mvc.Controller")
|
||||
dependencies.ifAnyMissingClasses("org.springframework.web.servlet.mvc.Controller")
|
||||
.add("org.springframework", "spring-webmvc", "4.0.0.BOOTSTRAP-SNAPSHOT");
|
||||
|
||||
dependencies.ifMissingClasses("org.apache.catalina.startup.Tomcat",
|
||||
dependencies.ifAnyMissingClasses("org.apache.catalina.startup.Tomcat",
|
||||
"org.eclipse.jetty.server.Server").add("org.eclipse.jetty",
|
||||
"jetty-webapp", "8.1.10.v20130312");
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.springframework.bootstrap.cli.compiler.GroovyCompiler;
|
|||
* changes.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class BootstrapRunner {
|
||||
|
||||
|
@ -71,11 +72,7 @@ public class BootstrapRunner {
|
|||
public synchronized void compileAndRun() throws Exception {
|
||||
try {
|
||||
|
||||
// Shutdown gracefully any running container
|
||||
if (this.runThread != null) {
|
||||
this.runThread.shutdown();
|
||||
this.runThread = null;
|
||||
}
|
||||
stop();
|
||||
|
||||
// Compile
|
||||
Class<?>[] classes = this.compiler.compile(this.file);
|
||||
|
@ -140,7 +137,7 @@ public class BootstrapRunner {
|
|||
}
|
||||
|
||||
/**
|
||||
* Shutdown the thread, closing any previously opened appplication context.
|
||||
* Shutdown the thread, closing any previously opened application context.
|
||||
*/
|
||||
public synchronized void shutdown() {
|
||||
if (this.applicationContext != null) {
|
||||
|
@ -188,4 +185,12 @@ public class BootstrapRunner {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
if (this.runThread != null) {
|
||||
this.runThread.shutdown();
|
||||
this.runThread = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright 2012-2013 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.bootstrap.cli;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class SampleIntegrationTests {
|
||||
|
||||
private RunCommand command;
|
||||
|
||||
private void start(final String sample) throws Exception {
|
||||
Future<RunCommand> future = Executors.newSingleThreadExecutor().submit(
|
||||
new Callable<RunCommand>() {
|
||||
@Override
|
||||
public RunCommand call() throws Exception {
|
||||
RunCommand command = new RunCommand();
|
||||
command.run(sample);
|
||||
return command;
|
||||
}
|
||||
});
|
||||
this.command = future.get(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@After
|
||||
public void stop() {
|
||||
if (this.command != null) {
|
||||
this.command.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void clean() {
|
||||
// SpringBootstrapCli.main("clean");
|
||||
// System.setProperty("ivy.message.logger.level", "4");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void appSample() throws Exception {
|
||||
start("samples/app.groovy");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void webSample() throws Exception {
|
||||
start("samples/web.groovy");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void serviceSample() throws Exception {
|
||||
start("samples/service.groovy");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
log4j.rootCategory=INFO, stdout
|
||||
|
||||
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n
|
||||
|
||||
log4j.category.org.springframework.bootstrap=DEBUG
|
|
@ -7,7 +7,7 @@
|
|||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>spring-bootstrap-trad-sample</artifactId>
|
||||
<name>Spring Bootstrap Trad Sample</name>
|
||||
<name>spring-bootstrap-trad-sample</name>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<properties>
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
*/
|
||||
package org.springframework.bootstrap.autoconfigure.service;
|
||||
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -41,7 +40,7 @@ public class ManagementAutoConfiguration implements ApplicationContextAware,
|
|||
private ApplicationContext parent;
|
||||
private ConfigurableApplicationContext context;
|
||||
|
||||
@ConditionalOnExpression("${container.port} == ${container.management_port}")
|
||||
@ConditionalOnExpression("${container.port:8080} == ${container.management_port:8080}")
|
||||
@Configuration
|
||||
@Import({ VarzAutoConfiguration.class, HealthzAutoConfiguration.class })
|
||||
public static class ManagementEndpointsConfiguration {
|
||||
|
|
|
@ -15,12 +15,15 @@
|
|||
*/
|
||||
package org.springframework.bootstrap.context.annotation;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.config.BeanExpressionContext;
|
||||
import org.springframework.beans.factory.config.BeanExpressionResolver;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.context.annotation.Condition;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
import org.springframework.core.type.ClassMetadata;
|
||||
|
||||
/**
|
||||
* A Condition that evaluates a SpEL expression.
|
||||
|
@ -30,6 +33,8 @@ import org.springframework.core.type.AnnotatedTypeMetadata;
|
|||
*/
|
||||
public class ExpressionCondition implements Condition {
|
||||
|
||||
private static Log logger = LogFactory.getLog(ExpressionCondition.class);
|
||||
|
||||
@Override
|
||||
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||
String value = (String) metadata.getAnnotationAttributes(
|
||||
|
@ -38,6 +43,14 @@ public class ExpressionCondition implements Condition {
|
|||
// For convenience allow user to provide bare expression with no #{} wrapper
|
||||
value = "#{" + value + "}";
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
StringBuilder builder = new StringBuilder("Evaluating expression");
|
||||
if (metadata instanceof ClassMetadata) {
|
||||
builder.append(" on " + ((ClassMetadata) metadata).getClassName());
|
||||
}
|
||||
builder.append(": " + value);
|
||||
logger.debug(builder.toString());
|
||||
}
|
||||
// Explicitly allow environment placeholders inside the expression
|
||||
value = context.getEnvironment().resolvePlaceholders(value);
|
||||
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
|
||||
|
|
Loading…
Reference in New Issue