From f62870e3edb1ac842d518dc9ea03ff4f4b94fe48 Mon Sep 17 00:00:00 2001 From: Kunal Shroff Date: Thu, 16 Jan 2025 16:06:15 -0500 Subject: [PATCH 1/4] Issue #3235 a formula to extract and format timestamp from pv values --- core/formula/doc/index.rst | 6 ++ core/formula/pom.xml | 11 +++ .../formula/time/TimestampFunction.java | 68 +++++++++++++++++++ ...studio.apputil.formula.spi.FormulaFunction | 2 + 4 files changed, 87 insertions(+) create mode 100644 core/formula/src/main/java/org/csstudio/apputil/formula/time/TimestampFunction.java diff --git a/core/formula/doc/index.rst b/core/formula/doc/index.rst index d0a83eea43..c4e9eb274d 100644 --- a/core/formula/doc/index.rst +++ b/core/formula/doc/index.rst @@ -164,6 +164,12 @@ Enum **indexOf(Enum e)** - Return the index of the enum value. +Time +---- + +**timestamp(VType value)** - returns the timestamp of the provided value formatted using the millisecond format. + +**timestamp(VType value, String format)** - returns the timestamp of the provided value formatted using the user defined format. Alarm ----- diff --git a/core/formula/pom.xml b/core/formula/pom.xml index 4c72940b7f..acc0eea629 100644 --- a/core/formula/pom.xml +++ b/core/formula/pom.xml @@ -17,6 +17,11 @@ org.phoebus core-vtype 4.7.4-SNAPSHOT + + + org.phoebus + core-util + 4.7.4-SNAPSHOT org.junit.jupiter @@ -30,5 +35,11 @@ 1.3 test + + org.phoebus + core-util + 4.7.4-SNAPSHOT + compile + diff --git a/core/formula/src/main/java/org/csstudio/apputil/formula/time/TimestampFunction.java b/core/formula/src/main/java/org/csstudio/apputil/formula/time/TimestampFunction.java new file mode 100644 index 0000000000..604096076b --- /dev/null +++ b/core/formula/src/main/java/org/csstudio/apputil/formula/time/TimestampFunction.java @@ -0,0 +1,68 @@ +package org.csstudio.apputil.formula.time; + +import org.csstudio.apputil.formula.array.BaseArrayFunction; +import org.csstudio.apputil.formula.spi.FormulaFunction; +import org.epics.vtype.Alarm; +import org.epics.vtype.Time; +import org.epics.vtype.VString; +import org.epics.vtype.VType; +import org.phoebus.core.vtypes.VTypeHelper; + +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.phoebus.util.time.TimestampFormats.MILLI_FORMAT; + +/** + * Extract the timestamps from PV values + */ +public class TimestampFunction implements FormulaFunction { + + final private static ZoneId zone = ZoneId.systemDefault(); + final private static VString emptyString = VString.of("", Alarm.none(), Time.now()); + + @Override + public String getCategory() { + return "time"; + } + + @Override + public String getName() { + return "timestamp"; + } + + @Override + public String getDescription() { + return "Returns the timestamp of the last update"; + } + + @Override + public List getArguments() { + return List.of("pv_name", "time format (optional)"); + } + + @Override + public boolean isVarArgs() { + return true; + } + + private Map formatters = new HashMap<>(); + + @Override + public VType compute(VType... args) { + if (args.length == 1) { + return VString.of(MILLI_FORMAT.format(VTypeHelper.getTimestamp(args[0])), Alarm.none(), Time.now()); + } else if (args.length == 2) { + String format = VTypeHelper.toString(args[1]); + if (!formatters.containsKey(format)) { + formatters.put(format, DateTimeFormatter.ofPattern(VTypeHelper.toString(args[1])).withZone(zone)); + } + return VString.of(formatters.get(format).format(VTypeHelper.getTimestamp(args[0])), Alarm.none(), Time.now()); + } + return emptyString; + + } +} diff --git a/core/formula/src/main/resources/META-INF/services/org.csstudio.apputil.formula.spi.FormulaFunction b/core/formula/src/main/resources/META-INF/services/org.csstudio.apputil.formula.spi.FormulaFunction index dda928c5b0..bfabcdc621 100644 --- a/core/formula/src/main/resources/META-INF/services/org.csstudio.apputil.formula.spi.FormulaFunction +++ b/core/formula/src/main/resources/META-INF/services/org.csstudio.apputil.formula.spi.FormulaFunction @@ -74,3 +74,5 @@ org.csstudio.apputil.formula.alarm.MinorAlarmFunction org.csstudio.apputil.formula.enums.IndexOfFunction org.csstudio.apputil.formula.enums.EnumOfFunction +# Time +org.csstudio.apputil.formula.time.TimestampFunction \ No newline at end of file From 98913d1b0437f3610a9a95b3accde2909ae0b7d4 Mon Sep 17 00:00:00 2001 From: georgweiss Date: Fri, 17 Jan 2025 12:55:33 +0100 Subject: [PATCH 2/4] Reinstating all channel finder client methods --- .../channelfinder/ChannelFinderClient.java | 296 ++++++- .../ChannelFinderClientImpl.java | 758 +++++++++++++++++- .../channelfinder/ChannelFinderException.java | 13 +- 3 files changed, 994 insertions(+), 73 deletions(-) diff --git a/app/channel/channelfinder/src/main/java/org/phoebus/channelfinder/ChannelFinderClient.java b/app/channel/channelfinder/src/main/java/org/phoebus/channelfinder/ChannelFinderClient.java index 2c2d0cd466..7df5b4d2b6 100644 --- a/app/channel/channelfinder/src/main/java/org/phoebus/channelfinder/ChannelFinderClient.java +++ b/app/channel/channelfinder/src/main/java/org/phoebus/channelfinder/ChannelFinderClient.java @@ -5,6 +5,9 @@ */ package org.phoebus.channelfinder; +import org.phoebus.channelfinder.Channel.Builder; + +import javax.ws.rs.core.MultivaluedMap; import java.util.Collection; import java.util.Map; @@ -24,6 +27,16 @@ public interface ChannelFinderClient { */ Collection getAllProperties(); + /** + * Get a list of names of all the properties currently present on the + * channelfinder service. + * + * @return list of names of all existing {@link Property}s. + */ + Collection getAllPropertyNames(); + + Collection getAllChannels(); + /** * GEt a list of all the tags * @@ -39,6 +52,204 @@ public interface ChannelFinderClient { */ Collection getAllTagNames(); + /** + * Returns a channel that exactly matches the channelName + * channelName. + * + * @param channelName - name of the required channel. + * @return {@link Channel} with name channelName or null + * @throws ChannelFinderException - channelfinder exception + */ + Channel getChannel(String channelName) throws ChannelFinderException; + + /** + * Destructively set a single channel channel, if the channel + * already exists it will be replaced with the given channel. + * + * @param channel the channel to be added + * @throws ChannelFinderException - channelfinder exception + */ + void set(Channel.Builder channel) throws ChannelFinderException; + + + /** + * Destructively set a Tag tag with no associated channels to the + * database. + * + * @param tag - the tag to be set. + */ + void set(Tag.Builder tag); + + /** + * Destructively set tag tag to channel channelName and + * remove the tag from all other channels. + * + * @param tag - the tag to be set. + * @param channelName - the channel to which the tag should be set on. + * @throws ChannelFinderException - channelfinder exception + */ + void set(Tag.Builder tag, String channelName) + throws ChannelFinderException; + + /** + * Set tag tag on the set of channels {channels} and remove it from + * all others. + * + * @param tag - the tag to be set. + * @param channelNames - the list of channels to which this tag will be added and + * removed from all others. + * @throws ChannelFinderException - channelfinder exception + */ + void set(Tag.Builder tag, Collection channelNames) + throws ChannelFinderException; + + /** + * Destructively set a new property property. + * + * @param prop - the property to be set. + */ + void set(Property.Builder prop) throws ChannelFinderException; + + /** + * Destructively set property prop and add it to the channel + * channelName and remove it from all others. + * + * @param prop - property to be set. + * @param channelName - the channel to which this property must be added. + */ + void set(Property.Builder prop, String channelName); + + /** + * Destructively set property prop and add it to the channels + * channelNames removing it from all other channels. By default all + * channels will contain the property with the same value specified in the + * prop.
+ * to individually set the value for each channel use channelPropertyMap. + * + * @param prop - the property to be set. + * @param channelNames - the channels to which this property should be added and + * removed from all others. + */ + void set(Property.Builder prop, Collection channelNames); + + /** + * Destructively set the property prop and add it to the channels + * specified in the channelPropertyMap, where the map key is the + * channel name and the associated value is the property value to be used + * for that channel. + * + * @param prop - the property to be set. + * @param channelPropertyMap - map with channel names and property values + */ + void set(Property.Builder prop, Map channelPropertyMap); + + /** + * Update existing channel with channel. + * + * @param channel - channel builder + * @throws ChannelFinderException - channelfinder exception + */ + void update(Channel.Builder channel) throws ChannelFinderException; + + /** + * Update Tag tag by adding it to Channel with name + * channelName, without affecting the other instances of this tag. + * + * @param tag the tag to be added + * @param channelName Name of the channel to which the tag is to be added + * @throws ChannelFinderException - channelfinder exception + */ + void update(Tag.Builder tag, String channelName) + throws ChannelFinderException; + + /** + * Update the Tag tag by adding it to the set of the channels with + * names channelNames, without affecting the other instances of + * this tag. + * + * @param tag - the tag that needs to be updated. + * @param channelNames - list of channels to which this tag should be added. + * @throws ChannelFinderException - channelfinder exception + */ + void update(Tag.Builder tag, Collection channelNames) + throws ChannelFinderException; + + /** + * Update Property property by adding it to the channel + * channelName, without affecting the other channels. + * + * @param property - the property to be updated + * @param channelName - the channel to which this property should be added or + * updated. + * @throws ChannelFinderException - channelfinder exception + */ + void update(Property.Builder property, String channelName) + throws ChannelFinderException; + + + /** + * Update the channels identified with channelNames with the + * property property + * + * @param property - property builder + * @param channelNames - list of channel names + * @throws ChannelFinderException - channelfinder exception + */ + void update(Property.Builder property, + Collection channelNames) throws ChannelFinderException; + + /** + * Update the property property on all channels specified in the + * channelPropValueMap, where the key in the map is the channel name and the + * value is the value for that property + * + * @param property - property builder + * @param channelPropValueMap - property value map + * @throws ChannelFinderException - channelfinder exception + */ + void update(Property.Builder property, Map channelPropValueMap) + throws ChannelFinderException; + + /** + * Search for channels who's name match the pattern pattern.
+ * The pattern can contain wildcard char * or ?.
+ * + * @param pattern - the search pattern for the channel names + * @return A Collection of channels who's name match the pattern + * pattern + * @throws ChannelFinderException - channelfinder exception + */ + Collection findByName(String pattern) + throws ChannelFinderException; + + /** + * Search for channels with tags who's name match the pattern + * pattern.
+ * The pattern can contain wildcard char * or ?.
+ * + * @param pattern - the search pattern for the tag names + * @return A Collection of channels which contain tags who's name match the + * pattern pattern + * @throws ChannelFinderException - channelfinder exception + */ + Collection findByTag(String pattern) + throws ChannelFinderException; + + /** + * Search for channels with properties who's Value match the pattern + * pattern.
+ * The pattern can contain wildcard char * or ?.
+ * + * @param property - the name of the property. + * @param pattern - the seatch pattern for the property value. + * @return A collection of channels containing the property with name + * propertyName who's value matches the pattern + * pattern. + * @throws ChannelFinderException - channelfinder exception + */ + Collection findByProperty(String property, + String... pattern) throws ChannelFinderException; + /** * Space seperated search criterias, patterns may include * and ? wildcards * channelNamePattern propertyName=valuePattern1,valuePattern2 @@ -76,6 +287,62 @@ public interface ChannelFinderClient { Collection find(Map map) throws ChannelFinderException; + /** + * uery for channels based on the multiple criteria specified in the map. + * Map.put("~name", "*")
+ * Map.put("~tag", "tag1")
+ * Map.put("Cell", "1")
+ * Map.put("Cell", "2")
+ * Map.put("Cell", "3")
+ *

+ * this will return all channels with name=any name AND tag=tag1 AND + * property Cell = 1 OR 2 OR 3. + * + * @param map - multivalued map of all search criteria + * @return Collection of channels which satisfy the search map. + * @throws ChannelFinderException - channelfinder exception + */ + Collection find(MultivaluedMap map) + throws ChannelFinderException; + + /** + * Completely Delete {tag} with name = tagName from all channels and the + * channelfinder service. + * + * @param tagName - name of tag to be deleted. + * @throws ChannelFinderException - channelfinder exception + */ + void deleteTag(String tagName) throws ChannelFinderException; + + /** + * Completely Delete property with name = propertyName from all channels and + * the channelfinder service. + * + * @param propertyName - name of property to be deleted. + * @throws ChannelFinderException - channelfinder exception + */ + void deleteProperty(String propertyName) + throws ChannelFinderException; + + /** + * Delete the channel identified by channel + * + * @param channelName channel to be removed + * @throws ChannelFinderException - channelfinder exception + */ + void deleteChannel(String channelName) throws ChannelFinderException; + + + /** + * Delete the set of channels identified by channels + * + * @param channels - list of channel builders + * @throws ChannelFinderException - channelfinder exception + */ + @Deprecated + void delete(Collection channels) + throws ChannelFinderException; + /** * Delete tag tag from the channel with the name * channelName @@ -119,33 +386,12 @@ void delete(Property.Builder property, String channelName) * @throws ChannelFinderException - channelfinder exception */ void delete(Property.Builder property, - Collection channelNames) throws ChannelFinderException; - - - /** - * - * Update the Tag tag by adding it to the set of the channels with - * names channelNames, without affecting the other instances of - * this tag. - * - * @param tag - * - the tag that needs to be updated. - * @param channelNames - * - list of channels to which this tag should be added. - * @throws ChannelFinderException - channelfinder exception - */ - void update(Tag.Builder tag, Collection channelNames) - throws ChannelFinderException; + Collection channelNames) throws ChannelFinderException; /** - * Update the channels identified with channelNames with the - * property property - * - * @param property - property builder - * @param channelNames - list of channel names - * @throws ChannelFinderException - channelfinder exception + * close */ - void update(Property.Builder property, - Collection channelNames) throws ChannelFinderException; + void close(); + void set(Collection channels); } diff --git a/app/channel/channelfinder/src/main/java/org/phoebus/channelfinder/ChannelFinderClientImpl.java b/app/channel/channelfinder/src/main/java/org/phoebus/channelfinder/ChannelFinderClientImpl.java index 49ad33dfe0..2ae82da1c0 100644 --- a/app/channel/channelfinder/src/main/java/org/phoebus/channelfinder/ChannelFinderClientImpl.java +++ b/app/channel/channelfinder/src/main/java/org/phoebus/channelfinder/ChannelFinderClientImpl.java @@ -7,6 +7,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import org.phoebus.util.http.QueryParamsHelper; @@ -17,18 +18,24 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedHashMap; import javax.ws.rs.core.MultivaluedMap; +import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.OutputStream; import java.net.Socket; import java.net.URI; +import java.net.URLEncoder; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; +import java.nio.charset.StandardCharsets; import java.security.SecureRandom; import java.security.cert.X509Certificate; import java.util.ArrayList; +import java.util.Arrays; import java.util.Base64; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -37,6 +44,7 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; import java.util.prefs.BackingStoreException; @@ -167,6 +175,20 @@ public void checkClientTrusted(X509Certificate[] chain, String authType) { this.executor = executor; } + /** + * Get a list of names of all the properties currently present on the + * channelfinder service. + * + * @return list of names of all existing {@link Property}s. + */ + @Override + public Collection getAllPropertyNames() { + Collection xmlProperties = getAllProperties(); + Collection allNames = new HashSet<>(); + xmlProperties.forEach(Property::getName); + return allNames; + } + /** * Get a list of all the properties currently present on the * channelfinder service. @@ -179,9 +201,7 @@ public Collection getAllProperties() { private final ObjectMapper mapper = new ObjectMapper(); @Override - public List call() { - List xmlproperties = new ArrayList<>(); - + public List call() { try { HttpRequest httpRequest = HttpRequest.newBuilder() .uri(URI.create(org.phoebus.channelfinder.Preferences.serviceURL + "/" + resourceProperties)) @@ -192,18 +212,18 @@ public List call() { HttpResponse httpResponse = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); - if(httpResponse.statusCode() != 200){ + if (httpResponse.statusCode() != 200) { throw new ChannelFinderException(httpResponse.statusCode(), httpResponse.body()); } - xmlproperties = mapper.readValue(httpResponse.body(), + List xmlproperties = mapper.readValue(httpResponse.body(), new TypeReference<>() { }); - + return xmlproperties.stream().map(Property::new).collect(Collectors.toList()); } catch (Exception e) { log.log(Level.WARNING, "Failed to retrieve channelfinder properties", e); + return Collections.emptyList(); } - return xmlproperties.stream().map(Property::new).collect(Collectors.toList()); } }); } @@ -234,7 +254,7 @@ public Collection call() { HttpResponse httpResponse = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); - if(httpResponse.statusCode() != 200){ + if (httpResponse.statusCode() != 200) { throw new ChannelFinderException(httpResponse.statusCode(), httpResponse.body()); } @@ -265,8 +285,6 @@ public Collection call() { @Override public Collection getAllTags() { return wrappedSubmit(() -> { - Collection allTags = new HashSet<>(); - List xmltags = new ArrayList<>(); try { HttpRequest httpRequest = HttpRequest.newBuilder() .uri(URI.create(org.phoebus.channelfinder.Preferences.serviceURL + "/" + resourceTags)) @@ -277,26 +295,34 @@ public Collection getAllTags() { HttpResponse httpResponse = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); - if(httpResponse.statusCode() != 200){ + if (httpResponse.statusCode() != 200) { throw new ChannelFinderException(httpResponse.statusCode(), httpResponse.body()); } - xmltags = mapper.readValue(httpResponse.body(), + List xmltags = mapper.readValue(httpResponse.body(), new TypeReference<>() { }); - } catch (IOException e) { + return xmltags.stream().map(Tag::new).collect(Collectors.toList()); + } catch (Exception e) { log.log(Level.WARNING, "Failed to parse the list of tags", e); - } catch (InterruptedException e) { - throw new ChannelFinderException(e.getMessage()); - } - for (XmlTag xmltag : xmltags) { - allTags.add(xmltag.getName()); + return Collections.emptyList(); } - return xmltags.stream().map(Tag::new).collect(Collectors.toList()); - }); } + /** + * Returns a channel that exactly matches the channelName + * channelName. + * + * @param channelName - name of the required channel. + * @return {@link Channel} with name channelName or null + * @throws ChannelFinderException - channelfinder exception + */ + @Override + public Channel getChannel(String channelName) throws ChannelFinderException { + return wrappedSubmit(new FindByChannelName(channelName)); + } + @Deprecated public static void resetPreferences() { try { @@ -306,8 +332,166 @@ public static void resetPreferences() { } } - public void set(Tag.Builder tag, Map channelTagMap) { - wrappedSubmit(new SetTag(tag.toXml(), channelTagMap)); + /** + * Destructively set a single channel channel, if the channel + * already exists it will be replaced with the given channel. + * + * @param channel the channel to be added + * @throws ChannelFinderException - channelfinder exception + */ + @Override + public void set(Channel.Builder channel) throws ChannelFinderException { + wrappedSubmit(new SetChannel(channel.toXml())); + } + + private class SetChannel implements Runnable { + private final XmlChannel pxmlChannel; + + public SetChannel(XmlChannel xmlChannel) { + super(); + this.pxmlChannel = xmlChannel; + } + + @Override + public void run() { + ObjectMapper mapper = new ObjectMapper(); + try { + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(org.phoebus.channelfinder.Preferences.serviceURL + "/" + resourceChannels + "/" + + URLEncoder.encode(pxmlChannel.getName(), StandardCharsets.UTF_8))) + .header("Content-Type", MediaType.APPLICATION_JSON) + .header("Authorization", basicAuthenticationHeader) + .PUT(HttpRequest.BodyPublishers.ofString(mapper.writeValueAsString(this.pxmlChannel))) + .build(); + HttpResponse httpResponse = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); + if (httpResponse.statusCode() != 200) { + throw new ChannelFinderException(httpResponse.statusCode(), httpResponse.body()); + } + } catch (Exception e) { + log.log(Level.WARNING, "Failed to set channel \"" + pxmlChannel.getName() + "\"", e); + } + } + } + + /** + * Search for channels who's name match the pattern pattern.
+ * The pattern can contain wildcard char * or ?.
+ * + * @param pattern - the search pattern for the channel names + * @return A Collection of channels who's name match the pattern + * pattern + * @throws ChannelFinderException - channelfinder exception + */ + @Override + public Collection findByName(String pattern) throws ChannelFinderException { + // return wrappedSubmit(new FindByParam("~name", pattern)); + Map searchMap = new HashMap<>(); + searchMap.put("~name", pattern); + return wrappedSubmit(new FindByMap(searchMap)); + } + + /** + * Search for channels with properties who's Value match the pattern + * pattern.
+ * The pattern can contain wildcard char * or ?.
+ * + * @param property - the name of the property. + * @param pattern - the seatch pattern for the property value. + * @return A collection of channels containing the property with name + * propertyName who's value matches the pattern + * pattern. + * @throws ChannelFinderException - channelfinder exception + */ + @Override + public Collection findByProperty(String property, String... pattern) throws ChannelFinderException { + Map propertyPatterns = new HashMap<>(); + if (pattern.length > 0) { + propertyPatterns.put(property, Arrays.stream(pattern).collect(Collectors.joining(","))); //$NON-NLS-1$ + } else { + propertyPatterns.put(property, "*"); //$NON-NLS-1$ + } + return wrappedSubmit(new FindByMap(propertyPatterns)); + } + + /** + * uery for channels based on the multiple criteria specified in the map. + * Map.put("~name", "*")
+ * Map.put("~tag", "tag1")
+ * Map.put("Cell", "1")
+ * Map.put("Cell", "2")
+ * Map.put("Cell", "3")
+ *

+ * this will return all channels with name=any name AND tag=tag1 AND + * property Cell = 1 OR 2 OR 3. + * + * @param map - multivalued map of all search criteria + * @return Collection of channels which satisfy the search map. + * @throws ChannelFinderException - channelfinder exception + */ + public Collection find(MultivaluedMap map) throws ChannelFinderException { + return wrappedSubmit(new FindByMap(map)); + } + + + /** + * Search for channels with tags who's name match the pattern + * pattern.
+ * The pattern can contain wildcard char * or ?.
+ * + * @param pattern - the search pattern for the tag names + * @return A Collection of channels which contain tags who's name match the + * pattern pattern + * @throws ChannelFinderException - channelfinder exception + */ + @Override + public Collection findByTag(String pattern) throws ChannelFinderException { + // return wrappedSubmit(new FindByParam("~tag", pattern)); + List and = Arrays.asList(pattern.split("&")); + MultivaluedMap searchMap = new MultivaluedHashMap<>(); + for (String string : and) { + searchMap.add("~tag", string); + } + return wrappedSubmit(new FindByMap(searchMap)); + } + + /** + * Destructively set a Tag tag with no associated channels to the + * database. + * + * @param tag - the tag to be set. + */ + @Override + public void set(Tag.Builder tag) { + wrappedSubmit(new SetTag(tag.toXml())); + } + + /** + * Set tag tag on the set of channels {channels} and remove it from + * all others. + * + * @param tag - the tag to be set. + * @param channelNames - the list of channels to which this tag will be added and + * removed from all others. + * @throws ChannelFinderException - channelfinder exception + */ + @Override + public void set(Tag.Builder tag, Collection channelNames) throws ChannelFinderException { + wrappedSubmit(new SetTag(tag.toXml(), channelNames)); + } + + /** + * Destructively set tag tag to channel channelName and + * remove the tag from all other channels. + * + * @param tag - the tag to be set. + * @param channelName - the channel to which the tag should be set on. + * @throws ChannelFinderException - channelfinder exception + */ + @Override + public void set(Tag.Builder tag, String channelName) throws ChannelFinderException { + Collection channelNames = new ArrayList<>(); + channelNames.add(channelName); + wrappedSubmit(new SetTag(tag.toXml(), channelNames)); } private class SetTag implements Runnable { @@ -327,21 +511,39 @@ private class SetTag implements Runnable { this.pxmlTag.setChannels(channels); } + SetTag(XmlTag xmlTag, Collection channelNames) { + super(); + this.pxmlTag = xmlTag; + List channels = new ArrayList<>(); + for (String channelName : channelNames) { + XmlChannel xmlChannel = new XmlChannel(channelName); + xmlChannel.addXmlTag(new XmlTag(this.pxmlTag.getName(), this.pxmlTag.getOwner())); + channels.add(xmlChannel); + } + this.pxmlTag.setChannels(channels); + } + + public SetTag(XmlTag xmlTag) { + super(); + this.pxmlTag = xmlTag; + } + @Override public void run() { ObjectMapper mapper = new ObjectMapper(); try { HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create(org.phoebus.channelfinder.Preferences.serviceURL + "/" + resourceTags + "/" + this.pxmlTag.getName())) + .uri(URI.create(org.phoebus.channelfinder.Preferences.serviceURL + "/" + resourceTags + "/" + + URLEncoder.encode(this.pxmlTag.getName(), StandardCharsets.UTF_8))) .header("Content-Type", MediaType.APPLICATION_JSON) .header("Accept", MediaType.APPLICATION_JSON) .header("Authorization", basicAuthenticationHeader) .PUT(HttpRequest.BodyPublishers.ofString(mapper.writeValueAsString(this.pxmlTag))) .build(); - HttpResponse httpResponse = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); - if(httpResponse.statusCode() != 200){ + HttpResponse httpResponse = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); + if (httpResponse.statusCode() != 200) { throw new ChannelFinderException(httpResponse.statusCode(), httpResponse.body()); } } catch (Exception e) { @@ -350,6 +552,166 @@ public void run() { } } + /** + * Destructively set property prop and add it to the channel + * channelName and remove it from all others. + * + * @param prop - property to be set. + * @param channelName - the channel to which this property must be added. + */ + @Override + public void set(Property.Builder prop, String channelName) { + Collection ch = new ArrayList<>(); + ch.add(channelName); + wrappedSubmit(new SetProperty(prop.toXml(), ch)); + } + + /** + * Destructively set a set of channels, if any channels already exists it is + * replaced. + * + * @param channels set of channels to be added + * @throws ChannelFinderException - channelfinder exception + */ + public void set(Collection channels) throws ChannelFinderException { + wrappedSubmit(new SetChannels(ChannelUtil.toCollectionXmlChannels(channels))); + } + + private class SetChannels implements Runnable { + private final List pxmlchannels; + + public SetChannels(List xmlchannels) { + super(); + this.pxmlchannels = xmlchannels; + } + + @Override + public void run() { + ObjectMapper mapper = new ObjectMapper(); + OutputStream out = new ByteArrayOutputStream(); + try { + mapper.writeValue(out, this.pxmlchannels); + final byte[] data = ((ByteArrayOutputStream) out).toByteArray(); + String test = new String(data); + + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(org.phoebus.channelfinder.Preferences.serviceURL + "/" + resourceChannels)) + .header("Content-Type", MediaType.APPLICATION_JSON) + .header("Authorization", basicAuthenticationHeader) + .PUT(HttpRequest.BodyPublishers.ofString(mapper.writeValueAsString(test))) + .build(); + + HttpResponse httpResponse = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); + if (httpResponse.statusCode() != 200) { + throw new ChannelFinderException(httpResponse.statusCode(), httpResponse.body()); + } + } catch (Exception e) { + log.log(Level.WARNING, "Failed to set channels ", e); + throw new ChannelFinderException(e); + } + } + } + + + /** + * Destructively set a new property property. + * + * @param prop - the property to be set. + */ + @Override + public void set(Property.Builder prop) throws ChannelFinderException { + wrappedSubmit(new SetProperty(prop.toXml())); + } + + /** + * Destructively set property prop and add it to the channels + * channelNames removing it from all other channels. By default all + * channels will contain the property with the same value specified in the + * prop.
+ * to individually set the value for each channel use channelPropertyMap. + * + * @param prop - the property to be set. + * @param channelNames - the channels to which this property should be added and + * removed from all others. + */ + @Override + public void set(Property.Builder prop, Collection channelNames) { + wrappedSubmit(new SetProperty(prop.toXml(), channelNames)); + } + + /** + * Destructively set the property prop and add it to the channels + * specified in the channelPropertyMap, where the map key is the + * channel name and the associated value is the property value to be used + * for that channel. + * + * @param prop - the property to be set. + * @param channelPropertyMap - map with channel names and property values + */ + @Override + public void set(Property.Builder prop, Map channelPropertyMap) { + wrappedSubmit(new SetProperty(prop.toXml(), channelPropertyMap)); + } + + private class SetProperty implements Runnable { + private final XmlProperty pxmlProperty; + private final ObjectMapper mapper = new ObjectMapper(); + + SetProperty(XmlProperty prop) { + this.pxmlProperty = prop; + } + + SetProperty(XmlProperty prop, Map channelPropertyMap) { + super(); + this.pxmlProperty = prop; + List channels = new ArrayList<>(); + for (Entry e : channelPropertyMap.entrySet()) { + XmlChannel xmlChannel = new XmlChannel(e.getKey()); + // need a copy to avoid a cycle + xmlChannel.addXmlProperty( + new XmlProperty(this.pxmlProperty.getName(), this.pxmlProperty.getOwner(), e.getValue())); + channels.add(xmlChannel); + } + this.pxmlProperty.setChannels(channels); + } + + SetProperty(XmlProperty prop, Collection channelNames) { + super(); + this.pxmlProperty = prop; + List channels = new ArrayList<>(); + for (String channelName : channelNames) { + XmlChannel xmlChannel = new XmlChannel(channelName); + // need a copy to avoid a linking cycle + xmlChannel.addXmlProperty(new XmlProperty(this.pxmlProperty.getName(), this.pxmlProperty.getOwner(), + this.pxmlProperty.getValue())); + channels.add(xmlChannel); + } + this.pxmlProperty.setChannels(channels); + } + + @Override + public void run() { + try { + + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(org.phoebus.channelfinder.Preferences.serviceURL + "/" + resourceProperties + "/" + + URLEncoder.encode(pxmlProperty.getName(), StandardCharsets.UTF_8))) + .header("Content-Type", MediaType.APPLICATION_JSON) + .header("Accept", MediaType.APPLICATION_JSON) + .header("Authorization", basicAuthenticationHeader) + .PUT(HttpRequest.BodyPublishers.ofString(mapper.writeValueAsString(this.pxmlProperty))) + .build(); + + HttpResponse httpResponse = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); + if (httpResponse.statusCode() != 200) { + throw new ChannelFinderException(httpResponse.statusCode(), httpResponse.body()); + } + } catch (Exception e) { + log.log(Level.WARNING, "Failed to process the list of properties ", e); + } + } + } + /** * Query for channels based on the Query string query example: * find("""SR* Cell=1,2 Tags=GolderOrbit,myTag")
@@ -387,6 +749,44 @@ public Collection find(Map map) throws ChannelFinderExc return wrappedSubmit(new FindByMap(map)); } + private class FindByChannelName implements Callable { + + private final String channelName; + private final ObjectMapper mapper = new ObjectMapper(); + + FindByChannelName(String channelName) { + super(); + this.channelName = channelName; + } + + @Override + public Channel call() { + mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); + try { + + HttpRequest httpRequest = HttpRequest.newBuilder() + .uri(URI.create(org.phoebus.channelfinder.Preferences.serviceURL + "/" + resourceChannels + "/" + + URLEncoder.encode(channelName, StandardCharsets.UTF_8))) + .header("Content-Type", MediaType.APPLICATION_JSON) + .GET() + .build(); + + HttpResponse httpResponse = + httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); + if (httpResponse.statusCode() != 200) { + throw new ChannelFinderException(httpResponse.statusCode(), httpResponse.body()); + } + + return new Channel(mapper.readValue(httpResponse.body(), XmlChannel.class)); + + } catch (Exception e) { + log.log(Level.WARNING, "Failed to find channel \"" + channelName + "\"", e); + return null; + } + } + + } + private class FindByMap implements Callable> { private final MultivaluedMap multivaluedMap; @@ -420,7 +820,7 @@ public Collection call() { .GET() .build(); HttpResponse httpResponse = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); - if(httpResponse.statusCode() != 200){ + if (httpResponse.statusCode() != 200) { throw new ChannelFinderException(httpResponse.statusCode(), httpResponse.body()); } xmlchannels = mapper.readValue(httpResponse.body(), new TypeReference<>() { @@ -510,6 +910,87 @@ public void delete(Tag.Builder tag, Collection channelNames) throws Chan } } + /** + * Completely Delete {tag} with name = tagName from all channels and the + * channelfinder service. + * + * @param tagName - name of tag to be deleted. + * @throws ChannelFinderException - throws exception + */ + @Override + public void deleteTag(String tagName) throws ChannelFinderException { + wrappedSubmit(new DeleteElement(resourceTags, tagName)); + } + + /** + * Completely Delete property with name = propertyName from all channels and + * the channelfinder service. + * + * @param propertyName - name of property to be deleted. + * @throws ChannelFinderException - throws exception + */ + @Override + public void deleteProperty(String propertyName) throws ChannelFinderException { + wrappedSubmit(new DeleteElement(resourceProperties, propertyName)); + } + + /** + * Delete the channel identified by channel + * + * @param channelName - channel to be removed + * @throws ChannelFinderException - channelfinder exception + */ + @Override + public void deleteChannel(String channelName) throws ChannelFinderException { + wrappedSubmit(new DeleteElement(resourceChannels, channelName)); // $NON-NLS-1$ + } + + /** + * Delete the set of channels identified by channels + * + * @param channels - channels to be deleted + * @throws ChannelFinderException - throws exception + */ + @Deprecated + @Override + public void delete(Collection channels) throws ChannelFinderException { + for (Channel.Builder channel : channels) { + deleteChannel(channel.build().getName()); + } + } + + + private class DeleteElement implements Runnable { + private final String elementType; + private final String elementName; + + DeleteElement(String elementType, String elementName) { + super(); + this.elementType = elementType; + this.elementName = elementName; + } + + @Override + public void run() { + try { + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(org.phoebus.channelfinder.Preferences.serviceURL + "/" + + this.elementType + "/" + + URLEncoder.encode(this.elementName, StandardCharsets.UTF_8))) + .header("Authorization", basicAuthenticationHeader) + .DELETE() + .build(); + HttpResponse httpResponse = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); + if (httpResponse.statusCode() != 200) { + throw new ChannelFinderException(httpResponse.statusCode(), httpResponse.body()); + } + } catch (Exception e) { + log.log(Level.WARNING, "Failed to delete element from channel ", e); + } + } + } + + /** * Remove property property from the channel with name * channelName @@ -558,8 +1039,8 @@ public void run() { HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(org.phoebus.channelfinder.Preferences.serviceURL + "/" + this.elementType + "/" + - this.elementName + "/" + - this.channelName)) + URLEncoder.encode(this.elementName, StandardCharsets.UTF_8) + "/" + + URLEncoder.encode(this.channelName, StandardCharsets.UTF_8))) .header("Accept", MediaType.APPLICATION_JSON) .header("Authorization", basicAuthenticationHeader) .DELETE() @@ -567,7 +1048,7 @@ public void run() { try { HttpResponse httpResponse = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); - if(httpResponse.statusCode() != 200){ + if (httpResponse.statusCode() != 200) { throw new ChannelFinderException(httpResponse.statusCode(), httpResponse.body()); } } catch (Exception e) { @@ -583,6 +1064,9 @@ private T wrappedSubmit(Callable callable) { } catch (InterruptedException e) { throw new RuntimeException(e); } catch (ExecutionException e) { + if (e.getCause() instanceof ChannelFinderException) { + throw (ChannelFinderException) e.getCause(); + } if (e.getMessage() != null) { throw new ChannelFinderException(e.getMessage()); } @@ -596,6 +1080,9 @@ private void wrappedSubmit(Runnable runnable) { } catch (InterruptedException e) { throw new RuntimeException(e); } catch (ExecutionException e) { + if (e.getCause() instanceof ChannelFinderException) { + throw (ChannelFinderException) e.getCause(); + } if (e.getMessage() != null) { throw new ChannelFinderException(e.getMessage()); } @@ -603,6 +1090,48 @@ private void wrappedSubmit(Runnable runnable) { } } + /** + * Update existing channel with channel. + * + * @param channel - channel builder + * @throws ChannelFinderException - channelfinder exception + */ + @Override + public void update(Channel.Builder channel) throws ChannelFinderException { + wrappedSubmit(new UpdateChannel(channel.toXml())); + } + + private class UpdateChannel implements Runnable { + private final XmlChannel channel; + private final ObjectMapper mapper = new ObjectMapper(); + + UpdateChannel(XmlChannel channel) { + super(); + this.channel = channel; + } + + @Override + public void run() { + try { + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(org.phoebus.channelfinder.Preferences.serviceURL + "/" + resourceChannels + "/" + + URLEncoder.encode(this.channel.getName(), StandardCharsets.UTF_8))) + .header("Content-Type", MediaType.APPLICATION_JSON) + .header("Authorization", basicAuthenticationHeader) + .POST(HttpRequest.BodyPublishers.ofString(mapper.writeValueAsString(this.channel))) + .build(); + + HttpResponse httpResponse = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); + if (httpResponse.statusCode() != 200) { + throw new ChannelFinderException(httpResponse.statusCode(), httpResponse.body()); + } + } catch (Exception e) { + throw new ChannelFinderException(e); + } + } + + } + /** * Update the Tag tag by adding it to the set of the channels with * names channelNames, without affecting the other instances of @@ -612,17 +1141,22 @@ private void wrappedSubmit(Runnable runnable) { * @param channelNames - list of channels to which this tag should be added. * @throws ChannelFinderException - channelfinder exception */ + @Override public void update(Tag.Builder tag, Collection channelNames) throws ChannelFinderException { wrappedSubmit(new UpdateTag(tag.toXml(), channelNames)); } /** - * @param property - property builder - * @param channelNames - list of channel names + * Update Tag tag by adding it to Channel with name + * channelName, without affecting the other instances of this tag. + * + * @param tag the tag to be added + * @param channelName Name of the channel to which the tag is to be added * @throws ChannelFinderException - channelfinder exception */ - public void update(Property.Builder property, Collection channelNames) throws ChannelFinderException { - wrappedSubmit(new UpdateProperty(property.toXml(), channelNames)); + @Override + public void update(Tag.Builder tag, String channelName) throws ChannelFinderException { + wrappedSubmit(new UpdateTag(tag.toXml(), channelName)); } @@ -636,6 +1170,14 @@ private class UpdateTag implements Runnable { this.pxmlTag = xmlTag; } + UpdateTag(XmlTag xmlTag, String ChannelName) { + super(); + this.pxmlTag = xmlTag; + List channels = new ArrayList<>(); + channels.add(new XmlChannel(ChannelName)); + this.pxmlTag.setChannels(channels); + } + UpdateTag(XmlTag xmlTag, Collection channelNames) { super(); this.pxmlTag = xmlTag; @@ -650,14 +1192,15 @@ private class UpdateTag implements Runnable { public void run() { try { HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create(org.phoebus.channelfinder.Preferences.serviceURL + "/" + resourceTags + "/" + this.pxmlTag.getName())) + .uri(URI.create(org.phoebus.channelfinder.Preferences.serviceURL + "/" + resourceTags + "/" + + URLEncoder.encode(this.pxmlTag.getName(), StandardCharsets.UTF_8))) .header("Content-Type", MediaType.APPLICATION_JSON) .header("Authorization", basicAuthenticationHeader) .POST(HttpRequest.BodyPublishers.ofString(mapper.writeValueAsString(this.pxmlTag))) .build(); HttpResponse httpResponse = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); - if(httpResponse.statusCode() != 200){ + if (httpResponse.statusCode() != 200) { throw new ChannelFinderException(httpResponse.statusCode(), httpResponse.body()); } } catch (JsonProcessingException e) { @@ -668,6 +1211,16 @@ public void run() { } } + /** + * @param property - property builder + * @param channelNames - list of channel names + * @throws ChannelFinderException - channelfinder exception + */ + @Override + public void update(Property.Builder property, Collection channelNames) throws ChannelFinderException { + wrappedSubmit(new UpdateProperty(property.toXml(), channelNames)); + } + private class UpdateProperty implements Runnable { private final XmlProperty pxmlProperty; private final ObjectMapper mapper = new ObjectMapper(); @@ -692,19 +1245,34 @@ private class UpdateProperty implements Runnable { xmlProperty.setChannels(channels); } + UpdateProperty(XmlProperty xmlProperty, Map channelPropValueMap) { + super(); + this.pxmlProperty = xmlProperty; + List channels = new ArrayList<>(); + for (Entry e : channelPropValueMap.entrySet()) { + XmlChannel xmlChannel = new XmlChannel(e.getKey()); + // need a defensive copy to avoid A cycle + xmlChannel.addXmlProperty(new XmlProperty(xmlProperty.getName(), xmlProperty.getOwner(), e.getValue())); + channels.add(xmlChannel); + } + xmlProperty.setChannels(channels); + } + @Override public void run() { try { + String s = mapper.writeValueAsString(this.pxmlProperty); HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create(org.phoebus.channelfinder.Preferences.serviceURL + "/" + resourceProperties + "/" + this.pxmlProperty.getName())) + .uri(URI.create(org.phoebus.channelfinder.Preferences.serviceURL + "/" + resourceProperties + "/" + + URLEncoder.encode(this.pxmlProperty.getName(), StandardCharsets.UTF_8))) .header("Content-Type", MediaType.APPLICATION_JSON) .header("Accept", MediaType.APPLICATION_JSON) - .header("Authorization", basicAuthenticationHeader) - .POST(HttpRequest.BodyPublishers.ofString(mapper.writeValueAsString(this.pxmlProperty))) + //.header("Authorization", basicAuthenticationHeader) + .POST(HttpRequest.BodyPublishers.ofString(s)) .build(); HttpResponse httpResponse = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); - if(httpResponse.statusCode() != 200){ + if (httpResponse.statusCode() != 200) { throw new ChannelFinderException(httpResponse.statusCode(), httpResponse.body()); } } catch (JsonProcessingException e) { @@ -714,4 +1282,116 @@ public void run() { } } } + + /** + * @param property - property builder + * @param channelPropValueMap - channel property value map + * @throws ChannelFinderException - channelfinder exception + */ + public void update(Property.Builder property, Map channelPropValueMap) + throws ChannelFinderException { + wrappedSubmit(new UpdateProperty(property.toXml(), channelPropValueMap)); + } + + /** + * Update Property property by adding it to the channel + * channelName, without affecting the other channels. + * + * @param property - the property to be updated + * @param channelName - the channel to which this property should be added or + * updated. + * @throws ChannelFinderException - channelfinder exception + */ + public void update(Property.Builder property, String channelName) throws ChannelFinderException { + wrappedSubmit(new UpdateChannelProperty(property.toXml(), channelName)); + } + + private class UpdateChannelProperty implements Runnable { + private final XmlProperty pxmlProperty; + private final ObjectMapper mapper = new ObjectMapper(); + + UpdateChannelProperty(XmlProperty xmlProperty, String channelName) { + super(); + this.pxmlProperty = xmlProperty; + XmlChannel xmlChannel = new XmlChannel(channelName); + List channels = new ArrayList<>(); + channels.add(xmlChannel); + // need a defensive copy to avoid A cycle + xmlChannel.addXmlProperty( + new XmlProperty(xmlProperty.getName(), xmlProperty.getOwner(), xmlProperty.getValue())); + xmlProperty.setChannels(channels); + } + + @Override + public void run() { + try { + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(org.phoebus.channelfinder.Preferences.serviceURL + "/" + resourceProperties + "/" + + URLEncoder.encode(this.pxmlProperty.getName(), StandardCharsets.UTF_8))) + .header("Content-Type", MediaType.APPLICATION_JSON) + .header("Accept", MediaType.APPLICATION_JSON) + .header("Authorization", basicAuthenticationHeader) + .POST(HttpRequest.BodyPublishers.ofString(mapper.writeValueAsString(this.pxmlProperty))) + .build(); + HttpResponse httpResponse = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); + if (httpResponse.statusCode() != 200) { + throw new ChannelFinderException(httpResponse.statusCode(), httpResponse.body()); + } + } catch (Exception e) { + log.log(Level.WARNING, "Failed to process the channel property ", e); + throw new ChannelFinderException(e); + } + } + } + + @Override + public Collection getAllChannels() { + ObjectMapper mapper = new ObjectMapper(); + try { + HttpRequest httpRequest = HttpRequest.newBuilder() + .uri(URI.create(org.phoebus.channelfinder.Preferences.serviceURL + "/" + resourceChannels)) + .header("Content-Type", MediaType.APPLICATION_JSON) + .GET() + .build(); + + HttpResponse httpResponse = + httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); + + if (httpResponse.statusCode() != 200) { + throw new ChannelFinderException(httpResponse.statusCode(), httpResponse.body()); + } + List xmlChannels = + mapper.readValue(httpResponse.body(), new TypeReference<>() { + }); + Collection set = new HashSet<>(); + for (XmlChannel channel : xmlChannels) { + set.add(new Channel(channel)); + } + return set; + } catch (Exception e) { + log.log(Level.WARNING, "Failed to retrieve all channels", e); + return Collections.emptyList(); + } + } + + /** + * close + */ + public void close() { + this.executor.shutdown(); // Disable new tasks from being submitted + try { + // Wait a while for existing tasks to terminate + if (!this.executor.awaitTermination(60, TimeUnit.SECONDS)) { + this.executor.shutdownNow(); // Cancel currently executing tasks + // Wait a while for tasks to respond to being cancelled + if (!this.executor.awaitTermination(60, TimeUnit.SECONDS)) + System.err.println("Pool did not terminate"); //$NON-NLS-1$ + } + } catch (InterruptedException ie) { + // (Re-)Cancel if current thread also interrupted + this.executor.shutdownNow(); + // Preserve interrupt status + Thread.currentThread().interrupt(); + } + } } diff --git a/app/channel/channelfinder/src/main/java/org/phoebus/channelfinder/ChannelFinderException.java b/app/channel/channelfinder/src/main/java/org/phoebus/channelfinder/ChannelFinderException.java index 07a5f3a337..0a145cff5d 100644 --- a/app/channel/channelfinder/src/main/java/org/phoebus/channelfinder/ChannelFinderException.java +++ b/app/channel/channelfinder/src/main/java/org/phoebus/channelfinder/ChannelFinderException.java @@ -23,17 +23,12 @@ public ChannelFinderException(String message) { super(message); } - public ChannelFinderException(int httpStatus, String message) { - super(message); - this.setStatus(httpStatus); + public ChannelFinderException(Throwable t) { + super(t); } - /** - * Set the associated HTTP status code which caused this exception. - * - * @param status the status to set - */ - public void setStatus(int httpStatus) { + public ChannelFinderException(int httpStatus, String message) { + super(message); this.httpStatus = httpStatus; } From f5c1938b458ebdb7e08c9e1dd92d82be2c29d469 Mon Sep 17 00:00:00 2001 From: kasemir Date: Fri, 17 Jan 2025 09:10:55 -0500 Subject: [PATCH 3/4] AutoClosable ChannelFinderClient --- .../java/org/phoebus/channelfinder/ChannelFinderClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/channel/channelfinder/src/main/java/org/phoebus/channelfinder/ChannelFinderClient.java b/app/channel/channelfinder/src/main/java/org/phoebus/channelfinder/ChannelFinderClient.java index 7df5b4d2b6..55d6b2245a 100644 --- a/app/channel/channelfinder/src/main/java/org/phoebus/channelfinder/ChannelFinderClient.java +++ b/app/channel/channelfinder/src/main/java/org/phoebus/channelfinder/ChannelFinderClient.java @@ -17,7 +17,7 @@ * * @author shroffk */ -public interface ChannelFinderClient { +public interface ChannelFinderClient extends AutoCloseable { /** * Get a list of all the properties currently present on the From 5475b43bbbd24304f8807888135c597d31c2e6f1 Mon Sep 17 00:00:00 2001 From: kasemir Date: Fri, 17 Jan 2025 10:39:29 -0500 Subject: [PATCH 4/4] ant and eclipse settings #3239 made core-formula depend on core-util. This adapts ant and eclipse settings --- build.xml | 4 ++-- core/formula/.classpath | 1 + core/formula/build.xml | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/build.xml b/build.xml index 2ee2660074..6feda98ecd 100644 --- a/build.xml +++ b/build.xml @@ -8,9 +8,9 @@ + - @@ -91,9 +91,9 @@ --> + - diff --git a/core/formula/.classpath b/core/formula/.classpath index 608f02b509..b006d4c227 100644 --- a/core/formula/.classpath +++ b/core/formula/.classpath @@ -6,6 +6,7 @@ + diff --git a/core/formula/build.xml b/core/formula/build.xml index d3203cf5b0..a246b9ec1d 100644 --- a/core/formula/build.xml +++ b/core/formula/build.xml @@ -12,6 +12,7 @@ +