commit de13fcd0f0e0705e22384d3223989b8400b3a25f Author: Emily Casey Date: Tue Apr 28 16:14:37 2020 -0400 Initial commit * sets up framework * provides mysql binding Signed-off-by: Emily Casey diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dae104f --- /dev/null +++ b/.gitignore @@ -0,0 +1,41 @@ +*~ +.#* +*# +*.sw* +_site/ +.factorypath +.gradletasknamecache +.DS_Store +.checkstyle +*.attach* +/application.yml +/application.properties +asciidoctor.css +atlassian-ide-plugin.xml +bin/ +build/ +dump.rdb +out +spring-shell.log +target/ +test-output +logs/ +scdf-logs/ +.flattened-pom.xml + +# Eclipse artifacts, including WTP generated manifests +.classpath +.project +.settings/ +.springBeans +spring-*/src/main/java/META-INF/MANIFEST.MF + +# IDEA artifacts and output dirs +*.iml +*.ipr +*.iws +.idea/ +rebel.xml + +# VSCode artifacts +.vscode/ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d5dd862 --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + 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 + + https://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. + diff --git a/cnb-bindings-boot/pom.xml b/cnb-bindings-boot/pom.xml new file mode 100644 index 0000000..55481e9 --- /dev/null +++ b/cnb-bindings-boot/pom.xml @@ -0,0 +1,29 @@ + + + 4.0.0 + cnb-bindings-boot + jar + CNB Bindings Spring Boot + Java CNB Boot Support + + org.springframework.cloud + cnb-bindings-parent + 0.0.1.BUILD-SNAPSHOT + + + + org.springframework.boot + spring-boot + + + org.springframework.cloud + cnb-bindings-jdbc + 0.0.1.BUILD-SNAPSHOT + + + org.jmockit + jmockit + test + + + diff --git a/cnb-bindings-boot/src/main/java/org/springframework/cloud/cnb/boot/CnbBindingProcessor.java b/cnb-bindings-boot/src/main/java/org/springframework/cloud/cnb/boot/CnbBindingProcessor.java new file mode 100644 index 0000000..0f7a411 --- /dev/null +++ b/cnb-bindings-boot/src/main/java/org/springframework/cloud/cnb/boot/CnbBindingProcessor.java @@ -0,0 +1,29 @@ +/* + * Copyright 2019 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.cloud.cnb.boot; + +import java.util.Map; + +import org.springframework.cloud.cnb.core.CnbBinding; + +public interface CnbBindingProcessor { + + boolean accept(CnbBinding binding); + + void process(CnbBinding binding, Map properties); + + CnbBindingProcessorProperties getProperties(); +} diff --git a/cnb-bindings-boot/src/main/java/org/springframework/cloud/cnb/boot/CnbBindingProcessorProperties.java b/cnb-bindings-boot/src/main/java/org/springframework/cloud/cnb/boot/CnbBindingProcessorProperties.java new file mode 100644 index 0000000..0a41688 --- /dev/null +++ b/cnb-bindings-boot/src/main/java/org/springframework/cloud/cnb/boot/CnbBindingProcessorProperties.java @@ -0,0 +1,71 @@ +/* + * Copyright 2019 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.cloud.cnb.boot; + +/** + * Properties describing a CfEnvProcessor, mainly used for better logging messages in {@link CnbBindingProcessor}. + * + * @author Mark Pollack + */ +public class CnbBindingProcessorProperties { + + private String propertyPrefixes; + + private String serviceName; + + private CnbBindingProcessorProperties() { + } + + public static Builder builder() { + return new CnbBindingProcessorProperties.Builder(); + } + + /** + * A string containing the values of property prefixes that will be set in the {@code process} method. Used + * for logging purposes. + * @return property prefix values set in the {@code process} method + */ + public String getPropertyPrefixes() { + return propertyPrefixes; + } + + /** + * A name that describes the service being processed, eg. 'Redis', 'MongoDB'. Used for logging purposes. + * @return name that describes the service being processed + */ + public String getServiceName() { + return serviceName; + } + + + public static class Builder { + private CnbBindingProcessorProperties processorProperties = new CnbBindingProcessorProperties(); + + public Builder propertyPrefixes(String propertyPrefixes) { + this.processorProperties.propertyPrefixes = propertyPrefixes; + return this; + } + + public Builder serviceName(String serviceName) { + this.processorProperties.serviceName = serviceName; + return this; + } + + public CnbBindingProcessorProperties build() { + return processorProperties; + } + } +} diff --git a/cnb-bindings-boot/src/main/java/org/springframework/cloud/cnb/boot/CnbBindingsPostProcessor.java b/cnb-bindings-boot/src/main/java/org/springframework/cloud/cnb/boot/CnbBindingsPostProcessor.java new file mode 100644 index 0000000..f8772ed --- /dev/null +++ b/cnb-bindings-boot/src/main/java/org/springframework/cloud/cnb/boot/CnbBindingsPostProcessor.java @@ -0,0 +1,145 @@ +/* + * Copyright 2019 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.cloud.cnb.boot; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.context.config.ConfigFileApplicationListener; +import org.springframework.boot.context.event.ApplicationPreparedEvent; +import org.springframework.boot.env.EnvironmentPostProcessor; +import org.springframework.cloud.cnb.core.CNBBindingsSingleton; +import org.springframework.cloud.cnb.core.CnbBinding; +import org.springframework.cloud.cnb.core.CnbBindings; +import org.springframework.context.ApplicationEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.AnnotationAwareOrderComparator; +import org.springframework.core.env.CommandLinePropertySource; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.MutablePropertySources; +import org.springframework.core.io.support.SpringFactoriesLoader; +import org.springframework.stereotype.Component; + +/** + * An EnvironmentPostProcessor that iterates over {@link CnbBindingProcessor} implementations to contribute + * Spring Boot properties for bound Cloud Foundry Services. + * + * Implementation of {@link CnbBindingProcessor }should be registered using the + * {@code resources/META-INF/spring.factories} property file. + * + * @author Mark Pollack + * @author David Turanski + */ +@Component +public class CnbBindingsPostProcessor implements EnvironmentPostProcessor, Ordered, ApplicationListener { + + private static DeferredLog DEFERRED_LOG = new DeferredLog(); + + private static int invocationCount; + + // Before ConfigFileApplicationListener so values there can use these ones + private int order = ConfigFileApplicationListener.DEFAULT_ORDER - 1; + + public CnbBindingsPostProcessor() { + } + + @Override + public int getOrder() { + return this.order; + } + + public void setOrder(int order) { + this.order = order; + } + + @Override + public void postProcessEnvironment(ConfigurableEnvironment environment, + SpringApplication application) { + + increaseInvocationCount(); + CnbBindings bindings = CNBBindingsSingleton.getCnbBindingsInstance(); + + if (bindings.hasBindings()) { + List allBindings = bindings.findAllBindings(); + + List cnbBindingProcessors = SpringFactoriesLoader + .loadFactories(CnbBindingProcessor.class, getClass().getClassLoader()); + AnnotationAwareOrderComparator.sort(cnbBindingProcessors); + + for (CnbBindingProcessor processor : cnbBindingProcessors) { + List cnbBindings = allBindings.stream() + .filter(processor::accept) + .collect(Collectors.toList()); + + + if (cnbBindings.size() == 1) { + CnbBinding binding = cnbBindings.get(0); + Map properties = new LinkedHashMap<>(); + + processor.process(binding, properties); + + MutablePropertySources propertySources = environment.getPropertySources(); + + if (propertySources.contains( + CommandLinePropertySource.COMMAND_LINE_PROPERTY_SOURCE_NAME)) { + propertySources.addAfter( + CommandLinePropertySource.COMMAND_LINE_PROPERTY_SOURCE_NAME, + new MapPropertySource(processor.getClass().getSimpleName(), properties)); + } else { + propertySources.addFirst( + new MapPropertySource(processor.getClass().getSimpleName(), properties)); + } + + if (invocationCount == 1) { + DEFERRED_LOG.info( + "Setting " + processor.getProperties().getPropertyPrefixes() + + " properties from bound service [" + + binding.getName() + "] using " + processor.getClass().getName()); + } + } + } + } else { + if (invocationCount == 1) { + DEFERRED_LOG.debug( + "Not setting properties, CNB Bindings not detected"); + } + } + } + + @Override + public void onApplicationEvent(ApplicationEvent event) { + if (event instanceof ApplicationPreparedEvent) { + DEFERRED_LOG + .switchTo(CnbBindingsPostProcessor.class); + } + } + + /** + * EnvironmentPostProcessors can end up getting called twice due to spring-cloud-commons + * functionality + */ + protected void increaseInvocationCount() { + synchronized (this) { + invocationCount++; + } + } + +} diff --git a/cnb-bindings-boot/src/main/java/org/springframework/cloud/cnb/boot/ConnectorLibraryDetector.java b/cnb-bindings-boot/src/main/java/org/springframework/cloud/cnb/boot/ConnectorLibraryDetector.java new file mode 100644 index 0000000..4a8a162 --- /dev/null +++ b/cnb-bindings-boot/src/main/java/org/springframework/cloud/cnb/boot/ConnectorLibraryDetector.java @@ -0,0 +1,46 @@ +/* + * Copyright 2019 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.cloud.cnb.boot; + +import org.springframework.util.ClassUtils; + +/** + * Determine if the Connector Library is on the classpath + * @author Mark Pollack + */ +public abstract class ConnectorLibraryDetector { + + public static String MESSAGE = "Exiting the application since the Spring Cloud Connector library has been detected on the classpath. Please remove this dependency from your project and set the environment variable JBP_CONFIG_SPRING_AUTO_RECONFIGURATION '{enabled: false}' in the Cloud Foundry manifest."; + + private static boolean usingConnectorLibrary; + + static { + ClassLoader classLoader = ConnectorLibraryDetector.class.getClassLoader(); + usingConnectorLibrary = ClassUtils.isPresent("org.springframework.cloud.Cloud", classLoader) || + ClassUtils.isPresent("org.cloudfoundry.reconfiguration.org.springframework.cloud.Cloud", classLoader); + } + + static boolean isUsingConnectorLibrary() { + return usingConnectorLibrary; + } + + static void assertNoConnectorLibrary() { + if (ConnectorLibraryDetector.isUsingConnectorLibrary()) { + throw new IllegalStateException(ConnectorLibraryDetector.MESSAGE); + } + } +} diff --git a/cnb-bindings-boot/src/main/java/org/springframework/cloud/cnb/boot/DataSourceCnbBindingProcessor.java b/cnb-bindings-boot/src/main/java/org/springframework/cloud/cnb/boot/DataSourceCnbBindingProcessor.java new file mode 100644 index 0000000..65b307b --- /dev/null +++ b/cnb-bindings-boot/src/main/java/org/springframework/cloud/cnb/boot/DataSourceCnbBindingProcessor.java @@ -0,0 +1,45 @@ +/* + * Copyright 2019 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.cloud.cnb.boot; + +import java.util.Map; + +import org.springframework.cloud.cnb.core.CnbBinding; +import org.springframework.cloud.cnb.jdbc.JdbcUrlCreator; + + +public class DataSourceCnbBindingProcessor implements CnbBindingProcessor{ + @Override + public boolean accept(CnbBinding binding) { + return JdbcUrlCreator.isJDCBBinding(binding); + } + + @Override + public void process(CnbBinding binding, Map properties) { + JdbcUrlCreator jdbcUrlCreator = new JdbcUrlCreator(binding); + properties.put("spring.datasource.url", jdbcUrlCreator.getJdbcUrl()); + properties.put("spring.datasource.username", jdbcUrlCreator.getUsername()); + properties.put("spring.datasource.password", jdbcUrlCreator.getPassword()); + properties.put("spring.datasource.driver-class-name", jdbcUrlCreator.getDriverClassName()); + } + + @Override + public CnbBindingProcessorProperties getProperties() { + return CnbBindingProcessorProperties.builder() + .propertyPrefixes("spring.datasource") + .build(); + } +} diff --git a/cnb-bindings-boot/src/main/java/org/springframework/cloud/cnb/boot/DeferredLog.java b/cnb-bindings-boot/src/main/java/org/springframework/cloud/cnb/boot/DeferredLog.java new file mode 100644 index 0000000..7c8c395 --- /dev/null +++ b/cnb-bindings-boot/src/main/java/org/springframework/cloud/cnb/boot/DeferredLog.java @@ -0,0 +1,269 @@ +/* + * Copyright 2012-2018 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.cloud.cnb.boot; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Deferred {@link Log} that can be used to store messages that shouldn't be written until + * the logging system is fully initialized. + * + * @author Phillip Webb + * @since 1.3.0 + */ +public class DeferredLog implements Log { + + private volatile Log destination; + + private final List lines = new ArrayList<>(); + + @Override + public boolean isTraceEnabled() { + synchronized (this.lines) { + return (this.destination != null) ? this.destination.isTraceEnabled() : true; + } + } + + @Override + public boolean isDebugEnabled() { + synchronized (this.lines) { + return (this.destination != null) ? this.destination.isDebugEnabled() : true; + } + } + + @Override + public boolean isInfoEnabled() { + synchronized (this.lines) { + return (this.destination != null) ? this.destination.isInfoEnabled() : true; + } + } + + @Override + public boolean isWarnEnabled() { + synchronized (this.lines) { + return (this.destination != null) ? this.destination.isWarnEnabled() : true; + } + } + + @Override + public boolean isErrorEnabled() { + synchronized (this.lines) { + return (this.destination != null) ? this.destination.isErrorEnabled() : true; + } + } + + @Override + public boolean isFatalEnabled() { + synchronized (this.lines) { + return (this.destination != null) ? this.destination.isFatalEnabled() : true; + } + } + + @Override + public void trace(Object message) { + log(LogLevel.TRACE, message, null); + } + + @Override + public void trace(Object message, Throwable t) { + log(LogLevel.TRACE, message, t); + } + + @Override + public void debug(Object message) { + log(LogLevel.DEBUG, message, null); + } + + @Override + public void debug(Object message, Throwable t) { + log(LogLevel.DEBUG, message, t); + } + + @Override + public void info(Object message) { + log(LogLevel.INFO, message, null); + } + + @Override + public void info(Object message, Throwable t) { + log(LogLevel.INFO, message, t); + } + + @Override + public void warn(Object message) { + log(LogLevel.WARN, message, null); + } + + @Override + public void warn(Object message, Throwable t) { + log(LogLevel.WARN, message, t); + } + + @Override + public void error(Object message) { + log(LogLevel.ERROR, message, null); + } + + @Override + public void error(Object message, Throwable t) { + log(LogLevel.ERROR, message, t); + } + + @Override + public void fatal(Object message) { + log(LogLevel.FATAL, message, null); + } + + @Override + public void fatal(Object message, Throwable t) { + log(LogLevel.FATAL, message, t); + } + + private void log(LogLevel level, Object message, Throwable t) { + synchronized (this.lines) { + if (this.destination != null) { + logTo(this.destination, level, message, t); + } + else { + this.lines.add(new Line(level, message, t)); + } + } + } + + /** + * Switch from deferred logging to immediate logging to the specified destination. + * @param destination the new log destination + * @since 2.1.0 + */ + public void switchTo(Class destination) { + switchTo(LogFactory.getLog(destination)); + } + + /** + * Switch from deferred logging to immediate logging to the specified destination. + * @param destination the new log destination + * @since 2.1.0 + */ + public void switchTo(Log destination) { + synchronized (this.lines) { + replayTo(destination); + this.destination = destination; + } + } + + /** + * Replay deferred logging to the specified destination. + * @param destination the destination for the deferred log messages + */ + public void replayTo(Class destination) { + replayTo(LogFactory.getLog(destination)); + } + + /** + * Replay deferred logging to the specified destination. + * @param destination the destination for the deferred log messages + */ + public void replayTo(Log destination) { + synchronized (this.lines) { + for (Line line : this.lines) { + logTo(destination, line.getLevel(), line.getMessage(), + line.getThrowable()); + } + this.lines.clear(); + } + } + + /** + * Replay from a source log to a destination log when the source is deferred. + * @param source the source logger + * @param destination the destination logger class + * @return the destination + */ + public static Log replay(Log source, Class destination) { + return replay(source, LogFactory.getLog(destination)); + } + + /** + * Replay from a source log to a destination log when the source is deferred. + * @param source the source logger + * @param destination the destination logger + * @return the destination + */ + public static Log replay(Log source, Log destination) { + if (source instanceof DeferredLog) { + ((DeferredLog) source).replayTo(destination); + } + return destination; + } + + private static void logTo(Log log, LogLevel level, Object message, + Throwable throwable) { + switch (level) { + case TRACE: + log.trace(message, throwable); + return; + case DEBUG: + log.debug(message, throwable); + return; + case INFO: + log.info(message, throwable); + return; + case WARN: + log.warn(message, throwable); + return; + case ERROR: + log.error(message, throwable); + return; + case FATAL: + log.fatal(message, throwable); + return; + } + } + + private static class Line { + + private final LogLevel level; + + private final Object message; + + private final Throwable throwable; + + Line(LogLevel level, Object message, Throwable throwable) { + this.level = level; + this.message = message; + this.throwable = throwable; + } + + public LogLevel getLevel() { + return this.level; + } + + public Object getMessage() { + return this.message; + } + + public Throwable getThrowable() { + return this.throwable; + } + + } + +} diff --git a/cnb-bindings-boot/src/main/java/org/springframework/cloud/cnb/boot/LogLevel.java b/cnb-bindings-boot/src/main/java/org/springframework/cloud/cnb/boot/LogLevel.java new file mode 100644 index 0000000..cc1f95b --- /dev/null +++ b/cnb-bindings-boot/src/main/java/org/springframework/cloud/cnb/boot/LogLevel.java @@ -0,0 +1,27 @@ +/* + * Copyright 2019 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.cloud.cnb.boot; + +/** + * Logging levels supported by a LoggingSystem. + * + * @author Phillip Webb + */ +public enum LogLevel { + + TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF + +} diff --git a/cnb-bindings-boot/src/main/resources/META-INF/spring.factories b/cnb-bindings-boot/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000..6862e0d --- /dev/null +++ b/cnb-bindings-boot/src/main/resources/META-INF/spring.factories @@ -0,0 +1,11 @@ +# Environment Post Processors +org.springframework.boot.env.EnvironmentPostProcessor=\ + org.springframework.cloud.cnb.boot.CnbBindingsPostProcessor +# Also register as a ApplicationListener to log what occurred in the post processing step +org.springframework.context.ApplicationListener=\ + org.springframework.cloud.cnb.boot.CnbBindingsPostProcessor +# CnbBindingsPostProcessor delegates to these CnbBindingsProcessors for each CF service +org.springframework.cloud.cnb.boot.CnbBindingProcessor=\ + org.springframework.cloud.cnb.boot.DataSourceCnbBindingProcessor + + diff --git a/cnb-bindings-boot/src/test/java/org/springframework/cloud/cnb/boot/CnbBindingsPostProcessorTest.java b/cnb-bindings-boot/src/test/java/org/springframework/cloud/cnb/boot/CnbBindingsPostProcessorTest.java new file mode 100644 index 0000000..727bcb2 --- /dev/null +++ b/cnb-bindings-boot/src/test/java/org/springframework/cloud/cnb/boot/CnbBindingsPostProcessorTest.java @@ -0,0 +1,88 @@ +/* + * Copyright 2019 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.cloud.cnb.boot; + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Map; + +import org.junit.Test; + +import org.springframework.boot.Banner; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.cloud.cnb.boot.test.EnvMock; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.util.CollectionUtils; + +import static org.assertj.core.api.Assertions.assertThat; + +public class CnbBindingsPostProcessorTest { + + @Test + public void testPostProcessEnvironment(){ + Path resourceDirectory = Paths.get("src", "test", "resources", "test-bindings"); + String bindingsDir = resourceDirectory.toFile().getAbsolutePath(); + + new EnvMock(bindingsDir); + + CnbBindingsPostProcessor environmentPostProcessor = new CnbBindingsPostProcessor(); + + environmentPostProcessor.postProcessEnvironment(getEnvironment(), + null); + assertThat(getEnvironment().getProperty("spring.datasource.url")) + .isEqualTo("jdbc:mysql://10.0.4.35:3306/mysql_name?user=mysql_username&password=mysql_password"); + assertThat( + getEnvironment().getProperty("spring.datasource.username")) + .isEqualTo("mysql_username"); + assertThat( + getEnvironment().getProperty("spring.datasource.password")) + .isEqualTo("mysql_password"); + } + + @Test + public void testNoBindingsPresent(){ + CnbBindingsPostProcessor environmentPostProcessor = new CnbBindingsPostProcessor(); + + // doen't fail + environmentPostProcessor.postProcessEnvironment(getEnvironment(), + null); + } + + public ConfigurableEnvironment getEnvironment() { + return getEnvironment(null); + } + + public ConfigurableEnvironment getEnvironment(Map properties) { + SpringApplicationBuilder builder = new SpringApplicationBuilder(TestApp.class) + .web(WebApplicationType.NONE); + if (!CollectionUtils.isEmpty(properties)) { + builder.properties(properties); + } + builder.bannerMode(Banner.Mode.OFF); + ConfigurableApplicationContext applicationContext = builder.run(); + ConfigurableEnvironment environment = applicationContext.getEnvironment(); + applicationContext.close(); + return environment; + } + + @SpringBootApplication + static class TestApp { + } + +} diff --git a/cnb-bindings-boot/src/test/java/org/springframework/cloud/cnb/boot/DataSourceCnbBindingProcessorTests.java b/cnb-bindings-boot/src/test/java/org/springframework/cloud/cnb/boot/DataSourceCnbBindingProcessorTests.java new file mode 100644 index 0000000..5368ed7 --- /dev/null +++ b/cnb-bindings-boot/src/test/java/org/springframework/cloud/cnb/boot/DataSourceCnbBindingProcessorTests.java @@ -0,0 +1,75 @@ +/* + * Copyright 2019 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.cloud.cnb.boot; + + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Test; + +import org.springframework.cloud.cnb.core.CnbBinding; + + +import static org.assertj.core.api.Assertions.assertThat; + +public class DataSourceCnbBindingProcessorTests { + + @Test + public void acceptIfJdbcTest() { + DataSourceCnbBindingProcessor bindingProcessor = new DataSourceCnbBindingProcessor(); + Map bindingMetadata = new HashMap(); + bindingMetadata.put("kind", "mysql"); + CnbBinding binding = new CnbBinding(bindingMetadata, new HashMap()); + assertThat(bindingProcessor.accept(binding)).isTrue(); + } + + @Test + public void rejectIfNotJdbcTest() { + DataSourceCnbBindingProcessor bindingProcessor = new DataSourceCnbBindingProcessor(); + Map bindingMetadata = new HashMap(); + bindingMetadata.put("kind", "redis"); + CnbBinding binding = new CnbBinding(bindingMetadata, new HashMap()); + assertThat(bindingProcessor.accept(binding)).isFalse(); + } + + @Test + public void processDataSourcePropertiesTest() { + DataSourceCnbBindingProcessor bindingProcessor = new DataSourceCnbBindingProcessor(); + Map bindingMetadata = new HashMap(); + bindingMetadata.put("kind", "test-kind"); + Map bindingSecret = new HashMap(); + bindingSecret.put("hostname", "10.0.4.35"); + bindingSecret.put("port", "3306"); + bindingSecret.put("db", "some-db"); + bindingSecret.put("username", "some-username"); + bindingSecret.put("password", "some-password"); + CnbBinding binding = new CnbBinding(bindingMetadata, bindingSecret); + Map properties = new HashMap(); + bindingProcessor.process(binding, properties); + assertThat(properties.get("spring.datasource.url")).isEqualTo("jdbc:testscheme://10.0.4.35:3306/some-db?user=some-username&password=some-password"); + assertThat(properties.get("spring.datasource.username")).isEqualTo("some-username"); + assertThat(properties.get("spring.datasource.password")).isEqualTo("some-password"); + assertThat(properties.get("spring.datasource.driver-class-name")).isEqualTo("test.kind.fake.jdbc.Driver"); + } + + @Test + public void processorPropertiesTest() { + DataSourceCnbBindingProcessor bindingProcessor = new DataSourceCnbBindingProcessor(); + CnbBindingProcessorProperties processorProperties = bindingProcessor.getProperties(); + } + +} diff --git a/cnb-bindings-boot/src/test/java/org/springframework/cloud/cnb/boot/DeferredLogTests.java b/cnb-bindings-boot/src/test/java/org/springframework/cloud/cnb/boot/DeferredLogTests.java new file mode 100644 index 0000000..c8a89b7 --- /dev/null +++ b/cnb-bindings-boot/src/test/java/org/springframework/cloud/cnb/boot/DeferredLogTests.java @@ -0,0 +1,194 @@ +/* + * Copyright 2019 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.cloud.cnb.boot; + + +import java.util.List; + +import org.apache.commons.logging.Log; +import org.junit.Test; + +import org.springframework.test.util.ReflectionTestUtils; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +/** + * Tests for {@link DeferredLog}. + * + * @author Phillip Webb + */ +public class DeferredLogTests { + + private DeferredLog deferredLog = new DeferredLog(); + + private Object message = "Message"; + + private Throwable throwable = new IllegalStateException(); + + private Log log = mock(Log.class); + + @Test + public void isTraceEnabled() { + assertThat(this.deferredLog.isTraceEnabled()).isTrue(); + } + + @Test + public void isDebugEnabled() { + assertThat(this.deferredLog.isDebugEnabled()).isTrue(); + } + + @Test + public void isInfoEnabled() { + assertThat(this.deferredLog.isInfoEnabled()).isTrue(); + } + + @Test + public void isWarnEnabled() { + assertThat(this.deferredLog.isWarnEnabled()).isTrue(); + } + + @Test + public void isErrorEnabled() { + assertThat(this.deferredLog.isErrorEnabled()).isTrue(); + } + + @Test + public void isFatalEnabled() { + assertThat(this.deferredLog.isFatalEnabled()).isTrue(); + } + + @Test + public void trace() { + this.deferredLog.trace(this.message); + this.deferredLog.replayTo(this.log); + verify(this.log).trace(this.message, null); + } + + @Test + public void traceWithThrowable() { + this.deferredLog.trace(this.message, this.throwable); + this.deferredLog.replayTo(this.log); + verify(this.log).trace(this.message, this.throwable); + } + + @Test + public void debug() { + this.deferredLog.debug(this.message); + this.deferredLog.replayTo(this.log); + verify(this.log).debug(this.message, null); + } + + @Test + public void debugWithThrowable() { + this.deferredLog.debug(this.message, this.throwable); + this.deferredLog.replayTo(this.log); + verify(this.log).debug(this.message, this.throwable); + } + + @Test + public void info() { + this.deferredLog.info(this.message); + this.deferredLog.replayTo(this.log); + verify(this.log).info(this.message, null); + } + + @Test + public void infoWithThrowable() { + this.deferredLog.info(this.message, this.throwable); + this.deferredLog.replayTo(this.log); + verify(this.log).info(this.message, this.throwable); + } + + @Test + public void warn() { + this.deferredLog.warn(this.message); + this.deferredLog.replayTo(this.log); + verify(this.log).warn(this.message, null); + } + + @Test + public void warnWithThrowable() { + this.deferredLog.warn(this.message, this.throwable); + this.deferredLog.replayTo(this.log); + verify(this.log).warn(this.message, this.throwable); + } + + @Test + public void error() { + this.deferredLog.error(this.message); + this.deferredLog.replayTo(this.log); + verify(this.log).error(this.message, null); + } + + @Test + public void errorWithThrowable() { + this.deferredLog.error(this.message, this.throwable); + this.deferredLog.replayTo(this.log); + verify(this.log).error(this.message, this.throwable); + } + + @Test + public void fatal() { + this.deferredLog.fatal(this.message); + this.deferredLog.replayTo(this.log); + verify(this.log).fatal(this.message, null); + } + + @Test + public void fatalWithThrowable() { + this.deferredLog.fatal(this.message, this.throwable); + this.deferredLog.replayTo(this.log); + verify(this.log).fatal(this.message, this.throwable); + } + + @Test + public void clearsOnReplayTo() { + this.deferredLog.info("1"); + this.deferredLog.fatal("2"); + Log log2 = mock(Log.class); + this.deferredLog.replayTo(this.log); + this.deferredLog.replayTo(log2); + verify(this.log).info("1", null); + verify(this.log).fatal("2", null); + verifyNoMoreInteractions(this.log); + verifyNoInteractions(log2); + } + + @SuppressWarnings("unchecked") + @Test + public void switchTo() { + List lines = (List) ReflectionTestUtils.getField(this.deferredLog, + "lines"); + assertThat(lines).isEmpty(); + + this.deferredLog.error(this.message, this.throwable); + assertThat(lines).hasSize(1); + + this.deferredLog.switchTo(this.log); + assertThat(lines).isEmpty(); + + this.deferredLog.info("Message2"); + assertThat(lines).isEmpty(); + + verify(this.log).error(this.message, this.throwable); + verify(this.log).info("Message2", null); + } +} + diff --git a/cnb-bindings-boot/src/test/java/org/springframework/cloud/cnb/boot/test/EnvMock.java b/cnb-bindings-boot/src/test/java/org/springframework/cloud/cnb/boot/test/EnvMock.java new file mode 100644 index 0000000..8fbc89c --- /dev/null +++ b/cnb-bindings-boot/src/test/java/org/springframework/cloud/cnb/boot/test/EnvMock.java @@ -0,0 +1,54 @@ +/* + * Copyright 2019 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.cloud.cnb.boot.test; + +import java.util.HashMap; +import java.util.Map; + +import mockit.MockUp; + +import org.springframework.cloud.cnb.core.CnbBindings; + + +/** + * @author Emily Casey + **/ +public class EnvMock { + private MockUp mockUp; + + public EnvMock(String cnbBindingsPath) { + + Map env = System.getenv(); + this.mockUp = new MockUp() { + @mockit.Mock + public String getenv(String name) { + if (name.equalsIgnoreCase(CnbBindings.CNB_BINDINGS)) { + return cnbBindingsPath; + } + return env.get(name); + } + + @mockit.Mock + public Map getenv() { + Map finalMap = new HashMap<>(); + finalMap.putAll(env); + finalMap.put("CNB_BINDINGS", cnbBindingsPath); + return finalMap; + } + }; + } +} diff --git a/cnb-bindings-boot/src/test/java/org/springframework/cloud/cnb/boot/test/TestJdbcKind.java b/cnb-bindings-boot/src/test/java/org/springframework/cloud/cnb/boot/test/TestJdbcKind.java new file mode 100644 index 0000000..7944d1c --- /dev/null +++ b/cnb-bindings-boot/src/test/java/org/springframework/cloud/cnb/boot/test/TestJdbcKind.java @@ -0,0 +1,40 @@ +/* + * Copyright 2019 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.cloud.cnb.boot.test; + +import org.springframework.cloud.cnb.core.CnbBinding; +import org.springframework.cloud.cnb.jdbc.JdbcKind; + +public class TestJdbcKind implements JdbcKind { + + @Override + public boolean forBinding(CnbBinding binding) { + if (binding.getKind().equals("test-kind")) { + return true; + } + return false; + } + + @Override + public String getScheme() { + return "testscheme"; + } + + @Override + public String getDriverClassName() { + return "test.kind.fake.jdbc.Driver"; + } +} diff --git a/cnb-bindings-boot/src/test/resources/META-INF/services/org.springframework.cloud.cnb.jdbc.JdbcKind b/cnb-bindings-boot/src/test/resources/META-INF/services/org.springframework.cloud.cnb.jdbc.JdbcKind new file mode 100644 index 0000000..112161c --- /dev/null +++ b/cnb-bindings-boot/src/test/resources/META-INF/services/org.springframework.cloud.cnb.jdbc.JdbcKind @@ -0,0 +1 @@ +org.springframework.cloud.cnb.boot.test.TestJdbcKind \ No newline at end of file diff --git a/cnb-bindings-boot/src/test/resources/test-bindings/p-mysql/metadata/kind b/cnb-bindings-boot/src/test/resources/test-bindings/p-mysql/metadata/kind new file mode 100644 index 0000000..0d46ca3 --- /dev/null +++ b/cnb-bindings-boot/src/test/resources/test-bindings/p-mysql/metadata/kind @@ -0,0 +1 @@ +mysql \ No newline at end of file diff --git a/cnb-bindings-boot/src/test/resources/test-bindings/p-mysql/metadata/provider b/cnb-bindings-boot/src/test/resources/test-bindings/p-mysql/metadata/provider new file mode 100644 index 0000000..17c9ec1 --- /dev/null +++ b/cnb-bindings-boot/src/test/resources/test-bindings/p-mysql/metadata/provider @@ -0,0 +1 @@ +p-mysql \ No newline at end of file diff --git a/cnb-bindings-boot/src/test/resources/test-bindings/p-mysql/metadata/tags b/cnb-bindings-boot/src/test/resources/test-bindings/p-mysql/metadata/tags new file mode 100644 index 0000000..06a445d --- /dev/null +++ b/cnb-bindings-boot/src/test/resources/test-bindings/p-mysql/metadata/tags @@ -0,0 +1 @@ +mysql,relational \ No newline at end of file diff --git a/cnb-bindings-boot/src/test/resources/test-bindings/p-mysql/secret/db b/cnb-bindings-boot/src/test/resources/test-bindings/p-mysql/secret/db new file mode 100644 index 0000000..fe26725 --- /dev/null +++ b/cnb-bindings-boot/src/test/resources/test-bindings/p-mysql/secret/db @@ -0,0 +1 @@ +mysql_name \ No newline at end of file diff --git a/cnb-bindings-boot/src/test/resources/test-bindings/p-mysql/secret/hostname b/cnb-bindings-boot/src/test/resources/test-bindings/p-mysql/secret/hostname new file mode 100644 index 0000000..bdcbc7f --- /dev/null +++ b/cnb-bindings-boot/src/test/resources/test-bindings/p-mysql/secret/hostname @@ -0,0 +1 @@ +10.0.4.35 \ No newline at end of file diff --git a/cnb-bindings-boot/src/test/resources/test-bindings/p-mysql/secret/password b/cnb-bindings-boot/src/test/resources/test-bindings/p-mysql/secret/password new file mode 100644 index 0000000..d297279 --- /dev/null +++ b/cnb-bindings-boot/src/test/resources/test-bindings/p-mysql/secret/password @@ -0,0 +1 @@ +mysql_password \ No newline at end of file diff --git a/cnb-bindings-boot/src/test/resources/test-bindings/p-mysql/secret/port b/cnb-bindings-boot/src/test/resources/test-bindings/p-mysql/secret/port new file mode 100644 index 0000000..080d920 --- /dev/null +++ b/cnb-bindings-boot/src/test/resources/test-bindings/p-mysql/secret/port @@ -0,0 +1 @@ +3306 \ No newline at end of file diff --git a/cnb-bindings-boot/src/test/resources/test-bindings/p-mysql/secret/username b/cnb-bindings-boot/src/test/resources/test-bindings/p-mysql/secret/username new file mode 100644 index 0000000..1dc5c4a --- /dev/null +++ b/cnb-bindings-boot/src/test/resources/test-bindings/p-mysql/secret/username @@ -0,0 +1 @@ +mysql_username \ No newline at end of file diff --git a/cnb-bindings-jdbc/pom.xml b/cnb-bindings-jdbc/pom.xml new file mode 100644 index 0000000..034c8d2 --- /dev/null +++ b/cnb-bindings-jdbc/pom.xml @@ -0,0 +1,32 @@ + + + 4.0.0 + cnb-bindings-jdbc + jar + CNB Bindings JDBC + CNB Bindings JDBC Support Library + + org.springframework.cloud + cnb-bindings-parent + 0.0.1.BUILD-SNAPSHOT + + + + + org.springframework.cloud + cnb-bindings + 0.0.1.BUILD-SNAPSHOT + + + + org.mariadb.jdbc + mariadb-java-client + test + + + + org.springframework.boot + spring-boot-starter-test + + + diff --git a/cnb-bindings-jdbc/src/main/java/org/springframework/cloud/cnb/jdbc/JdbcKind.java b/cnb-bindings-jdbc/src/main/java/org/springframework/cloud/cnb/jdbc/JdbcKind.java new file mode 100644 index 0000000..2e8f238 --- /dev/null +++ b/cnb-bindings-jdbc/src/main/java/org/springframework/cloud/cnb/jdbc/JdbcKind.java @@ -0,0 +1,24 @@ +/* + * Copyright 2019 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.cloud.cnb.jdbc; + +import org.springframework.cloud.cnb.core.CnbBinding; + +public interface JdbcKind { + boolean forBinding(CnbBinding binding); + String getScheme(); + String getDriverClassName(); +} diff --git a/cnb-bindings-jdbc/src/main/java/org/springframework/cloud/cnb/jdbc/JdbcUrlCreator.java b/cnb-bindings-jdbc/src/main/java/org/springframework/cloud/cnb/jdbc/JdbcUrlCreator.java new file mode 100644 index 0000000..b00f4ec --- /dev/null +++ b/cnb-bindings-jdbc/src/main/java/org/springframework/cloud/cnb/jdbc/JdbcUrlCreator.java @@ -0,0 +1,92 @@ +/* + * Copyright 2019 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.cloud.cnb.jdbc; + +import java.util.ServiceLoader; + +import org.springframework.cloud.cnb.core.CnbBinding; +import org.springframework.cloud.cnb.core.IllegalBindingException; + + +public class JdbcUrlCreator { + private static final String JDBC_PREFIX = "jdbc:"; + private final CnbBinding binding; + private final JdbcKind kind; + + public static boolean isJDCBBinding(CnbBinding binding) { + ServiceLoader loader = ServiceLoader.load(JdbcKind.class); + for (JdbcKind kind : loader) { + if (kind.forBinding(binding)) { + return true; + } + } + return false; + } + + public JdbcUrlCreator(CnbBinding binding) { + ServiceLoader loader = ServiceLoader.load(JdbcKind.class); + JdbcKind jdbcKind = null; + for (JdbcKind kind : loader) { + if (kind.forBinding(binding)) { + jdbcKind = kind; + break; + } + } + if (jdbcKind == null) { + throw new IllegalBindingException("no matching jdbc kind for binding"); + } + this.kind = jdbcKind; + this.binding = binding; + } + + public String getJdbcUrl() { + return String.format("%s%s://%s/%s%s", JDBC_PREFIX, kind.getScheme(), + buildHost(), + buildPath(), + buildQuery() + ); + } + + public String getDriverClassName() { + return kind.getDriverClassName(); + } + + private String buildHost() { + return String.format("%s:%s", + binding.getSecret().get("hostname"), + binding.getSecret().get("port") + ); + } + + private String buildPath() { + return binding.getSecret().get("db"); + } + + private String buildQuery() { + return String.format("?user=%s&password=%s", + binding.getSecret().get("username"), + binding.getSecret().get("password") + ); + } + + public String getUsername() { + return binding.getSecret().get("username"); + } + + public String getPassword() { + return binding.getSecret().get("password"); + } +} diff --git a/cnb-bindings-jdbc/src/main/java/org/springframework/cloud/cnb/jdbc/MysqlJdbcKind.java b/cnb-bindings-jdbc/src/main/java/org/springframework/cloud/cnb/jdbc/MysqlJdbcKind.java new file mode 100644 index 0000000..a604571 --- /dev/null +++ b/cnb-bindings-jdbc/src/main/java/org/springframework/cloud/cnb/jdbc/MysqlJdbcKind.java @@ -0,0 +1,51 @@ +/* + * Copyright 2019 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.cloud.cnb.jdbc; + +import org.springframework.cloud.cnb.core.CnbBinding; + +public class MysqlJdbcKind implements JdbcKind{ + + public static final String MYSQL_KIND = "mysql"; + public static final String MYSQL_SCHEME = "mysql"; + + @Override + public boolean forBinding(CnbBinding binding) { + return binding.getKind().equals(MYSQL_KIND); + } + + @Override + public String getScheme() { + return MYSQL_SCHEME; + } + + @Override + public String getDriverClassName() { + String driverClassNameToUse = null; + try { + driverClassNameToUse = "org.mariadb.jdbc.Driver"; + Class.forName(driverClassNameToUse, false, getClass().getClassLoader()); + } catch (ClassNotFoundException e) { + try { + driverClassNameToUse = "com.mysql.cj.jdbc.Driver"; + Class.forName(driverClassNameToUse, false, getClass().getClassLoader()); + } catch (ClassNotFoundException e2) { + return null; + } + } + return driverClassNameToUse; + } +} diff --git a/cnb-bindings-jdbc/src/main/resources/META-INF/services/org.springframework.cloud.cnb.jdbc.JdbcKind b/cnb-bindings-jdbc/src/main/resources/META-INF/services/org.springframework.cloud.cnb.jdbc.JdbcKind new file mode 100644 index 0000000..b9eeac1 --- /dev/null +++ b/cnb-bindings-jdbc/src/main/resources/META-INF/services/org.springframework.cloud.cnb.jdbc.JdbcKind @@ -0,0 +1 @@ +org.springframework.cloud.cnb.jdbc.MysqlJdbcKind \ No newline at end of file diff --git a/cnb-bindings-jdbc/src/test/java/org/springframework/cloud/cnb/jdbc/JdbcUrlCreatorTest.java b/cnb-bindings-jdbc/src/test/java/org/springframework/cloud/cnb/jdbc/JdbcUrlCreatorTest.java new file mode 100644 index 0000000..6d3426a --- /dev/null +++ b/cnb-bindings-jdbc/src/test/java/org/springframework/cloud/cnb/jdbc/JdbcUrlCreatorTest.java @@ -0,0 +1,45 @@ +/* + * Copyright 2019 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.cloud.cnb.jdbc; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Test; + +import org.springframework.cloud.cnb.core.CnbBinding; + +import static org.assertj.core.api.Assertions.assertThat; + + +public class JdbcUrlCreatorTest { + + @Test + public void testJdbcUrlCreator() { + Map mysqlMetadata = new HashMap(); + mysqlMetadata.put("kind", "mysql"); + Map mysqlSecret = new HashMap(); + mysqlSecret.put("hostname", "10.0.4.35"); + mysqlSecret.put("port", "3306"); + mysqlSecret.put("db", "some-db"); + mysqlSecret.put("username", "some-username"); + mysqlSecret.put("password", "some-password"); + CnbBinding mysqlBinding = new CnbBinding(mysqlMetadata, mysqlSecret); + JdbcUrlCreator jdbcUrlCreator = new JdbcUrlCreator(mysqlBinding); + String url = jdbcUrlCreator.getJdbcUrl(); + assertThat(url).isEqualTo("jdbc:mysql://10.0.4.35:3306/some-db?user=some-username&password=some-password"); + } +} diff --git a/cnb-bindings/pom.xml b/cnb-bindings/pom.xml new file mode 100644 index 0000000..83fd00a --- /dev/null +++ b/cnb-bindings/pom.xml @@ -0,0 +1,51 @@ + + + 4.0.0 + cnb-bindings + jar + CNB Bindings + Java CNB Bindings Core Library + + org.springframework.cloud + cnb-bindings-parent + 0.0.1.BUILD-SNAPSHOT + + + + + com.fasterxml.jackson.core + jackson-core + + + com.fasterxml.jackson.core + jackson-databind + + + org.springframework.boot + spring-boot-starter-test + test + + + org.jmockit + jmockit + test + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.1.1 + + + + test-jar + + + + + + + diff --git a/cnb-bindings/src/main/java/org/springframework/cloud/cnb/core/CNBBindingsSingleton.java b/cnb-bindings/src/main/java/org/springframework/cloud/cnb/core/CNBBindingsSingleton.java new file mode 100644 index 0000000..ae58337 --- /dev/null +++ b/cnb-bindings/src/main/java/org/springframework/cloud/cnb/core/CNBBindingsSingleton.java @@ -0,0 +1,37 @@ +/* + * Copyright 2019 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.cloud.cnb.core; + +/** + * JVM singleton for cases where you want to avoid reparsing the JSON per instance of {@code CfEnv} + * @author Mark Pollack + */ +public final class CNBBindingsSingleton { + + private static CnbBindings INSTANCE; + + private CNBBindingsSingleton() { + + } + + public synchronized static CnbBindings getCnbBindingsInstance() { + if (INSTANCE == null) { + INSTANCE = new CnbBindings(); + } + return INSTANCE; + } + +} diff --git a/cnb-bindings/src/main/java/org/springframework/cloud/cnb/core/CnbBinding.java b/cnb-bindings/src/main/java/org/springframework/cloud/cnb/core/CnbBinding.java new file mode 100644 index 0000000..915ee5d --- /dev/null +++ b/cnb-bindings/src/main/java/org/springframework/cloud/cnb/core/CnbBinding.java @@ -0,0 +1,95 @@ +/* + * Copyright 2019 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.cloud.cnb.core; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; + +public class CnbBinding { + + private final Map metadata; + private final Map secret; + + private String name; + private File bindingDir; + + public CnbBinding(Map metadata, Map secret) { + this.metadata = metadata; + this.secret = secret; + } + + public CnbBinding(File bindingDir) { + this.bindingDir = bindingDir; + this.metadata = subDirToMap("metadata"); + this.secret = subDirToMap("secret"); + this.name = bindingDir.getName(); + } + + public String getName() { + return this.name; + } + + public Map getSecret() { + return this.secret; + } + + public Map getAllMetadata() { + return this.metadata; + } + + public String getKind() { + return this.metadata.get("kind"); + } + + public String getProvider() { + return this.metadata.get("provider"); + } + + public String[] getTags() { + String tagsVal = this.metadata.get("tags"); + String[] tags = tagsVal.split(","); + return tags; + } + + private Map subDirToMap(String subdir) { + Path subDirPath = Paths.get(this.bindingDir.getPath(), subdir); + File subDir = subDirPath.toFile().getAbsoluteFile(); + if (!subDir.isDirectory()) { + throw new IllegalBindingException(subDir + "is not a directory"); + } + Map secret = new HashMap(); + for (File file : subDir.listFiles()) { + if (file.isDirectory()) { + continue; + } + secret.put(file.getName(), readFile(file)); + } + return secret; + } + + private String readFile(File file) { + try { + return new String(Files.readAllBytes(file.toPath())).trim(); + } catch (IOException e) { + throw new IllegalBindingException(e); + } + } +} diff --git a/cnb-bindings/src/main/java/org/springframework/cloud/cnb/core/CnbBindings.java b/cnb-bindings/src/main/java/org/springframework/cloud/cnb/core/CnbBindings.java new file mode 100644 index 0000000..ee82fee --- /dev/null +++ b/cnb-bindings/src/main/java/org/springframework/cloud/cnb/core/CnbBindings.java @@ -0,0 +1,69 @@ +/* + * Copyright 2019 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.cloud.cnb.core; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +/** + * Provides access to CNB Bindings. + * + * @author Emily Casey + */ +public class CnbBindings { + + public static final String CNB_BINDINGS = "CNB_BINDINGS"; + + private List bindings = new ArrayList<>(); + + public CnbBindings() { + String cnbBindingsDir = System.getenv(CNB_BINDINGS); + if (cnbBindingsDir == null) { + return; + } + File bindingsDir = new File(cnbBindingsDir); + if (!bindingsDir.exists()) { + return; + } + if (!bindingsDir.isDirectory()) { + throw new IllegalStateException(String.format("CNB_BINDINGS '%s' is not a directory", bindingsDir.toString())); + } + for (File file : bindingsDir.listFiles()) { + if (!file.isDirectory()) { + continue; + } + this.bindings.add(new CnbBinding(file)); + } + } + + public List findAllBindings() { + return this.bindings; + } + + public boolean hasBindings() { + return System.getenv(CNB_BINDINGS) != null; + } + + public CnbBinding findBindingByName(String name) { + for (CnbBinding binding : this.bindings) { + if (binding.getName().equals(name)) { + return binding; + } + } + return null; + } +} diff --git a/cnb-bindings/src/main/java/org/springframework/cloud/cnb/core/IllegalBindingException.java b/cnb-bindings/src/main/java/org/springframework/cloud/cnb/core/IllegalBindingException.java new file mode 100644 index 0000000..e90a353 --- /dev/null +++ b/cnb-bindings/src/main/java/org/springframework/cloud/cnb/core/IllegalBindingException.java @@ -0,0 +1,32 @@ +/* + * Copyright 2019 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.cloud.cnb.core; + +public class IllegalBindingException extends RuntimeException { + + public IllegalBindingException(String message) { + super(message); + } + + public IllegalBindingException(Throwable cause) { + super(cause); + } + + public IllegalBindingException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/cnb-bindings/src/test/java/org/springframework/cloud/cnb/core/CnbBindingsHasBindingsTests.java b/cnb-bindings/src/test/java/org/springframework/cloud/cnb/core/CnbBindingsHasBindingsTests.java new file mode 100644 index 0000000..6115885 --- /dev/null +++ b/cnb-bindings/src/test/java/org/springframework/cloud/cnb/core/CnbBindingsHasBindingsTests.java @@ -0,0 +1,42 @@ +/* + * Copyright 2019 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.cloud.cnb.core; + + +import org.junit.Ignore; +import org.junit.Test; + +import org.springframework.cloud.cnb.core.test.EnvMock; + +import static org.assertj.core.api.Assertions.assertThat; + + +public class CnbBindingsHasBindingsTests { + + @Test + public void testHasBindings() { + new EnvMock("some/path"); + CnbBindings cnbBindings = new CnbBindings(); + assertThat(cnbBindings.hasBindings()).isTrue(); + } + + @Test + @Ignore + public void testHasBindingsFalse() { + CnbBindings cnbBindings = new CnbBindings(); + assertThat(cnbBindings.hasBindings()).isFalse(); + } +} diff --git a/cnb-bindings/src/test/java/org/springframework/cloud/cnb/core/CnbBindingsTests.java b/cnb-bindings/src/test/java/org/springframework/cloud/cnb/core/CnbBindingsTests.java new file mode 100644 index 0000000..da96667 --- /dev/null +++ b/cnb-bindings/src/test/java/org/springframework/cloud/cnb/core/CnbBindingsTests.java @@ -0,0 +1,63 @@ +/* + * Copyright 2019 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.cloud.cnb.core; + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.Map; + +import org.junit.Test; + +import org.springframework.cloud.cnb.core.test.EnvMock; + +import static org.assertj.core.api.Assertions.assertThat; + +public class CnbBindingsTests { + + @Test + public void testBindings() { + Path resourceDirectory = Paths.get("src", "test", "resources", "test-bindings"); + String bindingsDir = resourceDirectory.toFile().getAbsolutePath(); + + new EnvMock(bindingsDir); + + CnbBindings cnbBindings = new CnbBindings(); + + List bindings = cnbBindings.findAllBindings(); + assertThat(bindings.size()).isEqualTo(1); + + CnbBinding mysqlBinding = cnbBindings.findBindingByName("p-mysql"); + Map mysqlSecret = mysqlBinding.getSecret(); + assertThat(mysqlSecret).containsEntry("hostname", "10.0.4.35") + .containsEntry("port", "3306") + .containsEntry("name", "mysql_name") + .containsEntry("username", "mysql_username") + .containsEntry("password", "mysql_password") + .containsEntry("uri", + "mysql://mysql_username:mysql_password@10.0.4.35:3306/cf_2e23d10a_8738_8c3c_66cf_13e44422698c?reconnect=true") + .containsEntry("jdbcUrl", + "jdbc:mysql://10.0.4.35:3306/cf_2e23d10a_8738_8c3c_66cf_13e44422698c?user=mysql_username&password=mysql_password"); + Map mysqlMetadata = mysqlBinding.getAllMetadata(); + assertThat(mysqlMetadata).containsEntry("kind", "mysql") + .containsEntry("provider", "p-mysql") + .containsEntry("tags", "mysql,relational"); + assertThat(mysqlBinding.getKind()).isEqualTo("mysql"); + assertThat(mysqlBinding.getProvider()).isEqualTo("p-mysql"); + assertThat(mysqlBinding.getTags()).contains("mysql", "relational"); + } + +} diff --git a/cnb-bindings/src/test/java/org/springframework/cloud/cnb/core/test/EnvMock.java b/cnb-bindings/src/test/java/org/springframework/cloud/cnb/core/test/EnvMock.java new file mode 100644 index 0000000..1a801a1 --- /dev/null +++ b/cnb-bindings/src/test/java/org/springframework/cloud/cnb/core/test/EnvMock.java @@ -0,0 +1,55 @@ +/* + * Copyright 2019 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.cloud.cnb.core.test; + +import java.util.HashMap; +import java.util.Map; + +import mockit.MockUp; + +import org.springframework.cloud.cnb.core.CnbBindings; + + + +/** + * @author Emily Casey + **/ +public class EnvMock { + private MockUp mockUp; + + public EnvMock(String cnbBindingsPath) { + + Map env = System.getenv(); + this.mockUp = new MockUp() { + @mockit.Mock + public String getenv(String name) { + if (name.equalsIgnoreCase(CnbBindings.CNB_BINDINGS)) { + return cnbBindingsPath; + } + return env.get(name); + } + + @mockit.Mock + public Map getenv() { + Map finalMap = new HashMap<>(); + finalMap.putAll(env); + finalMap.put("CNB_BINDINGS", cnbBindingsPath); + return finalMap; + } + }; + } +} diff --git a/cnb-bindings/src/test/resources/empty-binding/.gitkeep b/cnb-bindings/src/test/resources/empty-binding/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/cnb-bindings/src/test/resources/test-bindings/p-mysql/metadata/kind b/cnb-bindings/src/test/resources/test-bindings/p-mysql/metadata/kind new file mode 100644 index 0000000..0d46ca3 --- /dev/null +++ b/cnb-bindings/src/test/resources/test-bindings/p-mysql/metadata/kind @@ -0,0 +1 @@ +mysql \ No newline at end of file diff --git a/cnb-bindings/src/test/resources/test-bindings/p-mysql/metadata/provider b/cnb-bindings/src/test/resources/test-bindings/p-mysql/metadata/provider new file mode 100644 index 0000000..17c9ec1 --- /dev/null +++ b/cnb-bindings/src/test/resources/test-bindings/p-mysql/metadata/provider @@ -0,0 +1 @@ +p-mysql \ No newline at end of file diff --git a/cnb-bindings/src/test/resources/test-bindings/p-mysql/metadata/tags b/cnb-bindings/src/test/resources/test-bindings/p-mysql/metadata/tags new file mode 100644 index 0000000..06a445d --- /dev/null +++ b/cnb-bindings/src/test/resources/test-bindings/p-mysql/metadata/tags @@ -0,0 +1 @@ +mysql,relational \ No newline at end of file diff --git a/cnb-bindings/src/test/resources/test-bindings/p-mysql/secret/hostname b/cnb-bindings/src/test/resources/test-bindings/p-mysql/secret/hostname new file mode 100644 index 0000000..bdcbc7f --- /dev/null +++ b/cnb-bindings/src/test/resources/test-bindings/p-mysql/secret/hostname @@ -0,0 +1 @@ +10.0.4.35 \ No newline at end of file diff --git a/cnb-bindings/src/test/resources/test-bindings/p-mysql/secret/jdbcUrl b/cnb-bindings/src/test/resources/test-bindings/p-mysql/secret/jdbcUrl new file mode 100644 index 0000000..4873058 --- /dev/null +++ b/cnb-bindings/src/test/resources/test-bindings/p-mysql/secret/jdbcUrl @@ -0,0 +1 @@ +jdbc:mysql://10.0.4.35:3306/cf_2e23d10a_8738_8c3c_66cf_13e44422698c?user=mysql_username&password=mysql_password \ No newline at end of file diff --git a/cnb-bindings/src/test/resources/test-bindings/p-mysql/secret/name b/cnb-bindings/src/test/resources/test-bindings/p-mysql/secret/name new file mode 100644 index 0000000..fe26725 --- /dev/null +++ b/cnb-bindings/src/test/resources/test-bindings/p-mysql/secret/name @@ -0,0 +1 @@ +mysql_name \ No newline at end of file diff --git a/cnb-bindings/src/test/resources/test-bindings/p-mysql/secret/password b/cnb-bindings/src/test/resources/test-bindings/p-mysql/secret/password new file mode 100644 index 0000000..d297279 --- /dev/null +++ b/cnb-bindings/src/test/resources/test-bindings/p-mysql/secret/password @@ -0,0 +1 @@ +mysql_password \ No newline at end of file diff --git a/cnb-bindings/src/test/resources/test-bindings/p-mysql/secret/port b/cnb-bindings/src/test/resources/test-bindings/p-mysql/secret/port new file mode 100644 index 0000000..080d920 --- /dev/null +++ b/cnb-bindings/src/test/resources/test-bindings/p-mysql/secret/port @@ -0,0 +1 @@ +3306 \ No newline at end of file diff --git a/cnb-bindings/src/test/resources/test-bindings/p-mysql/secret/uri b/cnb-bindings/src/test/resources/test-bindings/p-mysql/secret/uri new file mode 100644 index 0000000..333992c --- /dev/null +++ b/cnb-bindings/src/test/resources/test-bindings/p-mysql/secret/uri @@ -0,0 +1 @@ +mysql://mysql_username:mysql_password@10.0.4.35:3306/cf_2e23d10a_8738_8c3c_66cf_13e44422698c?reconnect=true \ No newline at end of file diff --git a/cnb-bindings/src/test/resources/test-bindings/p-mysql/secret/username b/cnb-bindings/src/test/resources/test-bindings/p-mysql/secret/username new file mode 100644 index 0000000..1dc5c4a --- /dev/null +++ b/cnb-bindings/src/test/resources/test-bindings/p-mysql/secret/username @@ -0,0 +1 @@ +mysql_username \ No newline at end of file diff --git a/mvnw b/mvnw new file mode 100755 index 0000000..5bf251c --- /dev/null +++ b/mvnw @@ -0,0 +1,225 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven2 Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Migwn, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" + # TODO classpath? +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +echo $MAVEN_PROJECTBASEDIR +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/mvnw.cmd b/mvnw.cmd new file mode 100644 index 0000000..019bd74 --- /dev/null +++ b/mvnw.cmd @@ -0,0 +1,143 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven2 Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" + +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..b8bcf4e --- /dev/null +++ b/pom.xml @@ -0,0 +1,345 @@ + + + 4.0.0 + org.springframework.cloud + cnb-bindings-parent + 0.0.1.BUILD-SNAPSHOT + pom + + CNB Bindings Parent + Java Library for Accessing CNB Bindings + https://github.com/spring-cloud-incubator/cnb-bindings + + + + Apache License, Version 2.0 + https://www.apache.org/licenses/LICENSE-2.0.txt + repo + A business-friendly OSS license + + + + + https://github.com/spring-cloud-incubator/cnb-bindings + scm:git:git://github.com/spring-cloud-incubator/cnb-bindings.git + scm:git:ssh://git@github.com/spring-cloud-incubator/cnb-bindings.git + HEAD + + + + Pivotal Software, Inc. + https://www.spring.io + + + + + UTF-8 + UTF-8 + 1.8 + ${java.version} + ${java.version} + + 2.2.6.RELEASE + 1.24 + + + 3.8.0 + 0.7.9 + 2.20 + 3.0.2 + -Xdoclint:none + 2.10.1 + 1.5.6 + 1.5.0-alpha.11 + 2.0.15 + 2.1.0 + 5.0-all + 1.8 + 1.0b3 + 1.8.1 + 3.2.10 + 1.9.1 + + false + + + + cnb-bindings + cnb-bindings-jdbc + cnb-bindings-boot + + + + + + Emily Casey + ekcasey + + + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + + org.jmockit + jmockit + ${jmockit.version} + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${maven.compiler.source} + ${maven.compiler.target} + -parameters + + + + org.apache.maven.plugins + maven-source-plugin + + + attach-sources + + jar + + + + + + maven-javadoc-plugin + 3.0.1 + + + javadoc + + jar + + package + + + + true + + + + org.apache.maven.plugins + maven-surefire-plugin + ${surefire-maven-plugin.version} + + + **/*Tests.java + **/*Test.java + + + **/Abstract*.java + + + ${argLine} + + + + org.jacoco + jacoco-maven-plugin + + + agent + + prepare-agent + + + + report + test + + report + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 3.0.0 + + + com.puppycrawl.tools + checkstyle + 8.16 + + + + src/checkstyle/checkstyle.xml + true + + + + validate + validate + + check + + + + + + + + + org.sonarsource.scanner.maven + sonar-maven-plugin + ${sonar-maven-plugin.version} + + + org.jacoco + jacoco-maven-plugin + ${jacoco-maven-plugin.version} + + + org.apache.maven.plugins + maven-jar-plugin + 3.0.2 + + + org.apache.maven.plugins + maven-source-plugin + 3.0.1 + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.4 + + + attach-javadocs + + jar + + + ${javadoc.opts} + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 3.0.0 + + + com.puppycrawl.tools + checkstyle + 7.6.1 + + + + + + + + + + org.apache.maven.plugins + maven-jxr-plugin + 2.5 + + + + + + spring + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/libs-snapshot + + true + + + + spring-milestones + Spring Milestones + https://repo.spring.io/libs-milestone-local + + false + + + + spring-releases + Spring Releases + https://repo.spring.io/release + + false + + + + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/libs-snapshot-local + + true + + + + spring-milestones + Spring Milestones + https://repo.spring.io/libs-milestone-local + + false + + + + + + coverage + + + env.TRAVIS + true + + + + + + org.jacoco + jacoco-maven-plugin + 0.7.9 + + + agent + + prepare-agent + + + + report + test + + report + + + + + + + + + diff --git a/src/checkstyle/checkstyle-header.txt b/src/checkstyle/checkstyle-header.txt new file mode 100644 index 0000000..bc142db --- /dev/null +++ b/src/checkstyle/checkstyle-header.txt @@ -0,0 +1,15 @@ +^\Q/*\E$ +^\Q * Copyright \E(20\d\d\-)?20\d\d\Q the original author or authors.\E$ +^\Q *\E$ +^\Q * Licensed under the Apache License, Version 2.0 (the "License");\E$ +^\Q * you may not use this file except in compliance with the License.\E$ +^\Q * You may obtain a copy of the License at\E$ +^\Q *\E$ +^\Q * http://www.apache.org/licenses/LICENSE-2.0\E$ +^\Q *\E$ +^\Q * Unless required by applicable law or agreed to in writing, software\E$ +^\Q * distributed under the License is distributed on an "AS IS" BASIS,\E$ +^\Q * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\E$ +^\Q * See the License for the specific language governing permissions and\E$ +^\Q * limitations under the License.\E$ +^\Q */\E$ diff --git a/src/checkstyle/checkstyle.xml b/src/checkstyle/checkstyle.xml new file mode 100644 index 0000000..348389d --- /dev/null +++ b/src/checkstyle/checkstyle.xml @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/eclipse/eclipse-code-formatter.xml b/src/eclipse/eclipse-code-formatter.xml new file mode 100644 index 0000000..8dc3287 --- /dev/null +++ b/src/eclipse/eclipse-code-formatter.xml @@ -0,0 +1,397 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/eclipse/eclipse.importorder b/src/eclipse/eclipse.importorder new file mode 100644 index 0000000..080e73d --- /dev/null +++ b/src/eclipse/eclipse.importorder @@ -0,0 +1,7 @@ +#Organize Import Order +#Wed Apr 26 12:53:22 EDT 2017 +4=\# +3=org.springframework +2= +1=javax +0=java