20 changed files with 0 additions and 1241 deletions
@ -1,33 +0,0 @@
@@ -1,33 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||
<modelVersion>4.0.0</modelVersion> |
||||
<parent> |
||||
<groupId>org.springframework.boot</groupId> |
||||
<artifactId>spring-boot-tools</artifactId> |
||||
<version>1.2.0.BUILD-SNAPSHOT</version> |
||||
</parent> |
||||
<artifactId>spring-boot-configuration-metadata</artifactId> |
||||
<name>Spring Boot Configuration Metadata</name> |
||||
<description>Spring Boot Configuration Metadata</description> |
||||
<url>http://projects.spring.io/spring-boot/</url> |
||||
<organization> |
||||
<name>Pivotal Software, Inc.</name> |
||||
<url>http://www.spring.io</url> |
||||
</organization> |
||||
<properties> |
||||
<main.basedir>${basedir}/../..</main.basedir> |
||||
</properties> |
||||
<dependencies> |
||||
<dependency> |
||||
<groupId>org.json</groupId> |
||||
<artifactId>json</artifactId> |
||||
</dependency> |
||||
|
||||
<dependency> |
||||
<groupId>org.springframework</groupId> |
||||
<artifactId>spring-core</artifactId> |
||||
<scope>test</scope> |
||||
</dependency> |
||||
</dependencies> |
||||
</project> |
||||
@ -1,68 +0,0 @@
@@ -1,68 +0,0 @@
|
||||
/* |
||||
* Copyright 2012-2014 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.configurationmetadata; |
||||
|
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* Gather a collection of {@link ConfigurationMetadataProperty} that are sharing |
||||
* a common prefix. |
||||
* |
||||
* @author Stephane Nicoll |
||||
* @since 1.2.0 |
||||
*/ |
||||
public class ConfigurationMetadataGroup { |
||||
|
||||
private final String id; |
||||
|
||||
private final Map<String, ConfigurationMetadataSource> sources = |
||||
new HashMap<String, ConfigurationMetadataSource>(); |
||||
|
||||
private final Map<String, ConfigurationMetadataProperty> properties = |
||||
new HashMap<String, ConfigurationMetadataProperty>(); |
||||
|
||||
public ConfigurationMetadataGroup(String id) { |
||||
this.id = id; |
||||
} |
||||
|
||||
/** |
||||
* Return the id of the group. |
||||
*/ |
||||
public String getId() { |
||||
return this.id; |
||||
} |
||||
|
||||
/** |
||||
* Return the {@link ConfigurationMetadataSource sources} defining |
||||
* the properties of this group. |
||||
*/ |
||||
public Map<String, ConfigurationMetadataSource> getSources() { |
||||
return this.sources; |
||||
} |
||||
|
||||
/** |
||||
* Return the {@link ConfigurationMetadataProperty properties} defined in this group. |
||||
* <p>A property may appear more than once for a given source, potentially with conflicting |
||||
* type or documentation. This is a "merged" view of the properties of this group. |
||||
* @see ConfigurationMetadataSource#getProperties() |
||||
*/ |
||||
public Map<String, ConfigurationMetadataProperty> getProperties() { |
||||
return this.properties; |
||||
} |
||||
|
||||
} |
||||
@ -1,58 +0,0 @@
@@ -1,58 +0,0 @@
|
||||
/* |
||||
* Copyright 2012-2014 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.configurationmetadata; |
||||
|
||||
/** |
||||
* An extension of {@link ConfigurationMetadataProperty} that provides the |
||||
* a reference to its source. |
||||
* |
||||
* @author Stephane Nicoll |
||||
* @since 1.2.0 |
||||
*/ |
||||
class ConfigurationMetadataItem extends ConfigurationMetadataProperty { |
||||
|
||||
private String sourceType; |
||||
|
||||
private String sourceMethod; |
||||
|
||||
/** |
||||
* The class name of the source that contributed this property. For example, if the property |
||||
* was from a class annotated with {@code @ConfigurationProperties} this attribute would |
||||
* contain the fully qualified name of that class. |
||||
*/ |
||||
public String getSourceType() { |
||||
return this.sourceType; |
||||
} |
||||
|
||||
public void setSourceType(String sourceType) { |
||||
this.sourceType = sourceType; |
||||
} |
||||
|
||||
/** |
||||
* The full name of the method (include parenthesis and argument types) that contributed this |
||||
* property. For example, the name of a getter in a {@code @ConfigurationProperties} annotated |
||||
* class. |
||||
*/ |
||||
public String getSourceMethod() { |
||||
return this.sourceMethod; |
||||
} |
||||
|
||||
public void setSourceMethod(String sourceMethod) { |
||||
this.sourceMethod = sourceMethod; |
||||
} |
||||
|
||||
} |
||||
@ -1,113 +0,0 @@
@@ -1,113 +0,0 @@
|
||||
/* |
||||
* Copyright 2012-2014 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.configurationmetadata; |
||||
|
||||
/** |
||||
* Define a configuration item. |
||||
* |
||||
* @author Stephane Nicoll |
||||
* @since 1.2.0 |
||||
*/ |
||||
public class ConfigurationMetadataProperty { |
||||
|
||||
private String id; |
||||
|
||||
private String name; |
||||
|
||||
private String type; |
||||
|
||||
private String description; |
||||
|
||||
private Object defaultValue; |
||||
|
||||
private boolean deprecated; |
||||
|
||||
/** |
||||
* The full identifier of the property, in lowercase dashed form (e.g. my.group.simple-property) |
||||
*/ |
||||
public String getId() { |
||||
return this.id; |
||||
} |
||||
|
||||
public void setId(String id) { |
||||
this.id = id; |
||||
} |
||||
|
||||
/** |
||||
* The name of the property, in lowercase dashed form (e.g. simple-property). If this item |
||||
* does not belong to any group, the id is returned. |
||||
*/ |
||||
public String getName() { |
||||
return this.name; |
||||
} |
||||
|
||||
public void setName(String name) { |
||||
this.name = name; |
||||
} |
||||
|
||||
/** |
||||
* The class name of the data type of the property. For example, {@code java.lang.String}. |
||||
* <p>For consistency, the type of a primitive is specified using its wrapper counterpart, |
||||
* i.e. {@code boolean} becomes {@code java.lang.Boolean}. Collections type are harmonized |
||||
* to their interface counterpart and defines the actual generic types, i.e. |
||||
* {@code java.util.HashMap<java.lang.String,java.lang.Integer>} becomes |
||||
* {@code java.util.Map<java.lang.String,java.lang.Integer>} |
||||
* <p>Note that this class may be a complex type that gets converted from a String as values |
||||
* are bound. |
||||
*/ |
||||
public String getType() { |
||||
return this.type; |
||||
} |
||||
|
||||
public void setType(String type) { |
||||
this.type = type; |
||||
} |
||||
|
||||
/** |
||||
* A short description of the property, if any. |
||||
*/ |
||||
public String getDescription() { |
||||
return this.description; |
||||
} |
||||
|
||||
public void setDescription(String description) { |
||||
this.description = description; |
||||
} |
||||
|
||||
/** |
||||
* The default value, if any. |
||||
*/ |
||||
public Object getDefaultValue() { |
||||
return this.defaultValue; |
||||
} |
||||
|
||||
public void setDefaultValue(Object defaultValue) { |
||||
this.defaultValue = defaultValue; |
||||
} |
||||
|
||||
/** |
||||
* Specify if the property is deprecated |
||||
*/ |
||||
public boolean isDeprecated() { |
||||
return this.deprecated; |
||||
} |
||||
|
||||
public void setDeprecated(boolean deprecated) { |
||||
this.deprecated = deprecated; |
||||
} |
||||
|
||||
} |
||||
@ -1,46 +0,0 @@
@@ -1,46 +0,0 @@
|
||||
/* |
||||
* Copyright 2012-2014 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.configurationmetadata; |
||||
|
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* A repository of configuration metadata. |
||||
* |
||||
* @author Stephane Nicoll |
||||
* @since 1.2.0 |
||||
*/ |
||||
public interface ConfigurationMetadataRepository { |
||||
|
||||
/** |
||||
* Defines the name of the "root" group, that is the group that |
||||
* gathers all the properties that aren't attached to a specific |
||||
* group. |
||||
*/ |
||||
static final String ROOT_GROUP = "_ROOT_GROUP_"; |
||||
|
||||
/** |
||||
* Return the groups, indexed by id. |
||||
*/ |
||||
Map<String, ConfigurationMetadataGroup> getAllGroups(); |
||||
|
||||
/** |
||||
* Return the properties, indexed by id. |
||||
*/ |
||||
Map<String, ConfigurationMetadataProperty> getAllProperties(); |
||||
|
||||
} |
||||
@ -1,98 +0,0 @@
@@ -1,98 +0,0 @@
|
||||
/* |
||||
* Copyright 2012-2014 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.configurationmetadata; |
||||
|
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.nio.charset.Charset; |
||||
import java.util.Collection; |
||||
|
||||
import org.json.JSONException; |
||||
|
||||
/** |
||||
* Load a {@link ConfigurationMetadataRepository} from the content of arbitrary resource(s). |
||||
* |
||||
* @author Stephane Nicoll |
||||
* @since 1.2.0 |
||||
*/ |
||||
public class ConfigurationMetadataRepositoryJsonLoader { |
||||
|
||||
public static final Charset UTF_8 = Charset.forName("UTF-8"); |
||||
|
||||
private JsonReader reader = new JsonReader(); |
||||
|
||||
|
||||
/** |
||||
* Create a {@link ConfigurationMetadataRepository} with the metadata defined by |
||||
* the specified {@code resources} using {@link #UTF_8}. If the same config |
||||
* metadata items is held within different resources, the first that is loaded is kept. |
||||
*/ |
||||
public ConfigurationMetadataRepository loadAll(Collection<InputStream> resources) throws IOException { |
||||
return loadAll(resources, UTF_8); |
||||
} |
||||
|
||||
/** |
||||
* Create a {@link ConfigurationMetadataRepository} with the metadata defined by |
||||
* the specified {@code resources} using the specified {@link Charset}. If the |
||||
* same config metadata items is held within different resources, the first that |
||||
* is loaded is kept. |
||||
*/ |
||||
public ConfigurationMetadataRepository loadAll(Collection<InputStream> resources, Charset charset) throws IOException { |
||||
if (resources == null) { |
||||
throw new IllegalArgumentException("Resources must not be null."); |
||||
} |
||||
if (resources.size() == 1) { |
||||
return load(resources.iterator().next(), charset); |
||||
} |
||||
|
||||
SimpleConfigurationMetadataRepository repository = new SimpleConfigurationMetadataRepository(); |
||||
for (InputStream resource : resources) { |
||||
SimpleConfigurationMetadataRepository repo = load(resource, charset); |
||||
repository.include(repo); |
||||
} |
||||
return repository; |
||||
} |
||||
|
||||
private SimpleConfigurationMetadataRepository load(InputStream stream, Charset charset) throws IOException { |
||||
try { |
||||
RawConfigurationMetadata metadata = this.reader.read(stream, charset); |
||||
return create(metadata); |
||||
} |
||||
catch (IOException e) { |
||||
throw new IllegalArgumentException("Failed to read configuration metadata", e); |
||||
} |
||||
catch (JSONException e) { |
||||
throw new IllegalArgumentException("Invalid configuration metadata document", e); |
||||
} |
||||
} |
||||
|
||||
private SimpleConfigurationMetadataRepository create(RawConfigurationMetadata metadata) { |
||||
SimpleConfigurationMetadataRepository repository = new SimpleConfigurationMetadataRepository(); |
||||
repository.add(metadata.getSources()); |
||||
for (ConfigurationMetadataItem item : metadata.getItems()) { |
||||
ConfigurationMetadataSource source = null; |
||||
String sourceType = item.getSourceType(); |
||||
if (sourceType != null) { |
||||
source = metadata.getSource(sourceType); |
||||
} |
||||
repository.add(item, source); |
||||
} |
||||
return repository; |
||||
} |
||||
|
||||
} |
||||
|
||||
@ -1,110 +0,0 @@
@@ -1,110 +0,0 @@
|
||||
/* |
||||
* Copyright 2012-2014 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.configurationmetadata; |
||||
|
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* A source of configuration metadata. Also defines where |
||||
* the source is declared, for instance if it is defined |
||||
* as a {@code @Bean}. |
||||
* |
||||
* @author Stephane Nicoll |
||||
* @since 1.2.0 |
||||
*/ |
||||
public class ConfigurationMetadataSource { |
||||
|
||||
private String groupId; |
||||
|
||||
private String type; |
||||
|
||||
private String description; |
||||
|
||||
private String sourceType; |
||||
|
||||
private String sourceMethod; |
||||
|
||||
private final Map<String, ConfigurationMetadataProperty> properties |
||||
= new HashMap<String, ConfigurationMetadataProperty>(); |
||||
|
||||
/** |
||||
* The identifier of the group to which this source is associated |
||||
*/ |
||||
public String getGroupId() { |
||||
return this.groupId; |
||||
} |
||||
|
||||
void setGroupId(String groupId) { |
||||
this.groupId = groupId; |
||||
} |
||||
|
||||
/** |
||||
* The type of the source. Usually this is the fully qualified name |
||||
* of a class that defines one more configuration item. This class may or |
||||
* may not be available at runtime. |
||||
*/ |
||||
public String getType() { |
||||
return this.type; |
||||
} |
||||
|
||||
void setType(String type) { |
||||
this.type = type; |
||||
} |
||||
|
||||
/** |
||||
* The description of this source, if any. |
||||
*/ |
||||
public String getDescription() { |
||||
return this.description; |
||||
} |
||||
|
||||
void setDescription(String description) { |
||||
this.description = description; |
||||
} |
||||
|
||||
/** |
||||
* The type where this source is defined. This can be identical |
||||
* to the {@linkplain #getType() type} if the source is self-defined. |
||||
*/ |
||||
public String getSourceType() { |
||||
return this.sourceType; |
||||
} |
||||
|
||||
void setSourceType(String sourceType) { |
||||
this.sourceType = sourceType; |
||||
} |
||||
|
||||
/** |
||||
* The method name that defines this source, if any. |
||||
*/ |
||||
public String getSourceMethod() { |
||||
return this.sourceMethod; |
||||
} |
||||
|
||||
void setSourceMethod(String sourceMethod) { |
||||
this.sourceMethod = sourceMethod; |
||||
} |
||||
|
||||
/** |
||||
* Return the properties defined by this source. |
||||
*/ |
||||
public Map<String, ConfigurationMetadataProperty> getProperties() { |
||||
return this.properties; |
||||
} |
||||
|
||||
} |
||||
@ -1,116 +0,0 @@
@@ -1,116 +0,0 @@
|
||||
/* |
||||
* Copyright 2012-2014 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.configurationmetadata; |
||||
|
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.io.InputStreamReader; |
||||
import java.nio.charset.Charset; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
import org.json.JSONArray; |
||||
import org.json.JSONObject; |
||||
|
||||
/** |
||||
* Read standard json metadata format as {@link ConfigurationMetadataRepository} |
||||
* |
||||
* @author Stephane Nicoll |
||||
* @since 1.2.0 |
||||
*/ |
||||
class JsonReader { |
||||
|
||||
public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); |
||||
|
||||
private static final int BUFFER_SIZE = 4096; |
||||
|
||||
public RawConfigurationMetadata read(InputStream in) throws IOException { |
||||
return read(in, DEFAULT_CHARSET); |
||||
} |
||||
|
||||
public RawConfigurationMetadata read(InputStream in, Charset charset) throws IOException { |
||||
JSONObject json = readJson(in, charset); |
||||
List<ConfigurationMetadataSource> groups = parseAllSources(json); |
||||
List<ConfigurationMetadataItem> items = parseAllItems(json); |
||||
return new RawConfigurationMetadata(groups, items); |
||||
} |
||||
|
||||
private List<ConfigurationMetadataSource> parseAllSources(JSONObject root) { |
||||
List<ConfigurationMetadataSource> result = new ArrayList<ConfigurationMetadataSource>(); |
||||
if (!root.has("groups")) { |
||||
return result; |
||||
} |
||||
JSONArray sources = root.getJSONArray("groups"); |
||||
for (int i = 0; i < sources.length(); i++) { |
||||
JSONObject source = sources.getJSONObject(i); |
||||
result.add(parseSource(source)); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
private List<ConfigurationMetadataItem> parseAllItems(JSONObject root) { |
||||
List<ConfigurationMetadataItem> result = new ArrayList<ConfigurationMetadataItem>(); |
||||
if (!root.has("properties")) { |
||||
return result; |
||||
} |
||||
JSONArray items = root.getJSONArray("properties"); |
||||
for (int i = 0; i < items.length(); i++) { |
||||
JSONObject item = items.getJSONObject(i); |
||||
result.add(parseItem(item)); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
private ConfigurationMetadataSource parseSource(JSONObject json) { |
||||
ConfigurationMetadataSource source = new ConfigurationMetadataSource(); |
||||
source.setGroupId(json.getString("name")); |
||||
source.setType(json.optString("type", null)); |
||||
source.setDescription(json.optString("description", null)); |
||||
source.setSourceType(json.optString("sourceType", null)); |
||||
source.setSourceMethod(json.optString("sourceMethod", null)); |
||||
return source; |
||||
} |
||||
|
||||
private ConfigurationMetadataItem parseItem(JSONObject json) { |
||||
ConfigurationMetadataItem item = new ConfigurationMetadataItem(); |
||||
item.setId(json.getString("name")); |
||||
item.setType(json.optString("type", null)); |
||||
item.setDescription(json.optString("description", null)); |
||||
item.setDefaultValue(json.opt("defaultValue")); |
||||
item.setDeprecated(json.optBoolean("deprecated", false)); |
||||
item.setSourceType(json.optString("sourceType", null)); |
||||
item.setSourceMethod(json.optString("sourceMethod", null)); |
||||
return item; |
||||
} |
||||
|
||||
private JSONObject readJson(InputStream in, Charset charset) throws IOException { |
||||
try { |
||||
StringBuilder out = new StringBuilder(); |
||||
InputStreamReader reader = new InputStreamReader(in, charset); |
||||
char[] buffer = new char[BUFFER_SIZE]; |
||||
int bytesRead = -1; |
||||
while ((bytesRead = reader.read(buffer)) != -1) { |
||||
out.append(buffer, 0, bytesRead); |
||||
} |
||||
return new JSONObject(out.toString()); |
||||
} |
||||
finally { |
||||
in.close(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -1,78 +0,0 @@
@@ -1,78 +0,0 @@
|
||||
/* |
||||
* Copyright 2012-2014 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.configurationmetadata; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* A raw metadata structure. Used to initialize a {@link ConfigurationMetadataRepository}. |
||||
* |
||||
* @author Stephane Nicoll |
||||
* @since 1.2.0 |
||||
*/ |
||||
class RawConfigurationMetadata { |
||||
|
||||
private final List<ConfigurationMetadataSource> sources; |
||||
|
||||
private final List<ConfigurationMetadataItem> items; |
||||
|
||||
RawConfigurationMetadata(List<ConfigurationMetadataSource> sources, List<ConfigurationMetadataItem> items) { |
||||
this.sources = new ArrayList<ConfigurationMetadataSource>(sources); |
||||
this.items = new ArrayList<ConfigurationMetadataItem>(items); |
||||
for (ConfigurationMetadataItem item : this.items) { |
||||
resolveName(item); |
||||
} |
||||
} |
||||
|
||||
public List<ConfigurationMetadataSource> getSources() { |
||||
return this.sources; |
||||
} |
||||
|
||||
public ConfigurationMetadataSource getSource(String type) { |
||||
for (ConfigurationMetadataSource source : this.sources) { |
||||
if (type.equals(source.getType())) { |
||||
return source; |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
public List<ConfigurationMetadataItem> getItems() { |
||||
return this.items; |
||||
} |
||||
|
||||
/** |
||||
* Resolve the name of an item against this instance. |
||||
* @see ConfigurationMetadataProperty#setName(String) |
||||
*/ |
||||
private void resolveName(ConfigurationMetadataItem item) { |
||||
item.setName(item.getId()); // fallback
|
||||
if (item.getSourceType() == null) { |
||||
return; |
||||
} |
||||
ConfigurationMetadataSource source = getSource(item.getSourceType()); |
||||
if (source != null) { |
||||
String groupId = source.getGroupId(); |
||||
String id = item.getId(); |
||||
if (id.startsWith(groupId)) { // match
|
||||
String name = id.substring(groupId.length() + 1, id.length()); // "."
|
||||
item.setName(name); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -1,121 +0,0 @@
@@ -1,121 +0,0 @@
|
||||
/* |
||||
* Copyright 2012-2014 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.configurationmetadata; |
||||
|
||||
import java.util.Collection; |
||||
import java.util.Collections; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* The default {@link ConfigurationMetadataRepository} implementation. |
||||
* |
||||
* @author Stephane Nicoll |
||||
* @since 1.2.0 |
||||
*/ |
||||
public class SimpleConfigurationMetadataRepository implements ConfigurationMetadataRepository { |
||||
|
||||
private final Map<String, ConfigurationMetadataGroup> allGroups = new HashMap<String, ConfigurationMetadataGroup>(); |
||||
|
||||
@Override |
||||
public Map<String, ConfigurationMetadataGroup> getAllGroups() { |
||||
return Collections.unmodifiableMap(this.allGroups); |
||||
} |
||||
|
||||
@Override |
||||
public Map<String, ConfigurationMetadataProperty> getAllProperties() { |
||||
Map<String,ConfigurationMetadataProperty> properties = new HashMap<String, ConfigurationMetadataProperty>(); |
||||
for (ConfigurationMetadataGroup group : this.allGroups.values()) { |
||||
properties.putAll(group.getProperties()); |
||||
} |
||||
return properties; |
||||
} |
||||
|
||||
/** |
||||
* Register the specified {@link ConfigurationMetadataSource sources}. |
||||
*/ |
||||
public void add(Collection<ConfigurationMetadataSource> sources) { |
||||
for (ConfigurationMetadataSource source : sources) { |
||||
String groupId = source.getGroupId(); |
||||
ConfigurationMetadataGroup group = this.allGroups.get(groupId); |
||||
if (group == null) { |
||||
group = new ConfigurationMetadataGroup(groupId); |
||||
this.allGroups.put(groupId, group); |
||||
} |
||||
String sourceType = source.getType(); |
||||
if (sourceType != null) { |
||||
putIfAbsent(group.getSources(), sourceType, source); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Add a {@link ConfigurationMetadataProperty} with the {@link ConfigurationMetadataSource source} |
||||
* that defines it, if any. |
||||
*/ |
||||
public void add(ConfigurationMetadataProperty property, ConfigurationMetadataSource source) { |
||||
if (source != null) { |
||||
putIfAbsent(source.getProperties(),property.getId(), property); |
||||
} |
||||
putIfAbsent(getGroup(source).getProperties(), property.getId(), property); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Merge the content of the specified repository to this repository. |
||||
*/ |
||||
public void include(ConfigurationMetadataRepository repository) { |
||||
for (ConfigurationMetadataGroup group : repository.getAllGroups().values()) { |
||||
ConfigurationMetadataGroup existingGroup = this.allGroups.get(group.getId()); |
||||
if (existingGroup == null) { |
||||
this.allGroups.put(group.getId(), group); |
||||
} |
||||
else { |
||||
// Merge properties
|
||||
for (Map.Entry<String, ConfigurationMetadataProperty> entry : group.getProperties().entrySet()) { |
||||
putIfAbsent(existingGroup.getProperties(), entry.getKey(), entry.getValue()); |
||||
} |
||||
// Merge sources
|
||||
for (Map.Entry<String, ConfigurationMetadataSource> entry : group.getSources().entrySet()) { |
||||
putIfAbsent(existingGroup.getSources(), entry.getKey(), entry.getValue()); |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
private ConfigurationMetadataGroup getGroup(ConfigurationMetadataSource source) { |
||||
if (source == null) { |
||||
ConfigurationMetadataGroup rootGroup = this.allGroups.get(ROOT_GROUP); |
||||
if (rootGroup == null) { |
||||
rootGroup = new ConfigurationMetadataGroup(ROOT_GROUP); |
||||
this.allGroups.put(ROOT_GROUP, rootGroup); |
||||
} |
||||
return rootGroup; |
||||
} |
||||
else { |
||||
return this.allGroups.get(source.getGroupId()); |
||||
} |
||||
} |
||||
|
||||
private <V> void putIfAbsent(Map<String, V> map, String key, V value) { |
||||
if (!map.containsKey(key)) { |
||||
map.put(key, value); |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -1,66 +0,0 @@
@@ -1,66 +0,0 @@
|
||||
/* |
||||
* Copyright 2012-2014 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.configurationmetadata; |
||||
|
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
|
||||
import org.junit.Rule; |
||||
import org.junit.rules.ExpectedException; |
||||
|
||||
import org.springframework.core.io.ClassPathResource; |
||||
import org.springframework.core.io.Resource; |
||||
|
||||
import static org.junit.Assert.assertEquals; |
||||
import static org.junit.Assert.assertNotNull; |
||||
|
||||
/** |
||||
* |
||||
* @author Stephane Nicoll |
||||
*/ |
||||
public abstract class AbstractConfigurationMetadataTests { |
||||
|
||||
@Rule |
||||
public final ExpectedException thrown = ExpectedException.none(); |
||||
|
||||
protected void assertSource(ConfigurationMetadataSource actual, String groupId, String type, String sourceType) { |
||||
assertNotNull(actual); |
||||
assertEquals(groupId, actual.getGroupId()); |
||||
assertEquals(type, actual.getType()); |
||||
assertEquals(sourceType, actual.getSourceType()); |
||||
} |
||||
|
||||
protected void assertProperty(ConfigurationMetadataProperty actual, String id, String name, |
||||
Class<?> type, Object defaultValue) { |
||||
assertNotNull(actual); |
||||
assertEquals(id, actual.getId()); |
||||
assertEquals(name, actual.getName()); |
||||
String typeName = type != null ? type.getName() : null; |
||||
assertEquals(typeName, actual.getType()); |
||||
assertEquals(defaultValue, actual.getDefaultValue()); |
||||
} |
||||
|
||||
protected void assertItem(ConfigurationMetadataItem actual, String sourceType) { |
||||
assertNotNull(actual); |
||||
assertEquals(sourceType, actual.getSourceType()); |
||||
} |
||||
|
||||
protected InputStream getInputStreamFor(String name) throws IOException { |
||||
Resource r = new ClassPathResource("metadata/configuration-metadata-" + name + ".json"); |
||||
return r.getInputStream(); |
||||
} |
||||
} |
||||
@ -1,122 +0,0 @@
@@ -1,122 +0,0 @@
|
||||
/* |
||||
* Copyright 2012-2014 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.configurationmetadata; |
||||
|
||||
import java.io.IOException; |
||||
import java.util.Arrays; |
||||
import java.util.Collections; |
||||
import java.util.Map; |
||||
|
||||
import org.junit.Test; |
||||
|
||||
import static org.junit.Assert.assertEquals; |
||||
import static org.junit.Assert.assertTrue; |
||||
|
||||
/** |
||||
* Tests for {@link ConfigurationMetadataRepository}. |
||||
* |
||||
* @author Stephane Nicoll |
||||
*/ |
||||
public class ConfigurationMetadataRepositoryJsonLoaderTests extends AbstractConfigurationMetadataTests { |
||||
|
||||
private final ConfigurationMetadataRepositoryJsonLoader loader = new ConfigurationMetadataRepositoryJsonLoader(); |
||||
|
||||
@Test |
||||
public void nullResource() throws IOException { |
||||
thrown.expect(IllegalArgumentException.class); |
||||
loader.loadAll(null); |
||||
} |
||||
|
||||
@Test |
||||
public void simpleRepository() throws IOException { |
||||
ConfigurationMetadataRepository repo = loader.loadAll(Collections.singleton(getInputStreamFor("foo"))); |
||||
validateFoo(repo); |
||||
assertEquals(1, repo.getAllGroups().size()); |
||||
|
||||
contains(repo.getAllProperties(), "spring.foo.name", "spring.foo.description", "spring.foo.counter"); |
||||
assertEquals(3, repo.getAllProperties().size()); |
||||
} |
||||
|
||||
@Test |
||||
public void severalRepositoriesNoConflict() throws IOException { |
||||
ConfigurationMetadataRepository repo = loader.loadAll( |
||||
Arrays.asList(getInputStreamFor("foo"), getInputStreamFor("bar"))); |
||||
validateFoo(repo); |
||||
validateBar(repo); |
||||
assertEquals(2, repo.getAllGroups().size()); |
||||
|
||||
contains(repo.getAllProperties(), "spring.foo.name", "spring.foo.description", "spring.foo.counter", |
||||
"spring.bar.name", "spring.bar.description", "spring.bar.counter"); |
||||
assertEquals(6, repo.getAllProperties().size()); |
||||
} |
||||
|
||||
@Test |
||||
public void repositoryWithRoot() throws IOException { |
||||
ConfigurationMetadataRepository repo = loader.loadAll( |
||||
Arrays.asList(getInputStreamFor("foo"), getInputStreamFor("root"))); |
||||
validateFoo(repo); |
||||
assertEquals(2, repo.getAllGroups().size()); |
||||
|
||||
contains(repo.getAllProperties(), "spring.foo.name", "spring.foo.description", "spring.foo.counter", |
||||
"spring.root.name", "spring.root2.name"); |
||||
assertEquals(5, repo.getAllProperties().size()); |
||||
} |
||||
|
||||
@Test |
||||
public void severalRepositoriesIdenticalGroups() throws IOException { |
||||
ConfigurationMetadataRepository repo = loader.loadAll( |
||||
Arrays.asList(getInputStreamFor("foo"), getInputStreamFor("foo2"))); |
||||
assertEquals(1, repo.getAllGroups().size()); |
||||
ConfigurationMetadataGroup group = repo.getAllGroups().get("spring.foo"); |
||||
contains(group.getSources(), "org.acme.Foo", "org.acme.Foo2", "org.springframework.boot.FooProperties"); |
||||
assertEquals(3, group.getSources().size()); |
||||
contains(group.getProperties(), "spring.foo.name", "spring.foo.description", "spring.foo.counter", |
||||
"spring.foo.enabled", "spring.foo.type"); |
||||
assertEquals(5, group.getProperties().size()); |
||||
contains(repo.getAllProperties(), "spring.foo.name", "spring.foo.description", "spring.foo.counter", |
||||
"spring.foo.enabled", "spring.foo.type"); |
||||
assertEquals(5, repo.getAllProperties().size()); |
||||
} |
||||
|
||||
private void validateFoo(ConfigurationMetadataRepository repo) { |
||||
ConfigurationMetadataGroup group = repo.getAllGroups().get("spring.foo"); |
||||
contains(group.getSources(), "org.acme.Foo", "org.springframework.boot.FooProperties"); |
||||
ConfigurationMetadataSource source = group.getSources().get("org.acme.Foo"); |
||||
contains(source.getProperties(), "spring.foo.name", "spring.foo.description"); |
||||
assertEquals(2, source.getProperties().size()); |
||||
ConfigurationMetadataSource source2 = group.getSources().get("org.springframework.boot.FooProperties"); |
||||
contains(source2.getProperties(), "spring.foo.name", "spring.foo.counter"); |
||||
assertEquals(2, source2.getProperties().size()); |
||||
} |
||||
|
||||
private void validateBar(ConfigurationMetadataRepository repo) { |
||||
ConfigurationMetadataGroup group = repo.getAllGroups().get("spring.bar"); |
||||
contains(group.getSources(), "org.acme.Bar", "org.springframework.boot.BarProperties"); |
||||
ConfigurationMetadataSource source = group.getSources().get("org.acme.Bar"); |
||||
contains(source.getProperties(), "spring.bar.name", "spring.bar.description"); |
||||
assertEquals(2, source.getProperties().size()); |
||||
ConfigurationMetadataSource source2 = group.getSources().get("org.springframework.boot.BarProperties"); |
||||
contains(source2.getProperties(), "spring.bar.name", "spring.bar.counter"); |
||||
assertEquals(2, source2.getProperties().size()); |
||||
} |
||||
|
||||
private void contains(Map<String, ?> source, String... keys) { |
||||
for (String key : keys) { |
||||
assertTrue("Item '" + key + "' not found. Got " + source.keySet(), source.containsKey(key)); |
||||
} |
||||
} |
||||
} |
||||
@ -1,86 +0,0 @@
@@ -1,86 +0,0 @@
|
||||
/* |
||||
* Copyright 2012-2014 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.configurationmetadata; |
||||
|
||||
import java.io.IOException; |
||||
import java.util.List; |
||||
|
||||
import org.json.JSONException; |
||||
import org.junit.Test; |
||||
|
||||
import static org.junit.Assert.assertEquals; |
||||
import static org.junit.Assert.assertNull; |
||||
|
||||
/** |
||||
* Tests for {@link JsonReader} |
||||
* |
||||
* @author Stephane Nicoll |
||||
*/ |
||||
public class JsonReaderTests extends AbstractConfigurationMetadataTests { |
||||
|
||||
private final JsonReader reader = new JsonReader(); |
||||
|
||||
@Test |
||||
public void emptyMetadata() throws IOException { |
||||
RawConfigurationMetadata rawMetadata = reader.read(getInputStreamFor("empty")); |
||||
assertEquals(0, rawMetadata.getSources().size()); |
||||
assertEquals(0, rawMetadata.getItems().size()); |
||||
} |
||||
|
||||
@Test |
||||
public void invalidMetadata() throws IOException { |
||||
thrown.expect(JSONException.class); |
||||
reader.read(getInputStreamFor("invalid")); |
||||
} |
||||
|
||||
@Test |
||||
public void simpleMetadata() throws IOException { |
||||
RawConfigurationMetadata rawMetadata = reader.read(getInputStreamFor("foo")); |
||||
List<ConfigurationMetadataSource> sources = rawMetadata.getSources(); |
||||
assertEquals(2, sources.size()); |
||||
List<ConfigurationMetadataItem> items = rawMetadata.getItems(); |
||||
assertEquals(4, items.size()); |
||||
|
||||
|
||||
ConfigurationMetadataSource source = sources.get(0); |
||||
assertSource(source, "spring.foo", "org.acme.Foo", "org.acme.config.FooApp"); |
||||
assertEquals("foo()", source.getSourceMethod()); |
||||
assertEquals("This is Foo.", source.getDescription()); |
||||
ConfigurationMetadataItem item = items.get(0); |
||||
assertProperty(item, "spring.foo.name", "name", String.class, null); |
||||
assertItem(item, "org.acme.Foo"); |
||||
ConfigurationMetadataItem item2 = items.get(1); |
||||
assertProperty(item2, "spring.foo.description", "description", String.class, "FooBar"); |
||||
assertEquals("Foo description.", item2.getDescription()); |
||||
assertNull(item2.getSourceMethod()); |
||||
assertItem(item2, "org.acme.Foo"); |
||||
} |
||||
|
||||
@Test |
||||
public void rootMetadata() throws IOException { |
||||
RawConfigurationMetadata rawMetadata = reader.read(getInputStreamFor("root")); |
||||
List<ConfigurationMetadataSource> sources = rawMetadata.getSources(); |
||||
assertEquals(0, sources.size()); |
||||
List<ConfigurationMetadataItem> items = rawMetadata.getItems(); |
||||
assertEquals(2, items.size()); |
||||
|
||||
ConfigurationMetadataItem item = items.get(0); |
||||
assertProperty(item, "spring.root.name", "spring.root.name", String.class, null); |
||||
|
||||
} |
||||
|
||||
} |
||||
@ -1,40 +0,0 @@
@@ -1,40 +0,0 @@
|
||||
{ |
||||
"groups": [ |
||||
{ |
||||
"name": "spring.bar", |
||||
"type": "org.acme.Bar", |
||||
"sourceType": "org.acme.config.BarApp", |
||||
"sourceMethod": "bar()", |
||||
"description": "This is Bar." |
||||
}, |
||||
{ |
||||
"name": "spring.bar", |
||||
"type": "org.springframework.boot.BarProperties" |
||||
} |
||||
], |
||||
"properties": [ |
||||
{ |
||||
"name": "spring.bar.name", |
||||
"type": "java.lang.String", |
||||
"sourceType": "org.acme.Bar" |
||||
}, |
||||
{ |
||||
"name": "spring.bar.description", |
||||
"type": "java.lang.String", |
||||
"sourceType": "org.acme.Bar", |
||||
"description": "Bar description.", |
||||
"defaultValue": "BarFoo" |
||||
}, |
||||
{ |
||||
"name": "spring.bar.name", |
||||
"type": "java.lang.String", |
||||
"sourceType": "org.springframework.boot.BarProperties" |
||||
}, |
||||
{ |
||||
"name": "spring.bar.counter", |
||||
"type": "java.lang.Integer", |
||||
"sourceType": "org.springframework.boot.BarProperties", |
||||
"defaultValue": 0 |
||||
} |
||||
] |
||||
} |
||||
@ -1,3 +0,0 @@
@@ -1,3 +0,0 @@
|
||||
{ |
||||
"foo": "bar" |
||||
} |
||||
@ -1,40 +0,0 @@
@@ -1,40 +0,0 @@
|
||||
{ |
||||
"groups": [ |
||||
{ |
||||
"name": "spring.foo", |
||||
"type": "org.acme.Foo", |
||||
"sourceType": "org.acme.config.FooApp", |
||||
"sourceMethod": "foo()", |
||||
"description": "This is Foo." |
||||
}, |
||||
{ |
||||
"name": "spring.foo", |
||||
"type": "org.springframework.boot.FooProperties" |
||||
} |
||||
], |
||||
"properties": [ |
||||
{ |
||||
"name": "spring.foo.name", |
||||
"type": "java.lang.String", |
||||
"sourceType": "org.acme.Foo" |
||||
}, |
||||
{ |
||||
"name": "spring.foo.description", |
||||
"type": "java.lang.String", |
||||
"sourceType": "org.acme.Foo", |
||||
"description": "Foo description.", |
||||
"defaultValue": "FooBar" |
||||
}, |
||||
{ |
||||
"name": "spring.foo.name", |
||||
"type": "java.lang.String", |
||||
"sourceType": "org.springframework.boot.FooProperties" |
||||
}, |
||||
{ |
||||
"name": "spring.foo.counter", |
||||
"type": "java.lang.Integer", |
||||
"sourceType": "org.springframework.boot.FooProperties", |
||||
"defaultValue": 0 |
||||
} |
||||
] |
||||
} |
||||
@ -1,23 +0,0 @@
@@ -1,23 +0,0 @@
|
||||
{ |
||||
"groups": [ |
||||
{ |
||||
"name": "spring.foo", |
||||
"type": "org.acme.Foo2", |
||||
"sourceType": "org.acme.config.FooApp", |
||||
"sourceMethod": "foo2()", |
||||
"description": "This is Foo2." |
||||
} |
||||
], |
||||
"properties": [ |
||||
{ |
||||
"name": "spring.foo.enabled", |
||||
"type": "java.lang.Boolean", |
||||
"sourceType": "org.acme.Foo2" |
||||
}, |
||||
{ |
||||
"name": "spring.foo.type", |
||||
"type": "java.lang.String", |
||||
"sourceType": "org.acme.Foo2" |
||||
} |
||||
] |
||||
} |
||||
Loading…
Reference in new issue