package com.linkedin.databus2.core.container.request; /* * Copyright 2013 LinkedIn Corp. All rights reserved * * 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. */ import java.util.ArrayList; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import com.linkedin.databus.core.util.Base64; /** * Store a single version of Espresso's replication metadata schema for use in * version 2 of the relay-client "/register" protocol. * * See https://iwww.corp.linkedin.com/wiki/cf/display/ENGS/Espresso+Metadata+Schema * for specification. * * This class currently is a near-clone of RegisterResponseEntry, which is used * for database-source shemas in the /register call, and it could act as the base * class for RegisterResponseEntry (or derive from a common base class). But * conceptually it's a separate thing that could someday have its own, non-source- * related attributes or other behaviors, so keep it independent for now. * * TODO: rename RegisterResponseEntry to RegisterResponseSourceEntry? */ public class RegisterResponseMetadataEntry { public final static String METADATA_SCHEMAS_KEY = "metadataSchemas"; public static final String MODULE = RegisterResponseMetadataEntry.class.getName(); public static final Logger LOG = Logger.getLogger(MODULE); private String _schema; private short _version; private byte[] _crc32; public RegisterResponseMetadataEntry(short version, String schema, byte[] crc32) { super(); _version = version; _schema = schema; _crc32 = crc32; } public RegisterResponseMetadataEntry() { this((short)0, "n/a", new byte[4]); } public short getVersion() { return _version; } public byte[] getCrc32() { return _crc32.clone(); } public void setVersion(short version) { _version = version; } public String getSchema() { return _schema; } public static List<RegisterResponseMetadataEntry> createFromResponse(Map<String, List<Object>> responseMap, String hashKey, boolean optional) { // We initially expect only a single metadataSchema (for replication), but it's // versioned, so a List is the minimal requirement. If other kinds of metadata // schemas are ever added (e.g., with ID values to differentiate them), we'll // have to change this block to look more like the source- and key-schemas ones // above (i.e., build a hashmap of ID-to-list entries). List<Object> metadataObjectsList = responseMap.get(RegisterResponseMetadataEntry.METADATA_SCHEMAS_KEY); List<RegisterResponseMetadataEntry> metadataSchemasList = null; if (metadataObjectsList == null) { LOG.info("/register response v4 has no '" + RegisterResponseMetadataEntry.METADATA_SCHEMAS_KEY + "' entry"); } else { metadataSchemasList = reconstructMetadataSchemasList(metadataObjectsList); } return metadataSchemasList; } private static List<RegisterResponseMetadataEntry> reconstructMetadataSchemasList(List<Object> objectsList) { List<RegisterResponseMetadataEntry> schemasList = new ArrayList<RegisterResponseMetadataEntry>(); for (Object obj : objectsList) { boolean ok = false; if (obj instanceof Map) { @SuppressWarnings("unchecked") // just map Map<String, Object> map = (Map<String, Object>)obj; if (map.containsKey("version") && map.containsKey("schema") && map.containsKey("crc32")) { byte[] crc32Digest = Base64.decode((String) (map.get("crc32"))); schemasList.add(new RegisterResponseMetadataEntry(((Integer)map.get("version")).shortValue(), (String)map.get("schema"), crc32Digest)); ok = true; } } if (!ok) { throw new RuntimeException("/register response v4 metadata schemas deserialization error: object type = " + obj.getClass().getName()); } } return schemasList; } public void setSchema(String schema) { _schema = schema; } }