Fast forward existing prototype work
parent
80b151e2b3
commit
fb6b224470
@ -0,0 +1,11 @@
|
||||
.gradle
|
||||
*.sw?
|
||||
.#*
|
||||
*#
|
||||
/build
|
||||
.classpath
|
||||
.project
|
||||
.settings
|
||||
bin
|
||||
build
|
||||
target
|
@ -0,0 +1,5 @@
|
||||
language: java
|
||||
|
||||
install: mvn -U install --quiet -DskipTests=true
|
||||
script: mvn clean test
|
||||
|
@ -0,0 +1,111 @@
|
||||
# Spring Bootstrap
|
||||
Experimental work based on discussions at SpringOne2GX 2012. See also the 'bootstrap' branch of Spring.
|
||||
|
||||
|
||||
## Elevator Pitch
|
||||
Opinionated view of the Spring family so that new users can quickly get to the 'meat and potatoes'. Assumes no knowledge of the Java development ecosystem. Absolutely no code generation and no XML.
|
||||
|
||||
|
||||
## Installing
|
||||
You need to build from source for now, but when it's done instructions will look like this:
|
||||
|
||||
1) Get Java
|
||||
Download and install the Java SDK from www.java.com
|
||||
|
||||
2) Get Spring
|
||||
`curl -s try.springsource.org | bash` or use the Windows installer
|
||||
|
||||
3) Get to Work!
|
||||
spr run yoursourcefile.groovy
|
||||
|
||||
|
||||
## What? It's Groovy then? or like Grails? or another Roo?
|
||||
There is a command line tool that uses Groovy underneath so that we can present simple snippets that can just run:
|
||||
|
||||
@Controller
|
||||
class ThisWillActuallyRun {
|
||||
|
||||
@RequestMapping("/")
|
||||
@ResponseBody
|
||||
String home() {
|
||||
return "Hello World!"
|
||||
}
|
||||
}
|
||||
|
||||
By inspecting the code for well known annotations we can `@Grab` appropriate dependencies and also dynamically add `import` statements. Groovy makes this really easy.
|
||||
|
||||
If you don't want to use the command line tool, and you would rather work using Java and an IDE you can. Just add a `main()` method that calls `SpringApplication` and add `@EnableAutoConfiguration`:
|
||||
|
||||
import org.springframework.bootstrap.*;
|
||||
import org.springframework.context.annotation.*;
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
@ComponentScan
|
||||
public class MyApplication {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
SpringApplication.run(MyApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
import org.springframework.beans.factory.annotation.*;
|
||||
import org.springframework.stereotype.*;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@Controller
|
||||
public class SampleController {
|
||||
|
||||
@RequestMapping("/")
|
||||
@ResponseBody
|
||||
String home() {
|
||||
return "Hello World!"
|
||||
}
|
||||
}
|
||||
|
||||
## Under the hood
|
||||
There are a number of disparate parts of Bootstrap. Here are the important classes:
|
||||
|
||||
### The Spring CLI
|
||||
The 'spr' command line application compiles and runs Groovy source, adding `import` statements and `@Grab` annotations. The application can also watch files, automatically recompiling and restarting when they change.
|
||||
|
||||
### SpringApplication
|
||||
The `SpringApplication` class provides the main entry point for a standalone Spring Application. Its sole job is to create and refresh an appropriate Spring `ApplicationContext`. Any contained beans that implements `CommandLineRunner` will be executed after the context has started. A `SpringApplication` can load beans from a number of different sources, including classes, packages (scanned) or XML files. By default a `AnnotationConfigApplicationContext` or `AnnotationConfigEmbeddedWebApplicationContext` depending on your classpath.
|
||||
|
||||
### EmbeddedWebApplicationContext
|
||||
The `EmbeddedWebApplicationContext` will probably be part of Spring 4.0. It provides a Spring 'WebApplicationContext' that can bootstrap itself and start and embedded servlet container. Support is provided for Tomcat and Jetty.
|
||||
|
||||
### @EnableAutoConfigure
|
||||
The `@EnableAutoConfigure` can be used on a `@Configuration` class to trigger auto-configuration of the Spring context. Auto-configuration attempts to guess what beans a user might want based on their classpath. For example, If a 'HSQLDB' is on the classpath the user probably wants an in-memory database to be defined. Auto-configuration will back away as the user starts to define their own beans.
|
||||
|
||||
### @Conditional
|
||||
The `@Conditional` annotation will probably be part of Spring 4.0. It provides allows `@Configuration` classes to be skipped depending on conditions. Bootstrap provides `@ConditionalOnBean`, `@ConditionalOnMissingBean` and `@ConditionalOnClass` annotations are used when defining auto-configuration classes.
|
||||
|
||||
## Building the code
|
||||
Use maven to build the source code.
|
||||
|
||||
mvn clean install
|
||||
|
||||
## Importing into eclipse
|
||||
You can use m2e or `maven eclipse:eclipse`.
|
||||
|
||||
Project specific settings are configured for source formatting. If you are using m2e please follow these steps to install eclipse support:
|
||||
|
||||
* Select `Install new software` from the `help` menu
|
||||
* Click `Add...` to add a new repository
|
||||
* Click the `Archive...` button
|
||||
* Select `org.eclipse.m2e.maveneclipse.site-0.0.1-SNAPSHOT-site.zip` from the `eclipse` folder in this checkout
|
||||
* Install "Maven Integration for the maven-eclipse-plugin"
|
||||
|
||||
If you prefer you can import settings manually from the `/eclipse` folder.
|
||||
|
||||
## Samples
|
||||
The following samples are included. To run use `java -jar <archive>-full.jar`
|
||||
|
||||
* spring-bootstrap-simple-sample - A simple command line application
|
||||
* spring-bootstrap-jetty-sample - Embedded Jetty
|
||||
* spring-bootstrap-tomcat-sample - Embedded Tomcat
|
||||
* spring-bootstrap-data-sample - Spring Data JPA + Hibernate + HSQLDB
|
||||
|
@ -0,0 +1,291 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<profiles version="12">
|
||||
<profile kind="CodeFormatterProfile" name="Spring Bootstrap" version="12">
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.source" value="1.7"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="90"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="8"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="tab"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.compliance" value="1.7"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode" value="enabled"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="90"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.7"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
|
||||
</profile>
|
||||
</profiles>
|
@ -0,0 +1,385 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.codeComplete.argumentPrefixes=
|
||||
org.eclipse.jdt.core.codeComplete.argumentSuffixes=
|
||||
org.eclipse.jdt.core.codeComplete.fieldPrefixes=
|
||||
org.eclipse.jdt.core.codeComplete.fieldSuffixes=
|
||||
org.eclipse.jdt.core.codeComplete.localPrefixes=
|
||||
org.eclipse.jdt.core.codeComplete.localSuffixes=
|
||||
org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
|
||||
org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
|
||||
org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes=
|
||||
org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes=
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||
org.eclipse.jdt.core.compiler.doc.comment.support=enabled
|
||||
org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
|
||||
org.eclipse.jdt.core.compiler.problem.deadCode=warning
|
||||
org.eclipse.jdt.core.compiler.problem.deprecation=warning
|
||||
org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
|
||||
org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
|
||||
org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
|
||||
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
||||
org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
|
||||
org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
|
||||
org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning
|
||||
org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
|
||||
org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
|
||||
org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=default
|
||||
org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
|
||||
org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
|
||||
org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag
|
||||
org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=private
|
||||
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
|
||||
org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
|
||||
org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
|
||||
org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.nullReference=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
|
||||
org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
|
||||
org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
|
||||
org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
|
||||
org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
|
||||
org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
|
||||
org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
|
||||
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
|
||||
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.unusedImport=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
|
||||
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
|
||||
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
||||
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
|
||||
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
|
||||
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_assignment=0
|
||||
org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
|
||||
org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
|
||||
org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
|
||||
org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
|
||||
org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
|
||||
org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
|
||||
org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
|
||||
org.eclipse.jdt.core.formatter.blank_lines_after_package=1
|
||||
org.eclipse.jdt.core.formatter.blank_lines_before_field=0
|
||||
org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
|
||||
org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
|
||||
org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
|
||||
org.eclipse.jdt.core.formatter.blank_lines_before_method=1
|
||||
org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
|
||||
org.eclipse.jdt.core.formatter.blank_lines_before_package=0
|
||||
org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
|
||||
org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
|
||||
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
|
||||
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
|
||||
org.eclipse.jdt.core.formatter.comment.format_block_comments=true
|
||||
org.eclipse.jdt.core.formatter.comment.format_header=false
|
||||
org.eclipse.jdt.core.formatter.comment.format_html=true
|
||||
org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
|
||||
org.eclipse.jdt.core.formatter.comment.format_line_comments=true
|
||||
org.eclipse.jdt.core.formatter.comment.format_source_code=true
|
||||
org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
|
||||
org.eclipse.jdt.core.formatter.comment.indent_root_tags=false
|
||||
org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=do not insert
|
||||
org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert
|
||||
org.eclipse.jdt.core.formatter.comment.line_length=90
|
||||
org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
|
||||
org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
|
||||
org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
|
||||
org.eclipse.jdt.core.formatter.compact_else_if=true
|
||||
org.eclipse.jdt.core.formatter.continuation_indentation=2
|
||||
org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
|
||||
org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
|
||||
org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
|
||||
org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
|
||||
org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
|
||||
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
|
||||
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
|
||||
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
|
||||
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
|
||||
org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
|
||||
org.eclipse.jdt.core.formatter.indent_empty_lines=false
|
||||
org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
|
||||
org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
|
||||
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
|
||||
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
|
||||
org.eclipse.jdt.core.formatter.indentation.size=8
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
|
||||
org.eclipse.jdt.core.formatter.join_lines_in_comments=true
|
||||
org.eclipse.jdt.core.formatter.join_wrapped_lines=true
|
||||
org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
|
||||
org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
|
||||
org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
|
||||
org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
|
||||
org.eclipse.jdt.core.formatter.lineSplit=90
|
||||
org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
|
||||
org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
|
||||
org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
|
||||
org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
|
||||
org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
|
||||
org.eclipse.jdt.core.formatter.tabulation.char=tab
|
||||
org.eclipse.jdt.core.formatter.tabulation.size=4
|
||||
org.eclipse.jdt.core.formatter.use_on_off_tags=false
|
||||
org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
|
||||
org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
|
||||
org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
|
||||
org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
|
File diff suppressed because one or more lines are too long
Binary file not shown.
@ -0,0 +1,398 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.bootstrap</groupId>
|
||||
<artifactId>spring-bootstrap-parent</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
<prerequisites>
|
||||
<maven>3.0.0</maven>
|
||||
</prerequisites>
|
||||
<modules>
|
||||
<module>spring-bootstrap</module>
|
||||
<module>spring-bootstrap-service</module>
|
||||
<module>spring-bootstrap-applications</module>
|
||||
<module>spring-bootstrap-launcher</module>
|
||||
<module>spring-bootstrap-samples</module>
|
||||
<module>spring-bootstrap-cli</module>
|
||||
</modules>
|
||||
<properties>
|
||||
<java.version>1.6</java.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<dependency.springframework.version>4.0.0.BOOTSTRAP-SNAPSHOT</dependency.springframework.version>
|
||||
<dependency.security.javaconfig.version>1.0.0.CI-SNAPSHOT</dependency.security.javaconfig.version>
|
||||
<main.basedir>${project.basedir}</main.basedir>
|
||||
</properties>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-snapshots</id>
|
||||
<name>Spring Snapshots</name>
|
||||
<url>http://maven.springframework.org/snapshot</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>2.4</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-clean-plugin</artifactId>
|
||||
<version>2.5</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<version>2.7</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<version>2.6</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-eclipse-plugin</artifactId>
|
||||
<version>2.9</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<version>2.13</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-install-plugin</artifactId>
|
||||
<version>2.4</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>2.4</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>2.6</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>2.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.13</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-site-plugin</artifactId>
|
||||
<version>3.2</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>2.2.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>2.9</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-eclipse-plugin</artifactId>
|
||||
<configuration>
|
||||
<useProjectReferences>false</useProjectReferences>
|
||||
<additionalConfig>
|
||||
<file>
|
||||
<name>.settings/org.eclipse.jdt.ui.prefs</name>
|
||||
<location>${main.basedir}/eclipse/org.eclipse.jdt.ui.prefs</location>
|
||||
</file>
|
||||
<file>
|
||||
<name>.settings/org.eclipse.jdt.core.prefs</name>
|
||||
<location>${main.basedir}/eclipse/org.eclipse.jdt.core.prefs</location>
|
||||
</file>
|
||||
</additionalConfig>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-javadocs</id>
|
||||
<phase>verify</phase>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-sources</id>
|
||||
<phase>verify</phase>
|
||||
<goals>
|
||||
<goal>jar-no-fork</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<includes>
|
||||
<include>**/*Tests.java</include>
|
||||
</includes>
|
||||
<excludes>
|
||||
<exclude>**/Abstract*.java</exclude>
|
||||
</excludes>
|
||||
<junitArtifactName>junit:junit</junitArtifactName>
|
||||
<systemPropertyVariables>
|
||||
<java.security.egd>file:/dev/./urandom</java.security.egd>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>versions-maven-plugin</artifactId>
|
||||
<version>2.0</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>commons-httpclient</groupId>
|
||||
<artifactId>commons-httpclient</artifactId>
|
||||
<version>3.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.0.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.persistence</groupId>
|
||||
<artifactId>persistence-api</artifactId>
|
||||
<version>1.0.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.11</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
<version>1.7.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>1.7.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
<version>1.7.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-jdk14</artifactId>
|
||||
<version>1.7.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
<version>1.2.17</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>1.0.7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.1.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
<version>2.1.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat.embed</groupId>
|
||||
<artifactId>tomcat-embed-core</artifactId>
|
||||
<version>7.0.39</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat.embed</groupId>
|
||||
<artifactId>tomcat-embed-logging-juli</artifactId>
|
||||
<version>7.0.39</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat.embed</groupId>
|
||||
<artifactId>tomcat-embed-jasper</artifactId>
|
||||
<version>7.0.39</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.groovy</groupId>
|
||||
<artifactId>groovy</artifactId>
|
||||
<version>2.1.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-webapp</artifactId>
|
||||
<version>8.1.9.v20130131</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>javax.servlet</artifactId>
|
||||
<groupId>org.eclipse.jetty.orbit</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-util</artifactId>
|
||||
<version>8.1.9.v20130131</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-jsp</artifactId>
|
||||
<version>8.1.9.v20130131</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest-library</artifactId>
|
||||
<version>1.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-entitymanager</artifactId>
|
||||
<version>4.1.9.Final</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hsqldb</groupId>
|
||||
<artifactId>hsqldb</artifactId>
|
||||
<version>2.2.9</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>1.9.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-javaconfig</artifactId>
|
||||
<version>${dependency.security.javaconfig.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<version>${dependency.springframework.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-expression</artifactId>
|
||||
<version>${dependency.springframework.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>${dependency.springframework.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>${dependency.springframework.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>${dependency.springframework.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<version>${dependency.springframework.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-jdbc</artifactId>
|
||||
<version>${dependency.springframework.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-orm</artifactId>
|
||||
<version>${dependency.springframework.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>${dependency.springframework.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
<version>${dependency.springframework.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-jpa</artifactId>
|
||||
<version>1.3.0.RELEASE</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-jdbc</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-orm</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
<version>1.12</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest-library</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.bootstrap</groupId>
|
||||
<artifactId>spring-bootstrap-parent</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>spring-bootstrap-applications</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<properties>
|
||||
<main.basedir>${project.basedir}/..</main.basedir>
|
||||
</properties>
|
||||
<modules>
|
||||
<module>spring-bootstrap-application</module>
|
||||
<module>spring-bootstrap-batch-application</module>
|
||||
<module>spring-bootstrap-integration-application</module>
|
||||
<module>spring-bootstrap-jpa-application</module>
|
||||
<module>spring-bootstrap-web-application</module>
|
||||
</modules>
|
||||
</project>
|
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.bootstrap</groupId>
|
||||
<artifactId>spring-bootstrap-applications</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>spring-bootstrap-application</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<properties>
|
||||
<main.basedir>${project.basedir}/../..</main.basedir>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>spring-bootstrap</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-jdk14</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.bootstrap</groupId>
|
||||
<artifactId>spring-bootstrap-applications</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>spring-bootstrap-batch-application</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<properties>
|
||||
<main.basedir>${project.basedir}/../..</main.basedir>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>spring-bootstrap-application</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.bootstrap</groupId>
|
||||
<artifactId>spring-bootstrap-applications</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>spring-bootstrap-integration-application</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<properties>
|
||||
<main.basedir>${project.basedir}/../..</main.basedir>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>spring-bootstrap-application</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.bootstrap</groupId>
|
||||
<artifactId>spring-bootstrap-applications</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>spring-bootstrap-jpa-application</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<properties>
|
||||
<main.basedir>${project.basedir}/../..</main.basedir>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>spring-bootstrap-application</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.bootstrap</groupId>
|
||||
<artifactId>spring-bootstrap-applications</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>spring-bootstrap-web-application</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<properties>
|
||||
<main.basedir>${project.basedir}/../..</main.basedir>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>spring-bootstrap-application</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-webapp</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-util</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -0,0 +1,127 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<artifactId>spring-bootstrap-parent</artifactId>
|
||||
<groupId>org.springframework.bootstrap</groupId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>spring-bootstrap-cli</artifactId>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<transformers>
|
||||
<transformer>
|
||||
<resource>META-INF/spring.handlers</resource>
|
||||
</transformer>
|
||||
<transformer>
|
||||
<resource>META-INF/spring.factories</resource>
|
||||
</transformer>
|
||||
<transformer>
|
||||
<resource>META-INF/spring.schemas</resource>
|
||||
</transformer>
|
||||
<transformer />
|
||||
<transformer>
|
||||
<mainClass>${start-class}</mainClass>
|
||||
</transformer>
|
||||
</transformers>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>spring-bootstrap</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>true</createDependencyReducedPom>
|
||||
<filters>
|
||||
<filter>
|
||||
<artifact>*:*</artifact>
|
||||
<excludes>
|
||||
<exclude>META-INF/*.SF</exclude>
|
||||
<exclude>META-INF/*.DSA</exclude>
|
||||
<exclude>META-INF/*.RSA</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
</filters>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>make-distribution</id>
|
||||
<phase>install</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<inherited>false</inherited>
|
||||
<configuration>
|
||||
<descriptors>
|
||||
<descriptor>src/main/assembly/descriptor.xml</descriptor>
|
||||
</descriptors>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.11</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>hamcrest-core</artifactId>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>1.9.5</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>objenesis</artifactId>
|
||||
<groupId>org.objenesis</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>hamcrest-core</artifactId>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest-library</artifactId>
|
||||
<version>1.3</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>hamcrest-core</artifactId>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<properties>
|
||||
<main.basedir>${project.basedir}/..</main.basedir>
|
||||
<start-class>org.springframework.bootstrap.cli.SpringBootstrapCli</start-class>
|
||||
</properties>
|
||||
</project>
|
||||
|
@ -0,0 +1,107 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.bootstrap</groupId>
|
||||
<artifactId>spring-bootstrap-parent</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>spring-bootstrap-cli</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<properties>
|
||||
<main.basedir>${project.basedir}/..</main.basedir>
|
||||
<start-class>org.springframework.bootstrap.cli.SpringBootstrapCli</start-class>
|
||||
</properties>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>spring-bootstrap</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>true</createDependencyReducedPom>
|
||||
<filters>
|
||||
<filter>
|
||||
<artifact>*:*</artifact>
|
||||
<excludes>
|
||||
<exclude>META-INF/*.SF</exclude>
|
||||
<exclude>META-INF/*.DSA</exclude>
|
||||
<exclude>META-INF/*.RSA</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
</filters>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<transformers>
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/spring.handlers</resource>
|
||||
</transformer>
|
||||
<transformer
|
||||
implementation="org.springframework.bootstrap.maven.PropertiesMergingResourceTransformer">
|
||||
<resource>META-INF/spring.factories</resource>
|
||||
</transformer>
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/spring.schemas</resource>
|
||||
</transformer>
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||
<mainClass>${start-class}</mainClass>
|
||||
</transformer>
|
||||
</transformers>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<inherited>false</inherited>
|
||||
<configuration>
|
||||
<descriptors>
|
||||
<descriptor>src/main/assembly/descriptor.xml</descriptor>
|
||||
</descriptors>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>make-distribution</id>
|
||||
<phase>install</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.groovy</groupId>
|
||||
<artifactId>groovy</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.ivy</groupId>
|
||||
<artifactId>ivy</artifactId>
|
||||
<version>2.3.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.sf.jopt-simple</groupId>
|
||||
<artifactId>jopt-simple</artifactId>
|
||||
<version>4.4</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -0,0 +1,29 @@
|
||||
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
|
||||
class Example implements org.springframework.bootstrap.CommandLineRunner {
|
||||
|
||||
@org.springframework.beans.factory.annotation.Autowired
|
||||
private MyService myService;
|
||||
|
||||
public void run(String... args) {
|
||||
print "Hello " + this.myService.sayWorld();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@org.springframework.stereotype.Service
|
||||
class MyService {
|
||||
|
||||
public String sayWorld() {
|
||||
return "World!";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,24 @@
|
||||
@org.springframework.bootstrap.context.annotation.EnableAutoConfiguration
|
||||
@Controller
|
||||
class Example {
|
||||
|
||||
@Autowired
|
||||
private MyService myService;
|
||||
|
||||
@RequestMapping("/")
|
||||
@ResponseBody
|
||||
public String helloWorld() {
|
||||
return myService.sayWorld();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Service
|
||||
class MyService {
|
||||
|
||||
public String sayWorld() {
|
||||
return "World!";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,30 @@
|
||||
<assembly>
|
||||
<id>dist</id>
|
||||
<formats>
|
||||
<format>zip</format>
|
||||
<format>dir</format>
|
||||
</formats>
|
||||
<baseDirectory>spring-${project.version}</baseDirectory>
|
||||
<includeBaseDirectory>true</includeBaseDirectory>
|
||||
<fileSets>
|
||||
<fileSet>
|
||||
<directory>src/main/scripts</directory>
|
||||
<outputDirectory>bin</outputDirectory>
|
||||
<useDefaultExcludes>true</useDefaultExcludes>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>src/main/resources</directory>
|
||||
<outputDirectory>bin</outputDirectory>
|
||||
<useDefaultExcludes>true</useDefaultExcludes>
|
||||
<filtered>true</filtered>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
<dependencySets>
|
||||
<dependencySet>
|
||||
<includes>
|
||||
<include>org.springframework.bootstrap:spring-bootstrap-cli:jar:*</include>
|
||||
</includes>
|
||||
<outputDirectory>lib</outputDirectory>
|
||||
</dependencySet>
|
||||
</dependencySets>
|
||||
</assembly>
|
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
|
||||
/**
|
||||
* Abstract {@link Command} implementation.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public abstract class AbstractCommand implements Command {
|
||||
|
||||
private String name;
|
||||
|
||||
private boolean optionCommand;
|
||||
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* Create a new {@link AbstractCommand} instance.
|
||||
* @param name the name of the command
|
||||
* @param description the command description
|
||||
*/
|
||||
public AbstractCommand(String name, String description) {
|
||||
this(name, description, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link AbstractCommand} instance.
|
||||
* @param name the name of the command
|
||||
* @param description the command description
|
||||
* @param optionCommand if this command is an option command (see
|
||||
* {@link Command#isOptionCommand()}
|
||||
*/
|
||||
public AbstractCommand(String name, String description, boolean optionCommand) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.optionCommand = optionCommand;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return this.description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOptionCommand() {
|
||||
return this.optionCommand;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsageHelp() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printHelp(PrintStream out) throws IOException {
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Runtime exception wrapper that defines additional {@link Option}s that are understood
|
||||
* by the {@link SpringBootstrapCli}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class BootstrapCliException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
private final EnumSet<Option> options;
|
||||
|
||||
/**
|
||||
* Create a new {@link BootstrapCliException} with the specified options.
|
||||
* @param options the exception options
|
||||
*/
|
||||
public BootstrapCliException(Option... options) {
|
||||
this.options = asEnumSet(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link BootstrapCliException} with the specified options.
|
||||
* @param message the exception message to display to the user
|
||||
* @param options the exception options
|
||||
*/
|
||||
public BootstrapCliException(String message, Option... options) {
|
||||
super(message);
|
||||
this.options = asEnumSet(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link BootstrapCliException} with the specified options.
|
||||
* @param message the exception message to display to the user
|
||||
* @param cause the underlying cause
|
||||
* @param options the exception options
|
||||
*/
|
||||
public BootstrapCliException(String message, Throwable cause, Option... options) {
|
||||
super(message, cause);
|
||||
this.options = asEnumSet(options);
|
||||
}
|
||||
|
||||
private EnumSet<Option> asEnumSet(Option[] options) {
|
||||
if (options == null || options.length == 0) {
|
||||
return EnumSet.noneOf(Option.class);
|
||||
}
|
||||
return EnumSet.copyOf(Arrays.asList(options));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns options a set of options that are understood by the
|
||||
* {@link SpringBootstrapCli}.
|
||||
*/
|
||||
public Set<Option> getOptions() {
|
||||
return Collections.unmodifiableSet(this.options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specific options understood by the {@link SpringBootstrapCli}.
|
||||
*/
|
||||
public static enum Option {
|
||||
|
||||
/**
|
||||
* Print basic CLI usage information.
|
||||
*/
|
||||
SHOW_USAGE,
|
||||
|
||||
/**
|
||||
* Print the stack-trace of the exception.
|
||||
*/
|
||||
STACK_TRACE
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
|
||||
/**
|
||||
* A single command that can be run from the CLI.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @see #run(String...)
|
||||
*/
|
||||
public interface Command {
|
||||
|
||||
/**
|
||||
* Returns the name of the command.
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this is an 'option command'. An option command is a special
|
||||
* type of command that usually makes more sense to present as if it is an option. For
|
||||
* example '--help'.
|
||||
*/
|
||||
boolean isOptionCommand();
|
||||
|
||||
/**
|
||||
* Returns a description of the command.
|
||||
*/
|
||||
String getDescription();
|
||||
|
||||
/**
|
||||
* Returns usage help for the command. This should be a simple one-line string
|
||||
* describing basic usage. eg. '[options] <file>'. Do not include the name of
|
||||
* the command in this string.
|
||||
*/
|
||||
String getUsageHelp();
|
||||
|
||||
/**
|
||||
* Prints help for the command.
|
||||
* @param out the output writer to display help
|
||||
* @throws IOException
|
||||
*/
|
||||
void printHelp(PrintStream out) throws IOException;
|
||||
|
||||
/**
|
||||
* Run the command.
|
||||
* @param args command arguments (this will not include the command itself)
|
||||
* @throws Exception
|
||||
*/
|
||||
void run(String... args) throws Exception;
|
||||
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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 joptsimple.OptionParser;
|
||||
import joptsimple.OptionSet;
|
||||
|
||||
import static java.util.Arrays.*;
|
||||
|
||||
/**
|
||||
* {@link Command} to 'create' a new spring groovy script.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class CreateCommand extends OptionParsingCommand {
|
||||
|
||||
public CreateCommand() {
|
||||
super("create", "Create an new spring groovy script");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsageHelp() {
|
||||
return "[options] <file>";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected OptionParser createOptionParser() {
|
||||
OptionParser parser = new OptionParser();
|
||||
parser.acceptsAll(asList("overwite", "f"), "Overwrite any existing file");
|
||||
parser.accepts("type", "Create a specific application type").withOptionalArg()
|
||||
.ofType(String.class).describedAs("web, batch, integration");
|
||||
return parser;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run(OptionSet options) {
|
||||
throw new IllegalStateException("Not implemented"); // FIXME
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Exception thrown when no CLI options are specified.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class NoArgumentsException extends BootstrapCliException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Exception thrown when the 'help' command is issued without any arguments.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class NoHelpCommandArgumentsException extends BootstrapCliException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public NoHelpCommandArgumentsException() {
|
||||
super(Option.SHOW_USAGE);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Exception thrown when an unknown command is specified.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class NoSuchCommandException extends BootstrapCliException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public NoSuchCommandException(String name) {
|
||||
super(String.format("%1$s: '%2$s' is not a valid command. See '%1$s --help'.",
|
||||
SpringBootstrapCli.CLI_APP, name));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Exception thrown when an unknown root option is specified. This only applies to
|
||||
* {@link Command#isOptionCommand() option command}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class NoSuchOptionException extends BootstrapCliException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public NoSuchOptionException(String name) {
|
||||
super("Unknown option: --" + name, Option.SHOW_USAGE);
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
|
||||
import joptsimple.OptionParser;
|
||||
import joptsimple.OptionSet;
|
||||
|
||||
/**
|
||||
* Base class for any {@link Command}s that use an {@link OptionParser}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public abstract class OptionParsingCommand extends AbstractCommand {
|
||||
|
||||
private OptionParser parser;
|
||||
|
||||
public OptionParsingCommand(String name, String description) {
|
||||
super(name, description);
|
||||
this.parser = createOptionParser();
|
||||
}
|
||||
|
||||
protected abstract OptionParser createOptionParser();
|
||||
|
||||
@Override
|
||||
public void printHelp(PrintStream out) throws IOException {
|
||||
this.parser.printHelpOn(out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void run(String... args) throws Exception {
|
||||
OptionSet options = parser.parse(args);
|
||||
run(options);
|
||||
}
|
||||
|
||||
protected abstract void run(OptionSet options) throws Exception;
|
||||
|
||||
}
|
@ -0,0 +1,146 @@
|
||||
/*
|
||||
* 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.awt.Desktop;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import joptsimple.OptionParser;
|
||||
import joptsimple.OptionSet;
|
||||
import joptsimple.OptionSpec;
|
||||
|
||||
import org.springframework.bootstrap.cli.runner.BootstrapRunner;
|
||||
import org.springframework.bootstrap.cli.runner.BootstrapRunnerConfiguration;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
|
||||
/**
|
||||
* {@link Command} to 'run' a spring groovy script.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @see BootstrapRunner
|
||||
*/
|
||||
public class RunCommand extends OptionParsingCommand {
|
||||
|
||||
private OptionSpec<Void> noWatchOption; // FIXME
|
||||
|
||||
private OptionSpec<Void> editOption;
|
||||
|
||||
private OptionSpec<Void> noGuessImportsOption;
|
||||
|
||||
private OptionSpec<Void> noGuessDependenciesOption;
|
||||
|
||||
private OptionSpec<Void> verboseOption;
|
||||
|
||||
private OptionSpec<Void> quiteOption;
|
||||
|
||||
public RunCommand() {
|
||||
super("run", "Run a spring groovy script");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsageHelp() {
|
||||
return "[options] <file>";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected OptionParser createOptionParser() {
|
||||
OptionParser parser = new OptionParser();
|
||||
this.noWatchOption = parser.accepts("no-watch",
|
||||
"Do not watch the specified file for changes");
|
||||
this.editOption = parser.acceptsAll(asList("edit", "e"),
|
||||
"Open the file with the default system editor");
|
||||
this.noGuessImportsOption = parser.accepts("no-guess-imports",
|
||||
"Do not attempt to guess imports");
|
||||
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");
|
||||
return parser;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run(OptionSet options) throws Exception {
|
||||
List<String> nonOptionArguments = options.nonOptionArguments();
|
||||
File file = getFileArgument(nonOptionArguments);
|
||||
List<String> args = nonOptionArguments.subList(1, nonOptionArguments.size());
|
||||
|
||||
if (options.has(this.editOption)) {
|
||||
Desktop.getDesktop().edit(file);
|
||||
}
|
||||
|
||||
BootstrapRunnerConfiguration configuration = new BootstrapRunnerConfigurationAdapter(
|
||||
options);
|
||||
new BootstrapRunner(configuration, file, args.toArray(new String[args.size()]))
|
||||
.compileAndRun();
|
||||
}
|
||||
|
||||
private File getFileArgument(List<String> nonOptionArguments) {
|
||||
if (nonOptionArguments.size() == 0) {
|
||||
throw new RuntimeException("Please specify a file to run");
|
||||
}
|
||||
String filename = nonOptionArguments.get(0);
|
||||
File file = new File(filename);
|
||||
if (!file.isFile() || !file.canRead()) {
|
||||
throw new RuntimeException("Unable to read '" + filename + "'");
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple adapter class to present the {@link OptionSet} as a
|
||||
* {@link BootstrapRunnerConfiguration}.
|
||||
*/
|
||||
private class BootstrapRunnerConfigurationAdapter implements
|
||||
BootstrapRunnerConfiguration {
|
||||
|
||||
private OptionSet options;
|
||||
|
||||
public BootstrapRunnerConfigurationAdapter(OptionSet options) {
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWatchForFileChanges() {
|
||||
return !this.options.has(RunCommand.this.noWatchOption);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGuessImports() {
|
||||
return !this.options.has(RunCommand.this.noGuessImportsOption);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGuessDependencies() {
|
||||
return !this.options.has(RunCommand.this.noGuessDependenciesOption);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Level getLogLevel() {
|
||||
if (this.options.has(RunCommand.this.verboseOption)) {
|
||||
return Level.FINEST;
|
||||
}
|
||||
if (this.options.has(RunCommand.this.quiteOption)) {
|
||||
return Level.OFF;
|
||||
}
|
||||
return Level.INFO;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,214 @@
|
||||
/*
|
||||
* 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.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Spring Bootstrap Command Line Interface. This is the main entry-point for the spring
|
||||
* bootstrap command line application. This class will parse input arguments and delegate
|
||||
* to a suitable {@link Command} implementation based on the first argument.
|
||||
*
|
||||
* <p>
|
||||
* The '-d' and '--debug' switches are handled by this class, however, most argument
|
||||
* parsing is left to the {@link Command} implementation. The {@link OptionParsingCommand}
|
||||
* class provides a convenient base for command that need to parse arguments.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @see #main(String...)
|
||||
* @see BootstrapCliException
|
||||
* @see Command
|
||||
* @see OptionParsingCommand
|
||||
*/
|
||||
public class SpringBootstrapCli {
|
||||
|
||||
public static final String CLI_APP = "spr";
|
||||
|
||||
private static final Set<BootstrapCliException.Option> NO_EXCEPTION_OPTIONS = EnumSet
|
||||
.noneOf(BootstrapCliException.Option.class);
|
||||
|
||||
private List<Command> commands;
|
||||
|
||||
/**
|
||||
* Create a new {@link SpringBootstrapCli} implementation with the default set of
|
||||
* commands.
|
||||
*/
|
||||
public SpringBootstrapCli() {
|
||||
setCommands(Arrays.asList(new VersionCommand(), new RunCommand(),
|
||||
new CreateCommand()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the command available to the CLI. Primarily used to support testing. NOTE: The
|
||||
* 'help' command will be automatically provided in addition to this list.
|
||||
* @param commands the commands to add
|
||||
*/
|
||||
protected void setCommands(List<? extends Command> commands) {
|
||||
this.commands = new ArrayList<Command>(commands);
|
||||
this.commands.add(0, new HelpCommand());
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the CLI and handle and errors.
|
||||
* @param args the input arguments
|
||||
* @return a return status code (non zero is used to indicate an error)
|
||||
*/
|
||||
public int runAndHandleErrors(String... args) {
|
||||
String[] argsWithoutDebugFlags = removeDebugFlags(args);
|
||||
boolean debug = argsWithoutDebugFlags.length != args.length;
|
||||
try {
|
||||
run(argsWithoutDebugFlags);
|
||||
return 0;
|
||||
} catch (NoArgumentsException ex) {
|
||||
showUsage();
|
||||
return 1;
|
||||
} catch (Exception ex) {
|
||||
Set<BootstrapCliException.Option> options = NO_EXCEPTION_OPTIONS;
|
||||
if (ex instanceof BootstrapCliException) {
|
||||
options = ((BootstrapCliException) ex).getOptions();
|
||||
}
|
||||
errorMessage(ex.getMessage());
|
||||
if (options.contains(BootstrapCliException.Option.SHOW_USAGE)) {
|
||||
showUsage();
|
||||
}
|
||||
if (debug || options.contains(BootstrapCliException.Option.STACK_TRACE)) {
|
||||
printStackTrace(ex);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the arguments and run a suitable command.
|
||||
* @param args the arguments
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void run(String... args) throws Exception {
|
||||
if (args.length == 0) {
|
||||
throw new NoArgumentsException();
|
||||
}
|
||||
String commandName = args[0];
|
||||
String[] commandArguments = Arrays.copyOfRange(args, 1, args.length);
|
||||
find(commandName).run(commandArguments);
|
||||
}
|
||||
|
||||
private Command find(String name) {
|
||||
boolean isOption = name.startsWith("--");
|
||||
if (isOption) {
|
||||
name = name.substring(2);
|
||||
}
|
||||
for (Command candidate : this.commands) {
|
||||
if ((isOption && candidate.isOptionCommand() || !isOption)
|
||||
&& candidate.getName().equals(name)) {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
throw (isOption ? new NoSuchOptionException(name) : new NoSuchCommandException(
|
||||
name));
|
||||
}
|
||||
|
||||
protected void showUsage() {
|
||||
System.out.print("usage: " + CLI_APP + " ");
|
||||
for (Command command : this.commands) {
|
||||
if (command.isOptionCommand()) {
|
||||
System.out.print("[--" + command.getName() + "] ");
|
||||
}
|
||||
}
|
||||
System.out.println("");
|
||||
System.out.println(" <command> [<args>]");
|
||||
System.out.println("");
|
||||
System.out.println("Available commands are:");
|
||||
for (Command command : this.commands) {
|
||||
if (!command.isOptionCommand()) {
|
||||
System.out.println(String.format(" %1$-15s %2$s", command.getName(),
|
||||
command.getDescription()));
|
||||
}
|
||||
}
|
||||
System.out.println("");
|
||||
System.out
|
||||
.println("See 'spr help <command>' for more information on a specific command.");
|
||||
}
|
||||
|
||||
protected void errorMessage(String message) {
|
||||
System.err.println(message == null ? "Unexpected error" : message);
|
||||
}
|
||||
|
||||
protected void printStackTrace(Exception ex) {
|
||||
System.err.println("");
|
||||
ex.printStackTrace(System.err);
|
||||
System.err.println("");
|
||||
}
|
||||
|
||||
private String[] removeDebugFlags(String[] args) {
|
||||
List<String> rtn = new ArrayList<String>(args.length);
|
||||
for (String arg : args) {
|
||||
if (!("-d".equals(arg) || "--debug".equals(arg))) {
|
||||
rtn.add(arg);
|
||||
}
|
||||
}
|
||||
return rtn.toArray(new String[rtn.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal {@link Command} used for 'help' and '--help' requests.
|
||||
*/
|
||||
private class HelpCommand extends AbstractCommand {
|
||||
|
||||
public HelpCommand() {
|
||||
super("help", "Show command help", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(String... args) throws Exception {
|
||||
if (args.length == 0) {
|
||||
throw new NoHelpCommandArgumentsException();
|
||||
}
|
||||
String commandName = args[0];
|
||||
for (Command command : SpringBootstrapCli.this.commands) {
|
||||
if (!command.isOptionCommand() && command.getName().equals(commandName)) {
|
||||
System.out.println(CLI_APP + " " + command.getName() + " - "
|
||||
+ command.getDescription());
|
||||
System.out.println();
|
||||
if (command.getUsageHelp() != null) {
|
||||
System.out.println("usage: " + CLI_APP + " " + command.getName()
|
||||
+ " " + command.getUsageHelp());
|
||||
System.out.println();
|
||||
}
|
||||
command.printHelp(System.out);
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new NoSuchCommandException(commandName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The main CLI entry-point.
|
||||
* @param args CLI arguments
|
||||
*/
|
||||
public static void main(String... args) {
|
||||
int exitCode = new SpringBootstrapCli().runAndHandleErrors(args);
|
||||
if (exitCode != 0) {
|
||||
System.exit(exitCode);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* {@link Command} to displat the 'version' number.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class VersionCommand extends AbstractCommand {
|
||||
|
||||
public VersionCommand() {
|
||||
super("version", "Show the version", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(String... args) {
|
||||
throw new IllegalStateException("Not implemented"); // FIXME
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
import org.codehaus.groovy.ast.AnnotatedNode;
|
||||
import org.codehaus.groovy.ast.AnnotationNode;
|
||||
|
||||
/**
|
||||
* General purpose AST utilities.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public abstract class AstUtils {
|
||||
|
||||
/**
|
||||
* Determine if an {@link AnnotatedNode} has one or more of the specified annotations.
|
||||
*/
|
||||
public static boolean hasLeastOneAnnotation(AnnotatedNode node, String... annotations) {
|
||||
|
||||
for (AnnotationNode annotationNode : node.getAnnotations()) {
|
||||
for (String annotation : annotations) {
|
||||
if (annotation.equals(annotationNode.getClassNode().getName())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
import groovy.lang.GroovyClassLoader;
|
||||
|
||||
import org.codehaus.groovy.ast.ClassNode;
|
||||
import org.codehaus.groovy.classgen.GeneratorContext;
|
||||
import org.codehaus.groovy.control.CompilationFailedException;
|
||||
import org.codehaus.groovy.control.CompilePhase;
|
||||
import org.codehaus.groovy.control.SourceUnit;
|
||||
import org.codehaus.groovy.control.customizers.ImportCustomizer;
|
||||
|
||||
/**
|
||||
* Strategy that can be used to apply some auto-configuration during the
|
||||
* {@link CompilePhase#CONVERSION} Groovy compile phase.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public abstract class CompilerAutoConfiguration {
|
||||
|
||||
/**
|
||||
* Strategy method used to determine when compiler auto-configuration should be
|
||||
* applied. Defaults to always.
|
||||
* @param classNode the class node
|
||||
* @return {@code true} if the compiler should be auto configured using this class. If
|
||||
* this method returns {@code false} no other strategy methods will be called.
|
||||
*/
|
||||
public boolean matches(ClassNode classNode) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply any dependency customizations. This method will only be called if
|
||||
* {@link #matches} returns {@code true}.
|
||||
* @param dependencies dependency customizer
|
||||
* @throws CompilationFailedException
|
||||
*/
|
||||
public void applyDependencies(DependencyCustomizer dependencies)
|
||||
throws CompilationFailedException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply any import customizations. This method will only be called if
|
||||
* {@link #matches} returns {@code true}.
|
||||
* @param imports import customizer
|
||||
* @throws CompilationFailedException
|
||||
*/
|
||||
public void applyImports(ImportCustomizer imports) throws CompilationFailedException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply any customizations to the main class. This method will only be called if
|
||||
* {@link #matches} returns {@code true}. This method is useful when a groovy file
|
||||
* defines more than one class but customization only applies to the first class.
|
||||
*/
|
||||
public void applyToMainClass(GroovyClassLoader loader,
|
||||
GroovyCompilerConfiguration configuration, GeneratorContext generatorContext,
|
||||
SourceUnit source, ClassNode classNode) throws CompilationFailedException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply any additional configuration.
|
||||
*/
|
||||
public void apply(GroovyClassLoader loader,
|
||||
GroovyCompilerConfiguration configuration, GeneratorContext generatorContext,
|
||||
SourceUnit source, ClassNode classNode) throws CompilationFailedException {
|
||||
}
|
||||
}
|
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
import groovy.grape.Grape;
|
||||
import groovy.lang.Grapes;
|
||||
import groovy.lang.GroovyClassLoader;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Customizer that allows dependencies to be added during compilation. Delegates to Groovy
|
||||
* {@link Grapes} to actually resolve dependencies. This class provides a fluent API for
|
||||
* conditionally adding dependencies. For example:
|
||||
* {@code dependencies.ifMissing("com.corp.SomeClass").add(group, module, version)}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class DependencyCustomizer {
|
||||
|
||||
private final GroovyClassLoader loader;
|
||||
|
||||
private final List<Map<String, Object>> dependencies;
|
||||
|
||||
/**
|
||||
* Create a new {@link DependencyCustomizer} instance. The {@link #call()} method must
|
||||
* be used to actually resolve dependencies.
|
||||
* @param loader
|
||||
*/
|
||||
public DependencyCustomizer(GroovyClassLoader loader) {
|
||||
this.loader = loader;
|
||||
this.dependencies = new ArrayList<Map<String, Object>>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new nested {@link DependencyCustomizer}.
|
||||
* @param parent
|
||||
*/
|
||||
protected DependencyCustomizer(DependencyCustomizer parent) {
|
||||
this.loader = parent.loader;
|
||||
this.dependencies = parent.dependencies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a nested {@link DependencyCustomizer} that only applies if 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) {
|
||||
return new DependencyCustomizer(this) {
|
||||
@Override
|
||||
protected boolean canAdd() {
|
||||
for (String classname : classNames) {
|
||||
try {
|
||||
DependencyCustomizer.this.loader.loadClass(classname);
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
return DependencyCustomizer.this.canAdd();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a single dependencies.
|
||||
* @param group the group ID
|
||||
* @param module the module ID
|
||||
* @param version the version
|
||||
* @return this {@link DependencyCustomizer} for continued use
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public DependencyCustomizer add(String group, String module, String version) {
|
||||
if (canAdd()) {
|
||||
Map<String, Object> dependency = new HashMap<String, Object>();
|
||||
dependency.put("group", group);
|
||||
dependency.put("module", module);
|
||||
dependency.put("version", version);
|
||||
dependency.put("transitive", true);
|
||||
return add(dependency);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a dependencies.
|
||||
* @param dependencies a map of the dependencies to add.
|
||||
* @return this {@link DependencyCustomizer} for continued use
|
||||
*/
|
||||
public DependencyCustomizer add(Map<String, Object>... dependencies) {
|
||||
this.dependencies.addAll(Arrays.asList(dependencies));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Strategy called to test if dependencies can be added. Subclasses override as
|
||||
* requred.
|
||||
*/
|
||||
protected boolean canAdd() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the dependencies.
|
||||
*/
|
||||
void call() {
|
||||
HashMap<String, Object> args = new HashMap<String, Object>();
|
||||
args.put("classLoader", this.loader);
|
||||
Grape.grab(args, this.dependencies.toArray(new Map[this.dependencies.size()]));
|
||||
}
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
import groovy.lang.GroovyClassLoader;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.codehaus.groovy.ast.ClassNode;
|
||||
import org.codehaus.groovy.control.CompilationUnit;
|
||||
import org.codehaus.groovy.control.CompilerConfiguration;
|
||||
import org.codehaus.groovy.control.SourceUnit;
|
||||
|
||||
/**
|
||||
* Extension of the {@link GroovyClassLoader} that support for obtaining '.class' files as
|
||||
* resources.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class ExtendedGroovyClassLoader extends GroovyClassLoader {
|
||||
|
||||
private Map<String, byte[]> classResources = new HashMap<String, byte[]>();
|
||||
|
||||
public ExtendedGroovyClassLoader(ClassLoader loader, CompilerConfiguration config) {
|
||||
super(loader, config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getResourceAsStream(String name) {
|
||||
InputStream resourceStream = super.getResourceAsStream(name);
|
||||
if (resourceStream == null) {
|
||||
byte[] bytes = this.classResources.get(name);
|
||||
resourceStream = bytes == null ? null : new ByteArrayInputStream(bytes);
|
||||
}
|
||||
return resourceStream;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ClassCollector createCollector(CompilationUnit unit, SourceUnit su) {
|
||||
InnerLoader loader = AccessController
|
||||
.doPrivileged(new PrivilegedAction<InnerLoader>() {
|
||||
@Override
|
||||
public InnerLoader run() {
|
||||
return new InnerLoader(ExtendedGroovyClassLoader.this);
|
||||
}
|
||||
});
|
||||
return new ExtendedClassCollector(loader, unit, su);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inner collector class used to track as classes are added.
|
||||
*/
|
||||
protected class ExtendedClassCollector extends ClassCollector {
|
||||
|
||||
protected ExtendedClassCollector(InnerLoader loader, CompilationUnit unit,
|
||||
SourceUnit su) {
|
||||
super(loader, unit, su);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> createClass(byte[] code, ClassNode classNode) {
|
||||
Class<?> createdClass = super.createClass(code, classNode);
|
||||
ExtendedGroovyClassLoader.this.classResources.put(classNode.getName()
|
||||
.replace(".", "/") + ".class", code);
|
||||
return createdClass;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
import groovy.lang.GroovyClassLoader;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.codehaus.groovy.ast.ClassNode;
|
||||
import org.codehaus.groovy.classgen.GeneratorContext;
|
||||
import org.codehaus.groovy.control.CompilationFailedException;
|
||||
import org.codehaus.groovy.control.CompilePhase;
|
||||
import org.codehaus.groovy.control.CompilerConfiguration;
|
||||
import org.codehaus.groovy.control.SourceUnit;
|
||||
import org.codehaus.groovy.control.customizers.CompilationCustomizer;
|
||||
import org.codehaus.groovy.control.customizers.ImportCustomizer;
|
||||
import org.springframework.bootstrap.cli.compiler.autoconfigure.SpringBootstrapCompilerAutoConfiguration;
|
||||
import org.springframework.bootstrap.cli.compiler.autoconfigure.SpringMvcCompilerAutoConfiguration;
|
||||
|
||||
/**
|
||||
* Compiler for Groovy source files. Primarily a simple Facade for
|
||||
* {@link GroovyClassLoader#parseClass(File)} with the following additional features:
|
||||
* <ul>
|
||||
* <li>{@link CompilerAutoConfiguration} strategies will de applied during compilation</li>
|
||||
*
|
||||
* <li>Multiple classes can be returned if the Groovy source defines more than one Class</li>
|
||||
*
|
||||
* <li>Generated class files can also be loaded using
|
||||
* {@link ClassLoader#getResource(String)}</li>
|
||||
* <ul>
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class GroovyCompiler {
|
||||
|
||||
// FIXME could be a strategy
|
||||
private static final CompilerAutoConfiguration[] COMPILER_AUTO_CONFIGURATIONS = {
|
||||
new SpringBootstrapCompilerAutoConfiguration(),
|
||||
new SpringMvcCompilerAutoConfiguration(),
|
||||
new SpringBootstrapCompilerAutoConfiguration() };
|
||||
|
||||
private GroovyCompilerConfiguration configuration;
|
||||
|
||||
private ExtendedGroovyClassLoader loader;
|
||||
|
||||
/**
|
||||
* Create a new {@link GroovyCompiler} instance.
|
||||
* @param configuration the compiler configuration
|
||||
*/
|
||||
public GroovyCompiler(final GroovyCompilerConfiguration configuration) {
|
||||
this.configuration = configuration;
|
||||
CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
|
||||
this.loader = new ExtendedGroovyClassLoader(getClass().getClassLoader(),
|
||||
compilerConfiguration);
|
||||
compilerConfiguration
|
||||
.addCompilationCustomizers(new CompilerAutoConfigureCustomizer());
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the specified Groovy source files, applying any
|
||||
* {@link CompilerAutoConfiguration}s. All classes defined in the file will be
|
||||
* returned from this method with the first item being the primary class (defined at
|
||||
* the top of the file).
|
||||
* @param file the file to compile
|
||||
* @return compiled classes
|
||||
* @throws CompilationFailedException
|
||||
* @throws IOException
|
||||
*/
|
||||
public Class<?>[] compile(File file) throws CompilationFailedException, IOException {
|
||||
this.loader.clearCache();
|
||||
List<Class<?>> classes = new ArrayList<Class<?>>();
|
||||
Class<?> mainClass = this.loader.parseClass(file);
|
||||
for (Class<?> loadedClass : this.loader.getLoadedClasses()) {
|
||||
classes.add(loadedClass);
|
||||
}
|
||||
classes.remove(mainClass);
|
||||
classes.add(0, mainClass);
|
||||
return classes.toArray(new Class<?>[classes.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link CompilationCustomizer} to call {@link CompilerAutoConfiguration}s.
|
||||
*/
|
||||
private class CompilerAutoConfigureCustomizer extends CompilationCustomizer {
|
||||
|
||||
public CompilerAutoConfigureCustomizer() {
|
||||
super(CompilePhase.CONVERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void call(SourceUnit source, GeneratorContext context, ClassNode classNode)
|
||||
throws CompilationFailedException {
|
||||
ImportCustomizer importCustomizer = new ImportCustomizer();
|
||||
|
||||
// Early sweep to get dependencies
|
||||
DependencyCustomizer dependencyCustomizer = new DependencyCustomizer(
|
||||
GroovyCompiler.this.loader);
|
||||
for (CompilerAutoConfiguration autoConfiguration : COMPILER_AUTO_CONFIGURATIONS) {
|
||||
if (autoConfiguration.matches(classNode)) {
|
||||
if (GroovyCompiler.this.configuration.isGuessDependencies()) {
|
||||
autoConfiguration.applyDependencies(dependencyCustomizer);
|
||||
}
|
||||
}
|
||||
}
|
||||
dependencyCustomizer.call();
|
||||
|
||||
// Additional auto configuration
|
||||
for (CompilerAutoConfiguration autoConfiguration : COMPILER_AUTO_CONFIGURATIONS) {
|
||||
if (autoConfiguration.matches(classNode)) {
|
||||
if (GroovyCompiler.this.configuration.isGuessImports()) {
|
||||
autoConfiguration.applyImports(importCustomizer);
|
||||
importCustomizer.call(source, context, classNode);
|
||||
}
|
||||
if (source.getAST().getClasses().size() > 0
|
||||
&& classNode.equals(source.getAST().getClasses().get(0))) {
|
||||
autoConfiguration.applyToMainClass(GroovyCompiler.this.loader,
|
||||
GroovyCompiler.this.configuration, context, source,
|
||||
classNode);
|
||||
}
|
||||
autoConfiguration
|
||||
.apply(GroovyCompiler.this.loader,
|
||||
GroovyCompiler.this.configuration, context, source,
|
||||
classNode);
|
||||
}
|
||||
}
|
||||
importCustomizer.call(source, context, classNode);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.compiler;
|
||||
|
||||
/**
|
||||
* Configuration for the {@link GroovyCompiler}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public interface GroovyCompilerConfiguration {
|
||||
|
||||
/**
|
||||
* Returns if import declarations should be guessed.
|
||||
*/
|
||||
boolean isGuessImports();
|
||||
|
||||
/**
|
||||
* Returns if jar dependencies should be guessed.
|
||||
*/
|
||||
boolean isGuessDependencies();
|
||||
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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.compiler.autoconfigure;
|
||||
|
||||
import org.codehaus.groovy.ast.ClassNode;
|
||||
import org.codehaus.groovy.control.customizers.ImportCustomizer;
|
||||
import org.springframework.bootstrap.cli.compiler.AstUtils;
|
||||
import org.springframework.bootstrap.cli.compiler.CompilerAutoConfiguration;
|
||||
import org.springframework.bootstrap.cli.compiler.DependencyCustomizer;
|
||||
|
||||
/**
|
||||
* {@link CompilerAutoConfiguration} for Spring Batch.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class SpringBatchCompilerAutoConfiguration extends CompilerAutoConfiguration {
|
||||
|
||||
@Override
|
||||
public boolean matches(ClassNode classNode) {
|
||||
return AstUtils.hasLeastOneAnnotation(classNode, "EnableBatchProcessing");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyDependencies(DependencyCustomizer dependencies) {
|
||||
dependencies.ifMissingClasses("org.springframework.batch.core.Job").add(
|
||||
"org.springframework.batch", "spring-batch-core", "2.1.9.RELEASE");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyImports(ImportCustomizer imports) {
|
||||
imports.addImports(
|
||||
"org.springframework.batch.repeat.RepeatStatus",
|
||||
"org.springframework.batch.core.scope.context.ChunkContext",
|
||||
"org.springframework.batch.core.step.tasklet.Tasklet",
|
||||
"org.springframework.batch.core.configuration.annotation.StepScope",
|
||||
"org.springframework.batch.core.configuration.annotation.JobBuilderFactory",
|
||||
"org.springframework.batch.core.configuration.annotation.StepBuilderFactory",
|
||||
"org.springframework.batch.core.configuration.annotation.EnableBatchProcessing",
|
||||
"org.springframework.batch.core.Step",
|
||||
"org.springframework.batch.core.StepExecution",
|
||||
"org.springframework.batch.core.StepContribution",
|
||||
"org.springframework.batch.core.Job",
|
||||
"org.springframework.batch.core.JobExecution",
|
||||
"org.springframework.batch.core.JobParameter",
|
||||
"org.springframework.batch.core.JobParameters",
|
||||
"org.springframework.batch.core.launch.JobLauncher",
|
||||
"org.springframework.batch.core.converter.DefaultJobParametersConverter");
|
||||
}
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* 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.compiler.autoconfigure;
|
||||
|
||||
import groovy.lang.GroovyClassLoader;
|
||||
|
||||
import org.codehaus.groovy.ast.AnnotationNode;
|
||||
import org.codehaus.groovy.ast.ClassNode;
|
||||
import org.codehaus.groovy.classgen.GeneratorContext;
|
||||
import org.codehaus.groovy.control.CompilationFailedException;
|
||||
import org.codehaus.groovy.control.SourceUnit;
|
||||
import org.codehaus.groovy.control.customizers.ImportCustomizer;
|
||||
import org.springframework.bootstrap.cli.compiler.CompilerAutoConfiguration;
|
||||
import org.springframework.bootstrap.cli.compiler.DependencyCustomizer;
|
||||
import org.springframework.bootstrap.cli.compiler.GroovyCompilerConfiguration;
|
||||
|
||||
/**
|
||||
* {@link CompilerAutoConfiguration} for Spring Bootstrap.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class SpringBootstrapCompilerAutoConfiguration extends CompilerAutoConfiguration {
|
||||
|
||||
@Override
|
||||
public void applyDependencies(DependencyCustomizer dependencies) {
|
||||
dependencies.ifMissingClasses("org.springframework.bootstrap.SpringApplication")
|
||||
.add("org.springframework.bootstrap", "spring-bootstrap-application",
|
||||
"0.0.1-SNAPSHOT");
|
||||
// FIXME get the version
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyImports(ImportCustomizer imports) {
|
||||
imports.addImports("javax.sql.DataSource",
|
||||
"org.springframework.beans.factory.annotation.Autowired",
|
||||
"org.springframework.beans.factory.annotation.Value",
|
||||
"org.springframework.context.annotation.Import",
|
||||
"org.springframework.context.annotation.ImportResource",
|
||||
"org.springframework.context.annotation.Profile",
|
||||
"org.springframework.context.annotation.Scope",
|
||||
"org.springframework.context.annotation.Configuration",
|
||||
"org.springframework.context.annotation.Bean",
|
||||
"org.springframework.bootstrap.context.annotation.EnableAutoConfiguration");
|
||||
imports.addStarImports("org.springframework.stereotype");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyToMainClass(GroovyClassLoader loader,
|
||||
GroovyCompilerConfiguration configuration, GeneratorContext generatorContext,
|
||||
SourceUnit source, ClassNode classNode) throws CompilationFailedException {
|
||||
if (true) {
|
||||
addEnableAutoConfigurationAnnotation(source, classNode);
|
||||
}
|
||||
}
|
||||
|
||||
private void addEnableAutoConfigurationAnnotation(SourceUnit source,
|
||||
ClassNode classNode) {
|
||||
if (!hasEnableAutoConfigureAnnotation(classNode)) {
|
||||
try {
|
||||
Class<?> annotationClass = source
|
||||
.getClassLoader()
|
||||
.loadClass(
|
||||
"org.springframework.bootstrap.context.annotation.EnableAutoConfiguration");
|
||||
AnnotationNode annotationNode = new AnnotationNode(new ClassNode(
|
||||
annotationClass));
|
||||
classNode.addAnnotation(annotationNode);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasEnableAutoConfigureAnnotation(ClassNode classNode) {
|
||||
for (AnnotationNode node : classNode.getAnnotations()) {
|
||||
if ("EnableAutoConfiguration".equals(node.getClassNode()
|
||||
.getNameWithoutPackage())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.compiler.autoconfigure;
|
||||
|
||||
import org.codehaus.groovy.ast.ClassNode;
|
||||
import org.codehaus.groovy.control.customizers.ImportCustomizer;
|
||||
import org.springframework.bootstrap.cli.compiler.AstUtils;
|
||||
import org.springframework.bootstrap.cli.compiler.CompilerAutoConfiguration;
|
||||
import org.springframework.bootstrap.cli.compiler.DependencyCustomizer;
|
||||
|
||||
/**
|
||||
* {@link CompilerAutoConfiguration} for Spring MVC.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class SpringMvcCompilerAutoConfiguration extends CompilerAutoConfiguration {
|
||||
|
||||
@Override
|
||||
public void applyDependencies(DependencyCustomizer dependencies) {
|
||||
dependencies.ifMissingClasses("org.springframework.web.servlet.mvc.Controller")
|
||||
.add("org.springframework", "spring-webmvc", "4.0.0.BOOTSTRAP-SNAPSHOT");
|
||||
|
||||
dependencies.ifMissingClasses("org.apache.catalina.startup.Tomcat",
|
||||
"org.eclipse.jetty.server.Server").add("org.eclipse.jetty",
|
||||
"jetty-webapp", "8.1.10.v20130312");
|
||||
|
||||
// FIXME restore Tomcat when we can get reload to work
|
||||
// dependencies.ifMissingClasses("org.apache.catalina.startup.Tomcat",
|
||||
// "org.eclipse.jetty.server.Server")
|
||||
// .add("org.apache.tomcat.embed", "tomcat-embed-core", "7.0.37")
|
||||
// .add("org.apache.tomcat.embed", "tomcat-embed-logging-juli", "7.0.37");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(ClassNode classNode) {
|
||||
return AstUtils.hasLeastOneAnnotation(classNode, "Controller", "EnableWebMvc");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyImports(ImportCustomizer imports) {
|
||||
imports.addStarImports("org.springframework.web.bind.annotation",
|
||||
"org.springframework.web.servlet.config.annotation");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,191 @@
|
||||
/*
|
||||
* 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.runner;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.springframework.bootstrap.cli.compiler.GroovyCompiler;
|
||||
|
||||
/**
|
||||
* Compiles Groovy code running the resulting classes using a {@code SpringApplication}.
|
||||
* Takes care of threading and class-loading issues and can optionally monitor files for
|
||||
* changes.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class BootstrapRunner {
|
||||
|
||||
// FIXME logging
|
||||
|
||||
private BootstrapRunnerConfiguration configuration;
|
||||
|
||||
private final File file;
|
||||
|
||||
private final String[] args;
|
||||
|
||||
private final GroovyCompiler compiler;
|
||||
|
||||
private RunThread runThread;
|
||||
|
||||
private FileWatchThread fileWatchThread;
|
||||
|
||||
/**
|
||||
* Create a new {@link BootstrapRunner} instance.
|
||||
* @param configuration the configuration
|
||||
* @param file the file to compile/watch
|
||||
* @param args input arguments
|
||||
*/
|
||||
public BootstrapRunner(final BootstrapRunnerConfiguration configuration, File file,
|
||||
String... args) {
|
||||
this.configuration = configuration;
|
||||
this.file = file;
|
||||
this.args = args;
|
||||
this.compiler = new GroovyCompiler(configuration);
|
||||
if (configuration.getLogLevel().intValue() <= Level.FINE.intValue()) {
|
||||
System.setProperty("groovy.grape.report.downloads", "true");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile and run the application. This method is synchronized as it can be called by
|
||||
* file monitoring threads.
|
||||
* @throws Exception
|
||||
*/
|
||||
public synchronized void compileAndRun() throws Exception {
|
||||
try {
|
||||
|
||||
// Shutdown gracefully any running container
|
||||
if (this.runThread != null) {
|
||||
this.runThread.shutdown();
|
||||
this.runThread = null;
|
||||
}
|
||||
|
||||
// Compile
|
||||
Class<?>[] classes = this.compiler.compile(this.file);
|
||||
if (classes.length == 0) {
|
||||
throw new RuntimeException("No classes found in '" + this.file + "'");
|
||||
}
|
||||
|
||||
// Run in new thread to ensure that the context classloader is setup
|
||||
this.runThread = new RunThread(classes);
|
||||
this.runThread.start();
|
||||
this.runThread.join();
|
||||
|
||||
// Start monitoring for changes
|
||||
if (this.fileWatchThread == null
|
||||
&& this.configuration.isWatchForFileChanges()) {
|
||||
this.fileWatchThread = new FileWatchThread();
|
||||
this.fileWatchThread.start();
|
||||
}
|
||||
|
||||
} catch (Exception ex) {
|
||||
if (this.fileWatchThread == null) {
|
||||
throw ex;
|
||||
} else {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Thread used to launch the Spring Application with the correct context classloader.
|
||||
*/
|
||||
private class RunThread extends Thread {
|
||||
|
||||
private final Class<?>[] classes;
|
||||
|
||||
private Object applicationContext;
|
||||
|
||||
/**
|
||||
* Create a new {@link RunThread} instance.
|
||||
* @param classes the classes to launch
|
||||
*/
|
||||
public RunThread(Class<?>... classes) {
|
||||
this.classes = classes;
|
||||
if (classes.length != 0) {
|
||||
setContextClassLoader(classes[0].getClassLoader());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
// User reflection to load and call Spring
|
||||
Class<?> application = getContextClassLoader().loadClass(
|
||||
"org.springframework.bootstrap.SpringApplication");
|
||||
Method method = application.getMethod("run", Object[].class,
|
||||
String[].class);
|
||||
this.applicationContext = method.invoke(null, this.classes,
|
||||
BootstrapRunner.this.args);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown the thread, closing any previously opened appplication context.
|
||||
*/
|
||||
public synchronized void shutdown() {
|
||||
if (this.applicationContext != null) {
|
||||
try {
|
||||
Method method = this.applicationContext.getClass().getMethod("close");
|
||||
method.invoke(this.applicationContext);
|
||||
} catch (NoSuchMethodException ex) {
|
||||
// Not an application context that we can close
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
} finally {
|
||||
this.applicationContext = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Thread to watch for file changes and trigger recompile/reload.
|
||||
*/
|
||||
private class FileWatchThread extends Thread {
|
||||
|
||||
private long previous;
|
||||
|
||||
public FileWatchThread() {
|
||||
this.previous = BootstrapRunner.this.file.lastModified();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (true) {
|
||||
try {
|
||||
Thread.sleep(TimeUnit.SECONDS.toMillis(1));
|
||||
long current = BootstrapRunner.this.file.lastModified();
|
||||
if (this.previous < current) {
|
||||
this.previous = current;
|
||||
compileAndRun();
|
||||
}
|
||||
} catch (InterruptedException ex) {
|
||||
Thread.currentThread().interrupt();
|
||||
} catch (Exception ex) {
|
||||
// Swallow, will be reported by compileAndRun
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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.runner;
|
||||
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.springframework.bootstrap.cli.compiler.GroovyCompilerConfiguration;
|
||||
|
||||
/**
|
||||
* Configuration for the {@link BootstrapRunner}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public interface BootstrapRunnerConfiguration extends GroovyCompilerConfiguration {
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the source file should be monitored for changes and
|
||||
* automatically recompiled.
|
||||
*/
|
||||
boolean isWatchForFileChanges();
|
||||
|
||||
/**
|
||||
* Returns the logging level to use.
|
||||
*/
|
||||
Level getLogLevel();
|
||||
|
||||
}
|
@ -0,0 +1,186 @@
|
||||
package org.springframework.bootstrap.cli;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.BDDMockito.willThrow;
|
||||
import static org.mockito.Matchers.anyObject;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Tests for {@link SpringBootstrapCli}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class SpringBootstrapCliTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
private SpringBootstrapCli cli;
|
||||
|
||||
@Mock
|
||||
private Command regularCommand;
|
||||
|
||||
@Mock
|
||||
private Command optionCommand;
|
||||
|
||||
private Set<Call> calls = EnumSet.noneOf(Call.class);
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
this.cli = new SpringBootstrapCli() {
|
||||
|
||||
@Override
|
||||
protected void showUsage() {
|
||||
SpringBootstrapCliTests.this.calls.add(Call.SHOW_USAGE);
|
||||
super.showUsage();
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void errorMessage(String message) {
|
||||
SpringBootstrapCliTests.this.calls.add(Call.ERROR_MESSAGE);
|
||||
super.errorMessage(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void printStackTrace(Exception ex) {
|
||||
SpringBootstrapCliTests.this.calls.add(Call.PRINT_STACK_TRACE);
|
||||
super.printStackTrace(ex);
|
||||
}
|
||||
};
|
||||
given(this.regularCommand.getName()).willReturn("command");
|
||||
given(this.regularCommand.getDescription()).willReturn("A regular command");
|
||||
given(this.optionCommand.getName()).willReturn("option");
|
||||
given(this.optionCommand.getDescription()).willReturn("An optional command");
|
||||
given(this.optionCommand.isOptionCommand()).willReturn(true);
|
||||
this.cli.setCommands(Arrays.asList(this.regularCommand, this.optionCommand));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runWithoutArguments() throws Exception {
|
||||
this.thrown.expect(NoArgumentsException.class);
|
||||
this.cli.run();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runCommand() throws Exception {
|
||||
this.cli.run("command", "--arg1", "arg2");
|
||||
verify(this.regularCommand).run("--arg1", "arg2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runOptionCommand() throws Exception {
|
||||
this.cli.run("--option", "--arg1", "arg2");
|
||||
verify(this.optionCommand).run("--arg1", "arg2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runOptionCommandWithoutOption() throws Exception {
|
||||
this.cli.run("option", "--arg1", "arg2");
|
||||
verify(this.optionCommand).run("--arg1", "arg2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runOptionOnNonOptionCommand() throws Exception {
|
||||
this.thrown.expect(NoSuchOptionException.class);
|
||||
this.cli.run("--command", "--arg1", "arg2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingCommand() throws Exception {
|
||||
this.thrown.expect(NoSuchCommandException.class);
|
||||
this.cli.run("missing");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handlesSuccess() throws Exception {
|
||||
int status = this.cli.runAndHandleErrors("--option");
|
||||
assertThat(status, equalTo(0));
|
||||
assertThat(this.calls, equalTo((Set<Call>) EnumSet.noneOf(Call.class)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handlesNoArgumentsException() throws Exception {
|
||||
int status = this.cli.runAndHandleErrors();
|
||||
assertThat(status, equalTo(1));
|
||||
assertThat(this.calls, equalTo((Set<Call>) EnumSet.of(Call.SHOW_USAGE)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handlesNoSuchOptionException() throws Exception {
|
||||
int status = this.cli.runAndHandleErrors("--missing");
|
||||
assertThat(status, equalTo(1));
|
||||
assertThat(this.calls,
|
||||
equalTo((Set<Call>) EnumSet.of(Call.ERROR_MESSAGE, Call.SHOW_USAGE)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handlesRegularException() throws Exception {
|
||||
willThrow(new RuntimeException()).given(this.regularCommand).run();
|
||||
int status = this.cli.runAndHandleErrors("command");
|
||||
assertThat(status, equalTo(1));
|
||||
assertThat(this.calls, equalTo((Set<Call>) EnumSet.of(Call.ERROR_MESSAGE)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handlesExceptionWithDashD() throws Exception {
|
||||
willThrow(new RuntimeException()).given(this.regularCommand).run();
|
||||
int status = this.cli.runAndHandleErrors("command", "-d");
|
||||
assertThat(status, equalTo(1));
|
||||
assertThat(this.calls, equalTo((Set<Call>) EnumSet.of(Call.ERROR_MESSAGE,
|
||||
Call.PRINT_STACK_TRACE)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handlesExceptionWithDashDashDebug() throws Exception {
|
||||
willThrow(new RuntimeException()).given(this.regularCommand).run();
|
||||
int status = this.cli.runAndHandleErrors("command", "--debug");
|
||||
assertThat(status, equalTo(1));
|
||||
assertThat(this.calls, equalTo((Set<Call>) EnumSet.of(Call.ERROR_MESSAGE,
|
||||
Call.PRINT_STACK_TRACE)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exceptionMessages() throws Exception {
|
||||
assertThat(new NoSuchOptionException("name").getMessage(),
|
||||
equalTo("Unknown option: --name"));
|
||||
assertThat(new NoSuchCommandException("name").getMessage(),
|
||||
equalTo("spr: 'name' is not a valid command. See 'spr --help'."));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void help() throws Exception {
|
||||
this.cli.run("help", "command");
|
||||
verify(this.regularCommand).printHelp((PrintStream) anyObject());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void helpNoCommand() throws Exception {
|
||||
this.thrown.expect(NoHelpCommandArgumentsException.class);
|
||||
this.cli.run("help");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void helpUnknownCommand() throws Exception {
|
||||
this.thrown.expect(NoSuchCommandException.class);
|
||||
this.cli.run("help", "missing");
|
||||
}
|
||||
|
||||
private static enum Call {
|
||||
SHOW_USAGE, ERROR_MESSAGE, PRINT_STACK_TRACE
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
# Spring Bootstrap Groovy
|
||||
|
||||
Spring Bootstrap Groovy gives you the quickest possible getting
|
||||
started experience with Spring apps, whether you are writing a web
|
||||
app, a batch job or a standalone java app.
|
||||
|
||||
## Building and Testing
|
||||
|
||||
To avoid problems with classpaths and existing JVM-based build tools,
|
||||
Spring Bootstrap Groovy uses an exec plugin call to launch `groovyc`.
|
||||
You need to have a `sh` on your path along with `groovyc` (2.1.x),
|
||||
`find` and `xargs`. These tools are standard on a Mac or Linux
|
||||
distribution, and available using Cygwin on Windows. Once it is
|
||||
built, the zip file is portable.
|
||||
|
||||
Here are the steps to build and test:
|
||||
|
||||
$ mvn install
|
||||
|
||||
The `spring` executable is then available at
|
||||
`spring-bootstrap-groovy/target/spring-<VERSION>`. There is also a jar
|
||||
file with the Groovy Bootstrap components. The `spring` executable
|
||||
includes jars from `SPRING_HOME` in the classpath so you can run it
|
||||
while you are developing like this
|
||||
|
||||
$ export SPRING_HOME=<spring-bootstrap-groovy>/target
|
||||
$ <spring-bootstrap-groovy>/src/main/scripts/spring App.groovy
|
@ -0,0 +1,180 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.bootstrap</groupId>
|
||||
<artifactId>spring-bootstrap-parent</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>spring-bootstrap-groovy</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.bootstrap</groupId>
|
||||
<artifactId>spring-bootstrap</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>${dependency.springframework.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.groovy</groupId>
|
||||
<artifactId>groovy</artifactId>
|
||||
<version>2.1.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.ivy</groupId>
|
||||
<artifactId>ivy</artifactId>
|
||||
<version>2.2.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>grapes</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-clean-plugin</artifactId>
|
||||
<version>2.5</version>
|
||||
<configuration>
|
||||
<filesets>
|
||||
<fileset>
|
||||
<directory>${user.home}/.groovy/grapes</directory>
|
||||
<includes>
|
||||
<include>org.springframework*/**</include>
|
||||
</includes>
|
||||
<followSymlinks>false</followSymlinks>
|
||||
</fileset>
|
||||
</filesets>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
<build>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/groovy</directory>
|
||||
<filtering>true</filtering>
|
||||
<targetPath>../generated-sources/groovy</targetPath>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<!-- Using exec plugin to compile groovy because it needs to be forked
|
||||
cleanly. Only works if sh, find, xargs and groovyc are on PATH -->
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>1.2.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>compile-plugin</id>
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<goal>exec</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<executable>sh</executable>
|
||||
<arguments>
|
||||
<argument>-c</argument>
|
||||
<argument>find target/generated-sources/groovy -name *.groovy |
|
||||
xargs groovyc -d target/classes</argument>
|
||||
</arguments>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<inherited>false</inherited>
|
||||
<configuration>
|
||||
<descriptors>
|
||||
<descriptor>src/main/assembly/descriptor.xml</descriptor>
|
||||
</descriptors>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>make-distribution</id>
|
||||
<phase>install</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<compilerId>groovy-eclipse-compiler</compilerId>
|
||||
</configuration>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.groovy</groupId>
|
||||
<artifactId>groovy-eclipse-compiler</artifactId>
|
||||
<version>2.7.0-01</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<includes>
|
||||
<include>**/*Tests.java</include>
|
||||
</includes>
|
||||
<excludes>
|
||||
<exclude>**/Abstract*.java</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<!--This plugin's configuration is used to store Eclipse m2e settings
|
||||
only. It has no influence on the Maven build itself. -->
|
||||
<plugin>
|
||||
<groupId>org.eclipse.m2e</groupId>
|
||||
<artifactId>lifecycle-mapping</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<configuration>
|
||||
<lifecycleMappingMetadata>
|
||||
<pluginExecutions>
|
||||
<pluginExecution>
|
||||
<pluginExecutionFilter>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<versionRange>[3.0,)</versionRange>
|
||||
<goals>
|
||||
<goal>testCompile</goal>
|
||||
<goal>compile</goal>
|
||||
</goals>
|
||||
</pluginExecutionFilter>
|
||||
<action>
|
||||
<ignore></ignore>
|
||||
</action>
|
||||
</pluginExecution>
|
||||
</pluginExecutions>
|
||||
</lifecycleMappingMetadata>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>2.6</version>
|
||||
<configuration>
|
||||
<delimiters>
|
||||
<delimiter>@@</delimiter>
|
||||
</delimiters>
|
||||
<useDefaultDelimiters>false</useDefaultDelimiters>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
</project>
|
@ -0,0 +1,30 @@
|
||||
<assembly>
|
||||
<id>dist</id>
|
||||
<formats>
|
||||
<format>zip</format>
|
||||
<format>dir</format>
|
||||
</formats>
|
||||
<baseDirectory>spring-${project.version}</baseDirectory>
|
||||
<includeBaseDirectory>true</includeBaseDirectory>
|
||||
<fileSets>
|
||||
<fileSet>
|
||||
<directory>src/main/scripts</directory>
|
||||
<outputDirectory>bin</outputDirectory>
|
||||
<useDefaultExcludes>true</useDefaultExcludes>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>src/main/resources</directory>
|
||||
<outputDirectory>bin</outputDirectory>
|
||||
<useDefaultExcludes>true</useDefaultExcludes>
|
||||
<filtered>true</filtered>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
<dependencySets>
|
||||
<dependencySet>
|
||||
<includes>
|
||||
<include>org.springframework.bootstrap:spring-bootstrap-groovy:jar:*</include>
|
||||
</includes>
|
||||
<outputDirectory>lib</outputDirectory>
|
||||
</dependencySet>
|
||||
</dependencySets>
|
||||
</assembly>
|
@ -0,0 +1,52 @@
|
||||
package org.springframework.bootstrap.grapes
|
||||
|
||||
@GrabResolver(name='spring-milestone', root='http://repo.springframework.org/milestone')
|
||||
@GrabResolver(name='spring-snapshot', root='http://repo.springframework.org/snapshot')
|
||||
@GrabConfig(systemClassLoader=true)
|
||||
@Grab("org.springframework.bootstrap:spring-bootstrap:@@version@@")
|
||||
@Grab("org.springframework.batch:spring-batch-core:2.2.0.M1")
|
||||
@Grab("org.springframework:spring-context:@@dependency.springframework.version@@")
|
||||
class BatchGrapes {
|
||||
}
|
||||
|
||||
import org.springframework.bootstrap.context.annotation.ConditionalOnMissingBean
|
||||
import org.springframework.bootstrap.CommandLineRunner
|
||||
import org.springframework.batch.core.Job
|
||||
import org.springframework.batch.core.converter.DefaultJobParametersConverter
|
||||
import org.springframework.batch.core.converter.JobParametersConverter
|
||||
import org.springframework.batch.core.launch.JobLauncher
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.util.StringUtils
|
||||
import groovy.util.logging.Log
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(CommandLineRunner)
|
||||
@Log
|
||||
class BatchCommand {
|
||||
|
||||
@Autowired(required=false)
|
||||
private JobParametersConverter converter = new DefaultJobParametersConverter()
|
||||
|
||||
@Autowired
|
||||
private JobLauncher jobLauncher
|
||||
|
||||
@Autowired
|
||||
private Job job
|
||||
|
||||
@Bean
|
||||
CommandLineRunner batchCommandLineRunner() {
|
||||
return new CommandLineRunner() {
|
||||
void run(String... args) {
|
||||
log.info("Running default command line with: ${args}")
|
||||
launchJobFromProperties(StringUtils.splitArrayElementsIntoProperties(args, "="))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void launchJobFromProperties(Properties properties) {
|
||||
jobLauncher.run(job, converter.getJobParameters(properties))
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package org.springframework.bootstrap.grapes
|
||||
|
||||
@GrabResolver(name='spring-milestone', root='http://repo.springframework.org/milestone')
|
||||
@GrabConfig(systemClassLoader=true)
|
||||
@Grab("org.springframework:spring-jdbc:4.0.0.BOOTSTRAP-SNAPSHOT")
|
||||
@Grab("org.springframework.batch:spring-batch-core:2.2.0.M1")
|
||||
import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils
|
||||
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator
|
||||
import javax.annotation.PostConstruct
|
||||
import javax.sql.DataSource
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.core.env.Environment
|
||||
import org.springframework.core.io.ResourceLoader
|
||||
|
||||
@Configuration // TODO: make this conditional
|
||||
class BatchInitializationGrapes {
|
||||
|
||||
@Autowired
|
||||
private DataSource dataSource
|
||||
|
||||
@Autowired
|
||||
private Environment environment
|
||||
|
||||
@Autowired
|
||||
private ResourceLoader resourceLoader
|
||||
|
||||
@PostConstruct
|
||||
protected void initialize() {
|
||||
String platform = org.springframework.batch.support.DatabaseType.fromMetaData(dataSource).toString().toLowerCase()
|
||||
if (platform=="hsql") {
|
||||
platform = "hsqldb"
|
||||
}
|
||||
ResourceDatabasePopulator populator = new ResourceDatabasePopulator()
|
||||
populator.addScript(resourceLoader.getResource("org/springframework/batch/core/schema-${platform}.sql"))
|
||||
populator.setContinueOnError(true)
|
||||
DatabasePopulatorUtils.execute(populator, dataSource)
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package org.springframework.bootstrap.grapes
|
||||
|
||||
// Spring stuff needs to be on the system classloader apparently (when using @Configuration)
|
||||
@GrabResolver(name='spring-snapshot', root='http://repo.springframework.org/snapshot')
|
||||
@GrabConfig(systemClassLoader=true)
|
||||
@Grab("org.springframework:spring-context:@@dependency.springframework.version@@")
|
||||
@Grab("org.springframework.bootstrap:spring-bootstrap:@@version@@")
|
||||
@GrabExclude("commons-logging:commons-logging")
|
||||
@Grab("org.slf4j:jcl-over-slf4j:1.6.1")
|
||||
@Grab("org.slf4j:slf4j-jdk14:1.6.1")
|
||||
class BootstrapGrapes {
|
||||
}
|
||||
|
||||
import org.springframework.bootstrap.context.annotation.EnableAutoConfiguration
|
||||
import org.springframework.context.annotation.Configuration
|
||||
|
||||
@Configuration
|
||||
// @EnableAutoConfiguration
|
||||
class BootstrapAutoConfiguration {
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
package org.springframework.bootstrap.grapes
|
||||
|
||||
import org.springframework.core.type.StandardAnnotationMetadata
|
||||
import org.springframework.util.ClassUtils
|
||||
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory
|
||||
import groovy.util.logging.Log
|
||||
|
||||
@GrabResolver(name='spring-snapshot', root='http://repo.springframework.org/snapshot')
|
||||
@GrabConfig(systemClassLoader=true)
|
||||
@Grab("org.springframework:spring-core:4.0.0.BOOTSTRAP-SNAPSHOT")
|
||||
@GrabExclude("commons-logging:commons-logging")
|
||||
@Grab("org.slf4j:jcl-over-slf4j:1.6.1")
|
||||
@Grab("org.slf4j:slf4j-jdk14:1.6.1")
|
||||
@Log
|
||||
class Dependencies {
|
||||
|
||||
static List<String> defaults() {
|
||||
return ["org.springframework.bootstrap.grapes.BootstrapGrapes"]
|
||||
}
|
||||
|
||||
static List<String> dependencies(Collection<String> configs) {
|
||||
|
||||
def result = []
|
||||
if (isWeb(configs)) {
|
||||
log.info("Adding web dependencies.")
|
||||
result.addAll(web())
|
||||
}
|
||||
|
||||
if (isBatch(configs)) {
|
||||
log.info("Adding batch dependencies.")
|
||||
result.addAll(batch())
|
||||
result << "org.springframework.bootstrap.grapes.BatchCommand"
|
||||
result << "org.springframework.bootstrap.grapes.BatchInitializationGrapes"
|
||||
}
|
||||
|
||||
if (isHadoop(configs)) {
|
||||
log.info("Adding info dependencies.")
|
||||
result.addAll(hadoop())
|
||||
result << "org.springframework.bootstrap.grapes.HadoopContext"
|
||||
}
|
||||
|
||||
return result
|
||||
|
||||
}
|
||||
|
||||
static String[] web() {
|
||||
def result = []
|
||||
result << "org.springframework.bootstrap.grapes.WebGrapes"
|
||||
if (!isEmbeddedServerAvailable()) { result << "org.springframework.bootstrap.grapes.TomcatGrapes" }
|
||||
return result
|
||||
}
|
||||
|
||||
static String[] batch() {
|
||||
def result = []
|
||||
result << "org.springframework.bootstrap.grapes.BatchGrapes"
|
||||
return result
|
||||
}
|
||||
|
||||
static String[] hadoop() {
|
||||
def result = []
|
||||
result << "org.springframework.bootstrap.grapes.HadoopGrapes"
|
||||
return result
|
||||
}
|
||||
|
||||
static boolean isWeb(Collection<String> configs) {
|
||||
SimpleMetadataReaderFactory factory = new SimpleMetadataReaderFactory()
|
||||
return configs.any { config ->
|
||||
def meta = factory.getMetadataReader(config).getAnnotationMetadata()
|
||||
meta.hasAnnotation("org.springframework.stereotype.Controller") || meta.hasAnnotation("org.springframework.web.servlet.config.annotation.EnableWebMvc")
|
||||
}
|
||||
}
|
||||
|
||||
static boolean isHadoop(Collection<String> configs) {
|
||||
SimpleMetadataReaderFactory factory = new SimpleMetadataReaderFactory()
|
||||
return configs.any { config ->
|
||||
config.contains("Hadoop")
|
||||
}
|
||||
}
|
||||
|
||||
static boolean isBatch(Collection<String> configs) {
|
||||
SimpleMetadataReaderFactory factory = new SimpleMetadataReaderFactory()
|
||||
return configs.any { config ->
|
||||
def meta = factory.getMetadataReader(config).getAnnotationMetadata()
|
||||
meta.hasAnnotation("org.springframework.batch.core.configuration.annotation.EnableBatchProcessing")
|
||||
}
|
||||
}
|
||||
|
||||
static boolean isEmbeddedServerAvailable() {
|
||||
return ClassUtils.isPresent("org.apache.catalina.startup.Tomcat") || ClassUtils.isPresent("org.mortbay.jetty.Server")
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package org.springframework.bootstrap.grapes
|
||||
|
||||
@GrabConfig(systemClassLoader=true)
|
||||
@Grab("org.springframework.data:spring-data-hadoop:1.0.0.RELEASE")
|
||||
@Grab("org.springframework.bootstrap:spring-bootstrap:@@version@@")
|
||||
@Grab("org.springframework:spring-context:4.0.0.BOOTSTRAP-SNAPSHOT")
|
||||
@Grab("org.apache.hadoop:hadoop-examples:1.0.4")
|
||||
@GrabExclude("org.mortbay.jetty:sevlet-api-2.5")
|
||||
@GrabExclude("org.mortbay.jetty:jetty")
|
||||
@GrabExclude("org.mortbay.jetty:jetty-util")
|
||||
@GrabExclude("org.mortbay.jetty:jsp-2.1")
|
||||
@GrabExclude("org.mortbay.jetty:jsp-api-2.1")
|
||||
@GrabExclude("tomcat:jasper-runtime")
|
||||
@GrabExclude("tomcat:jasper-compiler")
|
||||
class HadoopGrapes {
|
||||
}
|
||||
|
||||
import org.springframework.bootstrap.context.annotation.ConditionalOnMissingBean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.context.annotation.ImportResource
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(org.apache.hadoop.conf.Configuration)
|
||||
@ImportResource("hadoop-context.xml")
|
||||
class HadoopContext {
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package org.springframework.bootstrap.grapes
|
||||
|
||||
@GrabConfig(systemClassLoader=true)
|
||||
// Grab some Tomcat dependencies
|
||||
@Grab("org.apache.tomcat.embed:tomcat-embed-core:7.0.32")
|
||||
// JULI logging has sensible defaults in JAVA_HOME, so no need for user to create it
|
||||
@Grab("org.apache.tomcat.embed:tomcat-embed-logging-juli:7.0.32")
|
||||
class TomcatGrapes {
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package org.springframework.bootstrap.grapes
|
||||
|
||||
@Grab("org.springframework:spring-webmvc:4.0.0.BOOTSTRAP-SNAPSHOT")
|
||||
class WebGrapes {
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:c="http://www.springframework.org/schema/c"
|
||||
xmlns:p="http://www.springframework.org/schema/p"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:hdp="http://www.springframework.org/schema/hadoop"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
|
||||
http://www.springframework.org/schema/hadoop http://www.springframework.org/schema/hadoop/spring-hadoop.xsd">
|
||||
|
||||
|
||||
<hdp:resource-loader id="hadoopResourceLoader" />
|
||||
|
||||
<hdp:configuration>
|
||||
fs.default.name=${hd.fs:hdfs://localhost:9000}
|
||||
</hdp:configuration>
|
||||
|
||||
<bean id="defaultResourceLoaders" class="org.springframework.data.hadoop.fs.CustomResourceLoaderRegistrar" p:loader-ref="hadoopResourceLoader" />
|
||||
|
||||
</beans>
|
@ -0,0 +1,100 @@
|
||||
import org.codehaus.groovy.control.customizers.ASTTransformationCustomizer
|
||||
import org.codehaus.groovy.ast.ClassHelper
|
||||
import groovy.util.logging.Log
|
||||
|
||||
def bootstrap = 'org.springframework.bootstrap.grapes.BootstrapGrapes' as Class
|
||||
|
||||
void addImport(module, path) {
|
||||
def name = path.lastIndexOf('.').with {it != -1 ? path[it+1..<path.length()] : path}
|
||||
if (name=="*") {
|
||||
// Doesn't work?
|
||||
name = path.lastIndexOf('.').with {path[0..<it] }
|
||||
module.addStarImport(name, [])
|
||||
} else {
|
||||
module.addImport(name, ClassHelper.make(path), [])
|
||||
}
|
||||
}
|
||||
|
||||
withConfig(configuration) {
|
||||
|
||||
ast(Log)
|
||||
|
||||
imports {
|
||||
normal 'javax.sql.DataSource'
|
||||
normal 'org.springframework.stereotype.Component'
|
||||
normal 'org.springframework.stereotype.Controller'
|
||||
normal 'org.springframework.stereotype.Repository'
|
||||
normal 'org.springframework.stereotype.Service'
|
||||
normal 'org.springframework.beans.factory.annotation.Autowired'
|
||||
normal 'org.springframework.beans.factory.annotation.Value'
|
||||
normal 'org.springframework.context.annotation.Import'
|
||||
normal 'org.springframework.context.annotation.ImportResource'
|
||||
normal 'org.springframework.context.annotation.Profile'
|
||||
normal 'org.springframework.context.annotation.Scope'
|
||||
normal 'org.springframework.context.annotation.Configuration'
|
||||
normal 'org.springframework.context.annotation.Bean'
|
||||
normal 'org.springframework.bootstrap.CommandLineRunner'
|
||||
}
|
||||
|
||||
def dependencySource = "org.springframework.bootstrap.grapes.Dependencies" as Class // TODO: maybe strategise this
|
||||
|
||||
inline(phase:'CONVERSION') { source, context, classNode ->
|
||||
|
||||
def module = source.getAST()
|
||||
|
||||
if (classNode.name.contains("Hadoop")) {
|
||||
def hadoop = dependencySource.hadoop() as Class[]
|
||||
['org.springframework.data.hadoop.mapreduce.JobRunner',
|
||||
'org.springframework.data.hadoop.mapreduce.JobFactoryBean'
|
||||
].each { path -> addImport(module, path) }
|
||||
module.addImport("HadoopConfiguration", ClassHelper.make("org.apache.hadoop.conf.Configuration"), [])
|
||||
}
|
||||
|
||||
classNode.annotations.each {
|
||||
|
||||
def name = it.classNode.name
|
||||
if (name=='Controller' || name=='EnableWebMvc') {
|
||||
def web = dependencySource.web() as Class[]
|
||||
['org.springframework.web.bind.annotation.RequestBody',
|
||||
'org.springframework.web.bind.annotation.RequestParam',
|
||||
'org.springframework.web.bind.annotation.PathVariable',
|
||||
'org.springframework.web.bind.annotation.RequestHeader',
|
||||
'org.springframework.web.bind.annotation.RequestMethod',
|
||||
'org.springframework.web.bind.annotation.RequestBody',
|
||||
'org.springframework.web.bind.annotation.ResponseBody',
|
||||
'org.springframework.web.bind.annotation.ResponseStatus',
|
||||
'org.springframework.web.bind.annotation.RequestMapping',
|
||||
'org.springframework.web.bind.annotation.ExceptionHandler',
|
||||
'org.springframework.web.bind.annotation.ModelAttribute',
|
||||
'org.springframework.web.bind.annotation.CookieValue',
|
||||
'org.springframework.web.servlet.config.annotation.EnableWebMvc',
|
||||
'org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry',
|
||||
'org.springframework.web.servlet.config.annotation.ViewControllerRegistry',
|
||||
'org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter'].each { path -> addImport(module, path) }
|
||||
}
|
||||
|
||||
if (name=='EnableBatchProcessing') {
|
||||
def batch = dependencySource.batch() as Class[]
|
||||
['org.springframework.batch.repeat.RepeatStatus',
|
||||
'org.springframework.batch.core.scope.context.ChunkContext',
|
||||
'org.springframework.batch.core.step.tasklet.Tasklet',
|
||||
'org.springframework.batch.core.configuration.annotation.StepScope',
|
||||
'org.springframework.batch.core.configuration.annotation.JobBuilderFactory',
|
||||
'org.springframework.batch.core.configuration.annotation.StepBuilderFactory',
|
||||
'org.springframework.batch.core.configuration.annotation.EnableBatchProcessing',
|
||||
'org.springframework.batch.core.Step',
|
||||
'org.springframework.batch.core.StepExecution',
|
||||
'org.springframework.batch.core.StepContribution',
|
||||
'org.springframework.batch.core.Job',
|
||||
'org.springframework.batch.core.JobExecution',
|
||||
'org.springframework.batch.core.JobParameter',
|
||||
'org.springframework.batch.core.JobParameters',
|
||||
'org.springframework.batch.core.launch.JobLauncher',
|
||||
'org.springframework.batch.core.converter.DefaultJobParametersConverter'].each { path -> addImport(module, path) }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
##############################################################################
|
||||
## ##
|
||||
## Groovy Classloading Configuration ##
|
||||
## ##
|
||||
##############################################################################
|
||||
|
||||
##
|
||||
## $Revision$ $Date$
|
||||
##
|
||||
## Note: do not add classes from java.lang here. No rt.jar and on some
|
||||
## platforms no tools.jar
|
||||
##
|
||||
## See http://groovy.codehaus.org/api/org/codehaus/groovy/tools/LoaderConfiguration.html
|
||||
## for the file format
|
||||
|
||||
# load required libraries
|
||||
load !{groovy.home}/lib/a*.jar
|
||||
load !{groovy.home}/lib/b*.jar
|
||||
load !{groovy.home}/lib/c*.jar
|
||||
load !{groovy.home}/lib/g*.jar
|
||||
load !{groovy.home}/lib/h*.jar
|
||||
load !{groovy.home}/lib/i*.jar
|
||||
load !{groovy.home}/lib/j*.jar
|
||||
load !{groovy.home}/lib/q*.jar
|
||||
load !{groovy.home}/lib/t*.jar
|
||||
load !{groovy.home}/lib/x*.jar
|
||||
|
||||
# load user specific libraries
|
||||
load !{user.home}/.groovy/lib/*.jar
|
||||
|
||||
# tools.jar for ant tasks
|
||||
load ${tools.jar}
|
||||
|
@ -0,0 +1,163 @@
|
||||
#!/bin/bash
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false;
|
||||
darwin=false;
|
||||
case "`uname`" in
|
||||
CYGWIN*)
|
||||
cygwin=true
|
||||
;;
|
||||
|
||||
Darwin*)
|
||||
darwin=true
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ "$SPRING_HOME" == "" ]; then
|
||||
SPRING_HOME=`cd "$(dirname $0)"/.. && pwd`
|
||||
fi
|
||||
SPRING_BIN=$(dirname $0)
|
||||
|
||||
export GROOVY_CONF="${SPRING_BIN}"/groovy.conf
|
||||
SPRING_HANDLER=auto
|
||||
|
||||
TARGETDIR=target/classes
|
||||
if [ -f build.gradle ]; then
|
||||
TARGETDIR=build/classes/main
|
||||
fi
|
||||
mkdir -p "${TARGETDIR%/}"
|
||||
|
||||
function find_classfile {
|
||||
classname="$( echo ${1%%.groovy} | sed -e 's,.*/,,')"
|
||||
package="$( grep ^package ${1} | sed -e 's,package\s,,g' -e 's,;,,g' -e 's,\.,/,g')"
|
||||
if [ "${package}" != "" ]; then package="${package}/"; fi
|
||||
for f in $( find "${TARGETDIR}" -name "${classname}.class" ); do
|
||||
if [ "${f}" == "${TARGETDIR}/${package}${classname}.class" ]; then
|
||||
echo $f; return 0
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
function is_compile_needed {
|
||||
config=$1
|
||||
STATOPTS="-c %X"
|
||||
if $darwin; then STATOPTS="-f %Dm"; fi
|
||||
# Compile .groovy files if necessary
|
||||
if [ ! -f ${config} ]; then
|
||||
echo "File ${config} does not exist. Did you point at the wrong file?"
|
||||
exit 3
|
||||
else
|
||||
classfile=$( find_classfile ${config} )
|
||||
if [ ! -f "${classfile}" -o $(stat "${STATOPTS}" ${config}) -gt $(stat "${STATOPTS}" ${classfile} 2>/dev/null || echo 0) ]; then
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
function is_option {
|
||||
echo "$1" | grep -q "^--.*"
|
||||
}
|
||||
|
||||
function is_groovy {
|
||||
[ "${1%%.groovy}" != "${1}" ]
|
||||
}
|
||||
|
||||
function convert_config_to_class {
|
||||
classfile=$( find_classfile ${config} )
|
||||
if [ -z "${classfile}" ]; then
|
||||
echo "No class found for ${config}. Compiler failed or class not defined?"
|
||||
exit 1
|
||||
fi
|
||||
config="${classfile#${TARGETDIR}/}"
|
||||
while [ "${config%/*}" != "${config}" ]; do
|
||||
config="${config%/*}"."${config##*/}"
|
||||
done
|
||||
}
|
||||
|
||||
config=$1; shift
|
||||
configs=()
|
||||
compilables=()
|
||||
while [ "$config" != "" ]; do
|
||||
if is_groovy "$config"; then
|
||||
if is_compile_needed "${config}"; then
|
||||
compilables[${#compilables[@]}]="${config}"
|
||||
fi
|
||||
configs[${#configs[@]}]="${config}"
|
||||
elif is_option "${config}"; then
|
||||
case "${config%=*}" in
|
||||
"--handler") SPRING_HANDLER="${config#*=}";;
|
||||
esac
|
||||
else
|
||||
args[${#args[@]}]="${config}"
|
||||
fi
|
||||
config=$1; shift
|
||||
done
|
||||
|
||||
CLASSPATH="${SPRING_BIN}":"${TARGETDIR}"
|
||||
|
||||
for f in "${SPRING_HOME}"/lib/*.jar; do
|
||||
CLASSPATH="${CLASSPATH}":$f
|
||||
done
|
||||
|
||||
for f in "${SPRING_HOME}"/*.jar; do
|
||||
CLASSPATH="${CLASSPATH}":$f
|
||||
done
|
||||
|
||||
if $cygwin; then
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
fi
|
||||
|
||||
if [ "${#compilables[@]}" -gt 0 ]; then
|
||||
groovyc -cp "${CLASSPATH}" --configscript "$SPRING_BIN"/customizer.groovy -d "${TARGETDIR}" "${compilables[@]}"
|
||||
fi
|
||||
|
||||
config_classes=("org.springframework.bootstrap.grapes.BootstrapAutoConfiguration.class")
|
||||
for config in "${configs[@]}"; do
|
||||
convert_config_to_class
|
||||
config_classes[${#config_classes[@]}]="${config}"
|
||||
done
|
||||
|
||||
if [ "${#config_classes[@]}" == "0" ]; then
|
||||
echo "No files to run."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
exec groovy -cp "${CLASSPATH}" -Dspring.home="${SPRING_HOME}" --configscript "$SPRING_BIN"/customizer.groovy "$SPRING_BIN"/spring-"${SPRING_HANDLER}".groovy "${config_classes[@]}" "${args[@]}"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,24 @@
|
||||
// Get the args and turn them into classes
|
||||
def configs = []
|
||||
def parameters = []
|
||||
args.each { arg ->
|
||||
if (arg.endsWith(".class")) {
|
||||
configs << arg.replaceAll(".class", "")
|
||||
} else {
|
||||
parameters << arg
|
||||
}
|
||||
}
|
||||
|
||||
// Dynamically grab some dependencies
|
||||
def dependencySource = "org.springframework.bootstrap.grapes.Dependencies" as Class // TODO: maybe strategise this
|
||||
def dependencies = [*dependencySource.defaults(), *dependencySource.dependencies(configs)]
|
||||
configs = dependencies + configs
|
||||
|
||||
// Do this before any Spring auto stuff is used in case it enhances the classpath
|
||||
configs = configs as Class[]
|
||||
parameters = parameters as String[]
|
||||
|
||||
// Now run the application
|
||||
def applicationClass = "org.springframework.bootstrap.SpringApplication" as Class
|
||||
|
||||
applicationClass.run(configs, parameters)
|
@ -0,0 +1,27 @@
|
||||
// Spring stuff needs to be on the system classloader apparently (when using @Configuration)
|
||||
@GrabResolver(name='spring-milestone', root='http://maven.springframework.org/milestone')
|
||||
@GrabConfig(systemClassLoader=true)
|
||||
@Grab("org.springframework:spring-context:4.0.0.BOOTSTRAP-SNAPSHOT")
|
||||
@GrabExclude("commons-logging:commons-logging")
|
||||
@Grab("org.slf4j:jcl-over-slf4j:1.6.1")
|
||||
@Grab("org.slf4j:slf4j-jdk14:1.6.1")
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext
|
||||
|
||||
// Now create a Spring context
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext()
|
||||
// Get the args and turn them into classes
|
||||
def configs = []
|
||||
def parameters = []
|
||||
boolean endconfigs = false
|
||||
args.each { arg ->
|
||||
if (arg.endsWith(".class")) {
|
||||
configs += arg.replaceAll(".class", "")
|
||||
} else {
|
||||
parameters += arg
|
||||
}
|
||||
}
|
||||
configs = configs as Class[]
|
||||
parameters = parameters as String[]
|
||||
// Register the config classes, can be @Configuration or @Component etc.
|
||||
ctx.register(configs)
|
||||
ctx.refresh()
|
@ -0,0 +1,8 @@
|
||||
@Controller
|
||||
class App {
|
||||
@RequestMapping("/")
|
||||
@ResponseBody
|
||||
String home() {
|
||||
return "Hello World!"
|
||||
}
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
@Configuration
|
||||
class Empty {
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
@Grab("org.hsqldb:hsqldb-j5:2.0.0")
|
||||
@EnableBatchProcessing
|
||||
class JobConfig {
|
||||
|
||||
@Autowired
|
||||
private JobBuilderFactory jobs
|
||||
|
||||
@Autowired
|
||||
private StepBuilderFactory steps
|
||||
|
||||
@Bean
|
||||
protected Tasklet tasklet() {
|
||||
return new Tasklet() {
|
||||
RepeatStatus execute(StepContribution contribution, ChunkContext context) {
|
||||
return RepeatStatus.FINISHED
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Bean
|
||||
Job job() throws Exception {
|
||||
return jobs.get("job").start(step1()).build()
|
||||
}
|
||||
|
||||
@Bean
|
||||
protected Step step1() throws Exception {
|
||||
return steps.get("step1").tasklet(tasklet()).build()
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
import java.io.File;
|
||||
|
||||
import org.springframework.bootstrap.CommandLineRunner;
|
||||
|
||||
@Component
|
||||
class Signal implements CommandLineRunner {
|
||||
|
||||
private File messages = new File("target/messages")
|
||||
|
||||
boolean ready = false
|
||||
|
||||
@Override
|
||||
void run(String... args) {
|
||||
messages.mkdirs()
|
||||
new File(messages, "ready").write("Ready!")
|
||||
ready = true
|
||||
}
|
||||
}
|
@ -0,0 +1,174 @@
|
||||
/*
|
||||
* Cloud Foundry 2012.02.03 Beta
|
||||
* Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved.
|
||||
*
|
||||
* This product is licensed to you under the Apache License, Version 2.0 (the "License").
|
||||
* You may not use this product except in compliance with the License.
|
||||
*
|
||||
* This product includes a number of subcomponents with
|
||||
* separate copyright notices and license terms. Your use of these
|
||||
* subcomponents is subject to the terms and conditions of the
|
||||
* subcomponent's license, as noted in the LICENSE file.
|
||||
*/
|
||||
|
||||
package org.springframework.bootstrap.groovy
|
||||
|
||||
/**
|
||||
* <p>As part of the gvm test suite we need to launch a bash shell and execute
|
||||
* multiple commands in it. This is tricky to do using Java's support for
|
||||
* working with external processes as the API can't tell you when a command
|
||||
* has finished executing.</p>
|
||||
* <p>This class provides some hacks that allow you to serially execute commands
|
||||
* in an external bash process in a fairly reliable manner and to retrieve the
|
||||
* output of those commands.</p>
|
||||
*/
|
||||
class BashEnv {
|
||||
|
||||
static final PROMPT = ""
|
||||
static final EXIT_CODE_CMD = 'echo "Exit code is: $?"'
|
||||
static final EXIT_CODE_PATTERN = ~/Exit code is: (\d+)\s*${PROMPT}?$/
|
||||
|
||||
private final Object outputLock = new Object()
|
||||
|
||||
def exitCode
|
||||
def process
|
||||
def processOutput = new StringBuilder()
|
||||
def commandOutput
|
||||
|
||||
// Command timeout in milliseconds
|
||||
def timeout = 5000
|
||||
def workDir
|
||||
def env
|
||||
|
||||
BashEnv(workDir, Map env) {
|
||||
this.workDir = workDir as File
|
||||
|
||||
env = env + [PS1: PROMPT]
|
||||
this.env = env.collect { k, v -> k + '=' + v }
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the external bash process.
|
||||
*/
|
||||
void start() {
|
||||
process = ["bash", "--noprofile", "--norc", "-i"].execute(env, workDir)
|
||||
|
||||
consumeProcessStream(process.inputStream)
|
||||
consumeProcessStream(process.errorStream)
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the external bash process and waits for it to finish.
|
||||
*/
|
||||
void stop() {
|
||||
execute("exit")
|
||||
process.waitFor()
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a command line to the external bash process and returns once the
|
||||
* command has finished executing. If the command is interactive and requires
|
||||
* input during it's execution (for example a y/n answer to a question) you
|
||||
* can provide that input as a list of strings.
|
||||
*/
|
||||
void execute(String cmdline, List inputs = []) {
|
||||
resetOutput()
|
||||
|
||||
if (cmdline != "exit") {
|
||||
exitCode = null
|
||||
}
|
||||
|
||||
process.outputStream << cmdline << "\n"
|
||||
process.outputStream.flush()
|
||||
|
||||
if (cmdline != "exit") {
|
||||
for (input in inputs) {
|
||||
process.outputStream << input << "\n"
|
||||
}
|
||||
process.outputStream << EXIT_CODE_CMD << "\n"
|
||||
process.outputStream.flush()
|
||||
}
|
||||
|
||||
def start = System.currentTimeMillis()
|
||||
while (cmdline != "exit") {
|
||||
Thread.sleep 100
|
||||
|
||||
synchronized (outputLock) {
|
||||
// Remove all the extraneous text that's not related to the
|
||||
// command's output. This includes the command string itself,
|
||||
// the 'echo' command to display the command's exit code, and
|
||||
// the exit code line.
|
||||
removeFromOutput(cmdline + "\n")
|
||||
removeFromOutput(PROMPT + EXIT_CODE_CMD + "\n")
|
||||
|
||||
def str = processOutput.toString()
|
||||
def m = EXIT_CODE_PATTERN.matcher(str)
|
||||
commandOutput = str
|
||||
if (m) {
|
||||
exitCode = m[0][1]
|
||||
|
||||
// Remove this exit code line from the output.
|
||||
commandOutput = m.replaceAll('')
|
||||
break
|
||||
}
|
||||
|
||||
// If the command times out, we should break out of the loop and
|
||||
// display whatever output has already been produced.
|
||||
if (System.currentTimeMillis() - start > timeout) {
|
||||
commandOutput = "ALERT! Command timed out. Last output was:\n\n${processOutput}"
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the exit code of the last command that was executed.
|
||||
*/
|
||||
int getStatus() {
|
||||
if (!exitCode) throw new IllegalStateException("Did you run execute() before getting the status?")
|
||||
return exitCode.toInteger()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the text output (both stdout and stderr) of the last command
|
||||
* that was executed.
|
||||
*/
|
||||
String getOutput() {
|
||||
return commandOutput
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the saved command output.
|
||||
*/
|
||||
void resetOutput() {
|
||||
synchronized (outputLock) {
|
||||
processOutput = new StringBuilder()
|
||||
}
|
||||
}
|
||||
|
||||
private void consumeProcessStream(final InputStream stream) {
|
||||
char[] buffer = new char[256]
|
||||
Thread.start {
|
||||
def reader = new InputStreamReader(stream)
|
||||
def charsRead = 0
|
||||
while (charsRead != -1) {
|
||||
charsRead = reader.read(buffer, 0, 256)
|
||||
if (charsRead > 0) {
|
||||
synchronized (outputLock) {
|
||||
processOutput.append(buffer, 0, charsRead)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void removeFromOutput(String line) {
|
||||
synchronized (outputLock) {
|
||||
def pos = processOutput.indexOf(line)
|
||||
if (pos != -1) {
|
||||
processOutput.delete(pos, pos + line.size() - 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Cloud Foundry 2012.02.03 Beta
|
||||
* Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved.
|
||||
*
|
||||
* This product is licensed to you under the Apache License, Version 2.0 (the "License").
|
||||
* You may not use this product except in compliance with the License.
|
||||
*
|
||||
* This product includes a number of subcomponents with
|
||||
* separate copyright notices and license terms. Your use of these
|
||||
* subcomponents is subject to the terms and conditions of the
|
||||
* subcomponent's license, as noted in the LICENSE file.
|
||||
*/
|
||||
|
||||
package org.springframework.bootstrap.groovy;
|
||||
|
||||
import static org.junit.Assert.*
|
||||
|
||||
import java.util.concurrent.ExecutorService
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
class ScriptTests {
|
||||
|
||||
private BashEnv bash
|
||||
|
||||
private ExecutorService executor = Executors.newFixedThreadPool(2)
|
||||
|
||||
@Before
|
||||
void init() {
|
||||
bash = new BashEnv(".", [SPRING_HOME: "target"])
|
||||
bash.start()
|
||||
bash.execute("export GVM_DIR=~/.gvm")
|
||||
bash.execute("source ~/.gvm/bin/gvm-init.sh")
|
||||
assertEquals("You need to install gvm to run these tests", 0, bash.status)
|
||||
bash.execute("gvm use groovy 2.1.0")
|
||||
assertEquals("You need to do this before running the tests: > gvm install groovy 2.1.0", 0, bash.status)
|
||||
}
|
||||
|
||||
@After
|
||||
void clean() {
|
||||
bash?.stop()
|
||||
}
|
||||
|
||||
@Test
|
||||
void testVanillaApplicationContext() {
|
||||
execute(bash, "src/main/scripts/spring src/test/apps/Empty.groovy")
|
||||
assertEquals(0, bash.status)
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBatchApplicationContext() {
|
||||
execute(bash, "src/main/scripts/spring src/test/apps/JobConfig.groovy foo=bar")
|
||||
assertEquals(0, bash.status)
|
||||
assertTrue(bash.output.contains("[SimpleJob: [name=job]] completed with the following parameters: [{foo=bar}]"))
|
||||
}
|
||||
|
||||
private void execute(BashEnv bash, String cmdline) {
|
||||
bash.execute(cmdline)
|
||||
if (bash.exitCode && bash.status!=0) {
|
||||
println "Unsuccessful execution (${cmdline}). Output: \n${bash.output}"
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Cloud Foundry 2012.02.03 Beta
|
||||
* Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved.
|
||||
*
|
||||
* This product is licensed to you under the Apache License, Version 2.0 (the "License").
|
||||
* You may not use this product except in compliance with the License.
|
||||
*
|
||||
* This product includes a number of subcomponents with
|
||||
* separate copyright notices and license terms. Your use of these
|
||||
* subcomponents is subject to the terms and conditions of the
|
||||
* subcomponent's license, as noted in the LICENSE file.
|
||||
*/
|
||||
|
||||
package org.springframework.bootstrap.groovy;
|
||||
|
||||
import static org.junit.Assert.*
|
||||
|
||||
import java.util.concurrent.ExecutorService
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
import org.springframework.web.client.RestTemplate
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
class WebScriptTests {
|
||||
|
||||
private BashEnv bash
|
||||
|
||||
private ExecutorService executor = Executors.newFixedThreadPool(2)
|
||||
|
||||
private File messages = new File("target/messages")
|
||||
|
||||
@Before
|
||||
void init() {
|
||||
assertTrue("Couldn't delete messages directory", messages.deleteDir())
|
||||
bash = new BashEnv(".", [SPRING_HOME: "target"])
|
||||
bash.start()
|
||||
bash.execute("export GVM_DIR=~/.gvm")
|
||||
bash.execute("source ~/.gvm/bin/gvm-init.sh")
|
||||
assertEquals("You need to install gvm to run these tests", 0, bash.status)
|
||||
bash.execute("gvm use groovy 2.1.0")
|
||||
assertEquals("You need to do this before running the tests: > gvm install groovy 2.1.0", 0, bash.status)
|
||||
}
|
||||
|
||||
@After
|
||||
void clean() {
|
||||
killit()
|
||||
bash?.stop()
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
void testWebApplicationContext() {
|
||||
executor.submit {
|
||||
execute(bash, "src/main/scripts/spring src/test/apps/App.groovy src/test/apps/Signal.groovy")
|
||||
}
|
||||
File ready = new File(messages, "ready")
|
||||
long timeout = 10000
|
||||
long t0 = System.currentTimeMillis()
|
||||
while (!ready.exists() && System.currentTimeMillis() - t0 < timeout) {
|
||||
println "Waiting for app to start"
|
||||
Thread.sleep(1000)
|
||||
}
|
||||
if (ready.exists()) {
|
||||
println ready.text
|
||||
} else {
|
||||
fail("Timed out waiting for app to start")
|
||||
}
|
||||
|
||||
// assertEquals(0, bash.status)
|
||||
def response = new RestTemplate().getForEntity("http://localhost:8080", String.class)
|
||||
assertEquals("Hello World!", response.body)
|
||||
}
|
||||
|
||||
private void killit() {
|
||||
BashEnv reaper = new BashEnv(".", [SPRING_HOME: "target"])
|
||||
reaper.start()
|
||||
reaper?.execute("pkill -9 -f '\\--configscript src/main/scripts/customizer.groovy'")
|
||||
reaper?.stop()
|
||||
}
|
||||
|
||||
private void execute(BashEnv bash, String cmdline) {
|
||||
bash.execute(cmdline)
|
||||
if (bash.exitCode && bash.status!=0) {
|
||||
println "Unsuccessful execution (${cmdline}). Output: \n${bash.output}"
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.bootstrap</groupId>
|
||||
<artifactId>spring-bootstrap-parent</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>spring-bootstrap-launcher</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<properties>
|
||||
<main.basedir>${project.basedir}/..</main.basedir>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>2.4</version>
|
||||
<type>maven-plugin</type>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.launcher;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.jar.JarEntry;
|
||||
|
||||
import org.springframework.bootstrap.launcher.jar.RandomAccessJarFile;
|
||||
|
||||
/**
|
||||
* {@link Launcher} for JAR based archives. This launcher assumes that dependency jars are
|
||||
* included inside a {@code /lib} directory.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class JarLauncher extends Launcher {
|
||||
|
||||
@Override
|
||||
protected boolean isNestedJarFile(JarEntry jarEntry) {
|
||||
return !jarEntry.isDirectory() && jarEntry.getName().startsWith("lib/");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void postProcessLib(RandomAccessJarFile jarFile,
|
||||
List<RandomAccessJarFile> lib) throws Exception {
|
||||
lib.add(0, jarFile);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
new JarLauncher().launch(args);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,198 @@
|
||||
/*
|
||||
* Copyright 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.launcher;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.security.CodeSource;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.jar.JarEntry;
|
||||
|
||||
import org.springframework.bootstrap.launcher.jar.RandomAccessJarFile;
|
||||
|
||||
/**
|
||||
* Base class for launchers that can start an application with a fully configured
|
||||
* classpath.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public abstract class Launcher {
|
||||
|
||||
/**
|
||||
* The main runner class. This must be loaded by the created ClassLoader so cannot be
|
||||
* directly referenced.
|
||||
*/
|
||||
private static final String RUNNER_CLASS = Launcher.class.getPackage().getName()
|
||||
+ ".MainMethodRunner";
|
||||
|
||||
/**
|
||||
* Launch the application. This method is the initial entry point that should be
|
||||
* called by a subclass {@code public static void main(String[] args)} method.
|
||||
* @param args the incoming arguments
|
||||
*/
|
||||
public void launch(String[] args) {
|
||||
try {
|
||||
launch(args, getClass().getProtectionDomain());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch the application given the protection domain.
|
||||
* @param args the incoming arguments
|
||||
* @param protectionDomain the protection domain
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void launch(String[] args, ProtectionDomain protectionDomain)
|
||||
throws Exception {
|
||||
CodeSource codeSource = protectionDomain.getCodeSource();
|
||||
URL codeSourceLocation = (codeSource == null ? null : codeSource.getLocation());
|
||||
String codeSourcePath = (codeSourceLocation == null ? null : codeSourceLocation
|
||||
.getPath());
|
||||
if (codeSourcePath == null) {
|
||||
throw new IllegalStateException("Unable to determine code source archive");
|
||||
}
|
||||
if (codeSourcePath.endsWith("/")) {
|
||||
throw new IllegalStateException("The specified code source path '"
|
||||
+ codeSourcePath + "' is not an archive");
|
||||
}
|
||||
launch(args, new File(codeSourcePath));
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch the application given the archive file
|
||||
* @param args the incoming arguments
|
||||
* @param archive the underlying (zip/war/jar) archive
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void launch(String[] args, File archive) throws Exception {
|
||||
RandomAccessJarFile jarFile = new RandomAccessJarFile(archive);
|
||||
|
||||
List<RandomAccessJarFile> lib = new ArrayList<RandomAccessJarFile>();
|
||||
Enumeration<JarEntry> jarEntries = jarFile.entries();
|
||||
while (jarEntries.hasMoreElements()) {
|
||||
JarEntry jarEntry = jarEntries.nextElement();
|
||||
if (isNestedJarFile(jarEntry)) {
|
||||
lib.add(jarFile.getNestedJarFile(jarEntry));
|
||||
}
|
||||
}
|
||||
postProcessLib(jarFile, lib);
|
||||
ClassLoader classLoader = createClassLoader(lib);
|
||||
launch(args, jarFile, classLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the specified {@link JarEntry} is a nested item that should be added
|
||||
* to the classpath. The method is called once for each entry.
|
||||
* @param jarEntry the jar entry
|
||||
* @return {@code true} if the entry is a nested item (jar or folder)
|
||||
*/
|
||||
protected abstract boolean isNestedJarFile(JarEntry jarEntry);
|
||||
|
||||
/**
|
||||
* Called to post-process lib entries before they are used. Implementations can add
|
||||
* and remove entries.
|
||||
* @param jarFile the jar file
|
||||
* @param lib the existing lib
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void postProcessLib(RandomAccessJarFile jarFile,
|
||||
List<RandomAccessJarFile> lib) throws Exception {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a classloader for the specified lib.
|
||||
* @param lib the lib
|
||||
* @return the classloader
|
||||
* @throws Exception
|
||||
*/
|
||||
protected ClassLoader createClassLoader(List<RandomAccessJarFile> lib)
|
||||
throws Exception {
|
||||
URL[] urls = new URL[lib.size()];
|
||||
for (int i = 0; i < urls.length; i++) {
|
||||
urls[i] = lib.get(i).getUrl();
|
||||
}
|
||||
return createClassLoader(urls);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a classloader for the specified URLs
|
||||
* @param urls the URLs
|
||||
* @return the classloader
|
||||
* @throws Exception
|
||||
*/
|
||||
protected ClassLoader createClassLoader(URL[] urls) throws Exception {
|
||||
return new URLClassLoader(urls, getClass().getClassLoader().getParent());
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch the application given the archive file and a fully configured classloader.
|
||||
* @param args the incoming arguments
|
||||
* @param jarFile the jar file
|
||||
* @param classLoader the classloader
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void launch(String[] args, RandomAccessJarFile jarFile,
|
||||
ClassLoader classLoader) throws Exception {
|
||||
String mainClass = getMainClass(jarFile);
|
||||
Runnable runner = createMainMethodRunner(mainClass, args, classLoader);
|
||||
Thread runnerThread = new Thread(runner);
|
||||
runnerThread.setContextClassLoader(classLoader);
|
||||
runnerThread.setName(Thread.currentThread().getName());
|
||||
runnerThread.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the main class that should be used to launch the application. By default
|
||||
* this method uses a {@code Start-Class} manifest entry.
|
||||
* @param jarFile the jar file
|
||||
* @return the main class
|
||||
* @throws Exception
|
||||
*/
|
||||
protected String getMainClass(RandomAccessJarFile jarFile) throws Exception {
|
||||
String mainClass = jarFile.getManifest().getMainAttributes()
|
||||
.getValue("Start-Class");
|
||||
if (mainClass == null) {
|
||||
throw new IllegalStateException("No 'Start-Class' manifest entry specified");
|
||||
}
|
||||
return mainClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the {@code MainMethodRunner} used to launch the application.
|
||||
* @param mainClass the main class
|
||||
* @param args the incoming arguments
|
||||
* @param classLoader the classloader
|
||||
* @return a runnable used to start the application
|
||||
* @throws Exception
|
||||
*/
|
||||
protected Runnable createMainMethodRunner(String mainClass, String[] args,
|
||||
ClassLoader classLoader) throws Exception {
|
||||
Class<?> runnerClass = classLoader.loadClass(RUNNER_CLASS);
|
||||
Constructor<?> constructor = runnerClass.getConstructor(String.class,
|
||||
String[].class);
|
||||
return (Runnable) constructor.newInstance(mainClass, args);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 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.launcher;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Utility class that used by {@link Launcher}s to call a main method. This class allows
|
||||
* methods to be executed within a thread configured with a specific context classloader.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class MainMethodRunner implements Runnable {
|
||||
|
||||
private String mainClassName;
|
||||
|
||||
private String[] args;
|
||||
|
||||
/**
|
||||
* Create a new {@link MainMethodRunner} instance.
|
||||
* @param mainClass the main class
|
||||
* @param args incoming arguments
|
||||
*/
|
||||
public MainMethodRunner(String mainClass, String[] args) {
|
||||
this.mainClassName = mainClass;
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Class<?> mainClass = Thread.currentThread().getContextClassLoader()
|
||||
.loadClass(mainClassName);
|
||||
Method mainMethod = mainClass.getDeclaredMethod("main", String[].class);
|
||||
if (mainMethod == null) {
|
||||
throw new IllegalStateException(mainClassName
|
||||
+ " does not have a main method");
|
||||
}
|
||||
mainMethod.invoke(null, new Object[] { args });
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 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.launcher;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.jar.JarEntry;
|
||||
|
||||
import org.springframework.bootstrap.launcher.jar.JarEntryFilter;
|
||||
import org.springframework.bootstrap.launcher.jar.RandomAccessJarFile;
|
||||
|
||||
/**
|
||||
* {@link Launcher} for WAR based archives. This launcher for standard WAR archives.
|
||||
* Supports dependencies in {@code WEB-INF/lib} as well as {@code WEB-INF/lib-provided},
|
||||
* classes are loaded from {@code WEB-INF/classes}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class WarLauncher extends Launcher {
|
||||
|
||||
@Override
|
||||
protected boolean isNestedJarFile(JarEntry jarEntry) {
|
||||
if (jarEntry.isDirectory()) {
|
||||
return jarEntry.getName().equals("WEB-INF/classes/");
|
||||
} else {
|
||||
return jarEntry.getName().startsWith("WEB-INF/lib/")
|
||||
|| jarEntry.getName().startsWith("WEB-INF/lib-provided/");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void postProcessLib(RandomAccessJarFile jarFile,
|
||||
List<RandomAccessJarFile> lib) throws Exception {
|
||||
lib.add(0, filterJarFile(jarFile));
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the specified WAR file to exclude elements that should not appear on the
|
||||
* classpath.
|
||||
* @param jarFile the source file
|
||||
* @return the filtered file
|
||||
* @throws IOException on error
|
||||
*/
|
||||
protected RandomAccessJarFile filterJarFile(RandomAccessJarFile jarFile)
|
||||
throws IOException {
|
||||
return jarFile.getFilteredJarFile(new JarEntryFilter() {
|
||||
|
||||
@Override
|
||||
public String apply(String entryName, JarEntry entry) {
|
||||
if (entryName.startsWith("META-INF/") || entryName.startsWith("WEB-INF/")) {
|
||||
return null;
|
||||
}
|
||||
return entryName;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
new WarLauncher().launch(args);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 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.launcher.data;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* Interface that provides read-only random access to some underlying data.
|
||||
* Implementations must allow concurrent reads in a thread-safe manner.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public interface RandomAccessData {
|
||||
|
||||
/**
|
||||
* Returns an {@link InputStream} that can be used to read the underling data. The
|
||||
* caller is responsible close the underlying stream.
|
||||
*
|
||||
* @return a new input stream that can be used to read the underlying data.
|
||||
*/
|
||||
InputStream getInputStream();
|
||||
|
||||
/**
|
||||
* Returns a new {@link RandomAccessData} for a specific subsection of this data.
|
||||
* @param offset the offset of the subsection
|
||||
* @param length the length of the subsection
|
||||
* @return the subsection data
|
||||
*/
|
||||
RandomAccessData getSubsection(long offset, long length);
|
||||
|
||||
/**
|
||||
* Returns the size of the data.
|
||||
* @return the size
|
||||
*/
|
||||
long getSize();
|
||||
|
||||
}
|
@ -0,0 +1,252 @@
|
||||
/*
|
||||
* Copyright 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.launcher.data;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.Semaphore;
|
||||
|
||||
/**
|
||||
* {@link RandomAccessData} implementation backed by a {@link RandomAccessFile}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class RandomAccessDataFile implements RandomAccessData {
|
||||
|
||||
private static final int DEFAULT_CONCURRENT_READS = 4;
|
||||
|
||||
private File file;
|
||||
|
||||
private final FilePool filePool;
|
||||
|
||||
private final long offset;
|
||||
|
||||
private final long length;
|
||||
|
||||
/**
|
||||
* Create a new {@link RandomAccessDataFile} backed by the specified file.
|
||||
* @param file the underlying file
|
||||
* @throws IllegalArgumentException if the file is null or does not exist
|
||||
* @see #RandomAccessDataFile(File, int)
|
||||
*/
|
||||
public RandomAccessDataFile(File file) {
|
||||
this(file, DEFAULT_CONCURRENT_READS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link RandomAccessDataFile} backed by the specified file.
|
||||
* @param file the underlying file
|
||||
* @param concurrentReads the maximum number of concurrent reads allowed on the
|
||||
* underlying file before blocking
|
||||
* @throws IllegalArgumentException if the file is null or does not exist
|
||||
* @see #RandomAccessDataFile(File)
|
||||
*/
|
||||
public RandomAccessDataFile(File file, int concurrentReads) {
|
||||
if (file == null) {
|
||||
throw new IllegalArgumentException("File must not be null");
|
||||
}
|
||||
if (!file.exists()) {
|
||||
throw new IllegalArgumentException("File must exist");
|
||||
}
|
||||
this.file = file;
|
||||
this.filePool = new FilePool(concurrentReads);
|
||||
this.offset = 0L;
|
||||
this.length = file.length();
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor used to create a {@link #getSubsection(long, long) subsection}.
|
||||
* @param pool the underlying pool
|
||||
* @param offset the offset of the section
|
||||
* @param length the length of the section
|
||||
*/
|
||||
private RandomAccessDataFile(FilePool pool, long offset, long length) {
|
||||
this.filePool = pool;
|
||||
this.offset = offset;
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the underling File.
|
||||
* @return the underlying file
|
||||
*/
|
||||
public File getFile() {
|
||||
return this.file;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() {
|
||||
return new DataInputStream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RandomAccessData getSubsection(long offset, long length) {
|
||||
if (offset < 0 || length < 0 || offset + length > this.length) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
return new RandomAccessDataFile(this.filePool, this.offset + offset, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSize() {
|
||||
return this.length;
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
this.filePool.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link RandomAccessDataInputStream} implementation for the
|
||||
* {@link RandomAccessDataFile}.
|
||||
*/
|
||||
private class DataInputStream extends InputStream {
|
||||
|
||||
private long position;
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return doRead(null, 0, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b) throws IOException {
|
||||
return read(b, 0, b == null ? 0 : b.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
if (b == null) {
|
||||
throw new NullPointerException("Bytes must not be null");
|
||||
}
|
||||
return doRead(b, off, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the actual read.
|
||||
* @param b the bytes to read or {@code null} when reading a single byte
|
||||
* @param off the offset of the byte array
|
||||
* @param len the length of data to read
|
||||
* @return the number of bytes read into {@code b} or the actual read byte if
|
||||
* {@code b} is {@code null}. Returns -1 when the end of the stream is reached
|
||||
* @throws IOException
|
||||
*/
|
||||
public int doRead(byte[] b, int off, int len) throws IOException {
|
||||
if (len == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (cap(len) <= 0) {
|
||||
return -1;
|
||||
}
|
||||
RandomAccessFile file = RandomAccessDataFile.this.filePool.acquire();
|
||||
try {
|
||||
file.seek(RandomAccessDataFile.this.offset + this.position);
|
||||
if (b == null) {
|
||||
int rtn = file.read();
|
||||
moveOn(rtn == -1 ? 0 : 1);
|
||||
return rtn;
|
||||
} else {
|
||||
return (int) moveOn(file.read(b, off, (int) cap(len)));
|
||||
}
|
||||
} finally {
|
||||
RandomAccessDataFile.this.filePool.release(file);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long skip(long n) throws IOException {
|
||||
return (n <= 0 ? 0 : moveOn(cap(n)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Cap the specified value such that it cannot exceed the number of bytes
|
||||
* remaining.
|
||||
* @param n the value to cap
|
||||
* @return the capped value
|
||||
*/
|
||||
private long cap(long n) {
|
||||
return Math.min(RandomAccessDataFile.this.length - this.position, n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the stream position forwards the specified amount
|
||||
* @param amount the amount to move
|
||||
* @return the amount moved
|
||||
*/
|
||||
private long moveOn(long amount) {
|
||||
this.position += amount;
|
||||
return amount;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Manage a pool that can be used to perform concurrent reads on the underlying
|
||||
* {@link RandomAccessFile}.
|
||||
*/
|
||||
private class FilePool {
|
||||
|
||||
private int size;
|
||||
|
||||
private final Semaphore available;
|
||||
|
||||
private final Queue<RandomAccessFile> files;
|
||||
|
||||
public FilePool(int size) {
|
||||
this.size = size;
|
||||
this.available = new Semaphore(size);
|
||||
this.files = new ConcurrentLinkedQueue<RandomAccessFile>();
|
||||
}
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
public RandomAccessFile acquire() throws IOException {
|
||||
try {
|
||||
this.available.acquire();
|
||||
RandomAccessFile file = this.files.poll();
|
||||
return (file == null ? new RandomAccessFile(
|
||||
RandomAccessDataFile.this.file, "r") : file);
|
||||
} catch (InterruptedException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void release(RandomAccessFile file) {
|
||||
this.files.add(file);
|
||||
this.available.release();
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
try {
|
||||
this.available.acquire(size);
|
||||
try {
|
||||
RandomAccessFile file = files.poll();
|
||||
while (file != null) {
|
||||
file.close();
|
||||
file = files.poll();
|
||||
}
|
||||
} finally {
|
||||
this.available.release(size);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Classes and interfaces to allows random access to a block of data.
|
||||
*
|
||||
* @see org.springframework.bootstrap.launcher.data.RandomAccessData
|
||||
*/
|
||||
package org.springframework.bootstrap.launcher.data;
|
||||
|
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 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.launcher.jar;
|
||||
|
||||
import java.util.jar.JarEntry;
|
||||
|
||||
/**
|
||||
* Interface that can be used to filter and optionally rename jar entries.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public interface JarEntryFilter {
|
||||
|
||||
/**
|
||||
* Apply the jar entry filter.
|
||||
* @param entryName the current entry name. This may be different that the original
|
||||
* entry name if a previous filter has been applied
|
||||
* @param entry the entry to filter
|
||||
* @return the new name of the entry or {@code null} if the entry should not be
|
||||
* included.
|
||||
*/
|
||||
String apply(String entryName, JarEntry entry);
|
||||
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 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.launcher.jar;
|
||||
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
import org.springframework.bootstrap.launcher.data.RandomAccessData;
|
||||
|
||||
/**
|
||||
* A {@link ZipEntry} returned from a {@link RandomAccessDataZipInputStream}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class RandomAccessDataZipEntry extends ZipEntry {
|
||||
|
||||
private RandomAccessData data;
|
||||
|
||||
/**
|
||||
* Create new {@link RandomAccessDataZipEntry} instance.
|
||||
* @param entry the underying {@link ZipEntry}
|
||||
* @param data the entry data
|
||||
*/
|
||||
public RandomAccessDataZipEntry(ZipEntry entry, RandomAccessData data) {
|
||||
super(entry);
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link RandomAccessData} for this entry.
|
||||
* @return the entry data
|
||||
*/
|
||||
public RandomAccessData getData() {
|
||||
return data;
|
||||
}
|
||||
}
|
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright 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.launcher.jar;
|
||||
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PushbackInputStream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import org.springframework.bootstrap.launcher.data.RandomAccessData;
|
||||
|
||||
/**
|
||||
* A {@link ZipInputStream} backed by {@link RandomAccessData}. Parsed entries provide
|
||||
* access to the underlying data {@link RandomAccessData#getSubsection(long, long)
|
||||
* subsection}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class RandomAccessDataZipInputStream extends ZipInputStream {
|
||||
|
||||
private RandomAccessData data;
|
||||
|
||||
private TrackingInputStream trackingInputStream;
|
||||
|
||||
/**
|
||||
* Create a new {@link RandomAccessData} instance.
|
||||
* @param data the source of the zip stream
|
||||
*/
|
||||
public RandomAccessDataZipInputStream(RandomAccessData data) {
|
||||
this(data, new TrackingInputStream(data.getInputStream()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor used so that we can call the super constructor with a
|
||||
* {@link TrackingInputStream}.
|
||||
* @param data the source of the zip stream
|
||||
* @param trackingInputStream a tracking input stream
|
||||
*/
|
||||
private RandomAccessDataZipInputStream(RandomAccessData data,
|
||||
TrackingInputStream trackingInputStream) {
|
||||
super(trackingInputStream);
|
||||
this.data = data;
|
||||
this.trackingInputStream = trackingInputStream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RandomAccessDataZipEntry getNextEntry() throws IOException {
|
||||
ZipEntry entry = super.getNextEntry();
|
||||
if (entry == null) {
|
||||
return null;
|
||||
}
|
||||
int start = getPosition();
|
||||
closeEntry();
|
||||
int end = getPosition();
|
||||
RandomAccessData entryData = this.data.getSubsection(start, end - start);
|
||||
return new RandomAccessDataZipEntry(entry, entryData);
|
||||
}
|
||||
|
||||
private int getPosition() throws IOException {
|
||||
int pushback = ((PushbackInputStream) this.in).available();
|
||||
return this.trackingInputStream.getPosition() - pushback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal stream that tracks reads to provide a position.
|
||||
*/
|
||||
private static class TrackingInputStream extends FilterInputStream {
|
||||
|
||||
private int position = 0;
|
||||
|
||||
protected TrackingInputStream(InputStream in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return moveOn(super.read(), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b) throws IOException {
|
||||
return moveOn(super.read(b), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
return moveOn(super.read(b, off, len), false);
|
||||
}
|
||||
|
||||
private int moveOn(int amount, boolean singleByteRead) {
|
||||
this.position += (amount == -1 ? 0 : (singleByteRead ? 1 : amount));
|
||||
return amount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int available() throws IOException {
|
||||
// Always return 0 so that we can accurately use PushbackInputStream.available
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getPosition() {
|
||||
return this.position;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,435 @@
|
||||
/*
|
||||
* Copyright 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.launcher.jar;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.JarURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLStreamHandler;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.jar.Manifest;
|
||||
import java.util.zip.Inflater;
|
||||
import java.util.zip.InflaterInputStream;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
import org.springframework.bootstrap.launcher.data.RandomAccessData;
|
||||
import org.springframework.bootstrap.launcher.data.RandomAccessDataFile;
|
||||
|
||||
/**
|
||||
* A Jar file that can loaded from a {@link RandomAccessDataFile}. This class extends and
|
||||
* behaves in the same was a the standard JDK {@link JarFile} the following additional
|
||||
* functionality.
|
||||
* <ul>
|
||||
* <li>Jar entries can be {@link JarEntryFilter filtered} during construction and new
|
||||
* filtered files can be {@link #getFilteredJarFile(JarEntryFilter...) created} from
|
||||
* existing files.</li>
|
||||
* <li>A nested {@link JarFile} can be
|
||||
* {@link #getNestedJarFile(ZipEntry, JarEntryFilter...) obtained} based on any directory
|
||||
* entry.</li>
|
||||
* <li>A nested {@link JarFile} can be
|
||||
* {@link #getNestedJarFile(ZipEntry, JarEntryFilter...) obtained} for embedded JAR files
|
||||
* (as long as their entry is not compressed).</li>
|
||||
* <li>Entry data can be {@link #getData(ZipEntry) accessed} as {@link RandomAccessData}.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class RandomAccessJarFile extends JarFile {
|
||||
|
||||
private final RandomAccessDataFile rootJarFile;
|
||||
|
||||
private RandomAccessData data;
|
||||
|
||||
private final String name;
|
||||
|
||||
private final long size;
|
||||
|
||||
private Map<String, JarEntry> entries = new LinkedHashMap<String, JarEntry>();
|
||||
|
||||
private Manifest manifest;
|
||||
|
||||
/**
|
||||
* Create a new {@link RandomAccessJarFile} backed by the specified file.
|
||||
* @param file the root jar file
|
||||
* @param filters an optional set of jar entry filters
|
||||
* @throws IOException
|
||||
*/
|
||||
public RandomAccessJarFile(File file, JarEntryFilter... filters) throws IOException {
|
||||
this(new RandomAccessDataFile(file));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link RandomAccessJarFile} backed by the specified file.
|
||||
* @param file the root jar file
|
||||
* @param filters an optional set of jar entry filters
|
||||
* @throws IOException
|
||||
*/
|
||||
public RandomAccessJarFile(RandomAccessDataFile file, JarEntryFilter... filters)
|
||||
throws IOException {
|
||||
this(file, file.getFile().getPath(), file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor used to create a new {@link RandomAccessJarFile} either
|
||||
* directly or from a nested entry.
|
||||
* @param rootJarFile the root jar file
|
||||
* @param name the name of this file
|
||||
* @param data the underlying data
|
||||
* @param filters an optional set of jar entry filters
|
||||
* @throws IOException
|
||||
*/
|
||||
private RandomAccessJarFile(RandomAccessDataFile rootJarFile, String name,
|
||||
RandomAccessData data, JarEntryFilter... filters) throws IOException {
|
||||
super(rootJarFile.getFile());
|
||||
this.rootJarFile = rootJarFile;
|
||||
this.name = name;
|
||||
this.data = data;
|
||||
this.size = data.getSize();
|
||||
|
||||
RandomAccessDataZipInputStream inputStream = new RandomAccessDataZipInputStream(
|
||||
data);
|
||||
try {
|
||||
RandomAccessDataZipEntry zipEntry = inputStream.getNextEntry();
|
||||
while (zipEntry != null) {
|
||||
addJarEntry(zipEntry, filters);
|
||||
zipEntry = inputStream.getNextEntry();
|
||||
}
|
||||
this.manifest = findManifest();
|
||||
if (this.manifest != null) {
|
||||
for (JarEntry containedEntry : this.entries.values()) {
|
||||
((Entry) containedEntry).configure(this.manifest);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
inputStream.close();
|
||||
}
|
||||
}
|
||||
|
||||
private void addJarEntry(RandomAccessDataZipEntry zipEntry, JarEntryFilter... filters) {
|
||||
Entry jarEntry = new Entry(zipEntry);
|
||||
String name = zipEntry.getName();
|
||||
for (JarEntryFilter filter : filters) {
|
||||
name = (filter == null || name == null ? name : filter.apply(name, jarEntry));
|
||||
}
|
||||
if (name != null) {
|
||||
jarEntry.setName(name);
|
||||
this.entries.put(name, jarEntry);
|
||||
}
|
||||
}
|
||||
|
||||
private Manifest findManifest() throws IOException {
|
||||
ZipEntry manifestEntry = getEntry(MANIFEST_NAME);
|
||||
if (manifestEntry != null) {
|
||||
BufferedInputStream inputStream = new BufferedInputStream(
|
||||
getInputStream(manifestEntry));
|
||||
return new Manifest(inputStream);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected final RandomAccessDataFile getRootJarFile() {
|
||||
return rootJarFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Manifest getManifest() throws IOException {
|
||||
return this.manifest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<JarEntry> entries() {
|
||||
return Collections.enumeration(this.entries.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public JarEntry getJarEntry(String name) {
|
||||
return (JarEntry) getEntry(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ZipEntry getEntry(String name) {
|
||||
return this.entries.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized InputStream getInputStream(ZipEntry ze) throws IOException {
|
||||
InputStream inputStream = getData(ze).getInputStream();
|
||||
if (ze.getMethod() == ZipEntry.DEFLATED) {
|
||||
inputStream = new InflaterInputStream(inputStream, new Inflater(true), 512);
|
||||
}
|
||||
return inputStream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a nested {@link RandomAccessJarFile} loaded from the specified entry.
|
||||
* @param ze the zip entry
|
||||
* @param filters an optional set of jar entry filters to be applied
|
||||
* @return a {@link RandomAccessJarFile} for the entry
|
||||
* @throws IOException
|
||||
*/
|
||||
public synchronized RandomAccessJarFile getNestedJarFile(final ZipEntry ze,
|
||||
JarEntryFilter... filters) throws IOException {
|
||||
if (ze == null) {
|
||||
throw new IllegalArgumentException("ZipEntry must not be null");
|
||||
}
|
||||
if (ze.isDirectory()) {
|
||||
final String directoryName = ze.getName();
|
||||
JarEntryFilter[] filtersToUse = new JarEntryFilter[filters.length + 1];
|
||||
System.arraycopy(filters, 0, filtersToUse, 1, filters.length);
|
||||
filtersToUse[0] = new JarEntryFilter() {
|
||||
@Override
|
||||
public String apply(String entryName, JarEntry entry) {
|
||||
if (entryName.startsWith(directoryName)
|
||||
&& !entryName.equals(directoryName)) {
|
||||
return entryName.substring(ze.getName().length());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
return new RandomAccessJarFile(this.rootJarFile, getName() + "!/"
|
||||
+ directoryName.substring(0, directoryName.length() - 1), this.data,
|
||||
filtersToUse);
|
||||
} else {
|
||||
if (ze.getMethod() != ZipEntry.STORED) {
|
||||
throw new IllegalStateException("Unable to open nested compressed entry "
|
||||
+ ze.getName());
|
||||
}
|
||||
return new RandomAccessJarFile(this.rootJarFile, getName() + "!/"
|
||||
+ ze.getName(), getData(ze), filters);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a new jar based on the filtered contents of this file.
|
||||
* @param filters the set of jar entry filters to be applied
|
||||
* @return a filtered {@link RandomAccessJarFile}
|
||||
* @throws IOException
|
||||
*/
|
||||
public synchronized RandomAccessJarFile getFilteredJarFile(JarEntryFilter... filters)
|
||||
throws IOException {
|
||||
return new RandomAccessJarFile(this.rootJarFile, getName(), this.data, filters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return {@link RandomAccessData} for the specified entry.
|
||||
* @param ze the zip entry
|
||||
* @return the entry {@link RandomAccessData}
|
||||
* @throws IOException
|
||||
*/
|
||||
private synchronized RandomAccessData getData(ZipEntry ze) throws IOException {
|
||||
if (!this.entries.containsValue(ze)) {
|
||||
throw new IllegalArgumentException("ZipEntry must be contained in this file");
|
||||
}
|
||||
return ((Entry) ze).getData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return (int) this.size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
this.rootJarFile.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a URL that can be used to access this JAR file. The returned URL will
|
||||
* connect using a {@link RandomAccessJarURLConnection}. NOTE: the specified URL
|
||||
* cannot be serialized and or cloned.
|
||||
* @return the URL
|
||||
* @throws MalformedURLException
|
||||
*/
|
||||
public URL getUrl() throws MalformedURLException {
|
||||
RandomAccessJarURLStreamHandler handler = new RandomAccessJarURLStreamHandler(
|
||||
this);
|
||||
return new URL("jar", "", -1, "file:" + getName() + "!/", handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* A single {@link JarEntry} in this file.
|
||||
*/
|
||||
private static class Entry extends JarEntry {
|
||||
|
||||
private String name;
|
||||
|
||||
private RandomAccessData entryData;
|
||||
|
||||
private Attributes attributes;
|
||||
|
||||
public Entry(RandomAccessDataZipEntry entry) {
|
||||
super(entry);
|
||||
this.entryData = entry.getData();
|
||||
}
|
||||
|
||||
void configure(Manifest manifest) {
|
||||
this.attributes = manifest.getAttributes(getName());
|
||||
}
|
||||
|
||||
void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return (this.name == null ? super.getName() : this.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Attributes getAttributes() throws IOException {
|
||||
return this.attributes;
|
||||
}
|
||||
|
||||
public RandomAccessData getData() {
|
||||
return this.entryData;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link URLStreamHandler} used to support {@link RandomAccessJarFile#getUrl()}.
|
||||
*/
|
||||
private static class RandomAccessJarURLStreamHandler extends URLStreamHandler {
|
||||
|
||||
private RandomAccessJarFile jarFile;
|
||||
|
||||
public RandomAccessJarURLStreamHandler(RandomAccessJarFile jarFile) {
|
||||
this.jarFile = jarFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected URLConnection openConnection(URL url) throws IOException {
|
||||
return new RandomAccessJarURLConnection(url, this.jarFile);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link RandomAccessJarURLConnection} used to support
|
||||
* {@link RandomAccessJarFile#getUrl()}.
|
||||
*/
|
||||
private static class RandomAccessJarURLConnection extends JarURLConnection {
|
||||
|
||||
private RandomAccessJarFile jarFile;
|
||||
|
||||
private JarEntry jarEntry;
|
||||
|
||||
private String jarEntryName;
|
||||
|
||||
private String contentType;
|
||||
|
||||
protected RandomAccessJarURLConnection(URL url, RandomAccessJarFile jarFile)
|
||||
throws MalformedURLException {
|
||||
super(new URL("jar:file:" + jarFile.getRootJarFile().getFile().getPath()
|
||||
+ "!/"));
|
||||
this.jarFile = jarFile;
|
||||
|
||||
String spec = url.getFile();
|
||||
int separator = spec.lastIndexOf("!/");
|
||||
if (separator == -1) {
|
||||
throw new MalformedURLException("no !/ found in url spec:" + spec);
|
||||
}
|
||||
if (separator + 2 != spec.length()) {
|
||||
this.jarEntryName = spec.substring(separator + 2);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect() throws IOException {
|
||||
if (this.jarEntryName != null) {
|
||||
this.jarEntry = this.jarFile.getJarEntry(this.jarEntryName);
|
||||
if (this.jarEntry == null) {
|
||||
throw new FileNotFoundException("JAR entry " + this.jarEntryName
|
||||
+ " not found in " + this.jarFile.getName());
|
||||
}
|
||||
}
|
||||
this.connected = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RandomAccessJarFile getJarFile() throws IOException {
|
||||
connect();
|
||||
return this.jarFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JarEntry getJarEntry() throws IOException {
|
||||
connect();
|
||||
return this.jarEntry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
connect();
|
||||
if (this.jarEntryName == null) {
|
||||
throw new IOException("no entry name specified");
|
||||
}
|
||||
return this.jarFile.getInputStream(this.jarEntry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentLength() {
|
||||
try {
|
||||
connect();
|
||||
return (int) (this.jarEntry == null ? this.jarFile.size() : this.jarEntry
|
||||
.getSize());
|
||||
} catch (IOException e) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getContent() throws IOException {
|
||||
connect();
|
||||
return (this.jarEntry == null ? this.jarFile : super.getContent());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContentType() {
|
||||
if (this.contentType == null) {
|
||||
// Guess the content type, don't bother with steams as mark is not
|
||||
// supported
|
||||
this.contentType = (this.jarEntryName == null ? "x-java/jar" : null);
|
||||
this.contentType = (this.contentType == null ? guessContentTypeFromName(this.jarEntryName)
|
||||
: contentType);
|
||||
this.contentType = (this.contentType == null ? "content/unknown"
|
||||
: contentType);
|
||||
}
|
||||
return this.contentType;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Support for loading and manipulating JAR/WAR files.
|
||||
*/
|
||||
package org.springframework.bootstrap.launcher.jar;
|
||||
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* System that allows self contained JAR/WAR archives to be launched using
|
||||
* {@code java -jar}. Archives can include nested packaged dependency JARs (there is
|
||||
* not need to create shade style jars) and are executed without unpacking. The only
|
||||
* constraint is that nested JARs must be stored in the archive uncompressed.
|
||||
*
|
||||
* @see org.springframework.bootstrap.launcher.JarLauncher
|
||||
* @see org.springframework.bootstrap.launcher.WarLauncher
|
||||
*/
|
||||
package org.springframework.bootstrap.launcher;
|
||||
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 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.launcher;
|
||||
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.TypeSafeMatcher;
|
||||
|
||||
/**
|
||||
* Hamcrest matcher to tests that a byte array starts with specific bytes.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class ByteArrayStartsWith extends TypeSafeMatcher<byte[]> {
|
||||
|
||||
private byte[] bytes;
|
||||
|
||||
public ByteArrayStartsWith(byte[] bytes) {
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendText("a byte array starting with ").appendValue(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean matchesSafely(byte[] item) {
|
||||
if (item.length < bytes.length) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
if (item[i] != bytes[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,313 @@
|
||||
/*
|
||||
* Copyright 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.launcher.data;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import org.hamcrest.Matcher;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.springframework.bootstrap.launcher.ByteArrayStartsWith;
|
||||
|
||||
/**
|
||||
* Tests for {@link RandomAccessDataFile}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class RandomAccessDataFileTest {
|
||||
|
||||
private static final byte[] BYTES;
|
||||
static {
|
||||
BYTES = new byte[256];
|
||||
for (int i = 0; i < BYTES.length; i++) {
|
||||
BYTES[i] = (byte) i;
|
||||
}
|
||||
}
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder temporaryFolder = new TemporaryFolder();
|
||||
|
||||
private File tempFile;
|
||||
|
||||
private RandomAccessDataFile file;
|
||||
|
||||
private InputStream inputStream;
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
this.tempFile = temporaryFolder.newFile();
|
||||
FileOutputStream outputStream = new FileOutputStream(tempFile);
|
||||
outputStream.write(BYTES);
|
||||
outputStream.close();
|
||||
this.file = new RandomAccessDataFile(tempFile);
|
||||
this.inputStream = file.getInputStream();
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanup() throws Exception {
|
||||
inputStream.close();
|
||||
file.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fileNotNull() throws Exception {
|
||||
thrown.expect(IllegalArgumentException.class);
|
||||
thrown.equals("File must not be null");
|
||||
new RandomAccessDataFile(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fileExists() throws Exception {
|
||||
thrown.expect(IllegalArgumentException.class);
|
||||
thrown.equals("File must exist");
|
||||
new RandomAccessDataFile(new File("/does/not/exist"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fileNotNullWithConcurrentReads() throws Exception {
|
||||
thrown.expect(IllegalArgumentException.class);
|
||||
thrown.equals("File must not be null");
|
||||
new RandomAccessDataFile(null, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fileExistsWithConcurrentReads() throws Exception {
|
||||
thrown.expect(IllegalArgumentException.class);
|
||||
thrown.equals("File must exist");
|
||||
new RandomAccessDataFile(new File("/does/not/exist"), 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inputStreamRead() throws Exception {
|
||||
for (int i = 0; i <= 255; i++) {
|
||||
assertThat(inputStream.read(), equalTo(i));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inputStreamReadNullBytes() throws Exception {
|
||||
thrown.expect(NullPointerException.class);
|
||||
thrown.expectMessage("Bytes must not be null");
|
||||
inputStream.read(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void intputStreamReadNullBytesWithOffset() throws Exception {
|
||||
thrown.expect(NullPointerException.class);
|
||||
thrown.expectMessage("Bytes must not be null");
|
||||
inputStream.read(null, 0, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inputStreamReadBytes() throws Exception {
|
||||
byte[] b = new byte[256];
|
||||
int amountRead = inputStream.read(b);
|
||||
assertThat(b, equalTo(BYTES));
|
||||
assertThat(amountRead, equalTo(256));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inputSteamReadOffsetBytes() throws Exception {
|
||||
byte[] b = new byte[7];
|
||||
inputStream.skip(1);
|
||||
int amountRead = inputStream.read(b, 2, 3);
|
||||
assertThat(b, equalTo(new byte[] { 0, 0, 1, 2, 3, 0, 0 }));
|
||||
assertThat(amountRead, equalTo(3));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inputStreamReadMoreBytesThanAvailable() throws Exception {
|
||||
byte[] b = new byte[257];
|
||||
int amountRead = inputStream.read(b);
|
||||
assertThat(b, startsWith(BYTES));
|
||||
assertThat(amountRead, equalTo(256));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inputStreamReadPastEnd() throws Exception {
|
||||
inputStream.skip(255);
|
||||
assertThat(inputStream.read(), equalTo(0xFF));
|
||||
assertThat(inputStream.read(), equalTo(-1));
|
||||
assertThat(inputStream.read(), equalTo(-1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inputStreamReadZeroLength() throws Exception {
|
||||
byte[] b = new byte[] { 0x0F };
|
||||
int amountRead = inputStream.read(b, 0, 0);
|
||||
assertThat(b, equalTo(new byte[] { 0x0F }));
|
||||
assertThat(amountRead, equalTo(0));
|
||||
assertThat(inputStream.read(), equalTo(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inputStreamSkip() throws Exception {
|
||||
long amountSkipped = inputStream.skip(4);
|
||||
assertThat(inputStream.read(), equalTo(4));
|
||||
assertThat(amountSkipped, equalTo(4L));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inputStreamSkipMoreThanAvailable() throws Exception {
|
||||
long amountSkipped = inputStream.skip(257);
|
||||
assertThat(inputStream.read(), equalTo(-1));
|
||||
assertThat(amountSkipped, equalTo(256L));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inputStreamSkipPastEnd() throws Exception {
|
||||
inputStream.skip(256);
|
||||
long amountSkipped = inputStream.skip(1);
|
||||
assertThat(amountSkipped, equalTo(0L));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subsectionNegativeOffset() throws Exception {
|
||||
thrown.expect(IndexOutOfBoundsException.class);
|
||||
file.getSubsection(-1, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subsectionNegativeLength() throws Exception {
|
||||
thrown.expect(IndexOutOfBoundsException.class);
|
||||
file.getSubsection(0, -1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subsectionZeroLength() throws Exception {
|
||||
RandomAccessData subsection = file.getSubsection(0, 0);
|
||||
assertThat(subsection.getInputStream().read(), equalTo(-1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subsectionTooBig() throws Exception {
|
||||
file.getSubsection(0, 256);
|
||||
thrown.expect(IndexOutOfBoundsException.class);
|
||||
file.getSubsection(0, 257);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subsectionTooBigWithOffset() throws Exception {
|
||||
file.getSubsection(1, 255);
|
||||
thrown.expect(IndexOutOfBoundsException.class);
|
||||
file.getSubsection(1, 256);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subsection() throws Exception {
|
||||
RandomAccessData subsection = file.getSubsection(1, 1);
|
||||
assertThat(subsection.getInputStream().read(), equalTo(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inputStreamReadPastSubsection() throws Exception {
|
||||
RandomAccessData subsection = file.getSubsection(1, 2);
|
||||
InputStream inputStream = subsection.getInputStream();
|
||||
assertThat(inputStream.read(), equalTo(1));
|
||||
assertThat(inputStream.read(), equalTo(2));
|
||||
assertThat(inputStream.read(), equalTo(-1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inputStreamReadBytesPastSubsection() throws Exception {
|
||||
RandomAccessData subsection = file.getSubsection(1, 2);
|
||||
InputStream inputStream = subsection.getInputStream();
|
||||
byte[] b = new byte[3];
|
||||
int amountRead = inputStream.read(b);
|
||||
assertThat(b, equalTo(new byte[] { 1, 2, 0 }));
|
||||
assertThat(amountRead, equalTo(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inputStreamSkipPastSubsection() throws Exception {
|
||||
RandomAccessData subsection = file.getSubsection(1, 2);
|
||||
InputStream inputStream = subsection.getInputStream();
|
||||
assertThat(inputStream.skip(3), equalTo(2L));
|
||||
assertThat(inputStream.read(), equalTo(-1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inputStreamSkipNegative() throws Exception {
|
||||
assertThat(inputStream.skip(-1), equalTo(0L));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFile() throws Exception {
|
||||
assertThat(file.getFile(), equalTo(tempFile));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void concurrentReads() throws Exception {
|
||||
ExecutorService executorService = Executors.newFixedThreadPool(20);
|
||||
List<Future<Boolean>> results = new ArrayList<Future<Boolean>>();
|
||||
for (int i = 0; i < 100; i++) {
|
||||
results.add(executorService.submit(new Callable<Boolean>() {
|
||||
|
||||
@Override
|
||||
public Boolean call() throws Exception {
|
||||
InputStream subsectionInputStream = file.getSubsection(0, 256)
|
||||
.getInputStream();
|
||||
byte[] b = new byte[256];
|
||||
subsectionInputStream.read(b);
|
||||
return Arrays.equals(b, BYTES);
|
||||
}
|
||||
}));
|
||||
}
|
||||
for (Future<Boolean> future : results) {
|
||||
assertThat(future.get(), equalTo(true));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void close() throws Exception {
|
||||
file.getInputStream().read();
|
||||
file.close();
|
||||
Field filePoolField = RandomAccessDataFile.class.getDeclaredField("filePool");
|
||||
filePoolField.setAccessible(true);
|
||||
Object filePool = filePoolField.get(file);
|
||||
Field filesField = filePool.getClass().getDeclaredField("files");
|
||||
filesField.setAccessible(true);
|
||||
Queue<?> queue = (Queue<?>) filesField.get(filePool);
|
||||
assertThat(queue.size(), equalTo(0));
|
||||
}
|
||||
|
||||
private static Matcher<? super byte[]> startsWith(byte[] bytes) {
|
||||
return new ByteArrayStartsWith(bytes);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright 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.launcher.jar;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.zip.CRC32;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.springframework.bootstrap.launcher.data.RandomAccessDataFile;
|
||||
|
||||
/**
|
||||
* Tests for {@link RandomAccessDataZipInputStream}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class RandomAccessDataZipInputStreamTest {
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder temporaryFolder = new TemporaryFolder();
|
||||
|
||||
private File file;
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
this.file = temporaryFolder.newFile();
|
||||
ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(file));
|
||||
try {
|
||||
writeDataEntry(zipOutputStream, "a", new byte[10]);
|
||||
writeDataEntry(zipOutputStream, "b", new byte[20]);
|
||||
} finally {
|
||||
zipOutputStream.close();
|
||||
}
|
||||
}
|
||||
|
||||
private void writeDataEntry(ZipOutputStream zipOutputStream, String name, byte[] data)
|
||||
throws IOException {
|
||||
ZipEntry entry = new ZipEntry(name);
|
||||
entry.setMethod(ZipEntry.STORED);
|
||||
entry.setSize(data.length);
|
||||
entry.setCompressedSize(data.length);
|
||||
CRC32 crc32 = new CRC32();
|
||||
crc32.update(data);
|
||||
entry.setCrc(crc32.getValue());
|
||||
zipOutputStream.putNextEntry(entry);
|
||||
zipOutputStream.write(data);
|
||||
zipOutputStream.closeEntry();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void entryData() throws Exception {
|
||||
RandomAccessDataZipInputStream z = new RandomAccessDataZipInputStream(
|
||||
new RandomAccessDataFile(file));
|
||||
try {
|
||||
RandomAccessDataZipEntry entry1 = z.getNextEntry();
|
||||
RandomAccessDataZipEntry entry2 = z.getNextEntry();
|
||||
assertThat(entry1.getName(), equalTo("a"));
|
||||
assertThat(entry1.getData().getSize(), equalTo(10L));
|
||||
assertThat(entry2.getName(), equalTo("b"));
|
||||
assertThat(entry2.getData().getSize(), equalTo(20L));
|
||||
assertThat(z.getNextEntry(), nullValue());
|
||||
} finally {
|
||||
z.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,331 @@
|
||||
/*
|
||||
* Copyright 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.launcher.jar;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.hamcrest.Matchers.sameInstance;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.JarURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.Enumeration;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.jar.JarOutputStream;
|
||||
import java.util.jar.Manifest;
|
||||
import java.util.zip.CRC32;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.springframework.bootstrap.launcher.data.RandomAccessDataFile;
|
||||
|
||||
/**
|
||||
* Tests for {@link RandomAccessJarFile}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class RandomAccessJarFileTest {
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder temporaryFolder = new TemporaryFolder();
|
||||
|
||||
private File rootJarFile;
|
||||
|
||||
private RandomAccessJarFile jarFile;
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
this.rootJarFile = temporaryFolder.newFile();
|
||||
FileOutputStream fileOutputStream = new FileOutputStream(this.rootJarFile);
|
||||
JarOutputStream jarOutputStream = new JarOutputStream(fileOutputStream);
|
||||
try {
|
||||
writeManifest(jarOutputStream, "j1");
|
||||
writeEntry(jarOutputStream, "1.dat", 1);
|
||||
writeEntry(jarOutputStream, "2.dat", 2);
|
||||
writeDirEntry(jarOutputStream, "d/");
|
||||
writeEntry(jarOutputStream, "d/9.dat", 9);
|
||||
|
||||
JarEntry nestedEntry = new JarEntry("nested.jar");
|
||||
byte[] nestedJarData = getNestedJarData();
|
||||
nestedEntry.setSize(nestedJarData.length);
|
||||
nestedEntry.setCompressedSize(nestedJarData.length);
|
||||
CRC32 crc32 = new CRC32();
|
||||
crc32.update(nestedJarData);
|
||||
nestedEntry.setCrc(crc32.getValue());
|
||||
|
||||
nestedEntry.setMethod(ZipEntry.STORED);
|
||||
jarOutputStream.putNextEntry(nestedEntry);
|
||||
jarOutputStream.write(nestedJarData);
|
||||
jarOutputStream.closeEntry();
|
||||
} finally {
|
||||
jarOutputStream.close();
|
||||
}
|
||||
this.jarFile = new RandomAccessJarFile(this.rootJarFile);
|
||||
}
|
||||
|
||||
private byte[] getNestedJarData() throws Exception {
|
||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
JarOutputStream jarOutputStream = new JarOutputStream(byteArrayOutputStream);
|
||||
writeManifest(jarOutputStream, "j2");
|
||||
writeEntry(jarOutputStream, "3.dat", 3);
|
||||
writeEntry(jarOutputStream, "4.dat", 4);
|
||||
jarOutputStream.close();
|
||||
return byteArrayOutputStream.toByteArray();
|
||||
}
|
||||
|
||||
private void writeManifest(JarOutputStream jarOutputStream, String name)
|
||||
throws Exception {
|
||||
writeDirEntry(jarOutputStream, "META-INF/");
|
||||
Manifest manifest = new Manifest();
|
||||
manifest.getMainAttributes().putValue("Built-By", name);
|
||||
manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
|
||||
jarOutputStream.putNextEntry(new ZipEntry("META-INF/MANIFEST.MF"));
|
||||
manifest.write(jarOutputStream);
|
||||
jarOutputStream.closeEntry();
|
||||
}
|
||||
|
||||
private void writeDirEntry(JarOutputStream jarOutputStream, String name)
|
||||
throws IOException {
|
||||
jarOutputStream.putNextEntry(new JarEntry(name));
|
||||
jarOutputStream.closeEntry();
|
||||
}
|
||||
|
||||
private void writeEntry(JarOutputStream jarOutputStream, String name, int data)
|
||||
throws IOException {
|
||||
jarOutputStream.putNextEntry(new JarEntry(name));
|
||||
jarOutputStream.write(new byte[] { (byte) data });
|
||||
jarOutputStream.closeEntry();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createFromFile() throws Exception {
|
||||
RandomAccessJarFile jarFile = new RandomAccessJarFile(this.rootJarFile);
|
||||
assertThat(jarFile.getName(), notNullValue(String.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createFromRandomAccessDataFile() throws Exception {
|
||||
RandomAccessDataFile randomAccessDataFile = new RandomAccessDataFile(
|
||||
this.rootJarFile, 1);
|
||||
RandomAccessJarFile jarFile = new RandomAccessJarFile(randomAccessDataFile);
|
||||
assertThat(jarFile.getName(), notNullValue(String.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getManifest() throws Exception {
|
||||
assertThat(jarFile.getManifest().getMainAttributes().getValue("Built-By"),
|
||||
equalTo("j1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getEntries() throws Exception {
|
||||
Enumeration<JarEntry> entries = jarFile.entries();
|
||||
assertThat(entries.nextElement().getName(), equalTo("META-INF/"));
|
||||
assertThat(entries.nextElement().getName(), equalTo("META-INF/MANIFEST.MF"));
|
||||
assertThat(entries.nextElement().getName(), equalTo("1.dat"));
|
||||
assertThat(entries.nextElement().getName(), equalTo("2.dat"));
|
||||
assertThat(entries.nextElement().getName(), equalTo("d/"));
|
||||
assertThat(entries.nextElement().getName(), equalTo("d/9.dat"));
|
||||
assertThat(entries.nextElement().getName(), equalTo("nested.jar"));
|
||||
assertThat(entries.hasMoreElements(), equalTo(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getJarEntry() throws Exception {
|
||||
JarEntry entry = jarFile.getJarEntry("1.dat");
|
||||
assertThat(entry, notNullValue(ZipEntry.class));
|
||||
assertThat(entry.getName(), equalTo("1.dat"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getInputStream() throws Exception {
|
||||
InputStream inputStream = jarFile.getInputStream(jarFile.getEntry("1.dat"));
|
||||
assertThat(inputStream.read(), equalTo(1));
|
||||
assertThat(inputStream.read(), equalTo(-1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getName() throws Exception {
|
||||
assertThat(jarFile.getName(), equalTo(rootJarFile.getPath()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSize() throws Exception {
|
||||
assertThat(jarFile.size(), equalTo((int) rootJarFile.length()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void close() throws Exception {
|
||||
RandomAccessDataFile randomAccessDataFile = spy(new RandomAccessDataFile(
|
||||
this.rootJarFile, 1));
|
||||
RandomAccessJarFile jarFile = new RandomAccessJarFile(randomAccessDataFile);
|
||||
jarFile.close();
|
||||
verify(randomAccessDataFile).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getUrl() throws Exception {
|
||||
URL url = jarFile.getUrl();
|
||||
assertThat(url.toString(), equalTo("jar:file:" + rootJarFile.getPath() + "!/"));
|
||||
JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
|
||||
assertThat(jarURLConnection.getJarFile(), sameInstance((JarFile) jarFile));
|
||||
assertThat(jarURLConnection.getJarEntry(), nullValue());
|
||||
assertThat(jarURLConnection.getContentLength(), greaterThan(1));
|
||||
assertThat(jarURLConnection.getContent(), sameInstance((Object) jarFile));
|
||||
assertThat(jarURLConnection.getContentType(), equalTo("x-java/jar"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getEntryUrl() throws Exception {
|
||||
URL url = new URL(jarFile.getUrl(), "1.dat");
|
||||
assertThat(url.toString(), equalTo("jar:file:" + rootJarFile.getPath()
|
||||
+ "!/1.dat"));
|
||||
JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
|
||||
assertThat(jarURLConnection.getJarFile(), sameInstance((JarFile) jarFile));
|
||||
assertThat(jarURLConnection.getJarEntry(),
|
||||
sameInstance(jarFile.getJarEntry("1.dat")));
|
||||
assertThat(jarURLConnection.getContentLength(), equalTo(1));
|
||||
assertThat(jarURLConnection.getContent(), instanceOf(InputStream.class));
|
||||
assertThat(jarURLConnection.getContentType(), equalTo("content/unknown"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getMissingEntryUrl() throws Exception {
|
||||
URL url = new URL(jarFile.getUrl(), "missing.dat");
|
||||
assertThat(url.toString(), equalTo("jar:file:" + rootJarFile.getPath()
|
||||
+ "!/missing.dat"));
|
||||
thrown.expect(FileNotFoundException.class);
|
||||
((JarURLConnection) url.openConnection()).getJarEntry();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getUrlStream() throws Exception {
|
||||
URL url = jarFile.getUrl();
|
||||
url.openConnection();
|
||||
thrown.expect(IOException.class);
|
||||
url.openStream();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getEntryUrlStream() throws Exception {
|
||||
URL url = new URL(jarFile.getUrl(), "1.dat");
|
||||
url.openConnection();
|
||||
InputStream stream = url.openStream();
|
||||
assertThat(stream.read(), equalTo(1));
|
||||
assertThat(stream.read(), equalTo(-1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNestedJarFile() throws Exception {
|
||||
RandomAccessJarFile nestedJarFile = jarFile.getNestedJarFile(jarFile
|
||||
.getEntry("nested.jar"));
|
||||
|
||||
Enumeration<JarEntry> entries = nestedJarFile.entries();
|
||||
assertThat(entries.nextElement().getName(), equalTo("META-INF/"));
|
||||
assertThat(entries.nextElement().getName(), equalTo("META-INF/MANIFEST.MF"));
|
||||
assertThat(entries.nextElement().getName(), equalTo("3.dat"));
|
||||
assertThat(entries.nextElement().getName(), equalTo("4.dat"));
|
||||
assertThat(entries.hasMoreElements(), equalTo(false));
|
||||
|
||||
InputStream inputStream = nestedJarFile.getInputStream(nestedJarFile
|
||||
.getEntry("3.dat"));
|
||||
assertThat(inputStream.read(), equalTo(3));
|
||||
assertThat(inputStream.read(), equalTo(-1));
|
||||
|
||||
URL url = nestedJarFile.getUrl();
|
||||
assertThat(url.toString(), equalTo("jar:file:" + rootJarFile.getPath()
|
||||
+ "!/nested.jar!/"));
|
||||
assertThat(((JarURLConnection) url.openConnection()).getJarFile(),
|
||||
sameInstance((JarFile) nestedJarFile));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNestedJarDirectory() throws Exception {
|
||||
RandomAccessJarFile nestedJarFile = jarFile.getNestedJarFile(jarFile
|
||||
.getEntry("d/"));
|
||||
|
||||
Enumeration<JarEntry> entries = nestedJarFile.entries();
|
||||
assertThat(entries.nextElement().getName(), equalTo("9.dat"));
|
||||
assertThat(entries.hasMoreElements(), equalTo(false));
|
||||
|
||||
InputStream inputStream = nestedJarFile.getInputStream(nestedJarFile
|
||||
.getEntry("9.dat"));
|
||||
assertThat(inputStream.read(), equalTo(9));
|
||||
assertThat(inputStream.read(), equalTo(-1));
|
||||
|
||||
URL url = nestedJarFile.getUrl();
|
||||
assertThat(url.toString(), equalTo("jar:file:" + rootJarFile.getPath() + "!/d!/"));
|
||||
assertThat(((JarURLConnection) url.openConnection()).getJarFile(),
|
||||
sameInstance((JarFile) nestedJarFile));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDirectoryInputStream() throws Exception {
|
||||
InputStream inputStream = jarFile.getInputStream(jarFile.getEntry("d/"));
|
||||
assertThat(inputStream, notNullValue());
|
||||
assertThat(inputStream.read(), equalTo(-1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFilteredJarFile() throws Exception {
|
||||
RandomAccessJarFile filteredJarFile = jarFile
|
||||
.getFilteredJarFile(new JarEntryFilter() {
|
||||
@Override
|
||||
public String apply(String entryName, JarEntry entry) {
|
||||
if (entryName.equals("1.dat")) {
|
||||
return "x.dat";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
Enumeration<JarEntry> entries = filteredJarFile.entries();
|
||||
assertThat(entries.nextElement().getName(), equalTo("x.dat"));
|
||||
assertThat(entries.hasMoreElements(), equalTo(false));
|
||||
|
||||
InputStream inputStream = filteredJarFile.getInputStream(filteredJarFile
|
||||
.getEntry("x.dat"));
|
||||
assertThat(inputStream.read(), equalTo(1));
|
||||
assertThat(inputStream.read(), equalTo(-1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sensibleToString() throws Exception {
|
||||
assertThat(jarFile.toString(), equalTo(rootJarFile.getPath()));
|
||||
assertThat(jarFile.getNestedJarFile(jarFile.getEntry("nested.jar")).toString(),
|
||||
equalTo(rootJarFile.getPath() + "!/nested.jar"));
|
||||
}
|
||||
}
|
@ -0,0 +1,148 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.bootstrap</groupId>
|
||||
<artifactId>spring-bootstrap-parent</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>spring-bootstrap-samples</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<properties>
|
||||
<main.basedir>${project.basedir}/..</main.basedir>
|
||||
</properties>
|
||||
<modules>
|
||||
<module>spring-bootstrap-sample</module>
|
||||
<module>spring-bootstrap-data-sample</module>
|
||||
<module>spring-bootstrap-jetty-sample</module>
|
||||
<module>spring-bootstrap-simple-sample</module>
|
||||
<module>spring-bootstrap-tomcat-sample</module>
|
||||
<module>spring-bootstrap-profile-sample</module>
|
||||
<module>spring-bootstrap-service-sample</module>
|
||||
<module>spring-bootstrap-trad-sample</module>
|
||||
<module>spring-bootstrap-xml-sample</module>
|
||||
</modules>
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>unpack</id>
|
||||
<phase>prepare-package</phase>
|
||||
<inherited>true</inherited>
|
||||
<goals>
|
||||
<goal>unpack</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifactItems>
|
||||
<artifactItem>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>spring-bootstrap-launcher</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>jar</type>
|
||||
</artifactItem>
|
||||
</artifactItems>
|
||||
<outputDirectory>${project.build.directory}/assembly</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>copy</id>
|
||||
<phase>prepare-package</phase>
|
||||
<inherited>true</inherited>
|
||||
<goals>
|
||||
<goal>copy-dependencies</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputDirectory>${project.build.directory}/assembly/lib</outputDirectory>
|
||||
<scope>runtime</scope>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<configuration>
|
||||
<descriptors>
|
||||
<descriptor>${project.parent.basedir}/src/main/assembly/jar-with-dependencies.xml</descriptor>
|
||||
</descriptors>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>org.springframework.bootstrap.launcher.JarLauncher</mainClass>
|
||||
</manifest>
|
||||
<manifestEntries>
|
||||
<Start-Class>${start-class}</Start-Class>
|
||||
</manifestEntries>
|
||||
</archive>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>jar-with-dependencies</id>
|
||||
<phase>package</phase>
|
||||
<inherited>true</inherited>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>spring-bootstrap</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>true</createDependencyReducedPom>
|
||||
<filters>
|
||||
<filter>
|
||||
<artifact>*:*</artifact>
|
||||
<excludes>
|
||||
<exclude>META-INF/*.SF</exclude>
|
||||
<exclude>META-INF/*.DSA</exclude>
|
||||
<exclude>META-INF/*.RSA</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
</filters>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<transformers>
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/spring.handlers</resource>
|
||||
</transformer>
|
||||
<transformer
|
||||
implementation="org.springframework.bootstrap.maven.PropertiesMergingResourceTransformer">
|
||||
<resource>META-INF/spring.factories</resource>
|
||||
</transformer>
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>META-INF/spring.schemas</resource>
|
||||
</transformer>
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||
<mainClass>${start-class}</mainClass>
|
||||
</transformer>
|
||||
</transformers>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
</project>
|
@ -0,0 +1,83 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.bootstrap</groupId>
|
||||
<artifactId>spring-bootstrap-samples</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>spring-bootstrap-data-sample</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<properties>
|
||||
<main.basedir>${project.basedir}/../..</main.basedir>
|
||||
<start-class>org.springframework.bootstrap.sample.data.DataBootstrapApplication</start-class>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>spring-bootstrap</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-jdk14</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-webapp</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-util</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-orm</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-jdbc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-entitymanager</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-jpa</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hsqldb</groupId>
|
||||
<artifactId>hsqldb</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
@ -0,0 +1,17 @@
|
||||
package org.springframework.bootstrap.sample.data;
|
||||
|
||||
import org.springframework.bootstrap.SpringApplication;
|
||||
import org.springframework.bootstrap.context.annotation.EnableAutoConfiguration;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@ComponentScan
|
||||
@EnableAutoConfiguration
|
||||
public class DataBootstrapApplication {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
SpringApplication.run(DataBootstrapApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
package org.springframework.bootstrap.sample.data.domain;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
|
||||
@Entity
|
||||
public class City implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String name;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String state;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String country;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String map;
|
||||
|
||||
protected City() {
|
||||
}
|
||||
|
||||
public City(String name, String country) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.country = country;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public String getState() {
|
||||
return this.state;
|
||||
}
|
||||
|
||||
public String getCountry() {
|
||||
return this.country;
|
||||
}
|
||||
|
||||
public String getMap() {
|
||||
return this.map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName() + "," + getState() + "," + getCountry();
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
package org.springframework.bootstrap.sample.data.domain;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
|
||||
import org.hibernate.annotations.NaturalId;
|
||||
|
||||
@Entity
|
||||
public class Hotel implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
@ManyToOne(optional = false)
|
||||
@NaturalId
|
||||
private City city;
|
||||
|
||||
@Column(nullable = false)
|
||||
@NaturalId
|
||||
private String name;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String address;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String zip;
|
||||
|
||||
@OneToMany(fetch = FetchType.LAZY, mappedBy = "hotel")
|
||||
private Set<Review> reviews;
|
||||
|
||||
protected Hotel() {
|
||||
}
|
||||
|
||||
public Hotel(City city, String name) {
|
||||
this.city = city;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public City getCity() {
|
||||
return this.city;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return this.address;
|
||||
}
|
||||
|
||||
public String getZip() {
|
||||
return this.zip;
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package org.springframework.bootstrap.sample.data.domain;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
import java.math.RoundingMode;
|
||||
|
||||
public class HotelSummary implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final MathContext MATH_CONTEXT = new MathContext(2,
|
||||
RoundingMode.HALF_UP);
|
||||
|
||||
private City city;
|
||||
|
||||
private String name;
|
||||
|
||||
private Double averageRating;
|
||||
|
||||
private Integer averageRatingRounded;
|
||||
|
||||
public HotelSummary(City city, String name, Double averageRating) {
|
||||
this.city = city;
|
||||
this.name = name;
|
||||
this.averageRating = averageRating == null ? null : new BigDecimal(averageRating,
|
||||
MATH_CONTEXT).doubleValue();
|
||||
this.averageRatingRounded = averageRating == null ? null : (int) Math
|
||||
.round(averageRating);
|
||||
}
|
||||
|
||||
public City getCity() {
|
||||
return this.city;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public Double getAverageRating() {
|
||||
return this.averageRating;
|
||||
}
|
||||
|
||||
public Integer getAverageRatingRounded() {
|
||||
return this.averageRatingRounded;
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package org.springframework.bootstrap.sample.data.domain;
|
||||
|
||||
public enum Rating {
|
||||
TERRIBLE, POOR, AVERAGE, GOOD, EXCELLENT,
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package org.springframework.bootstrap.sample.data.domain;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class RatingCount implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Rating rating;
|
||||
|
||||
private long count;
|
||||
|
||||
public RatingCount(Rating rating, long count) {
|
||||
this.rating = rating;
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
public Rating getRating() {
|
||||
return this.rating;
|
||||
}
|
||||
|
||||
public long getCount() {
|
||||
return this.count;
|
||||
}
|
||||
}
|
@ -0,0 +1,113 @@
|
||||
package org.springframework.bootstrap.sample.data.domain;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@Entity
|
||||
public class Review implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
@ManyToOne(optional = false)
|
||||
private Hotel hotel;
|
||||
|
||||
@Column(nullable = false)
|
||||
private int index;
|
||||
|
||||
@Column(nullable = false)
|
||||
@Enumerated(EnumType.ORDINAL)
|
||||
private Rating rating;
|
||||
|
||||
@Column(nullable = false)
|
||||
@Temporal(TemporalType.DATE)
|
||||
private Date checkInDate;
|
||||
|
||||
@Column(nullable = false)
|
||||
@Enumerated(EnumType.ORDINAL)
|
||||
private TripType tripType;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String title;
|
||||
|
||||
@Column(nullable = false, length = 5000)
|
||||
private String details;
|
||||
|
||||
protected Review() {
|
||||
}
|
||||
|
||||
public Review(Hotel hotel, int index, ReviewDetails details) {
|
||||
Assert.notNull(hotel, "Hotel must not be null");
|
||||
Assert.notNull(details, "Details must not be null");
|
||||
this.hotel = hotel;
|
||||
this.index = index;
|
||||
this.rating = details.getRating();
|
||||
this.checkInDate = details.getCheckInDate();
|
||||
this.tripType = details.getTripType();
|
||||
this.title = details.getTitle();
|
||||
this.details = details.getDetails();
|
||||
}
|
||||
|
||||
public Hotel getHotel() {
|
||||
return this.hotel;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return this.index;
|
||||
}
|
||||
|
||||
public Rating getRating() {
|
||||
return this.rating;
|
||||
}
|
||||
|
||||
public void setRating(Rating rating) {
|
||||
this.rating = rating;
|
||||
}
|
||||
|
||||
public Date getCheckInDate() {
|
||||
return this.checkInDate;
|
||||
}
|
||||
|
||||
public void setCheckInDate(Date checkInDate) {
|
||||
this.checkInDate = checkInDate;
|
||||
}
|
||||
|
||||
public TripType getTripType() {
|
||||
return this.tripType;
|
||||
}
|
||||
|
||||
public void setTripType(TripType tripType) {
|
||||
this.tripType = tripType;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return this.title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getDetails() {
|
||||
return this.details;
|
||||
}
|
||||
|
||||
public void setDetails(String details) {
|
||||
this.details = details;
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
package org.springframework.bootstrap.sample.data.domain;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
//FIXME Hibernate bug HHH-5792 prevents this being embedded
|
||||
|
||||
public class ReviewDetails implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Rating rating;
|
||||
|
||||
private Date checkInDate;
|
||||
|
||||
private TripType tripType;
|
||||
|
||||
private String title;
|
||||
|
||||
private String details;
|
||||
|
||||
public ReviewDetails() {
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public ReviewDetails(String title, Rating rating) {
|
||||
this.title = title;
|
||||
this.rating = rating;
|
||||
}
|
||||
|
||||
public Rating getRating() {
|
||||
return this.rating;
|
||||
}
|
||||
|
||||
public void setRating(Rating rating) {
|
||||
this.rating = rating;
|
||||
}
|
||||
|
||||
public Date getCheckInDate() {
|
||||
return this.checkInDate;
|
||||
}
|
||||
|
||||
public void setCheckInDate(Date checkInDate) {
|
||||
this.checkInDate = checkInDate;
|
||||
}
|
||||
|
||||
public TripType getTripType() {
|
||||
return this.tripType;
|
||||
}
|
||||
|
||||
public void setTripType(TripType tripType) {
|
||||
this.tripType = tripType;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return this.title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getDetails() {
|
||||
return this.details;
|
||||
}
|
||||
|
||||
public void setDetails(String details) {
|
||||
this.details = details;
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package org.springframework.bootstrap.sample.data.domain;
|
||||
|
||||
public enum TripType {
|
||||
BUSINESS, COUPLES, FAMILY, FRIENDS, SOLO
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package org.springframework.bootstrap.sample.data.domain.repository;
|
||||
|
||||
import org.springframework.bootstrap.sample.data.domain.City;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.repository.Repository;
|
||||
|
||||
public interface CityRepository extends Repository<City, Long> {
|
||||
|
||||
Page<City> findAll(Pageable pageable);
|
||||
|
||||
Page<City> findByNameLikeAndCountryLikeAllIgnoringCase(String name, String country,
|
||||
Pageable pageable);
|
||||
|
||||
City findByNameAndCountryAllIgnoringCase(String name, String country);
|
||||
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package org.springframework.bootstrap.sample.data.domain.repository;
|
||||
|
||||
import org.springframework.bootstrap.sample.data.domain.City;
|
||||
import org.springframework.bootstrap.sample.data.domain.Hotel;
|
||||
import org.springframework.data.repository.Repository;
|
||||
|
||||
public interface HotelRepository extends Repository<Hotel, Long> {
|
||||
|
||||
Hotel findByCityAndName(City city, String name);
|
||||
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
package org.springframework.bootstrap.sample.data.domain.repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.PersistenceContext;
|
||||
import javax.persistence.Query;
|
||||
|
||||
import org.springframework.bootstrap.sample.data.domain.City;
|
||||
import org.springframework.bootstrap.sample.data.domain.Hotel;
|
||||
import org.springframework.bootstrap.sample.data.domain.HotelSummary;
|
||||
import org.springframework.bootstrap.sample.data.domain.RatingCount;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.domain.Sort.Order;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public class HotelSummaryRepository {
|
||||
|
||||
private static final String AVERAGE_REVIEW_FUNCTION = "avg(r.rating)";
|
||||
|
||||
private static final String FIND_BY_CITY_QUERY = "select new "
|
||||
+ HotelSummary.class.getName() + "(h.city, h.name, "
|
||||
+ AVERAGE_REVIEW_FUNCTION
|
||||
+ ") from Hotel h left outer join h.reviews r where h.city = ?1 group by h";
|
||||
|
||||
private static final String FIND_BY_CITY_COUNT_QUERY = "select count(h) from Hotel h where h.city = ?1";
|
||||
|
||||
private static final String FIND_RATING_COUNTS_QUERY = "select new "
|
||||
+ RatingCount.class.getName() + "(r.rating, count(r)) "
|
||||
+ "from Review r where r.hotel = ?1 group by r.rating order by r.rating DESC";
|
||||
|
||||
private EntityManager entityManager;
|
||||
|
||||
public Page<HotelSummary> findByCity(City city, Pageable pageable) {
|
||||
StringBuilder queryString = new StringBuilder(FIND_BY_CITY_QUERY);
|
||||
applySorting(queryString, pageable == null ? null : pageable.getSort());
|
||||
|
||||
Query query = entityManager.createQuery(queryString.toString());
|
||||
query.setParameter(1, city);
|
||||
query.setFirstResult(pageable.getOffset());
|
||||
query.setMaxResults(pageable.getPageSize());
|
||||
|
||||
Query countQuery = entityManager.createQuery(FIND_BY_CITY_COUNT_QUERY);
|
||||
countQuery.setParameter(1, city);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<HotelSummary> content = query.getResultList();
|
||||
|
||||
Long total = (Long) countQuery.getSingleResult();
|
||||
|
||||
return new PageImpl<HotelSummary>(content, pageable, total);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<RatingCount> findRatingCounts(Hotel hotel) {
|
||||
Query query = entityManager.createQuery(FIND_RATING_COUNTS_QUERY);
|
||||
query.setParameter(1, hotel);
|
||||
return query.getResultList();
|
||||
}
|
||||
|
||||
private void applySorting(StringBuilder query, Sort sort) {
|
||||
if (sort != null) {
|
||||
query.append(" order by");
|
||||
for (Order order : sort) {
|
||||
String aliasedProperty = getAliasedProperty(order.getProperty());
|
||||
query.append(String.format(" %s %s,", aliasedProperty, order
|
||||
.getDirection().name().toLowerCase(Locale.US)));
|
||||
}
|
||||
query.deleteCharAt(query.length() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
private String getAliasedProperty(String property) {
|
||||
if (property.equals("averageRating")) {
|
||||
return AVERAGE_REVIEW_FUNCTION;
|
||||
}
|
||||
return "h." + property;
|
||||
}
|
||||
|
||||
@PersistenceContext
|
||||
public void setEntityManager(EntityManager entityManager) {
|
||||
this.entityManager = entityManager;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package org.springframework.bootstrap.sample.data.domain.repository;
|
||||
|
||||
import org.springframework.bootstrap.sample.data.domain.Hotel;
|
||||
import org.springframework.bootstrap.sample.data.domain.Review;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.repository.Repository;
|
||||
|
||||
public interface ReviewRepository extends Repository<Review, Long> {
|
||||
|
||||
Page<Review> findByHotel(Hotel hotel, Pageable pageable);
|
||||
|
||||
Review findByHotelAndIndex(Hotel hotel, int index);
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue