mirror of
https://gitee.com/dcren/initializr.git
synced 2025-07-17 01:46:19 +08:00
Make SingleSelectCapability thread-safe
Closes gh-1105
This commit is contained in:
parent
9f19c6fa50
commit
42b701ab1a
@ -126,7 +126,7 @@ public class InitializrMetadataTestBuilder {
|
|||||||
packaging.setId(id);
|
packaging.setId(id);
|
||||||
packaging.setName(id);
|
packaging.setName(id);
|
||||||
packaging.setDefault(defaultValue);
|
packaging.setDefault(defaultValue);
|
||||||
it.getPackagings().getContent().add(packaging);
|
it.getPackagings().addContent(packaging);
|
||||||
});
|
});
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -141,7 +141,7 @@ public class InitializrMetadataTestBuilder {
|
|||||||
element.setId(version);
|
element.setId(version);
|
||||||
element.setName(version);
|
element.setName(version);
|
||||||
element.setDefault(defaultValue);
|
element.setDefault(defaultValue);
|
||||||
it.getJavaVersions().getContent().add(element);
|
it.getJavaVersions().addContent(element);
|
||||||
});
|
});
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -156,7 +156,7 @@ public class InitializrMetadataTestBuilder {
|
|||||||
element.setId(id);
|
element.setId(id);
|
||||||
element.setName(id);
|
element.setName(id);
|
||||||
element.setDefault(defaultValue);
|
element.setDefault(defaultValue);
|
||||||
it.getLanguages().getContent().add(element);
|
it.getLanguages().addContent(element);
|
||||||
});
|
});
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -172,7 +172,7 @@ public class InitializrMetadataTestBuilder {
|
|||||||
element.setId(id);
|
element.setId(id);
|
||||||
element.setName(id);
|
element.setName(id);
|
||||||
element.setDefault(defaultValue);
|
element.setDefault(defaultValue);
|
||||||
it.getBootVersions().getContent().add(element);
|
it.getBootVersions().addContent(element);
|
||||||
});
|
});
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -200,8 +200,7 @@ public class InitializrMetadata {
|
|||||||
* @param versionsMetadata the Spring Boot boot versions metadata to use
|
* @param versionsMetadata the Spring Boot boot versions metadata to use
|
||||||
*/
|
*/
|
||||||
public void updateSpringBootVersions(List<DefaultMetadataElement> versionsMetadata) {
|
public void updateSpringBootVersions(List<DefaultMetadataElement> versionsMetadata) {
|
||||||
this.bootVersions.getContent().clear();
|
this.bootVersions.setContent(versionsMetadata);
|
||||||
this.bootVersions.getContent().addAll(versionsMetadata);
|
|
||||||
List<Version> bootVersions = this.bootVersions.getContent().stream().map((it) -> Version.parse(it.getId()))
|
List<Version> bootVersions = this.bootVersions.getContent().stream().map((it) -> Version.parse(it.getId()))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
VersionParser parser = new VersionParser(bootVersions);
|
VersionParser parser = new VersionParser(bootVersions);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2019 the original author or authors.
|
* Copyright 2012-2020 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -16,8 +16,13 @@
|
|||||||
|
|
||||||
package io.spring.initializr.metadata;
|
package io.spring.initializr.metadata;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.locks.ReadWriteLock;
|
||||||
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
@ -30,7 +35,9 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
|||||||
public class SingleSelectCapability extends ServiceCapability<List<DefaultMetadataElement>>
|
public class SingleSelectCapability extends ServiceCapability<List<DefaultMetadataElement>>
|
||||||
implements Defaultable<DefaultMetadataElement> {
|
implements Defaultable<DefaultMetadataElement> {
|
||||||
|
|
||||||
private final List<DefaultMetadataElement> content = new CopyOnWriteArrayList<>();
|
private final List<DefaultMetadataElement> content = new ArrayList<>();
|
||||||
|
|
||||||
|
private final ReadWriteLock contentLock = new ReentrantReadWriteLock();
|
||||||
|
|
||||||
@JsonCreator
|
@JsonCreator
|
||||||
SingleSelectCapability(@JsonProperty("id") String id) {
|
SingleSelectCapability(@JsonProperty("id") String id) {
|
||||||
@ -43,7 +50,18 @@ public class SingleSelectCapability extends ServiceCapability<List<DefaultMetada
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<DefaultMetadataElement> getContent() {
|
public List<DefaultMetadataElement> getContent() {
|
||||||
return this.content;
|
return Collections.unmodifiableList(withReadableContent(ArrayList::new));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addContent(DefaultMetadataElement element) {
|
||||||
|
withWritableContent((content) -> content.add(element));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContent(List<DefaultMetadataElement> newContent) {
|
||||||
|
withWritableContent((content) -> {
|
||||||
|
content.clear();
|
||||||
|
content.addAll(newContent);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -51,7 +69,8 @@ public class SingleSelectCapability extends ServiceCapability<List<DefaultMetada
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public DefaultMetadataElement getDefault() {
|
public DefaultMetadataElement getDefault() {
|
||||||
return this.content.stream().filter(DefaultMetadataElement::isDefault).findFirst().orElse(null);
|
return withReadableContent(
|
||||||
|
(content) -> content.stream().filter(DefaultMetadataElement::isDefault).findFirst().orElse(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -60,16 +79,39 @@ public class SingleSelectCapability extends ServiceCapability<List<DefaultMetada
|
|||||||
* @return the element or {@code null}
|
* @return the element or {@code null}
|
||||||
*/
|
*/
|
||||||
public DefaultMetadataElement get(String id) {
|
public DefaultMetadataElement get(String id) {
|
||||||
return this.content.stream().filter((it) -> id.equals(it.getId())).findFirst().orElse(null);
|
return withReadableContent(
|
||||||
|
(content) -> content.stream().filter((it) -> id.equals(it.getId())).findFirst().orElse(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void merge(List<DefaultMetadataElement> otherContent) {
|
public void merge(List<DefaultMetadataElement> otherContent) {
|
||||||
|
withWritableContent((content) -> {
|
||||||
otherContent.forEach((it) -> {
|
otherContent.forEach((it) -> {
|
||||||
if (get(it.getId()) == null) {
|
if (get(it.getId()) == null) {
|
||||||
this.content.add(it);
|
this.content.add(it);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> T withReadableContent(Function<List<DefaultMetadataElement>, T> consumer) {
|
||||||
|
this.contentLock.readLock().lock();
|
||||||
|
try {
|
||||||
|
return consumer.apply(this.content);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
this.contentLock.readLock().unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void withWritableContent(Consumer<List<DefaultMetadataElement>> consumer) {
|
||||||
|
this.contentLock.writeLock().lock();
|
||||||
|
try {
|
||||||
|
consumer.accept(this.content);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
this.contentLock.writeLock().unlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2019 the original author or authors.
|
* Copyright 2012-2020 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package io.spring.initializr.metadata;
|
package io.spring.initializr.metadata;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
@ -34,17 +36,17 @@ class SingleSelectCapabilityTests {
|
|||||||
@Test
|
@Test
|
||||||
void defaultNoDefault() {
|
void defaultNoDefault() {
|
||||||
SingleSelectCapability capability = new SingleSelectCapability("test");
|
SingleSelectCapability capability = new SingleSelectCapability("test");
|
||||||
capability.getContent().add(DefaultMetadataElement.create("foo", false));
|
capability.setContent(Arrays.asList(DefaultMetadataElement.create("foo", false),
|
||||||
capability.getContent().add(DefaultMetadataElement.create("bar", false));
|
DefaultMetadataElement.create("bar", false)));
|
||||||
assertThat(capability.getDefault()).isNull();
|
assertThat(capability.getDefault()).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void defaultType() {
|
void defaultType() {
|
||||||
SingleSelectCapability capability = new SingleSelectCapability("test");
|
SingleSelectCapability capability = new SingleSelectCapability("test");
|
||||||
capability.getContent().add(DefaultMetadataElement.create("foo", false));
|
DefaultMetadataElement first = DefaultMetadataElement.create("foo", false);
|
||||||
DefaultMetadataElement second = DefaultMetadataElement.create("bar", true);
|
DefaultMetadataElement second = DefaultMetadataElement.create("bar", true);
|
||||||
capability.getContent().add(second);
|
capability.setContent(Arrays.asList(first, second));
|
||||||
assertThat(capability.getDefault()).isEqualTo(second);
|
assertThat(capability.getDefault()).isEqualTo(second);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,11 +54,11 @@ class SingleSelectCapabilityTests {
|
|||||||
void mergeAddEntry() {
|
void mergeAddEntry() {
|
||||||
SingleSelectCapability capability = new SingleSelectCapability("test");
|
SingleSelectCapability capability = new SingleSelectCapability("test");
|
||||||
DefaultMetadataElement foo = DefaultMetadataElement.create("foo", false);
|
DefaultMetadataElement foo = DefaultMetadataElement.create("foo", false);
|
||||||
capability.getContent().add(foo);
|
capability.setContent(Arrays.asList(foo));
|
||||||
|
|
||||||
SingleSelectCapability anotherCapability = new SingleSelectCapability("test");
|
SingleSelectCapability anotherCapability = new SingleSelectCapability("test");
|
||||||
DefaultMetadataElement bar = DefaultMetadataElement.create("bar", false);
|
DefaultMetadataElement bar = DefaultMetadataElement.create("bar", false);
|
||||||
anotherCapability.getContent().add(bar);
|
anotherCapability.setContent(Arrays.asList(bar));
|
||||||
|
|
||||||
capability.merge(anotherCapability);
|
capability.merge(anotherCapability);
|
||||||
assertThat(capability.getContent()).hasSize(2);
|
assertThat(capability.getContent()).hasSize(2);
|
||||||
|
Loading…
Reference in New Issue
Block a user