From 5e8888ac394ff32bd45aa4dcf31bb8e54e4bd01d Mon Sep 17 00:00:00 2001 From: georgweiss Date: Fri, 10 Jan 2025 13:54:58 +0100 Subject: [PATCH 1/2] Migrated to annotated preferences in channel finder client --- .../phoebus/channelfinder/CFProperties.java | 41 ------------------- .../ChannelFinderClientImpl.java | 11 ++--- .../phoebus/channelfinder/Preferences.java | 41 +++++++++++++++++++ 3 files changed, 45 insertions(+), 48 deletions(-) delete mode 100644 app/channel/channelfinder/src/main/java/org/phoebus/channelfinder/CFProperties.java create mode 100644 app/channel/channelfinder/src/main/java/org/phoebus/channelfinder/Preferences.java diff --git a/app/channel/channelfinder/src/main/java/org/phoebus/channelfinder/CFProperties.java b/app/channel/channelfinder/src/main/java/org/phoebus/channelfinder/CFProperties.java deleted file mode 100644 index 27434fb0e7..0000000000 --- a/app/channel/channelfinder/src/main/java/org/phoebus/channelfinder/CFProperties.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Copyright (C) 2010-2012 Brookhaven National Laboratory - * Copyright (C) 2010-2012 Helmholtz-Zentrum Berlin für Materialien und Energie GmbH - * All rights reserved. Use is subject to license terms. - */ -package org.phoebus.channelfinder; - -import org.phoebus.framework.preferences.PreferencesReader; - -/** - * The CFProperties objects holds the properties associated with the - * channelfinder client library initialized using the channelfinder_preferences.properties - * or default values. - * - * The order in which these files will be read. 1. properties file specified - * using the system property channelfinder_preferences.properties. 2. - * channelfinder_preferences.properties file in the users home direcotory. 3. - * channelfinder_preferences.properties file in the C:/ on windows and /etc/ on linux. 4. - * channelfinder_preferences.properties default file packaged with the library. - * - * @author shroffk - * - */ -class CFProperties { - final PreferencesReader prefs; - - CFProperties() { - - prefs = new PreferencesReader(CFProperties.class, "/channelfinder_preferences.properties"); - } - - /** - * check java preferences for the requested key - * @param key preferences key - * @return preferences value - */ - String getPreferenceValue(String key) { - return prefs.get(key); - } - -} 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 8c212a9701..1494099601 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 @@ -73,8 +73,6 @@ public class ChannelFinderClientImpl implements ChannelFinderClient { private static final String resourceProperties = "resources/properties"; private static final String resourceTags = "resources/tags"; - - private static CFProperties properties = new CFProperties(); private static final Logger log = Logger.getLogger(ChannelFinderClient.class.getName()); /** * A Builder class to help create the client to the Channelfinder Service @@ -105,7 +103,7 @@ public static class CFCBuilder { private CFCBuilder() { - this.uri = URI.create(properties.getPreferenceValue("serviceURL")); + this.uri = URI.create(org.phoebus.channelfinder.Preferences.serviceURL); this.protocol = this.uri.getScheme(); } @@ -259,9 +257,8 @@ public boolean verify(String hostname, SSLSession session) { } } if (this.withHTTPAuthentication) { - this.httpBasicAuthFilter = new HTTPBasicAuthFilter( - properties.getPreferenceValue("username"), - properties.getPreferenceValue("password")); + this.httpBasicAuthFilter = new HTTPBasicAuthFilter(org.phoebus.channelfinder.Preferences.username, + org.phoebus.channelfinder.Preferences.password); } return new ChannelFinderClientImpl(this.uri, this.clientConfig, this.httpBasicAuthFilter, this.executor); @@ -278,7 +275,7 @@ public boolean verify(String hostname, SSLSession session) { cfAuthenticatedResource.addFilter(httpBasicAuthFilter); } // TODO add a preference to add logging - if(Boolean.parseBoolean(properties.getPreferenceValue("rawFiltering"))) { + if(org.phoebus.channelfinder.Preferences.rawFiltering) { client.addFilter(new RawLoggingFilter(Logger.getLogger(RawLoggingFilter.class.getName()))); } this.executor = executor; diff --git a/app/channel/channelfinder/src/main/java/org/phoebus/channelfinder/Preferences.java b/app/channel/channelfinder/src/main/java/org/phoebus/channelfinder/Preferences.java new file mode 100644 index 0000000000..eceefcb451 --- /dev/null +++ b/app/channel/channelfinder/src/main/java/org/phoebus/channelfinder/Preferences.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2024 European Spallation Source ERIC. + */ + +package org.phoebus.channelfinder; + +import org.phoebus.framework.preferences.AnnotatedPreferences; +import org.phoebus.framework.preferences.Preference; + +/** + * The {@link Preferences} object holds the properties associated with the + * channel finder client library initialized using the channelfinder_preferences.properties + * or default values. + * + * The order in which these files will be read. 1. properties file specified + * using the system property channelfinder_preferences.properties. 2. + * channelfinder_preferences.properties file in the users home direcotory. 3. + * channelfinder_preferences.properties file in the C:/ on windows and /etc/ on linux. 4. + * channelfinder_preferences.properties default file packaged with the library. + * + * @author shroffk + * + */ +public class Preferences { + + @Preference + public static String serviceURL; + + @Preference + public static boolean rawFiltering; + + @Preference + public static String username; + + @Preference + public static String password; + + static { + AnnotatedPreferences.initialize(Preferences.class, "/channelfinder_preferences.properties"); + } +} From 6307d6b217cd57c969b8dab012791c291572a25a Mon Sep 17 00:00:00 2001 From: georgweiss Date: Tue, 14 Jan 2025 16:09:36 +0100 Subject: [PATCH 2/2] Switch to native HttpClient in channel finder client --- app/channel/channelfinder/pom.xml | 10 +- .../channelfinder/ChannelFinderClient.java | 549 ++----- .../ChannelFinderClientImpl.java | 1389 +++++------------ .../channelfinder/ChannelFinderException.java | 80 +- .../channelfinder/RawLoggingFilter.java | 252 --- 5 files changed, 514 insertions(+), 1766 deletions(-) delete mode 100644 app/channel/channelfinder/src/main/java/org/phoebus/channelfinder/RawLoggingFilter.java diff --git a/app/channel/channelfinder/pom.xml b/app/channel/channelfinder/pom.xml index df93acc4e0..0f763052fc 100644 --- a/app/channel/channelfinder/pom.xml +++ b/app/channel/channelfinder/pom.xml @@ -17,6 +17,11 @@ core-security 4.7.4-SNAPSHOT + + org.phoebus + core-util + 4.7.4-SNAPSHOT + com.fasterxml.jackson.core jackson-core @@ -34,10 +39,5 @@ jackson-databind ${jackson.version} - - com.sun.jersey - jersey-client - 1.19 - 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 77a1c7eb9a..2c2d0cd466 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 @@ -8,429 +8,144 @@ import java.util.Collection; import java.util.Map; -import javax.ws.rs.core.MultivaluedMap; - -import org.phoebus.channelfinder.Channel.Builder; - /** * A Client object to query the channelfinder service for channels based on * channel names and/or properties and tags associated with channels. - * + * * @author shroffk - * */ public interface ChannelFinderClient { - /** - * Get a list of all the properties currently present on the - * channelfinder service. - * - * @return list of all existing {@link Property}s. - */ - public 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. - */ - public Collection getAllPropertyNames(); - - public Collection getAllChannels(); - - /** - * GEt a list of all the tags - * @return list of all tags - */ - public Collection getAllTags(); - - /** - * Get a list of names of all the tags currently present on the - * channelfinder service. - * - * @return a list of names of all the existing {@link Tag}s. - */ - public 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 - */ - public 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 - */ - public 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. - */ - public 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 - */ - public 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 - */ - public void set(Tag.Builder tag, Collection channelNames) - throws ChannelFinderException; - - /** - * Destructively set a new property property. - * - * @param prop - * - the property to be set. - */ - public 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. - */ - public 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. - */ - public 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 - */ - public void set(Property.Builder prop, - Map channelPropertyMap); - - /** - * Update existing channel with channel. - * - * @param channel - channel builder - * @throws ChannelFinderException - channelfinder exception - */ - public 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 - */ - public 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 - */ - public 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 - */ - public 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 - */ - public 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 - */ - public 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 - */ - public 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 - */ - public 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 - */ - public Collection findByProperty(String property, - String... pattern) throws ChannelFinderException; - - /** - * Space seperated search criterias, patterns may include * and ? wildcards - * channelNamePattern propertyName=valuePattern1,valuePattern2 - * Tags=tagNamePattern Each criteria is logically ANDed, || seperated values - * are logically ORed - * - * Query for channels based on the Query string query example: - * find("SR* Cell=1,2 Tags=GolderOrbit,myTag)
- * - * this will return all channels with names starting with SR AND have - * property Cell=1 OR 2 AND have tags goldenOrbit AND myTag.
- * - * IMP: each criteria is logically AND'ed while multiple values for - * Properties are OR'ed.
- * - * - * @param query - channelfinder query - * @return Collection of channels which satisfy the search criteria. - * @throws ChannelFinderException - channelfinder exception - */ - public Collection find(String query) throws ChannelFinderException; - - /** - * Query for channels based on the multiple criteria specified in the map. - * Map.put("~name", "*")
- * Map.put("~tag", "tag1")
- * Map.put("Cell", "1,2,3") - * - * this will return all channels with name=any name AND tag=tag1 AND - * property Cell = 1 OR 2 OR 3. - * - * @param map - search map - * @return Collection of channels which satisfy the search map. - * @throws ChannelFinderException - channelfinder exception - */ - public 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 - */ - public 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 - */ - public 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 - */ - public void deleteProperty(String propertyName) - throws ChannelFinderException; - - /** - * Delete the channel identified by channel - * - * @param channelName - * channel to be removed - * @throws ChannelFinderException - channelfinder exception - */ - public 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 - public void delete(Collection channels) - throws ChannelFinderException; - - /** - * Delete tag tag from the channel with the name - * channelName - * - * @param tag - * - the tag to be deleted. - * @param channelName - * - the channel from which to delete the tag tag - * @throws ChannelFinderException - channelfinder exception - */ - public void delete(Tag.Builder tag, String channelName) - throws ChannelFinderException; - - /** - * Remove the tag tag from all the channels channelNames - * - * @param tag - * - the tag to be deleted. - * @param channelNames - * - the channels from which to delete the tag tag - * @throws ChannelFinderException - channelfinder exception - */ - public void delete(Tag.Builder tag, Collection channelNames) - throws ChannelFinderException; - - /** - * Remove property property from the channel with name - * channelName - * - * @param property - * - the property to be deleted. - * @param channelName - * - the channel from which to delete the property - * property - * @throws ChannelFinderException - channelfinder exception - */ - public void delete(Property.Builder property, String channelName) - throws ChannelFinderException; - - /** - * Remove the property property from the set of channels - * channelNames - * - * @param property - * - the property to be deleted. - * @param channelNames - * - the channels from which to delete the property - * property - * @throws ChannelFinderException - channelfinder exception - */ - public void delete(Property.Builder property, - Collection channelNames) throws ChannelFinderException; - - /** - * close - */ - public void close(); + /** + * Get a list of all the properties currently present on the + * channelfinder service. + * + * @return list of all existing {@link Property}s. + */ + Collection getAllProperties(); + + /** + * GEt a list of all the tags + * + * @return list of all tags + */ + Collection getAllTags(); + + /** + * Get a list of names of all the tags currently present on the + * channelfinder service. + * + * @return a list of names of all the existing {@link Tag}s. + */ + Collection getAllTagNames(); + + /** + * Space seperated search criterias, patterns may include * and ? wildcards + * channelNamePattern propertyName=valuePattern1,valuePattern2 + * Tags=tagNamePattern Each criteria is logically ANDed, || seperated values + * are logically ORed + *

+ * Query for channels based on the Query string query example: + * find("SR* Cell=1,2 Tags=GolderOrbit,myTag)
+ *

+ * this will return all channels with names starting with SR AND have + * property Cell=1 OR 2 AND have tags goldenOrbit AND myTag.
+ *

+ * IMP: each criteria is logically AND'ed while multiple values for + * Properties are OR'ed.
+ * + * @param query - channelfinder query + * @return Collection of channels which satisfy the search criteria. + * @throws ChannelFinderException - channelfinder exception + */ + Collection find(String query) throws ChannelFinderException; + + /** + * Query for channels based on the multiple criteria specified in the map. + * Map.put("~name", "*")
+ * Map.put("~tag", "tag1")
+ * Map.put("Cell", "1,2,3") + *

+ * this will return all channels with name=any name AND tag=tag1 AND + * property Cell = 1 OR 2 OR 3. + * + * @param map - search map + * @return Collection of channels which satisfy the search map. + * @throws ChannelFinderException - channelfinder exception + */ + Collection find(Map map) + throws ChannelFinderException; + + /** + * Delete tag tag from the channel with the name + * channelName + * + * @param tag - the tag to be deleted. + * @param channelName - the channel from which to delete the tag tag + * @throws ChannelFinderException - channelfinder exception + */ + void delete(Tag.Builder tag, String channelName) + throws ChannelFinderException; + + /** + * Remove the tag tag from all the channels channelNames + * + * @param tag - the tag to be deleted. + * @param channelNames - the channels from which to delete the tag tag + * @throws ChannelFinderException - channelfinder exception + */ + void delete(Tag.Builder tag, Collection channelNames) + throws ChannelFinderException; + + /** + * Remove property property from the channel with name + * channelName + * + * @param property - the property to be deleted. + * @param channelName - the channel from which to delete the property + * property + * @throws ChannelFinderException - channelfinder exception + */ + void delete(Property.Builder property, String channelName) + throws ChannelFinderException; + + /** + * Remove the property property from the set of channels + * channelNames + * + * @param property - the property to be deleted. + * @param channelNames - the channels from which to delete the property + * property + * @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; + + /** + * 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; - public 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 1494099601..49ad33dfe0 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 @@ -5,42 +5,30 @@ */ package org.phoebus.channelfinder; -import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; -import com.sun.jersey.api.client.Client; -import com.sun.jersey.api.client.ClientHandlerException; -import com.sun.jersey.api.client.ClientResponse; -import com.sun.jersey.api.client.UniformInterfaceException; -import com.sun.jersey.api.client.WebResource; -import com.sun.jersey.api.client.config.ClientConfig; -import com.sun.jersey.api.client.config.DefaultClientConfig; -import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter; -import com.sun.jersey.client.urlconnection.HTTPSProperties; -import com.sun.jersey.core.util.MultivaluedMapImpl; -import org.phoebus.channelfinder.Channel.Builder; -import org.phoebus.security.managers.DummyX509TrustManager; - -import javax.net.ssl.HostnameVerifier; +import org.phoebus.util.http.QueryParamsHelper; + import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSession; +import javax.net.ssl.SSLEngine; import javax.net.ssl.TrustManager; +import javax.net.ssl.X509ExtendedTrustManager; 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.security.KeyManagementException; -import java.security.NoSuchAlgorithmException; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +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; @@ -49,7 +37,6 @@ 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; @@ -59,136 +46,48 @@ /** * A Client object to query the channelfinder service for channels based on * channel names and/or properties and tags associated with channels. - * + * * @author shroffk - * */ public class ChannelFinderClientImpl implements ChannelFinderClient { - private final WebResource cfAuthenticatedResource; - private final WebResource cfResource; + private ExecutorService executor; - private final ExecutorService executor; + private HttpClient httpClient; + private final String basicAuthenticationHeader; private static final String resourceChannels = "resources/channels"; private static final String resourceProperties = "resources/properties"; private static final String resourceTags = "resources/tags"; - private static final Logger log = Logger.getLogger(ChannelFinderClient.class.getName()); + private static final Logger log = Logger.getLogger(ChannelFinderClientImpl.class.getName()); + /** * A Builder class to help create the client to the Channelfinder Service - * + * * @author shroffk - * */ public static class CFCBuilder { // required - private URI uri = null; - - // optional - private boolean withHTTPAuthentication = true; - private HTTPBasicAuthFilter httpBasicAuthFilter = null; + private final URI uri; - private ClientConfig clientConfig = null; - private TrustManager[] trustManager = new TrustManager[] { new DummyX509TrustManager() };; @SuppressWarnings("unused") private SSLContext sslContext = null; - private String protocol = null; - private String username = null; - private String password = null; + private final ExecutorService executor = Executors.newSingleThreadExecutor(); - private ExecutorService executor = Executors.newSingleThreadExecutor(); - - - private CFCBuilder() - { + private CFCBuilder() { this.uri = URI.create(org.phoebus.channelfinder.Preferences.serviceURL); - this.protocol = this.uri.getScheme(); - } - - private CFCBuilder(URI uri) - { - this.uri = uri; - this.protocol = this.uri.getScheme(); } /** * Creates a {@link CFCBuilder} for a CF client to Default URL in the * channelfinder_preferences.properties. - * - * @return {@link CFCBuilder} - */ - public static CFCBuilder serviceURL() - { - return new CFCBuilder(); - } - - /** - * Creates a {@link CFCBuilder} for a CF client to URI uri. - * - * @param uri - service uri - * @return {@link CFCBuilder} - */ - public static CFCBuilder serviceURL(String uri) - { - return new CFCBuilder(URI.create(uri)); - } - - /** - * Creates a {@link CFCBuilder} for a CF client to {@link URI} - * uri. * - * @param uri - service uri * @return {@link CFCBuilder} */ - public static CFCBuilder serviceURL(URI uri) { - return new CFCBuilder(uri); - } - - /** - * Enable of Disable the HTTP authentication on the client connection. - * - * @param withHTTPAuthentication - - * @return {@link CFCBuilder} - */ - public CFCBuilder withHTTPAuthentication(boolean withHTTPAuthentication) { - this.withHTTPAuthentication = withHTTPAuthentication; - return this; - } - - /** - * Set the username to be used for HTTP Authentication. - * - * @param username - username - * @return {@link CFCBuilder} - */ - public CFCBuilder username(String username) { - this.username = username; - return this; - } - - /** - * Set the password to be used for the HTTP Authentication. - * - * @param password - password - * @return {@link CFCBuilder} - */ - public CFCBuilder password(String password) { - this.password = password; - return this; - } - - /** - * set the {@link ClientConfig} to be used while creating the - * channelfinder client connection. - * - * @param clientConfig - client config - * @return {@link CFCBuilder} - */ - public CFCBuilder withClientConfig(ClientConfig clientConfig) { - this.clientConfig = clientConfig; - return this; + public static CFCBuilder serviceURL() { + return new CFCBuilder(); } @SuppressWarnings("unused") @@ -197,117 +96,75 @@ private CFCBuilder withSSLContext(SSLContext sslContext) { return this; } - /** - * Set the trustManager that should be used for authentication. - * - * @param trustManager - trust manager - * @return {@link CFCBuilder} - */ - public CFCBuilder withTrustManager(TrustManager[] trustManager) { - this.trustManager = trustManager; - return this; - } - - /** - * Provide your own executor on which the queries are to be made.
- * By default a single threaded executor is used. - * - * @param executor - executor - * @return {@link CFCBuilder} - */ - public CFCBuilder withExecutor(ExecutorService executor) { - this.executor = executor; - return this; - } - /** * Will actually create a {@link ChannelFinderClientImpl} object using * the configuration informoation in this builder. - * + * * @return {@link ChannelFinderClientImpl} */ public ChannelFinderClient create() throws ChannelFinderException { - if(this.uri == null || this.uri.toString().isEmpty()){ + if (this.uri == null || this.uri.toString().isEmpty()) { log.warning("Cannot create a channel finder client as URL is null or empty"); return null; } log.info("Creating a channelfinder client to : " + this.uri); - if (this.protocol.equalsIgnoreCase("http")) { //$NON-NLS-1$ - this.clientConfig = new DefaultClientConfig(); - } else if (this.protocol.equalsIgnoreCase("https")) { //$NON-NLS-1$ - if (this.clientConfig == null) { - SSLContext sslContext = null; - try { - sslContext = SSLContext.getInstance("SSL"); //$NON-NLS-1$ - sslContext.init(null, this.trustManager, null); - } catch (NoSuchAlgorithmException e) { - throw new ChannelFinderException(e.getMessage()); - } catch (KeyManagementException e) { - throw new ChannelFinderException(e.getMessage()); - } - this.clientConfig = new DefaultClientConfig(); - this.clientConfig.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, - new HTTPSProperties(new HostnameVerifier() { - - @Override - public boolean verify(String hostname, SSLSession session) { - return true; - } - }, sslContext)); - } - } - if (this.withHTTPAuthentication) { - this.httpBasicAuthFilter = new HTTPBasicAuthFilter(org.phoebus.channelfinder.Preferences.username, - org.phoebus.channelfinder.Preferences.password); - } - return new ChannelFinderClientImpl(this.uri, this.clientConfig, this.httpBasicAuthFilter, this.executor); + return new ChannelFinderClientImpl(this.uri, this.executor); } } - ChannelFinderClientImpl(URI uri, ClientConfig config, HTTPBasicAuthFilter httpBasicAuthFilter, - ExecutorService executor) { - Client client = Client.create(config); - client.setFollowRedirects(true); - cfResource = client.resource(uri.toString()); - cfAuthenticatedResource = client.resource(uri.toString()); - if (httpBasicAuthFilter != null) { - cfAuthenticatedResource.addFilter(httpBasicAuthFilter); - } - // TODO add a preference to add logging - if(org.phoebus.channelfinder.Preferences.rawFiltering) { - client.addFilter(new RawLoggingFilter(Logger.getLogger(RawLoggingFilter.class.getName()))); - } - this.executor = executor; - } + ChannelFinderClientImpl(URI uri, ExecutorService 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. - */ - public Collection getAllPropertyNames() { - return wrappedSubmit(new Callable>() { - private final ObjectMapper mapper = new ObjectMapper(); - @Override - public Collection call() throws Exception { - Collection allProperties = new HashSet(); - List xmlproperties = new ArrayList(); - try { - xmlproperties = mapper.readValue( - cfResource.path(resourceProperties).accept(MediaType.APPLICATION_JSON).get(String.class), - new TypeReference>() { - }); - } catch (JsonParseException e) { - log.log(Level.WARNING, "Failed to retrieve channelfinder properties", e); - } - for (XmlProperty xmlproperty : xmlproperties) { - allProperties.add(xmlproperty.getName()); - } - return allProperties; + basicAuthenticationHeader = "Basic " + Base64.getEncoder().encodeToString((org.phoebus.channelfinder.Preferences.username + ":" + + org.phoebus.channelfinder.Preferences.password).getBytes()); + + if (uri.getScheme().equalsIgnoreCase("http")) { //$NON-NLS-1$ + httpClient = HttpClient.newBuilder().build(); + } else if (uri.getScheme().equalsIgnoreCase("https")) { + try { + TrustManager PROMISCUOUS_TRUST_MANAGER = new X509ExtendedTrustManager() { + @Override + public java.security.cert.X509Certificate[] getAcceptedIssuers() { + return new java.security.cert.X509Certificate[0]; + } + + @Override + public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) { + } + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType, Socket socket) { + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType, Socket socket) { + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType, SSLEngine engine) { + } + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType, SSLEngine engine) { + } + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) { + } + }; + + SSLContext sslContext = SSLContext.getInstance("SSL"); // OR TLS + sslContext.init(null, new TrustManager[]{PROMISCUOUS_TRUST_MANAGER}, new SecureRandom()); + httpClient = HttpClient.newBuilder().sslContext(sslContext).build(); + } catch (Exception e) { + log.log(Level.WARNING, + "Failed to properly create the elastic rest client to: " + org.phoebus.channelfinder.Preferences.serviceURL + , e); + return; } - }); + } + + this.executor = executor; } /** @@ -316,21 +173,37 @@ public Collection call() throws Exception { * * @return list of all existing {@link Property}s. */ + @Override public Collection getAllProperties() { return wrappedSubmit(new Callable>() { private final ObjectMapper mapper = new ObjectMapper(); + @Override - public List call() throws Exception { + public List call() { List xmlproperties = new ArrayList<>(); + try { - xmlproperties = mapper.readValue( - cfResource.path(resourceProperties).accept(MediaType.APPLICATION_JSON).get(String.class), - new TypeReference>() { + HttpRequest httpRequest = HttpRequest.newBuilder() + .uri(URI.create(org.phoebus.channelfinder.Preferences.serviceURL + "/" + resourceProperties)) + .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()); + } + + xmlproperties = mapper.readValue(httpResponse.body(), + new TypeReference<>() { }); + } catch (Exception e) { log.log(Level.WARNING, "Failed to retrieve channelfinder properties", e); } - return xmlproperties.stream().map(xmlProperty -> {return new Property(xmlProperty);}).collect(Collectors.toList()); + return xmlproperties.stream().map(Property::new).collect(Collectors.toList()); } }); } @@ -341,673 +214,145 @@ public List call() throws Exception { * * @return a list of names of all the existing {@link Tag}s. */ + @Override public Collection getAllTagNames() { - return wrappedSubmit(new Callable>() { + return wrappedSubmit(new Callable<>() { private final ObjectMapper mapper = new ObjectMapper(); @Override public Collection call() { - Collection allTags = new HashSet(); - List xmltags = new ArrayList(); + Collection allTags = new HashSet<>(); + List xmltags = new ArrayList<>(); try { - xmltags = mapper.readValue( - cfResource.path(resourceTags) - .accept(MediaType.APPLICATION_JSON) - .get(String.class), new TypeReference>() { }); - } catch ( JsonParseException | JsonMappingException e) { - log.log(Level.WARNING, "Failed to parse the list of tags", e); - } catch ( IOException e) { - log.log(Level.WARNING, "Failed to parse the list of tags", e); - } catch (UniformInterfaceException e) { - throw new ChannelFinderException(e); - } catch (ClientHandlerException e) { - throw new ChannelFinderException(e); - } - for (XmlTag xmltag : xmltags) { - allTags.add(xmltag.getName()); - } - return allTags; - } - }); - } - private final ObjectMapper mapper = new ObjectMapper(); - /** - * Get a list of names of all the tags currently present on the - * channelfinder service. - * - * @return a list of names of all the existing {@link Tag}s. - */ - public Collection getAllTags() { - return wrappedSubmit(new Callable>() { - - @Override - public List call() { - Collection allTags = new HashSet(); - List xmltags = new ArrayList(); - try { - xmltags = mapper.readValue( - cfResource.path(resourceTags) - .accept(MediaType.APPLICATION_JSON) - .get(String.class), new TypeReference>() { }); - } catch ( JsonParseException | JsonMappingException e) { - log.log(Level.WARNING, "Failed to parse the list of tags", e); - } catch ( IOException e) { - log.log(Level.WARNING, "Failed to parse the list of tags", e); - } catch (UniformInterfaceException e) { - throw new ChannelFinderException(e); - } catch (ClientHandlerException e) { - throw new ChannelFinderException(e); - } - for (XmlTag xmltag : xmltags) { - allTags.add(xmltag.getName()); - } - return xmltags.stream().map(xmlTag -> new Tag(xmlTag)).collect(Collectors.toList()); - - } - }); - } + HttpRequest httpRequest = HttpRequest.newBuilder() + .uri(URI.create(org.phoebus.channelfinder.Preferences.serviceURL + "/" + resourceTags)) + .header("Content-Type", MediaType.APPLICATION_JSON) + .GET() + .build(); - @Deprecated - public static void resetPreferences() { - try { - Preferences.userNodeForPackage(ChannelFinderClientImpl.class).clear(); - } catch (BackingStoreException e) { - log.log(Level.WARNING, "Failed to retrieve channelfinder preferences", e); - } - } - - /** - * 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 - */ - public Channel getChannel(String channelName) throws ChannelFinderException { - try { - return wrappedSubmit(new FindByChannelName(channelName)); - } catch (ChannelFinderException e) { - if (e.getStatus().equals(ClientResponse.Status.NOT_FOUND)) { - return null; - } else { - throw e; - } - } - - } - - 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() throws UniformInterfaceException - { - mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); - try { - return new Channel(mapper.readValue(cfResource.path(resourceChannels).path(channelName) - .get(ClientResponse.class).getEntityInputStream(), XmlChannel.class)); - } catch (JsonParseException | JsonMappingException e) { - log.log(Level.WARNING, "Failed to process the list of channels", e); - } catch ( IOException e) { - log.log(Level.WARNING, "Failed to parse the list of tags", e); - } catch (UniformInterfaceException e) { - throw new ChannelFinderException(e); - } - return null; - } - - } - - /** - * 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 - */ - public void set(Channel.Builder channel) throws ChannelFinderException { - wrappedSubmit(new SetChannel(channel.toXml())); - } - - private class SetChannel implements Runnable { - private XmlChannel pxmlChannel = new XmlChannel(); - - public SetChannel(XmlChannel xmlChannel) { - super(); - this.pxmlChannel = xmlChannel; - } - - @Override - public void run() { - ObjectMapper mapper = new ObjectMapper(); - try { - cfAuthenticatedResource - .path(resourceChannels).path(this.pxmlChannel.getName()) - .type(MediaType.APPLICATION_JSON) - .put(mapper.writeValueAsString(this.pxmlChannel)); - } catch (JsonProcessingException e) { - log.log(Level.WARNING, "Failed to process the list of channel ", e); - } - } - } + HttpResponse httpResponse = + httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); - /** - * 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 List pxmlchannels = null; - - 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); - cfAuthenticatedResource - .path(resourceChannels) - .type(MediaType.APPLICATION_JSON) - .put(test); - } catch (JsonParseException | JsonMappingException e) { - log.log(Level.WARNING, "Failed to process the list of channels ", e); - } catch ( IOException e) { - log.log(Level.WARNING, "Failed to parse the list of tags", e); - } - } - } - - /** - * Destructively set a Tag tag with no associated channels to the - * database. - * - * @param tag - the tag to be set. - */ - public void set(Tag.Builder tag) { - wrappedSubmit(new SetTag(tag.toXml())); - } - - /** - * 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 - */ - public void set(Tag.Builder tag, String channelName) throws ChannelFinderException { - Collection channelNames = new ArrayList(); - channelNames.add(channelName); - wrappedSubmit(new SetTag(tag.toXml(), channelNames)); - } - - /** - * 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 - */ - public void set(Tag.Builder tag, Collection channelNames) throws ChannelFinderException { - wrappedSubmit(new SetTag(tag.toXml(), channelNames)); - } - - public void set(Tag.Builder tag, Map channelTagMap) { - wrappedSubmit(new SetTag(tag.toXml(), channelTagMap)); - } - - private class SetTag implements Runnable { - private XmlTag pxmlTag; - - public SetTag(XmlTag xmlTag) { - super(); - this.pxmlTag = xmlTag; - } - - SetTag(XmlTag xmlTag, Map channelTagMap) { - super(); - this.pxmlTag = xmlTag; - List channels = new ArrayList(); - for (Entry e : channelTagMap.entrySet()) { - XmlChannel xmlChannel = new XmlChannel(e.getKey()); - // need a copy to avoid a cycle - xmlChannel - .addXmlProperty(new XmlProperty(this.pxmlTag.getName(), this.pxmlTag.getOwner(), e.getValue())); - channels.add(xmlChannel); - } - 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); - } - - @Override - public void run() { - ObjectMapper mapper = new ObjectMapper(); - try { - cfAuthenticatedResource - .path(resourceTags).path(this.pxmlTag.getName()) - .type(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON) - .put(mapper.writeValueAsString(this.pxmlTag)); - } catch (JsonProcessingException e) { - log.log(Level.WARNING, "Failed to process the list of tags ", e); - } - } - } - - /** - * Destructively set a new property property. - * - * @param prop - the property to be set. - */ - public void set(Property.Builder prop) throws ChannelFinderException { - wrappedSubmit(new SetProperty(prop.toXml())); - } - - /** - * 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. - */ - public void set(Property.Builder prop, String channelName) { - Collection ch = new ArrayList(); - ch.add(channelName); - wrappedSubmit(new SetProperty(prop.toXml(), ch)); - } - - /** - * 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. - */ - 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 - */ - public void set(Property.Builder prop, Map channelPropertyMap) { - wrappedSubmit(new SetProperty(prop.toXml(), channelPropertyMap)); - } - - private class SetProperty implements Runnable { - private 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 { - cfAuthenticatedResource.path(resourceProperties).path(this.pxmlProperty.getName()).type(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON).put(mapper.writeValueAsString(this.pxmlProperty)); - } catch (JsonProcessingException e) { - log.log(Level.WARNING, "Failed to process the list of properties ", e); - } - } - } - - /** - * Update existing channel with channel. - * - * @param channel - channel builder - * @throws ChannelFinderException - channelfinder exception - */ - public void update(Channel.Builder channel) throws ChannelFinderException { - wrappedSubmit(new UpdateChannel(channel.toXml())); - } - - private class UpdateChannel implements Runnable { - private XmlChannel channel; - private final ObjectMapper mapper = new ObjectMapper(); - - UpdateChannel(XmlChannel channel) { - super(); - this.channel = channel; - } - - @Override - public void run() { - try { - cfAuthenticatedResource.path(resourceChannels) - .path(this.channel.getName()) - .type(MediaType.APPLICATION_JSON) - .post(mapper.writeValueAsString(this.channel)); - } catch (UniformInterfaceException e) { - throw new ChannelFinderException(e); - } catch (JsonProcessingException e) { - log.log(Level.WARNING, "Failed to process the list of channel ", e); - } - } - - } - - /** - * 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(Tag.Builder tag, String channelName) throws ChannelFinderException { - wrappedSubmit(new UpdateTag(tag.toXml(), channelName)); - } - - /** - * 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 - */ - public void update(Tag.Builder tag, Collection channelNames) throws ChannelFinderException { - wrappedSubmit(new UpdateTag(tag.toXml(), channelNames)); - } - - private class UpdateTag implements Runnable { - private XmlTag pxmlTag; - private final ObjectMapper mapper = new ObjectMapper(); - - @SuppressWarnings("unused") - UpdateTag(XmlTag xmlTag) { - super(); - 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; - List channels = new ArrayList(); - for (String channelName : channelNames) { - channels.add(new XmlChannel(channelName, "")); - } - xmlTag.setChannels(channels); - } + if(httpResponse.statusCode() != 200){ + throw new ChannelFinderException(httpResponse.statusCode(), httpResponse.body()); + } - @Override - public void run() { - try { - cfAuthenticatedResource - .path(resourceTags).path(this.pxmlTag.getName()) - .type(MediaType.APPLICATION_JSON) - .post(mapper.writeValueAsString(this.pxmlTag)); - } catch (UniformInterfaceException e) { - throw new ChannelFinderException(e); - } catch (JsonProcessingException e) { - log.log(Level.WARNING, "Failed to process the list of channel ", e); + xmltags = mapper.readValue(httpResponse.body(), + new TypeReference<>() { + }); + } catch (IOException 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 allTags; } - } + }); } + private final ObjectMapper mapper = new ObjectMapper(); + /** - * Update Property property by adding it to the channel - * channelName, without affecting the other channels. + * Get a list of names of all the tags currently present on the + * channelfinder service. * - * @param property - the property to be updated - * @param channelName - the channel to which this property should be added or - * updated. - * @throws ChannelFinderException - channelfinder exception + * @return a list of names of all the existing {@link Tag}s. */ - public void update(Property.Builder property, String channelName) throws ChannelFinderException { - wrappedSubmit(new UpdateChannelProperty(property.toXml(), channelName)); - } + @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)) + .header("Content-Type", MediaType.APPLICATION_JSON) + .GET() + .build(); - private class UpdateChannelProperty implements Runnable { - private final String channelName; - private XmlProperty pxmlProperty; - private final ObjectMapper mapper = new ObjectMapper(); + HttpResponse httpResponse = + httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); - UpdateChannelProperty(XmlProperty xmlProperty, String channelName) { - super(); - this.pxmlProperty = xmlProperty; - this.channelName = channelName; - XmlChannel xmlChannel = new XmlChannel(this.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); - } + if(httpResponse.statusCode() != 200){ + throw new ChannelFinderException(httpResponse.statusCode(), httpResponse.body()); + } - @Override - public void run() { - try { - cfAuthenticatedResource.path(resourceProperties) - .path(this.pxmlProperty.getName()) - .type(MediaType.APPLICATION_JSON) - .put(mapper.writeValueAsString(this.pxmlProperty)); - } catch (UniformInterfaceException e) { - throw new ChannelFinderException(e); - } catch (JsonProcessingException e) { - log.log(Level.WARNING, "Failed to process the property ", e); + xmltags = mapper.readValue(httpResponse.body(), + new TypeReference<>() { + }); + } catch (IOException 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 xmltags.stream().map(Tag::new).collect(Collectors.toList()); - /** - * @param property - property builder - * @param channelNames - list of channel names - * @throws ChannelFinderException - channelfinder exception - */ - public void update(Property.Builder property, Collection channelNames) throws ChannelFinderException { - wrappedSubmit(new UpdateProperty(property.toXml(), channelNames)); + }); } - /** - * @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)); + @Deprecated + public static void resetPreferences() { + try { + Preferences.userNodeForPackage(ChannelFinderClientImpl.class).clear(); + } catch (BackingStoreException e) { + log.log(Level.WARNING, "Failed to retrieve channelfinder preferences", e); + } } - private class UpdateProperty implements Runnable { - private XmlProperty pxmlProperty; - private final ObjectMapper mapper = new ObjectMapper(); - - @SuppressWarnings("unused") - UpdateProperty(XmlProperty xmlProperty) { - super(); - this.pxmlProperty = xmlProperty; - } + public void set(Tag.Builder tag, Map channelTagMap) { + wrappedSubmit(new SetTag(tag.toXml(), channelTagMap)); + } - UpdateProperty(XmlProperty xmlProperty, Collection channelNames) { - super(); - this.pxmlProperty = xmlProperty; - List channels = new ArrayList(); - for (String channelName : channelNames) { - XmlChannel xmlChannel = new XmlChannel(channelName); - // need a defensive copy to avoid A cycle - xmlChannel.addXmlProperty( - new XmlProperty(xmlProperty.getName(), xmlProperty.getOwner(), xmlProperty.getValue())); - channels.add(xmlChannel); - } - xmlProperty.setChannels(channels); - } + private class SetTag implements Runnable { + private final XmlTag pxmlTag; - UpdateProperty(XmlProperty xmlProperty, Map channelPropValueMap) { + SetTag(XmlTag xmlTag, Map channelTagMap) { super(); - this.pxmlProperty = xmlProperty; - List channels = new ArrayList(); - for (Entry e : channelPropValueMap.entrySet()) { + this.pxmlTag = xmlTag; + List channels = new ArrayList<>(); + for (Entry e : channelTagMap.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())); + // need a copy to avoid a cycle + xmlChannel + .addXmlProperty(new XmlProperty(this.pxmlTag.getName(), this.pxmlTag.getOwner(), e.getValue())); channels.add(xmlChannel); } - xmlProperty.setChannels(channels); + this.pxmlTag.setChannels(channels); } @Override public void run() { + ObjectMapper mapper = new ObjectMapper(); try { - cfAuthenticatedResource.path(resourceProperties).path(this.pxmlProperty.getName()).type(MediaType.APPLICATION_JSON) - .accept(MediaType.APPLICATION_JSON).post(mapper.writeValueAsString(this.pxmlProperty)); - } catch (UniformInterfaceException e) { - throw new ChannelFinderException(e); - } catch (JsonProcessingException e) { - log.log(Level.WARNING, "Failed to process the list of channel ", 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 - */ - 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 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 - */ - public Collection findByTag(String pattern) throws ChannelFinderException { - // return wrappedSubmit(new FindByParam("~tag", pattern)); - List and = Arrays.asList(pattern.split("&")); - MultivaluedMap searchMap = new MultivaluedMapImpl(); - for (String string : and) { - searchMap.add("~tag", string); - } - 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 - */ - 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$ + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(org.phoebus.channelfinder.Preferences.serviceURL + "/" + resourceTags + "/" + this.pxmlTag.getName())) + .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){ + throw new ChannelFinderException(httpResponse.statusCode(), httpResponse.body()); + } + } catch (Exception e) { + log.log(Level.WARNING, "Failed to process the list of tags ", e); + } } - return wrappedSubmit(new FindByMap(propertyPatterns)); } /** * Query for channels based on the Query string query example: - * find("SR* Cell=1,2 Tags=GolderOrbit,myTag)
+ * find("""SR* Cell=1,2 Tags=GolderOrbit,myTag")
*

* this will return all channels with names starting with SR AND have * property Cell=1 OR 2 AND have tags goldenOrbit AND myTag.
@@ -1019,6 +364,7 @@ public Collection findByProperty(String property, String... pattern) th * @return Collection of channels which satisfy the search criteria. * @throws ChannelFinderException - channelfinder exception */ + @Override public Collection find(String query) throws ChannelFinderException { return wrappedSubmit(new FindByMap(buildSearchMap(query))); } @@ -1036,78 +382,67 @@ public Collection find(String query) throws ChannelFinderException { * @return Collection of channels which satisfy the search map. * @throws ChannelFinderException - channelfinder exception */ + @Override public Collection find(Map map) throws ChannelFinderException { return wrappedSubmit(new FindByMap(map)); } - /** - * 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)); - } - private class FindByMap implements Callable> { - private MultivaluedMapImpl map; + private final MultivaluedMap multivaluedMap; private final ObjectMapper mapper = new ObjectMapper(); FindByMap(Map map) { - MultivaluedMapImpl mMap = new MultivaluedMapImpl(); + MultivaluedMap multivaluedMap = new MultivaluedHashMap<>(); for (Entry entry : map.entrySet()) { String key = entry.getKey(); - for (String value : Arrays.asList(entry.getValue().split(","))) { - mMap.add(key, value.trim()); + for (String value : entry.getValue().split(",")) { + multivaluedMap.put(key, List.of(value.trim())); } } - this.map = mMap; + this.multivaluedMap = multivaluedMap; } FindByMap(MultivaluedMap map) { - this.map = new MultivaluedMapImpl(); - this.map.putAll(map); + this.multivaluedMap = new MultivaluedHashMap<>(); + this.multivaluedMap.putAll(map); } @Override - public Collection call() throws Exception { - Collection channels = new HashSet(); - List xmlchannels = new ArrayList(); + public Collection call() { + Collection channels = new HashSet<>(); + List xmlchannels = new ArrayList<>(); long start = System.currentTimeMillis(); try { - xmlchannels = mapper.readValue(cfResource.path(resourceChannels) - .queryParams(this.map) - .accept(MediaType.APPLICATION_JSON).get(String.class), new TypeReference>() { - }); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(org.phoebus.channelfinder.Preferences.serviceURL + "/" + resourceChannels + "?" + QueryParamsHelper.mapToQueryParams(multivaluedMap))) + .header("Content-Type", MediaType.APPLICATION_JSON) + .GET() + .build(); + HttpResponse httpResponse = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); + if(httpResponse.statusCode() != 200){ + throw new ChannelFinderException(httpResponse.statusCode(), httpResponse.body()); + } + xmlchannels = mapper.readValue(httpResponse.body(), new TypeReference<>() { + }); } catch (Exception e) { - log.log(Level.WARNING, "Error creating channels:", e); + log.log(Level.WARNING, "Error creating channels:", e); } - log.log(Level.FINE, "Finished mapping to xml. (Time: " + String.valueOf(System.currentTimeMillis()-start) + " ms)"); + log.log(Level.FINE, "Finished mapping to xml. (Time: " + (System.currentTimeMillis() - start) + " ms)"); start = System.currentTimeMillis(); for (XmlChannel xmlchannel : xmlchannels) { channels.add(new Channel(xmlchannel)); } - log.log(Level.FINE, "Finished creating new channels. (Time: " + String.valueOf(System.currentTimeMillis()-start) + " ms)"); + log.log(Level.FINE, "Finished creating new channels. (Time: " + (System.currentTimeMillis() - start) + " ms)"); return Collections.unmodifiableCollection(channels); } } public static MultivaluedMap buildSearchMap(String searchPattern) { - MultivaluedMap map = new MultivaluedMapImpl(); + MultivaluedMap map = new MultivaluedHashMap<>(); searchPattern = searchPattern.replaceAll(", ", ","); - List searchWords = Arrays.asList(searchPattern.split("\\s")); - List searchNames = new ArrayList(); + String[] searchWords = searchPattern.split("\\s"); + List searchNames = new ArrayList<>(); for (String searchWord : searchWords) { if (!searchWord.contains("=")) { // this is a name value @@ -1146,73 +481,6 @@ public static MultivaluedMap buildSearchMap(String searchPattern return map; } - /** - * 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 - */ - 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 - */ - 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 - */ - public void deleteChannel(String channelName) throws ChannelFinderException - { - wrappedSubmit(new DeleteElement(resourceChannels, channelName)); // $NON-NLS-1$ - } - - 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() { - cfAuthenticatedResource.path(elementType).path(elementName).delete(); - } - - } - - /** - * Delete the set of channels identified by channels - * - * @param channels - channels to be deleted - * @throws ChannelFinderException - throws exception - */ - @Deprecated - public void delete(Collection channels) throws ChannelFinderException - { - for (Channel.Builder channel : channels) { - deleteChannel(channel.build().getName()); - } - } - /** * Delete tag tag from the channel with the name * channelName @@ -1221,8 +489,8 @@ public void delete(Collection channels) throws ChannelFinderExc * @param channelName - the channel from which to delete the tag tag * @throws ChannelFinderException - throws exception */ - public void delete(Tag.Builder tag, String channelName) throws ChannelFinderException - { + @Override + public void delete(Tag.Builder tag, String channelName) throws ChannelFinderException { wrappedSubmit(new DeleteElementfromChannel(resourceTags, tag // $NON-NLS-1$ .toXml().getName(), channelName)); } @@ -1234,8 +502,8 @@ public void delete(Tag.Builder tag, String channelName) throws ChannelFinderExce * @param channelNames - the channels from which to delete the tag tag * @throws ChannelFinderException - throws exception */ - public void delete(Tag.Builder tag, Collection channelNames) throws ChannelFinderException - { + @Override + public void delete(Tag.Builder tag, Collection channelNames) throws ChannelFinderException { // TODO optimize using the /tags/ payload with list of channels for (String channelName : channelNames) { delete(tag, channelName); @@ -1251,8 +519,8 @@ public void delete(Tag.Builder tag, Collection channelNames) throws Chan * property * @throws ChannelFinderException - throws exception */ - public void delete(Property.Builder property, String channelName) throws ChannelFinderException - { + @Override + public void delete(Property.Builder property, String channelName) throws ChannelFinderException { wrappedSubmit(new DeleteElementfromChannel(resourceProperties, property.build().getName(), channelName)); } @@ -1265,21 +533,19 @@ public void delete(Property.Builder property, String channelName) throws Channel * property * @throws ChannelFinderException - throws exception */ - public void delete(Property.Builder property, Collection channelNames) throws ChannelFinderException - { + @Override + public void delete(Property.Builder property, Collection channelNames) throws ChannelFinderException { for (String channel : channelNames) { delete(property, channel); } } - private class DeleteElementfromChannel implements Runnable - { + private class DeleteElementfromChannel implements Runnable { private final String elementType; private final String elementName; private final String channelName; - DeleteElementfromChannel(String elementType, String elementName, String channelName) - { + DeleteElementfromChannel(String elementType, String elementName, String channelName) { super(); this.elementType = elementType; this.elementName = elementName; @@ -1287,50 +553,38 @@ private class DeleteElementfromChannel implements Runnable } @Override - public void run() - { - cfAuthenticatedResource - .path(this.elementType) - .path(this.elementName) - .path(this.channelName) - .accept(MediaType.APPLICATION_JSON).delete(); - } + public void run() { - } + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(org.phoebus.channelfinder.Preferences.serviceURL + "/" + + this.elementType + "/" + + this.elementName + "/" + + this.channelName)) + .header("Accept", MediaType.APPLICATION_JSON) + .header("Authorization", basicAuthenticationHeader) + .DELETE() + .build(); - /** - * 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$ + try { + 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); } - } catch (InterruptedException ie) - { - // (Re-)Cancel if current thread also interrupted - this.executor.shutdownNow(); - // Preserve interrupt status - Thread.currentThread().interrupt(); } + } - private T wrappedSubmit(Callable callable) - { + private T wrappedSubmit(Callable callable) { try { return this.executor.submit(callable).get(); } catch (InterruptedException e) { throw new RuntimeException(e); } catch (ExecutionException e) { - if (e.getCause() != null && e.getCause() instanceof UniformInterfaceException) { - throw new ChannelFinderException((UniformInterfaceException) e.getCause()); + if (e.getMessage() != null) { + throw new ChannelFinderException(e.getMessage()); } throw new RuntimeException(e); } @@ -1342,35 +596,122 @@ private void wrappedSubmit(Runnable runnable) { } catch (InterruptedException e) { throw new RuntimeException(e); } catch (ExecutionException e) { - if (e.getCause() != null && e.getCause() instanceof UniformInterfaceException) { - throw new ChannelFinderException((UniformInterfaceException) e.getCause()); + if (e.getMessage() != null) { + throw new ChannelFinderException(e.getMessage()); } throw new RuntimeException(e); } } - public Collection getAllChannels() - { - ObjectMapper mapper = new ObjectMapper(); - List xmlchannels = new ArrayList(); - try { - xmlchannels = mapper.readValue( - cfAuthenticatedResource - .path(resourceChannels) - .accept(MediaType.APPLICATION_JSON) - .get(String.class), new TypeReference>() { - }); - } catch (JsonParseException | JsonMappingException e) { - log.log(Level.WARNING, "Failed to parse the list of channels ", e); - } catch ( IOException e) { - log.log(Level.WARNING, "Failed to parse the list of channels", e); - } catch (UniformInterfaceException 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 + * 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 + */ + 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 + * @throws ChannelFinderException - channelfinder exception + */ + public void update(Property.Builder property, Collection channelNames) throws ChannelFinderException { + wrappedSubmit(new UpdateProperty(property.toXml(), channelNames)); + } + + + private class UpdateTag implements Runnable { + private final XmlTag pxmlTag; + private final ObjectMapper mapper = new ObjectMapper(); + + @SuppressWarnings("unused") + UpdateTag(XmlTag xmlTag) { + super(); + this.pxmlTag = xmlTag; + } + + UpdateTag(XmlTag xmlTag, Collection channelNames) { + super(); + this.pxmlTag = xmlTag; + List channels = new ArrayList<>(); + for (String channelName : channelNames) { + channels.add(new XmlChannel(channelName, "")); + } + xmlTag.setChannels(channels); + } + + @Override + public void run() { + try { + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(org.phoebus.channelfinder.Preferences.serviceURL + "/" + resourceTags + "/" + this.pxmlTag.getName())) + .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){ + throw new ChannelFinderException(httpResponse.statusCode(), httpResponse.body()); + } + } catch (JsonProcessingException e) { + log.log(Level.WARNING, "Failed to update tag ", e); + } catch (IOException | InterruptedException e) { + throw new ChannelFinderException(e.getMessage()); + } + } + } + + private class UpdateProperty implements Runnable { + private final XmlProperty pxmlProperty; + private final ObjectMapper mapper = new ObjectMapper(); + + @SuppressWarnings("unused") + UpdateProperty(XmlProperty xmlProperty) { + super(); + this.pxmlProperty = xmlProperty; + } + + UpdateProperty(XmlProperty xmlProperty, Collection channelNames) { + super(); + this.pxmlProperty = xmlProperty; + List channels = new ArrayList<>(); + for (String channelName : channelNames) { + XmlChannel xmlChannel = new XmlChannel(channelName); + // need a defensive copy to avoid A cycle + xmlChannel.addXmlProperty( + new XmlProperty(xmlProperty.getName(), xmlProperty.getOwner(), xmlProperty.getValue())); + channels.add(xmlChannel); + } + xmlProperty.setChannels(channels); } - Collection set = new HashSet(); - for (XmlChannel channel : xmlchannels) { - set.add(new Channel(channel)); + + @Override + public void run() { + + try { + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(org.phoebus.channelfinder.Preferences.serviceURL + "/" + resourceProperties + "/" + this.pxmlProperty.getName())) + .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 (JsonProcessingException e) { + log.log(Level.WARNING, "Failed to update property ", e); + } catch (IOException | InterruptedException e) { + throw new ChannelFinderException(e.getMessage()); + } } - return set; } } 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 31763051ee..07a5f3a337 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 @@ -5,101 +5,45 @@ */ package org.phoebus.channelfinder; -import com.sun.jersey.api.client.ClientHandlerException; -import com.sun.jersey.api.client.ClientResponse.Status; -import com.sun.jersey.api.client.UniformInterfaceException; -import java.io.IOException; -import java.io.Reader; -import java.io.StringReader; -import java.net.SocketException; - -import javax.swing.text.html.parser.ParserDelegator; - /** * A Exception Type for various channelfinder exception conditions. - * - * @author shroffk * + * @author shroffk */ public class ChannelFinderException extends RuntimeException { /** - * + * */ private static final long serialVersionUID = 6279865221993808192L; - private Status status; - - public ChannelFinderException() { - super(); - } + private int httpStatus; public ChannelFinderException(String message) { super(message); } - public ChannelFinderException(UniformInterfaceException cause) { - super(parseErrorMsg(cause), cause); - this.setStatus(Status.fromStatusCode(cause.getResponse().getStatus())); - } - - public ChannelFinderException(ClientHandlerException cause) { - super(cause.getMessage()); - if(cause.getCause() instanceof SocketException) { - this.setStatus(Status.NOT_FOUND); - } else { - this.setStatus(Status.SEE_OTHER); - } - } - - private static String parseErrorMsg(UniformInterfaceException ex) { - String entity = ex.getResponse().getEntity(String.class); - try { - ClientResponseParser callback = new ClientResponseParser(); - Reader reader = new StringReader(entity); - new ParserDelegator().parse(reader, callback, false); - return callback.getMessage(); - } catch (IOException e) { - return "Could not retrieve message from server"; - } - } - - public ChannelFinderException(Status status, String message) { + public ChannelFinderException(int httpStatus, String message) { super(message); - this.setStatus(status); - } - - /** - * - * @param status - * - the http error status code - * @param cause - * - the original UniformInterfaceException - * @param message - * - additional error information - */ - public ChannelFinderException(Status status, Throwable cause, String message) { - super(message, cause); - this.setStatus(status); + this.setStatus(httpStatus); } /** * Set the associated HTTP status code which caused this exception. - * - * @param status - * the status to set + * + * @param status the status to set */ - public void setStatus(Status status) { - this.status = status; + public void setStatus(int httpStatus) { + this.httpStatus = httpStatus; } /** * Returns the associated HTTP status code which caused this exception. - * + * * @return the status */ - public Status getStatus() { - return status; + public int getStatus() { + return httpStatus; } } diff --git a/app/channel/channelfinder/src/main/java/org/phoebus/channelfinder/RawLoggingFilter.java b/app/channel/channelfinder/src/main/java/org/phoebus/channelfinder/RawLoggingFilter.java deleted file mode 100644 index 6a6da18672..0000000000 --- a/app/channel/channelfinder/src/main/java/org/phoebus/channelfinder/RawLoggingFilter.java +++ /dev/null @@ -1,252 +0,0 @@ -/** - * Copyright (C) 2010-2012 Brookhaven National Laboratory - * Copyright (C) 2010-2012 Helmholtz-Zentrum Berlin für Materialien und Energie GmbH - * All rights reserved. Use is subject to license terms. - */ -/* - * Copyright 2010 Brookhaven National Laboratory - * All rights reserved. Use is subject to license terms. - */ - - -package org.phoebus.channelfinder; - -import com.sun.jersey.api.client.AbstractClientRequestAdapter; -import com.sun.jersey.api.client.ClientHandlerException; -import com.sun.jersey.api.client.ClientRequest; -import com.sun.jersey.api.client.ClientRequestAdapter; -import com.sun.jersey.api.client.ClientResponse; -import com.sun.jersey.api.client.filter.ClientFilter; -import com.sun.jersey.core.util.ReaderWriter; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PrintStream; -import java.util.List; -import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.ws.rs.core.MultivaluedMap; - -/** - * A Raw HTML request/response logging filter. - * added level check to the handle. - * - * @author Paul.Sandoz@Sun.Com, shroffk - */ -public class RawLoggingFilter extends ClientFilter { - - private static final Logger LOGGER = Logger - .getLogger(RawLoggingFilter.class.getName()); - - private static final String NOTIFICATION_PREFIX = "* "; - - private static final String REQUEST_PREFIX = "> "; - - private static final String RESPONSE_PREFIX = "< "; - - private final class Adapter extends AbstractClientRequestAdapter { - private final StringBuilder b; - - Adapter(ClientRequestAdapter cra, StringBuilder b) { - super(cra); - this.b = b; - } - - public OutputStream adapt(ClientRequest request, OutputStream out) - throws IOException { - return new LoggingOutputStream(getAdapter().adapt(request, out), b); - } - - } - - private final class LoggingOutputStream extends OutputStream { - private final OutputStream out; - - private final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - - private final StringBuilder b; - - LoggingOutputStream(OutputStream out, StringBuilder b) { - this.out = out; - this.b = b; - } - - @Override - public void write(byte[] b) throws IOException { - baos.write(b); - out.write(b); - } - - @Override - public void write(byte[] b, int off, int len) throws IOException { - baos.write(b, off, len); - out.write(b, off, len); - } - - @Override - public void write(int b) throws IOException { - baos.write(b); - out.write(b); - } - - @Override - public void close() throws IOException { - printEntity(b, baos.toByteArray()); - log(b); - out.close(); - } - } - - private final PrintStream loggingStream; - - private final Logger logger; - - private long _id = 0; - - /** - * Create a logging filter logging the request and response to a default JDK - * logger, named as the fully qualified class name of this class. - */ - public RawLoggingFilter() { - this(LOGGER); - } - - /** - * Create a logging filter logging the request and response to a JDK logger. - * - * @param logger - * the logger to log requests and responses. - */ - public RawLoggingFilter(Logger logger) { - this.loggingStream = null; - this.logger = logger; - } - - /** - * Create a logging filter logging the request and response to print stream. - * - * @param loggingStream - * the print stream to log requests and responses. - */ - public RawLoggingFilter(PrintStream loggingStream) { - this.loggingStream = loggingStream; - this.logger = null; - } - - private void log(StringBuilder b) { - if (logger != null) { - logger.fine(b.toString()); - } else { - loggingStream.print(b); - } - } - - private StringBuilder prefixId(StringBuilder b, long id) { - b.append(Long.toString(id)).append(" "); - return b; - } - - @Override - public ClientResponse handle(ClientRequest request) - throws ClientHandlerException { - if (this.logger.isLoggable(Level.FINE)) { - long id = ++this._id; - logRequest(id, request); - - ClientResponse response = getNext().handle(request); - - logResponse(id, response); - - return response; - } else{ - return getNext().handle(request); - } - - } - - private void logRequest(long id, ClientRequest request) { - StringBuilder b = new StringBuilder(); - - printRequestLine(b, id, request); - printRequestHeaders(b, id, request.getHeaders()); - - if (request.getEntity() != null) { - request.setAdapter(new Adapter(request.getAdapter(), b)); - } else { - log(b); - } - } - - private void printRequestLine(StringBuilder b, long id, - ClientRequest request) { - prefixId(b, id).append(NOTIFICATION_PREFIX) - .append("Client out-bound request").append("\n"); - prefixId(b, id).append(REQUEST_PREFIX).append(request.getMethod()) - .append(" ").append(request.getURI().toASCIIString()) - .append("\n"); - } - - private void printRequestHeaders(StringBuilder b, long id, - MultivaluedMap headers) { - for (Map.Entry> e : headers.entrySet()) { - String header = e.getKey(); - for (Object value : e.getValue()) { - prefixId(b, id).append(REQUEST_PREFIX).append(header) - .append(": ") - .append(ClientRequest.getHeaderValue(value)) - .append("\n"); - } - } - prefixId(b, id).append(REQUEST_PREFIX).append("\n"); - } - - private void logResponse(long id, ClientResponse response) { - StringBuilder b = new StringBuilder(); - - printResponseLine(b, id, response); - printResponseHeaders(b, id, response.getHeaders()); - - ByteArrayOutputStream out = new ByteArrayOutputStream(); - InputStream in = response.getEntityInputStream(); - try { - ReaderWriter.writeTo(in, out); - - byte[] requestEntity = out.toByteArray(); - printEntity(b, requestEntity); - response.setEntityInputStream(new ByteArrayInputStream( - requestEntity)); - } catch (IOException ex) { - throw new ClientHandlerException(ex); - } - log(b); - } - - private void printResponseLine(StringBuilder b, long id, - ClientResponse response) { - prefixId(b, id).append(NOTIFICATION_PREFIX) - .append("Client in-bound response").append("\n"); - prefixId(b, id).append(RESPONSE_PREFIX) - .append(Integer.toString(response.getStatus())).append("\n"); - } - - private void printResponseHeaders(StringBuilder b, long id, - MultivaluedMap headers) { - for (Map.Entry> e : headers.entrySet()) { - String header = e.getKey(); - for (String value : e.getValue()) { - prefixId(b, id).append(RESPONSE_PREFIX).append(header) - .append(": ").append(value).append("\n"); - } - } - prefixId(b, id).append(RESPONSE_PREFIX).append("\n"); - } - - private void printEntity(StringBuilder b, byte[] entity) throws IOException { - if (entity.length == 0) - return; - b.append(new String(entity)).append("\n"); - } -} \ No newline at end of file