All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.aeron.ChannelUri Maven / Gradle / Ivy

There is a newer version: 1.46.7
Show newest version
/*
 * Copyright 2014-2017 Real Logic Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.aeron;

import java.util.*;

import static io.aeron.CommonContext.SPY_PREFIX;

/**
 * Parser for Aeron channel URIs. The format is:
 * 
 * aeron-uri = "aeron:" media [ "?" param *( "|" param ) ]
 * media     = *( "[^?:]" )
 * param     = key "=" value
 * key       = *( "[^=]" )
 * value     = *( "[^|]" )
 * 
*

* Multiple params with the same key are allowed, the last value specified takes precedence. * @see ChannelUriStringBuilder */ public class ChannelUri { private enum State { MEDIA, PARAMS_KEY, PARAMS_VALUE } /** * URI Scheme for Aeron channels. */ public static final String AERON_SCHEME = "aeron"; /** * Qualifier for spy subscriptions. */ public static final String SPY_QUALIFIER = "aeron-spy"; private static final String AERON_PREFIX = AERON_SCHEME + ":"; private final String prefix; private final String media; private final Map params; /** * Construct with the components provided to avoid parsing. * * @param prefix empty if no prefix is required otherwise expected to be 'aeron-spy' * @param media for the channel which is typically "udp" or "ipc". * @param params for the query string as key value pairs. */ public ChannelUri(final String prefix, final String media, final Map params) { this.prefix = prefix; this.media = media; this.params = params; } /** * Construct with the components provided to avoid parsing. * * @param media for the channel which is typically "udp" or "ipc". * @param params for the query string as key value pairs. */ public ChannelUri(final String media, final Map params) { this("", media, params); } /** * The prefix for the channel. * * @return the prefix for the channel. */ public String prefix() { return prefix; } /** * The media over which the channel operates. * * @return the media over which the channel operates. */ public String media() { return media; } /** * The scheme for the URI. Must be "aeron". * * @return the scheme for the URI. */ public String scheme() { return AERON_SCHEME; } /** * Get a value for a given parameter key. * * @param key to lookup. * @return the value if set for the key otherwise null. */ public String get(final String key) { return params.get(key); } /** * Get the value for a given parameter key or the default value provided if the key does not exist. * * @param key to lookup. * @param defaultValue to be returned if no key match is found. * @return the value if set for the key otherwise the default value provided. */ public String get(final String key, final String defaultValue) { final String value = params.get(key); if (null != value) { return value; } return defaultValue; } /** * Put a key and value pair in the map of params. * * @param key of the param to be put. * @param value of the param to be put. * @return the existing value otherwise null. */ public String put(final String key, final String value) { return params.put(key, value); } /** * Does the URI contain a value for the given key. * * @param key to be lookup. * @return true if the key has a value otherwise false. */ public boolean containsKey(final String key) { return params.containsKey(key); } /** * Generate a String representation of the URI that is valid for an Aeron channel. * * @return a String representation of the URI that is valid for an Aeron channel. */ public String toString() { final StringBuilder sb; if (prefix == null || "".equals(prefix)) { sb = new StringBuilder((params.size() * 20) + 10); } else { sb = new StringBuilder((params.size() * 20) + 20); sb.append(SPY_PREFIX); } sb.append(AERON_PREFIX).append(media); if (params.size() > 0) { sb.append('?'); for (final Map.Entry entry : params.entrySet()) { sb.append(entry.getKey()).append('=').append(entry.getValue()).append('|'); } sb.setLength(sb.length() - 1); } return sb.toString(); } /** * Parse a {@link CharSequence} which contains an Aeron URI. * * @param cs to be parsed. * @return a new {@link ChannelUri} representing the URI string. */ public static ChannelUri parse(final CharSequence cs) { int position = 0; final String prefix; if (startsWith(cs, SPY_PREFIX)) { prefix = SPY_QUALIFIER; position = SPY_PREFIX.length(); } else { prefix = ""; } if (!startsWith(cs, position, AERON_PREFIX)) { throw new IllegalArgumentException("Aeron URIs must start with 'aeron:', found: '" + cs + "'"); } else { position += AERON_PREFIX.length(); } final StringBuilder builder = new StringBuilder(); final Map params = new HashMap<>(); String media = null; String key = null; State state = State.MEDIA; for (int i = position; i < cs.length(); i++) { final char c = cs.charAt(i); switch (state) { case MEDIA: switch (c) { case '?': media = builder.toString(); builder.setLength(0); state = State.PARAMS_KEY; break; case ':': throw new IllegalArgumentException("Encountered ':' within media definition"); default: builder.append(c); } break; case PARAMS_KEY: switch (c) { case '=': key = builder.toString(); builder.setLength(0); state = State.PARAMS_VALUE; break; default: builder.append(c); } break; case PARAMS_VALUE: switch (c) { case '|': params.put(key, builder.toString()); builder.setLength(0); state = State.PARAMS_KEY; break; default: builder.append(c); } break; default: throw new IllegalStateException("Que? state=" + state); } } switch (state) { case MEDIA: media = builder.toString(); break; case PARAMS_VALUE: params.put(key, builder.toString()); break; default: throw new IllegalArgumentException("No more input found, but was in state: " + state); } return new ChannelUri(prefix, media, params); } private static boolean startsWith(final CharSequence input, final int position, final CharSequence prefix) { if ((input.length() - position) < prefix.length()) { return false; } for (int i = 0; i < prefix.length(); i++) { if (input.charAt(position + i) != prefix.charAt(i)) { return false; } } return true; } private static boolean startsWith(final CharSequence input, final CharSequence prefix) { return startsWith(input, 0, prefix); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy