com.netflix.discovery.converters.jackson.builder.StringInterningAmazonInfoBuilder Maven / Gradle / Ivy
/*
* Copyright 2016 Netflix, Inc.
*
* 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 com.netflix.discovery.converters.jackson.builder;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.netflix.appinfo.AmazonInfo;
import com.netflix.appinfo.AmazonInfo.MetaDataKey;
import com.netflix.appinfo.DataCenterInfo.Name;
import com.netflix.discovery.converters.EnumLookup;
import com.netflix.discovery.util.DeserializerStringCache;
import com.netflix.discovery.util.DeserializerStringCache.CacheScope;
import com.netflix.discovery.util.StringCache;
import vlsi.utils.CompactHashMap;
/**
* Amazon instance info builder that is doing key names interning, together with
* value interning for selected keys (see {@link StringInterningAmazonInfoBuilder#VALUE_INTERN_KEYS}).
*
* The amount of string objects that is interned here is very limited in scope, and is done by calling
* {@link String#intern()}, with no custom build string cache.
*
* @author Tomasz Bak
*/
public class StringInterningAmazonInfoBuilder extends JsonDeserializer{
private static final Map VALUE_INTERN_KEYS;
private static final char[] BUF_METADATA = "metadata".toCharArray();
static {
HashMap keys = new HashMap<>();
keys.put(MetaDataKey.accountId.getName(), CacheScope.GLOBAL_SCOPE);
keys.put(MetaDataKey.amiId.getName(), CacheScope.GLOBAL_SCOPE);
keys.put(MetaDataKey.availabilityZone.getName(), CacheScope.GLOBAL_SCOPE);
keys.put(MetaDataKey.instanceType.getName(), CacheScope.GLOBAL_SCOPE);
keys.put(MetaDataKey.vpcId.getName(), CacheScope.GLOBAL_SCOPE);
keys.put(MetaDataKey.publicIpv4.getName(), CacheScope.APPLICATION_SCOPE);
keys.put(MetaDataKey.localHostname.getName(), CacheScope.APPLICATION_SCOPE);
VALUE_INTERN_KEYS = keys;
}
private HashMap metadata;
public StringInterningAmazonInfoBuilder withName(String name) {
return this;
}
public StringInterningAmazonInfoBuilder withMetadata(HashMap metadata) {
this.metadata = metadata;
if (metadata.isEmpty()) {
return this;
}
for (Map.Entry entry : metadata.entrySet()) {
String key = entry.getKey().intern();
if (VALUE_INTERN_KEYS.containsKey(key)) {
entry.setValue(StringCache.intern(entry.getValue()));
}
}
return this;
}
public AmazonInfo build() {
return new AmazonInfo(Name.Amazon.name(), metadata);
}
@Override
public AmazonInfo deserialize(JsonParser jp, DeserializationContext context)
throws IOException {
Map metadata = new CompactHashMap<>();
DeserializerStringCache intern = DeserializerStringCache.from(context);
JsonToken jsonToken;
while((jsonToken = jp.nextToken()) != JsonToken.END_OBJECT){
jsonToken = jp.nextToken();
if (EnumLookup.equals(BUF_METADATA, jp.getTextCharacters(), jp.getTextOffset(), jp.getTextLength())) {
jsonToken = jp.nextToken();
while((jsonToken = jp.nextToken()) != JsonToken.END_OBJECT) {
String metadataKey = intern.apply(jp, CacheScope.GLOBAL_SCOPE);
jp.nextToken();
CacheScope scope = VALUE_INTERN_KEYS.get(metadataKey);
String metadataValue = (scope != null) ? intern.apply(jp, scope) : intern.apply(jp, CacheScope.APPLICATION_SCOPE);
metadata.put(metadataKey, metadataValue);
}
}
else {
jsonToken = jp.nextToken();
}
}
return new AmazonInfo(Name.Amazon.name(), metadata);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy