diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index f497e8ad..46b55e20 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -22,10 +22,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - name: Set up JDK 11 + - name: Set up JDK 17 uses: actions/setup-java@v3 with: - java-version: '11' + java-version: '17' distribution: 'temurin' cache: maven - uses: ankane/setup-elasticsearch@v1 diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index b90899e0..052db743 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -19,10 +19,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - name: Set up JDK 11 + - name: Set up JDK 17 uses: actions/setup-java@v3 with: - java-version: '11' + java-version: '17' distribution: 'temurin' cache: maven - name: Build with Maven @@ -39,10 +39,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - name: Set up JDK 11 + - name: Set up JDK 17 uses: actions/setup-java@v3 with: - java-version: '11' + java-version: '17' distribution: 'temurin' cache: maven - name: Test with Maven @@ -59,10 +59,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - name: Set up JDK 11 + - name: Set up JDK 17 uses: actions/setup-java@v3 with: - java-version: '11' + java-version: '17' distribution: 'temurin' cache: maven - uses: ankane/setup-elasticsearch@v1 diff --git a/Dockerfile b/Dockerfile index 40320a0f..86f9a183 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,3 @@ -FROM openjdk:11-jre +FROM openjdk:17-jre WORKDIR /channelfinder ADD https://repo1.maven.org/maven2/org/phoebus/app-channel-channelfinder/4.7.2/app-channel-channelfinder-4.7.2.jar . diff --git a/Dockerfile.integrationtest b/Dockerfile.integrationtest index b79760f2..2874e08b 100644 --- a/Dockerfile.integrationtest +++ b/Dockerfile.integrationtest @@ -16,7 +16,7 @@ # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ------------------------------------------------------------------------------ -FROM openjdk:11 +FROM openjdk:17 # deployment unit COPY target/ChannelFinder-*.jar /channelfinder/ChannelFinder-*.jar diff --git a/README.md b/README.md index 2057b43b..a34c2552 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ Collected installation recipes and notes may be found on [wiki pages](https://gi * Prerequisites - * JDK 11 + * JDK 17 * Elastic version 8.2.x * LDAP server, e.g. OpenLDAP @@ -45,7 +45,7 @@ Collected installation recipes and notes may be found on [wiki pages](https://gi * Build ``` # Debian 10 -sudo apt-get install openjdk-11-jdk maven git curl wget +sudo apt-get install openjdk-17-jdk maven git curl wget wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.2.0-amd64.deb sudo dpkg -i elasticsearch-8.2.0-amd64.deb sudo systemctl start elasticsearch diff --git a/pom.xml b/pom.xml index 9ff646ce..fc7f1456 100644 --- a/pom.xml +++ b/pom.xml @@ -55,24 +55,6 @@ - - - javax.xml.bind - jaxb-api - 2.3.0 - - - com.sun.xml.bind - jaxb-core - 2.3.0 - - - com.sun.xml.bind - jaxb-impl - 2.3.0 - - org.springframework.boot spring-boot-starter @@ -85,11 +67,6 @@ org.springframework.data spring-data-commons - - javax.servlet - javax.servlet-api - provided - org.junit.jupiter @@ -346,8 +323,8 @@ maven-compiler-plugin 3.11.0 - 11 - 11 + 17 + 17 ${project.build.sourceEncoding} @@ -423,7 +400,7 @@ -Xdoclint:none - 11 + 17 diff --git a/src/main/java/org/phoebus/channelfinder/ChannelManager.java b/src/main/java/org/phoebus/channelfinder/ChannelManager.java index f6ee485d..9998fe6e 100644 --- a/src/main/java/org/phoebus/channelfinder/ChannelManager.java +++ b/src/main/java/org/phoebus/channelfinder/ChannelManager.java @@ -1,18 +1,5 @@ package org.phoebus.channelfinder; -import static org.phoebus.channelfinder.CFResourceDescriptors.CHANNEL_RESOURCE_URI; - -import java.text.MessageFormat; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.stream.Collectors; -import java.util.stream.StreamSupport; - -import javax.servlet.ServletContext; - import com.google.common.collect.FluentIterable; import com.google.common.collect.Lists; import org.phoebus.channelfinder.AuthorizationService.ROLES; @@ -35,10 +22,21 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.server.ResponseStatusException; +import javax.servlet.ServletContext; +import java.text.MessageFormat; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; + +import static org.phoebus.channelfinder.CFResourceDescriptors.CHANNEL_RESOURCE_URI; + @CrossOrigin @RestController @RequestMapping(CHANNEL_RESOURCE_URI) @@ -76,11 +74,10 @@ public class ChannelManager { */ @GetMapping public List query(@RequestParam MultiValueMap allRequestParams) { - return channelRepository.search(allRequestParams).getChannels(); + return channelRepository.search(allRequestParams).channels(); } @GetMapping("/combined") - @ResponseBody public SearchResult combinedQuery(@RequestParam MultiValueMap allRequestParams) { return channelRepository.search(allRequestParams); } @@ -129,19 +126,11 @@ public Channel create(@PathVariable("channelName") String channelName, @RequestB validateChannelRequest(channel); // check if authorized owner - if(!authorizationService.isAuthorizedOwner(SecurityContextHolder.getContext().getAuthentication(), channel)) { - String message = MessageFormat.format(TextUtil.USER_NOT_AUTHORIZED_ON_CHANNEL, channel.toLog()); - logger.log(Level.SEVERE, message, new ResponseStatusException(HttpStatus.UNAUTHORIZED)); - throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, message, null); - } + checkAndThrow(!authorizationService.isAuthorizedOwner(SecurityContextHolder.getContext().getAuthentication(), channel), TextUtil.USER_NOT_AUTHORIZED_ON_CHANNEL, channel, HttpStatus.UNAUTHORIZED); Optional existingChannel = channelRepository.findById(channelName); boolean present = existingChannel.isPresent(); if(present) { - if(!authorizationService.isAuthorizedOwner(SecurityContextHolder.getContext().getAuthentication(), existingChannel.get())) { - String message = MessageFormat.format(TextUtil.USER_NOT_AUTHORIZED_ON_CHANNEL, existingChannel.get().toLog()); - logger.log(Level.SEVERE, message, new ResponseStatusException(HttpStatus.UNAUTHORIZED)); - throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, message, null); - } + checkAndThrow(!authorizationService.isAuthorizedOwner(SecurityContextHolder.getContext().getAuthentication(), existingChannel.get()), TextUtil.USER_NOT_AUTHORIZED_ON_CHANNEL, existingChannel.get(), HttpStatus.UNAUTHORIZED); // delete existing channel channelRepository.deleteById(channelName); } @@ -177,26 +166,16 @@ public Iterable create(@RequestBody Iterable channels) { Map existingChannels = channelRepository.findAllById(StreamSupport .stream(channels.spliterator(), true) .map(Channel::getName) - .collect(Collectors.toUnmodifiableList())) - .stream().collect(Collectors.toMap(Channel::getName, channel -> { - return channel; - })); + .toList()) + .stream().collect(Collectors.toMap(Channel::getName, channel -> channel)); for(Channel channel: channels) { boolean present = existingChannels.containsKey(channel.getName()); if(present) { Channel existingChannel = existingChannels.get(channel.getName()); - if(!authorizationService.isAuthorizedOwner(SecurityContextHolder.getContext().getAuthentication(), existingChannel)) { - String message = MessageFormat.format(TextUtil.USER_NOT_AUTHORIZED_ON_CHANNEL, existingChannel.toLog()); - logger.log(Level.SEVERE, message, new ResponseStatusException(HttpStatus.UNAUTHORIZED)); - throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, message, null); - } + checkAndThrow(!authorizationService.isAuthorizedOwner(SecurityContextHolder.getContext().getAuthentication(), existingChannel), TextUtil.USER_NOT_AUTHORIZED_ON_CHANNEL, existingChannel, HttpStatus.UNAUTHORIZED); channel.setOwner(existingChannel.getOwner()); } else { - if(!authorizationService.isAuthorizedOwner(SecurityContextHolder.getContext().getAuthentication(), channel)) { - String message = MessageFormat.format(TextUtil.USER_NOT_AUTHORIZED_ON_CHANNEL, channel.toLog()); - logger.log(Level.SEVERE, message, new ResponseStatusException(HttpStatus.UNAUTHORIZED)); - throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, message, null); - } + checkAndThrow(!authorizationService.isAuthorizedOwner(SecurityContextHolder.getContext().getAuthentication(), channel), TextUtil.USER_NOT_AUTHORIZED_ON_CHANNEL, channel, HttpStatus.UNAUTHORIZED); } } logger.log(Level.INFO, "Completed Authorization check : " + (System.currentTimeMillis() - start) + "ms"); @@ -212,17 +191,7 @@ public Iterable create(@RequestBody Iterable channels) { start = System.currentTimeMillis(); // reset owners of attached tags/props back to existing owners - Map propOwners = StreamSupport - .stream(propertyRepository.findAll().spliterator(), true) - .collect(Collectors.toUnmodifiableMap(Property::getName, Property::getOwner)); - Map tagOwners = StreamSupport - .stream(tagRepository.findAll().spliterator(), true) - .collect(Collectors.toUnmodifiableMap(Tag::getName, Tag::getOwner)); - - for(Channel channel: channels) { - channel.getProperties().forEach(prop -> prop.setOwner(propOwners.get(prop.getName()))); - channel.getTags().forEach(tag -> tag.setOwner(tagOwners.get(tag.getName()))); - } + resetOwnersToExisting(channels); logger.log(Level.INFO, "Completed reset tag and property ownership : " + (System.currentTimeMillis() - start) + "ms"); start = System.currentTimeMillis(); @@ -243,6 +212,20 @@ public Iterable create(@RequestBody Iterable channels) { } } + private void resetOwnersToExisting(Iterable channels) { + Map propOwners = StreamSupport + .stream(propertyRepository.findAll().spliterator(), true) + .collect(Collectors.toUnmodifiableMap(Property::getName, Property::getOwner)); + Map tagOwners = StreamSupport + .stream(tagRepository.findAll().spliterator(), true) + .collect(Collectors.toUnmodifiableMap(Tag::getName, Tag::getOwner)); + + for(Channel channel: channels) { + channel.getProperties().forEach(prop -> prop.setOwner(propOwners.get(prop.getName()))); + channel.getTags().forEach(tag -> tag.setOwner(tagOwners.get(tag.getName()))); + } + } + /** * POST method for merging properties and tags of the channel identified by the * payload into an existing channel. @@ -263,21 +246,13 @@ public Channel update(@PathVariable("channelName") String channelName, @RequestB channelManagerAudit.log(Level.INFO, () -> MessageFormat.format(TextUtil.PATH_POST_VALIDATION_TIME, servletContext.getContextPath(), time)); // check if authorized owner - if(!authorizationService.isAuthorizedOwner(SecurityContextHolder.getContext().getAuthentication(), channel)) { - String message = MessageFormat.format(TextUtil.USER_NOT_AUTHORIZED_ON_CHANNEL, channel.toLog()); - logger.log(Level.SEVERE, message, new ResponseStatusException(HttpStatus.UNAUTHORIZED)); - throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, message, null); - } + checkAndThrow(!authorizationService.isAuthorizedOwner(SecurityContextHolder.getContext().getAuthentication(), channel), TextUtil.USER_NOT_AUTHORIZED_ON_CHANNEL, channel, HttpStatus.UNAUTHORIZED); Optional existingChannel = channelRepository.findById(channelName); boolean present = existingChannel.isPresent(); Channel newChannel; if(present) { - if(!authorizationService.isAuthorizedOwner(SecurityContextHolder.getContext().getAuthentication(), existingChannel.get())) { - String message = MessageFormat.format(TextUtil.USER_NOT_AUTHORIZED_ON_CHANNEL, existingChannel.get().toLog()); - logger.log(Level.SEVERE, message, new ResponseStatusException(HttpStatus.UNAUTHORIZED)); - throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, message, null); - } + checkAndThrow(!authorizationService.isAuthorizedOwner(SecurityContextHolder.getContext().getAuthentication(), existingChannel.get()), TextUtil.USER_NOT_AUTHORIZED_ON_CHANNEL, existingChannel.get(), HttpStatus.UNAUTHORIZED); newChannel = existingChannel.get(); newChannel.setOwner(channel.getOwner()); newChannel.addProperties(channel.getProperties()); @@ -325,18 +300,10 @@ public Iterable update(@RequestBody Iterable channels) { Optional existingChannel = channelRepository.findById(channel.getName()); boolean present = existingChannel.isPresent(); if(present) { - if(!authorizationService.isAuthorizedOwner(SecurityContextHolder.getContext().getAuthentication(), existingChannel.get())) { - String message = MessageFormat.format(TextUtil.USER_NOT_AUTHORIZED_ON_CHANNEL, existingChannel.get().toLog()); - logger.log(Level.SEVERE, message, new ResponseStatusException(HttpStatus.UNAUTHORIZED)); - throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, message, null); - } + checkAndThrow(!authorizationService.isAuthorizedOwner(SecurityContextHolder.getContext().getAuthentication(), existingChannel.get()), TextUtil.USER_NOT_AUTHORIZED_ON_CHANNEL, existingChannel.get(), HttpStatus.UNAUTHORIZED); channel.setOwner(existingChannel.get().getOwner()); } else { - if(!authorizationService.isAuthorizedOwner(SecurityContextHolder.getContext().getAuthentication(), channel)) { - String message = MessageFormat.format(TextUtil.USER_NOT_AUTHORIZED_ON_CHANNEL, channel.toLog()); - logger.log(Level.SEVERE, message, new ResponseStatusException(HttpStatus.UNAUTHORIZED)); - throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, message, null); - } + checkAndThrow(!authorizationService.isAuthorizedOwner(SecurityContextHolder.getContext().getAuthentication(), channel), TextUtil.USER_NOT_AUTHORIZED_ON_CHANNEL, channel, HttpStatus.UNAUTHORIZED); } } @@ -346,19 +313,8 @@ public Iterable update(@RequestBody Iterable channels) { final long time = System.currentTimeMillis() - start; channelManagerAudit.log(Level.INFO, () -> MessageFormat.format(TextUtil.PATH_POST_PREPERATION_TIME, servletContext.getContextPath(), time)); - start = System.currentTimeMillis(); // reset owners of attached tags/props back to existing owners - Map propOwners = StreamSupport - .stream(propertyRepository.findAll().spliterator(), true) - .collect(Collectors.toUnmodifiableMap(Property::getName, Property::getOwner)); - Map tagOwners = StreamSupport - .stream(tagRepository.findAll().spliterator(), true) - .collect(Collectors.toUnmodifiableMap(Tag::getName, Tag::getOwner)); - - for(Channel channel: channels) { - channel.getProperties().forEach(prop -> prop.setOwner(propOwners.get(prop.getName()))); - channel.getTags().forEach(tag -> tag.setOwner(tagOwners.get(tag.getName()))); - } + resetOwnersToExisting(channels); channelManagerAudit.log(Level.INFO, () -> MessageFormat.format(TextUtil.PATH_POST_PREPERATION_TIME, servletContext.getContextPath(), time)); // update channels @@ -408,17 +364,6 @@ public void remove(@PathVariable("channelName") String channelName) { } } - /** - * Check that the existing channel and the channel in the request body match - * - * @param existing - * @param request - * @return - */ - boolean validateChannel(Channel existing, Channel request) { - return existing.getName().equals(request.getName()); - } - /** * Checks if * 1. the channel name is not null and matches the name in the body @@ -428,37 +373,30 @@ boolean validateChannel(Channel existing, Channel request) { * @param channel channel to be validated */ public void validateChannelRequest(Channel channel) { - // 1 - if (channel.getName() == null || channel.getName().isEmpty()) { - String message = MessageFormat.format(TextUtil.CHANNEL_NAME_CANNOT_BE_NULL_OR_EMPTY, channel.toLog()); - logger.log(Level.SEVERE, message, new ResponseStatusException(HttpStatus.BAD_REQUEST)); - throw new ResponseStatusException(HttpStatus.BAD_REQUEST, message, null); - } + // 1 + checkAndThrow(channel.getName() == null || channel.getName().isEmpty(), TextUtil.CHANNEL_NAME_CANNOT_BE_NULL_OR_EMPTY, channel, HttpStatus.BAD_REQUEST); // 2 - if (channel.getOwner() == null || channel.getOwner().isEmpty()) { - String message = MessageFormat.format(TextUtil.CHANNEL_OWNER_CANNOT_BE_NULL_OR_EMPTY, channel.toLog()); - logger.log(Level.SEVERE, message, new ResponseStatusException(HttpStatus.BAD_REQUEST)); - throw new ResponseStatusException(HttpStatus.BAD_REQUEST, message, null); - } + checkAndThrow(channel.getOwner() == null || channel.getOwner().isEmpty(), TextUtil.CHANNEL_OWNER_CANNOT_BE_NULL_OR_EMPTY, channel, HttpStatus.BAD_REQUEST); // 3 - List tagNames = channel.getTags().stream().map(Tag::getName).collect(Collectors.toList()); - for(String tagName:tagNames) { - if(!tagRepository.existsById(tagName)) { - String message = MessageFormat.format(TextUtil.TAG_NAME_DOES_NOT_EXIST, tagName); - logger.log(Level.SEVERE, message, new ResponseStatusException(HttpStatus.NOT_FOUND)); - throw new ResponseStatusException(HttpStatus.NOT_FOUND, message); - } - } + checkTags(channel); // 3 - List propertyNames = channel.getProperties().stream().map(Property::getName).collect(Collectors.toList()); - List propertyValues = channel.getProperties().stream().map(Property::getValue).collect(Collectors.toList()); + checkProperties(channel); + } + + private void checkProperties(Channel channel) { + List propertyNames = channel.getProperties().stream().map(Property::getName).toList(); + List propertyValues = channel.getProperties().stream().map(Property::getValue).toList(); for(String propertyName:propertyNames) { if(!propertyRepository.existsById(propertyName)) { String message = MessageFormat.format(TextUtil.PROPERTY_NAME_DOES_NOT_EXIST, propertyName); logger.log(Level.SEVERE, message, new ResponseStatusException(HttpStatus.NOT_FOUND)); throw new ResponseStatusException(HttpStatus.NOT_FOUND, message); - } + } } + checkValues(propertyNames, propertyValues); + } + + private void checkValues(List propertyNames, List propertyValues) { for(String propertyValue:propertyValues) { if(propertyValue == null || propertyValue.isEmpty()) { String message = MessageFormat.format(TextUtil.PROPERTY_VALUE_NULL_OR_EMPTY, propertyNames.get(propertyValues.indexOf(propertyValue)), propertyValue); @@ -468,6 +406,25 @@ public void validateChannelRequest(Channel channel) { } } + private void checkTags(Channel channel) { + List tagNames = channel.getTags().stream().map(Tag::getName).toList(); + for(String tagName:tagNames) { + if(!tagRepository.existsById(tagName)) { + String message = MessageFormat.format(TextUtil.TAG_NAME_DOES_NOT_EXIST, tagName); + logger.log(Level.SEVERE, message, new ResponseStatusException(HttpStatus.NOT_FOUND)); + throw new ResponseStatusException(HttpStatus.NOT_FOUND, message); + } + } + } + + private static void checkAndThrow(boolean channel, String channelNameCannotBeNullOrEmpty, Channel channel1, HttpStatus badRequest) { + if (channel) { + String message = MessageFormat.format(channelNameCannotBeNullOrEmpty, channel1.toLog()); + logger.log(Level.SEVERE, message, new ResponseStatusException(badRequest)); + throw new ResponseStatusException(badRequest, message, null); + } + } + /** * Checks if * 1. the tag names are not null @@ -480,26 +437,18 @@ public void validateChannelRequest(Iterable channels) { List existingProperties = StreamSupport .stream(propertyRepository.findAll().spliterator(), true) .map(Property::getName) - .collect(Collectors.toUnmodifiableList()); + .toList(); List existingTags = StreamSupport .stream(tagRepository.findAll().spliterator(), true) .map(Tag::getName) - .collect(Collectors.toUnmodifiableList()); + .toList(); for(Channel channel: channels) { // 1 - if (channel.getName() == null || channel.getName().isEmpty()) { - String message = MessageFormat.format(TextUtil.CHANNEL_NAME_CANNOT_BE_NULL_OR_EMPTY, channel.toLog()); - logger.log(Level.SEVERE, message, new ResponseStatusException(HttpStatus.BAD_REQUEST)); - throw new ResponseStatusException(HttpStatus.BAD_REQUEST, message, null); - } + checkAndThrow(channel.getName() == null || channel.getName().isEmpty(), TextUtil.CHANNEL_NAME_CANNOT_BE_NULL_OR_EMPTY, channel, HttpStatus.BAD_REQUEST); // 2 - if (channel.getOwner() == null || channel.getOwner().isEmpty()) { - String message = MessageFormat.format(TextUtil.CHANNEL_OWNER_CANNOT_BE_NULL_OR_EMPTY, channel.toLog()); - logger.log(Level.SEVERE, message, new ResponseStatusException(HttpStatus.BAD_REQUEST)); - throw new ResponseStatusException(HttpStatus.BAD_REQUEST, message, null); - } + checkAndThrow(channel.getOwner() == null || channel.getOwner().isEmpty(), TextUtil.CHANNEL_OWNER_CANNOT_BE_NULL_OR_EMPTY, channel, HttpStatus.BAD_REQUEST); // 3 - List tagNames = channel.getTags().stream().map(Tag::getName).collect(Collectors.toList()); + List tagNames = channel.getTags().stream().map(Tag::getName).toList(); for(String tagName:tagNames) { if(!existingTags.contains(tagName)) { String message = MessageFormat.format(TextUtil.TAG_NAME_DOES_NOT_EXIST, tagName); @@ -508,8 +457,8 @@ public void validateChannelRequest(Iterable channels) { } } // 3 - List propertyNames = channel.getProperties().stream().map(Property::getName).collect(Collectors.toList()); - List propertyValues = channel.getProperties().stream().map(Property::getValue).collect(Collectors.toList()); + List propertyNames = channel.getProperties().stream().map(Property::getName).toList(); + List propertyValues = channel.getProperties().stream().map(Property::getValue).toList(); for(String propertyName:propertyNames) { if(!existingProperties.contains(propertyName)) { String message = MessageFormat.format(TextUtil.PROPERTY_NAME_DOES_NOT_EXIST, propertyName); @@ -517,13 +466,7 @@ public void validateChannelRequest(Iterable channels) { throw new ResponseStatusException(HttpStatus.NOT_FOUND, message); } } - for(String propertyValue:propertyValues) { - if(propertyValue == null || propertyValue.isEmpty()) { - String message = MessageFormat.format(TextUtil.PROPERTY_VALUE_NULL_OR_EMPTY, propertyNames.get(propertyValues.indexOf(propertyValue)), propertyValue); - logger.log(Level.SEVERE, message, new ResponseStatusException(HttpStatus.BAD_REQUEST)); - throw new ResponseStatusException(HttpStatus.BAD_REQUEST, message); - } - } + checkValues(propertyNames, propertyValues); } } diff --git a/src/main/java/org/phoebus/channelfinder/PropertyRepository.java b/src/main/java/org/phoebus/channelfinder/PropertyRepository.java index 217bd81a..125f07c3 100644 --- a/src/main/java/org/phoebus/channelfinder/PropertyRepository.java +++ b/src/main/java/org/phoebus/channelfinder/PropertyRepository.java @@ -225,7 +225,7 @@ public Optional findById(String propertyName, boolean withChannels) { if(withChannels) { MultiValueMap params = new LinkedMultiValueMap<>(); params.add(property.getName(), "*"); - property.setChannels(channelRepository.search(params).getChannels()); + property.setChannels(channelRepository.search(params).channels()); } return Optional.of(property); } else { @@ -330,7 +330,7 @@ public void deleteById(String propertyName) { BulkRequest.Builder br = new BulkRequest.Builder().refresh(Refresh.True); MultiValueMap params = new LinkedMultiValueMap<>(); params.add(propertyName, "*"); - List channels = channelRepository.search(params).getChannels(); + List channels = channelRepository.search(params).channels(); while (channels.size() > 0) { for (Channel channel : channels) { channel.removeProperty( @@ -360,7 +360,7 @@ public void deleteById(String propertyName) { } params.set("~search_after", channels.get(channels.size() - 1).getName()); - channels = channelRepository.search(params).getChannels(); + channels = channelRepository.search(params).channels(); } } catch (ElasticsearchException | IOException e) { String message = MessageFormat.format(TextUtil.FAILED_TO_DELETE_PROPERTY, propertyName); diff --git a/src/main/java/org/phoebus/channelfinder/TagRepository.java b/src/main/java/org/phoebus/channelfinder/TagRepository.java index b7dac3b1..fcdca00b 100644 --- a/src/main/java/org/phoebus/channelfinder/TagRepository.java +++ b/src/main/java/org/phoebus/channelfinder/TagRepository.java @@ -2,6 +2,7 @@ import java.io.IOException; import java.text.MessageFormat; +import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.logging.Level; @@ -104,14 +105,14 @@ public List indexAll(List tags) { } // TODO cleanup? or throw exception? } else { - return findAllById(tags.stream().map(Tag::getName).collect(Collectors.toList())); + return findAllById(tags.stream().map(Tag::getName).toList()); } } catch (IOException e) { String message = MessageFormat.format(TextUtil.FAILED_TO_INDEX_TAGS, tags); logger.log(Level.SEVERE, message, e); throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, message, null); } - return null; + return Collections.emptyList(); } /** @@ -186,7 +187,7 @@ public Iterable saveAll(Iterable tags) { return (Iterable) findAllById( StreamSupport.stream(tags.spliterator(), false) .map(Tag::getName) - .collect(Collectors.toList())); + .toList()); } } catch (IOException e) { String message = MessageFormat.format(TextUtil.FAILED_TO_INDEX_TAGS, tags); @@ -226,7 +227,7 @@ public Optional findById(String tagId, boolean withChannels) { if(withChannels) { MultiValueMap params = new LinkedMultiValueMap<>(); params.add("~tag", tag.getName()); - tag.setChannels(channelRepository.search(params).getChannels()); + tag.setChannels(channelRepository.search(params).channels()); } return Optional.of(tag); } else { @@ -267,7 +268,7 @@ public Iterable findAll() { .size(10000) .sort(SortOptions.of(s -> s.field(FieldSort.of(f -> f.field("name"))))); SearchResponse response = client.search(searchBuilder.build(), Tag.class); - return response.hits().hits().stream().map(Hit::source).collect(Collectors.toList()); + return response.hits().hits().stream().map(Hit::source).toList(); } catch (ElasticsearchException | IOException e) { logger.log(Level.SEVERE, TextUtil.FAILED_TO_FIND_ALL_TAGS, e); throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, TextUtil.FAILED_TO_FIND_ALL_TAGS, null); @@ -283,14 +284,14 @@ public Iterable findAll() { @Override public List findAllById(Iterable tagIds) { try { - List ids = StreamSupport.stream(tagIds.spliterator(), false).collect(Collectors.toList()); + List ids = StreamSupport.stream(tagIds.spliterator(), false).toList(); SearchRequest.Builder searchBuilder = new Builder() .index(esService.getES_TAG_INDEX()) .query(IdsQuery.of(q -> q.values(ids))._toQuery()) .size(10000) .sort(SortOptions.of(s -> s.field(FieldSort.of(f -> f.field("name"))))); SearchResponse response = client.search(searchBuilder.build(), Tag.class); - return response.hits().hits().stream().map(Hit::source).collect(Collectors.toList()); + return response.hits().hits().stream().map(Hit::source).toList(); } catch (ElasticsearchException | IOException e) { logger.log(Level.SEVERE, TextUtil.FAILED_TO_FIND_ALL_TAGS, e); throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, TextUtil.FAILED_TO_FIND_ALL_TAGS, null); @@ -329,18 +330,10 @@ public void deleteById(String tagName) { BulkRequest.Builder br = new BulkRequest.Builder().refresh(Refresh.True); MultiValueMap params = new LinkedMultiValueMap<>(); params.add("~tag", tagName); - List channels = channelRepository.search(params).getChannels(); - while (channels.size() > 0) { + List channels = channelRepository.search(params).channels(); + while (!channels.isEmpty()) { for (Channel channel : channels) { -// br.operations(op -> op.update( -// u -> u.index(esService.getES_CHANNEL_INDEX()) -// .id(channel.getName()) -// .action(a -> a.script( -// Script.of(script -> script.inline( -// InlineScript.of( -// i -> i.source("ctx._source.tags.removeIf(list_item -> list_item.name == params.remove_tag);") -// .params("remove_tag", JsonData.of(tagName))))))))); // Or channel.removeTag(channel.getTags().stream().filter(tag -> tagName.equalsIgnoreCase(tag.getName())).findAny().get()); br.operations(op -> op.update( @@ -366,7 +359,7 @@ public void deleteById(String tagName) { } params.set("~search_after", channels.get(channels.size() - 1).getName()); - channels = channelRepository.search(params).getChannels(); + channels = channelRepository.search(params).channels(); } } catch (ElasticsearchException | IOException e) { diff --git a/src/main/java/org/phoebus/channelfinder/entity/Channel.java b/src/main/java/org/phoebus/channelfinder/entity/Channel.java index 87175c27..10d7f6a2 100644 --- a/src/main/java/org/phoebus/channelfinder/entity/Channel.java +++ b/src/main/java/org/phoebus/channelfinder/entity/Channel.java @@ -9,9 +9,6 @@ * All rights reserved. Use is subject to license terms. * #L% */ - -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlType; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -22,8 +19,6 @@ * @author Ralph Lange {@literal } */ -@XmlRootElement(name="channel") -@XmlType (propOrder={"name","owner","properties","tags"}) public class Channel { private String name; private String owner; diff --git a/src/main/java/org/phoebus/channelfinder/entity/Property.java b/src/main/java/org/phoebus/channelfinder/entity/Property.java index ad6f9fee..3be7ccaf 100644 --- a/src/main/java/org/phoebus/channelfinder/entity/Property.java +++ b/src/main/java/org/phoebus/channelfinder/entity/Property.java @@ -12,8 +12,6 @@ import com.fasterxml.jackson.annotation.JsonIgnore; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlType; import java.util.ArrayList; import java.util.List; @@ -22,8 +20,6 @@ * * @author Ralph Lange {@literal } */ -@XmlRootElement(name="property") -@XmlType (propOrder={"name","owner","value","channels"}) public class Property { private String name; private String owner; diff --git a/src/main/java/org/phoebus/channelfinder/entity/Scroll.java b/src/main/java/org/phoebus/channelfinder/entity/Scroll.java index d2bf356b..51be0ae9 100644 --- a/src/main/java/org/phoebus/channelfinder/entity/Scroll.java +++ b/src/main/java/org/phoebus/channelfinder/entity/Scroll.java @@ -3,11 +3,6 @@ import java.util.ArrayList; import java.util.List; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlType; - -@XmlRootElement(name="scroll") -@XmlType (propOrder={"id","channels"}) public class Scroll { private String id; private List channels = new ArrayList<>(); diff --git a/src/main/java/org/phoebus/channelfinder/entity/SearchResult.java b/src/main/java/org/phoebus/channelfinder/entity/SearchResult.java index 343a627e..43ab51d3 100644 --- a/src/main/java/org/phoebus/channelfinder/entity/SearchResult.java +++ b/src/main/java/org/phoebus/channelfinder/entity/SearchResult.java @@ -4,13 +4,7 @@ import java.util.List; -public class SearchResult { - private final long count; - private final List channels; - public SearchResult(List channels, long count) { - this.channels = channels; - this.count = count; - } +public record SearchResult(List channels, long count) { @Override public String toString() { @@ -21,25 +15,17 @@ public String toString() { } @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - SearchResult that = (SearchResult) o; - return count == that.count && Objects.equal(channels, that.channels); - } - - @Override - public int hashCode() { - return Objects.hashCode(count, channels); - } - - public long getCount() { - return count; - } + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + SearchResult that = (SearchResult) o; + return count == that.count && Objects.equal(channels, that.channels); + } - public List getChannels() { - return channels; - } + @Override + public int hashCode() { + return Objects.hashCode(count, channels); + } - } \ No newline at end of file +} \ No newline at end of file diff --git a/src/main/java/org/phoebus/channelfinder/entity/Tag.java b/src/main/java/org/phoebus/channelfinder/entity/Tag.java index 815d2c4e..ed2166b7 100644 --- a/src/main/java/org/phoebus/channelfinder/entity/Tag.java +++ b/src/main/java/org/phoebus/channelfinder/entity/Tag.java @@ -12,8 +12,6 @@ import com.fasterxml.jackson.annotation.JsonIgnore; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlType; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -23,8 +21,6 @@ * * @author Ralph Lange {@literal } */ -@XmlRootElement(name="tag") -@XmlType (propOrder={"name","owner","channels"}) public class Tag { private String name; private String owner; diff --git a/src/main/java/org/phoebus/channelfinder/epics/ChannelFinderEpicsService.java b/src/main/java/org/phoebus/channelfinder/epics/ChannelFinderEpicsService.java index 31965cfa..c26e2e68 100644 --- a/src/main/java/org/phoebus/channelfinder/epics/ChannelFinderEpicsService.java +++ b/src/main/java/org/phoebus/channelfinder/epics/ChannelFinderEpicsService.java @@ -145,7 +145,7 @@ public PVAStructure run() throws MustBeArrayException { } } - List result = channelRepository.search(searchParameters).getChannels(); + List result = channelRepository.search(searchParameters).channels(); final Map> channelTable = new HashMap<>(); final Map> channelPropertyTable = new HashMap<>(); diff --git a/src/test/java/org/phoebus/channelfinder/ChannelRepositorySearchIT.java b/src/test/java/org/phoebus/channelfinder/ChannelRepositorySearchIT.java index 853035a8..908ac587 100644 --- a/src/test/java/org/phoebus/channelfinder/ChannelRepositorySearchIT.java +++ b/src/test/java/org/phoebus/channelfinder/ChannelRepositorySearchIT.java @@ -82,10 +82,10 @@ void searchTest() { searchParameters.add("~name", channelNames.get(0)); SearchResult result = channelRepository.search(searchParameters); long countResult = channelRepository.count(searchParameters); - Assertions.assertEquals(1, result.getCount()); - Assertions.assertEquals(1, result.getChannels().size()); + Assertions.assertEquals(1, result.count()); + Assertions.assertEquals(1, result.channels().size()); Assertions.assertEquals(1, countResult); - Assertions.assertEquals(result.getChannels().get(0).getName(), channelNames.get(0)); + Assertions.assertEquals(result.channels().get(0).getName(), channelNames.get(0)); logger.log(Level.INFO, "Search for all channels via wildcards"); searchName(2, "BR:C001-BI:2{BLA}Pos:?-RB"); @@ -142,8 +142,8 @@ private void assertSearchCount(long expectedResultCount, int expectedChannelsCou long countResult = channelRepository.count(searchParameters); // Assert - Assertions.assertEquals(expectedResultCount, result.getCount()); - Assertions.assertEquals(expectedChannelsCount, result.getChannels().size()); + Assertions.assertEquals(expectedResultCount, result.count()); + Assertions.assertEquals(expectedChannelsCount, result.channels().size()); Assertions.assertEquals(expectedQueryCount, countResult); } @@ -156,7 +156,7 @@ private void checkGroup(int bucket, String key, String value) { SearchResult result = channelRepository.search(searchParameters); long countResult = channelRepository.count(searchParameters); Integer expectedCount = CELLS * bucket; - Assertions.assertEquals(expectedCount, Integer.valueOf(result.getChannels().size()), "Search: " + maptoString(searchParameters)); + Assertions.assertEquals(expectedCount, Integer.valueOf(result.channels().size()), "Search: " + maptoString(searchParameters)); Assertions.assertEquals(expectedCount, Integer.valueOf((int) countResult)); } diff --git a/src/test/java/org/phoebus/channelfinder/PropertyManagerIT.java b/src/test/java/org/phoebus/channelfinder/PropertyManagerIT.java index b0c45f89..28c32d73 100644 --- a/src/test/java/org/phoebus/channelfinder/PropertyManagerIT.java +++ b/src/test/java/org/phoebus/channelfinder/PropertyManagerIT.java @@ -330,7 +330,7 @@ void createXmlPropertiesWithOverride() { MultiValueMap params = new LinkedMultiValueMap(); params.add("testProperty0WithChannels", "*"); // verify the property was removed from the old channels - Assertions.assertEquals(Arrays.asList(testChannels.get(1)), channelRepository.search(params).getChannels(), "Failed to delete the property from channels"); + Assertions.assertEquals(Arrays.asList(testChannels.get(1)), channelRepository.search(params).channels(), "Failed to delete the property from channels"); } /** @@ -736,7 +736,7 @@ void deleteXmlProperty() { params.add("testProperty0WithChannels", "*"); // verify the property was deleted and removed from all associated channels Assertions.assertFalse(propertyRepository.existsById(testProperty0WithChannels.getName()), "Failed to delete the property"); - Assertions.assertEquals(new ArrayList(), channelRepository.search(params).getChannels(), "Failed to delete the property from channels"); + Assertions.assertEquals(new ArrayList(), channelRepository.search(params).channels(), "Failed to delete the property from channels"); } /** @@ -757,7 +757,7 @@ void deleteXmlPropertyFromChannel() { // Verify the property is removed from the testChannel0 MultiValueMap searchParameters = new LinkedMultiValueMap(); searchParameters.add("testProperty0WithChannels", "*"); - Assertions.assertFalse(channelRepository.search(searchParameters).getChannels().stream().anyMatch(ch -> { + Assertions.assertFalse(channelRepository.search(searchParameters).channels().stream().anyMatch(ch -> { return ch.getName().equals(testChannel0.getName()); }), "Failed to delete the property from channel"); } diff --git a/src/test/java/org/phoebus/channelfinder/PropertyRepositoryIT.java b/src/test/java/org/phoebus/channelfinder/PropertyRepositoryIT.java index 970b14e0..130926e1 100644 --- a/src/test/java/org/phoebus/channelfinder/PropertyRepositoryIT.java +++ b/src/test/java/org/phoebus/channelfinder/PropertyRepositoryIT.java @@ -256,7 +256,7 @@ void deleteXmlProperty() { MultiValueMap params = new LinkedMultiValueMap(); params.add("testProperty","*"); - List chans = channelRepository.search(params).getChannels(); + List chans = channelRepository.search(params).channels(); // verify the property was deleted from channels as expected Assertions.assertTrue(chans.isEmpty(), "Failed to remove property from channel"); } diff --git a/src/test/java/org/phoebus/channelfinder/TagManagerIT.java b/src/test/java/org/phoebus/channelfinder/TagManagerIT.java index 0ab1ac68..03ffc52d 100644 --- a/src/test/java/org/phoebus/channelfinder/TagManagerIT.java +++ b/src/test/java/org/phoebus/channelfinder/TagManagerIT.java @@ -292,7 +292,7 @@ void createXmlTagsWithOverride() { MultiValueMap params = new LinkedMultiValueMap(); params.add("~tag", testTag0WithChannels.getName()); // verify the tag was removed from the old channels - Assertions.assertEquals(Arrays.asList(testChannel1), channelRepository.search(params).getChannels(), "Failed to change the channels the tag is attached to correctly"); + Assertions.assertEquals(Arrays.asList(testChannel1), channelRepository.search(params).channels(), "Failed to change the channels the tag is attached to correctly"); } /** @@ -628,7 +628,7 @@ void deleteXmlTag() { params.add("~tag", testTag1.getName()); // verify the tag was deleted and removed from all associated channels Assertions.assertFalse(tagRepository.existsById(testTag1.getName()), "Failed to delete the tag"); - Assertions.assertEquals(new ArrayList(), channelRepository.search(params).getChannels(), "Failed to delete the tag from channels"); + Assertions.assertEquals(new ArrayList(), channelRepository.search(params).channels(), "Failed to delete the tag from channels"); } /** @@ -648,7 +648,7 @@ void deleteXmlTagFromChannel() { // Verify the tag is removed from the testChannel0 MultiValueMap searchParameters = new LinkedMultiValueMap(); searchParameters.add("~tag", testTag1.getName()); - Assertions.assertFalse(channelRepository.search(searchParameters).getChannels().stream().anyMatch(ch -> { + Assertions.assertFalse(channelRepository.search(searchParameters).channels().stream().anyMatch(ch -> { return ch.getName().equals(testChannels().get(0).getName()); }), "Failed to delete the tag from channel"); } diff --git a/src/test/java/org/phoebus/channelfinder/TagRepositoryIT.java b/src/test/java/org/phoebus/channelfinder/TagRepositoryIT.java index 5464f1cb..427b2299 100644 --- a/src/test/java/org/phoebus/channelfinder/TagRepositoryIT.java +++ b/src/test/java/org/phoebus/channelfinder/TagRepositoryIT.java @@ -228,7 +228,7 @@ void deleteXmlTag() { // verify the tag was deleted from all channels as expected MultiValueMap params = new LinkedMultiValueMap(); params.add("~tag","testChannel"); - List chans = channelRepository.search(params).getChannels(); + List chans = channelRepository.search(params).channels(); Assertions.assertTrue(chans.isEmpty(), "Failed to remove tag from channel"); // channel clean up