/* * Copyright 2016 LINE Corporation * * LINE Corporation licenses this file to you 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 com.linecorp.armeria.common.zookeeper; import static java.util.Objects.requireNonNull; import java.nio.charset.StandardCharsets; import java.util.HashSet; import java.util.Set; import java.util.regex.Pattern; import com.linecorp.armeria.client.Endpoint; import com.linecorp.armeria.client.endpoint.EndpointGroupException; final class DefaultNodeValueCodec implements NodeValueCodec { static final DefaultNodeValueCodec INSTANCE = new DefaultNodeValueCodec(); private static final String segmentDelimiter = ","; private static final String fieldDelimiter = ":"; private static final Pattern SEGMENT_DELIMITER = Pattern.compile("\\s*" + segmentDelimiter + "\\s*"); @Override public Endpoint decode(String segment) { final String[] tokens = segment.split(fieldDelimiter); final Endpoint endpoint; switch (tokens.length) { case 1: //host endpoint = Endpoint.of(segment); break; case 2: { //host and port final String host = tokens[0]; final int port = Integer.parseInt(tokens[1]); if (port == 0) { endpoint = Endpoint.of(host); } else { endpoint = Endpoint.of(host, port); } break; } case 3: { //host , port , weight final String host = tokens[0]; final int port = Integer.parseInt(tokens[1]); final int weight = Integer.parseInt(tokens[2]); if (port == 0) { endpoint = Endpoint.of(host).withWeight(weight); } else { endpoint = Endpoint.of(host, port, weight); } break; } default: //unknown throw new EndpointGroupException( "invalid endpoint list: " + segment); } return endpoint; } @Override public Set<Endpoint> decodeAll(String valueString) { Set<Endpoint> endpoints = new HashSet<>(); try { for (String segment : SEGMENT_DELIMITER.split(valueString)) { endpoints.add(decode(segment)); } } catch (Exception e) { throw new EndpointGroupException("invalid endpoint list: " + valueString, e); } if (endpoints.isEmpty()) { throw new EndpointGroupException("ZNode does not contain any endpoints."); } return endpoints; } @Override public byte[] encodeAll(Iterable<Endpoint> endpoints) { requireNonNull(endpoints, "endpoints"); StringBuilder nodeValue = new StringBuilder(); endpoints.forEach(endpoint -> nodeValue.append(endpoint.host()).append(fieldDelimiter).append( endpoint.port()).append(fieldDelimiter).append(endpoint.weight()).append(segmentDelimiter)); //delete the last unused segment delimiter if (nodeValue.length() > 0) { nodeValue.deleteCharAt(nodeValue.length() - 1); } return nodeValue.toString().getBytes(StandardCharsets.UTF_8); } @Override public byte[] encode(Endpoint endpoint) { return (endpoint.host() + fieldDelimiter + endpoint.port() + fieldDelimiter + endpoint.weight()) .getBytes(StandardCharsets.UTF_8); } }