| /* |
| * Copyright 2011 Google 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.google.ipc.invalidation.common; |
| |
| import com.google.common.base.Receiver; |
| import com.google.ipc.invalidation.util.Bytes; |
| import com.google.ipc.invalidation.util.LazyString; |
| import com.google.ipc.invalidation.util.TextBuilder; |
| import com.google.protobuf.ByteString; |
| import com.google.protos.ipc.invalidation.ClientProtocol.ApplicationClientIdP; |
| import com.google.protos.ipc.invalidation.ClientProtocol.ClientHeader; |
| import com.google.protos.ipc.invalidation.ClientProtocol.ClientToServerMessage; |
| import com.google.protos.ipc.invalidation.ClientProtocol.ConfigChangeMessage; |
| import com.google.protos.ipc.invalidation.ClientProtocol.ErrorMessage; |
| import com.google.protos.ipc.invalidation.ClientProtocol.InfoMessage; |
| import com.google.protos.ipc.invalidation.ClientProtocol.InfoRequestMessage; |
| import com.google.protos.ipc.invalidation.ClientProtocol.InitializeMessage; |
| import com.google.protos.ipc.invalidation.ClientProtocol.InvalidationMessage; |
| import com.google.protos.ipc.invalidation.ClientProtocol.InvalidationP; |
| import com.google.protos.ipc.invalidation.ClientProtocol.ObjectIdP; |
| import com.google.protos.ipc.invalidation.ClientProtocol.PropertyRecord; |
| import com.google.protos.ipc.invalidation.ClientProtocol.ProtocolVersion; |
| import com.google.protos.ipc.invalidation.ClientProtocol.RegistrationMessage; |
| import com.google.protos.ipc.invalidation.ClientProtocol.RegistrationP; |
| import com.google.protos.ipc.invalidation.ClientProtocol.RegistrationStatus; |
| import com.google.protos.ipc.invalidation.ClientProtocol.RegistrationStatusMessage; |
| import com.google.protos.ipc.invalidation.ClientProtocol.RegistrationSubtree; |
| import com.google.protos.ipc.invalidation.ClientProtocol.RegistrationSummary; |
| import com.google.protos.ipc.invalidation.ClientProtocol.RegistrationSyncMessage; |
| import com.google.protos.ipc.invalidation.ClientProtocol.RegistrationSyncRequestMessage; |
| import com.google.protos.ipc.invalidation.ClientProtocol.ServerHeader; |
| import com.google.protos.ipc.invalidation.ClientProtocol.ServerToClientMessage; |
| import com.google.protos.ipc.invalidation.ClientProtocol.StatusP; |
| import com.google.protos.ipc.invalidation.ClientProtocol.TokenControlMessage; |
| |
| import java.util.Collection; |
| |
| |
| /** |
| * Utilities to make it easier/cleaner/shorter for printing and converting protobufs to strings in |
| * . This class exposes methods to return objects such that their toString method returns a |
| * compact representation of the proto. These methods can be used in the Ticl |
| * |
| */ |
| public class CommonProtoStrings2 { |
| |
| // |
| // Implementation notes: The following methods return the object as mentioned above for different |
| // protos. Each method (except for a couple of them) essentially calls a private static method |
| // that uses a TextBuilder to construct the final string. Each method has the following spec: |
| // Returns a compact string representation for {@code <parameter-name>} for logging |
| // |
| |
| /** See spec in implementation notes. */ |
| public static Object toLazyCompactString(final ByteString byteString) { |
| if (byteString == null) { |
| return null; |
| } |
| return new Object() { |
| @Override |
| public String toString() { |
| return Bytes.toString(byteString.toByteArray()); |
| } |
| }; |
| } |
| |
| /** See spec in implementation notes. */ |
| public static Object toLazyCompactString(final byte[] bytes) { |
| if (bytes == null) { |
| return null; |
| } |
| return new Object() { |
| @Override |
| public String toString() { |
| return Bytes.toString(bytes); |
| } |
| }; |
| } |
| |
| /** See spec in implementation notes. */ |
| public static Object toLazyCompactString(final ObjectIdP objectId) { |
| return LazyString.toLazyCompactString(objectId, new Receiver<TextBuilder>() { |
| @Override |
| public void accept(TextBuilder builder) { |
| toCompactString(builder, objectId); |
| } |
| }); |
| } |
| |
| /** See spec in implementation notes. */ |
| public static Object toLazyCompactString(final InvalidationP invalidation) { |
| return LazyString.toLazyCompactString(invalidation, new Receiver<TextBuilder>() { |
| @Override |
| public void accept(TextBuilder builder) { |
| toCompactString(builder, invalidation); |
| } |
| }); |
| } |
| |
| /** See spec in implementation notes. */ |
| public static Object toLazyCompactString(final RegistrationP registration) { |
| return LazyString.toLazyCompactString(registration, new Receiver<TextBuilder>() { |
| @Override |
| public void accept(TextBuilder builder) { |
| toCompactString(builder, registration); |
| } |
| }); |
| } |
| |
| /** See spec in implementation notes. */ |
| public static Object toLazyCompactString(final ApplicationClientIdP applicationId) { |
| return LazyString.toLazyCompactString(applicationId, new Receiver<TextBuilder>() { |
| @Override |
| public void accept(TextBuilder builder) { |
| toCompactString(builder, applicationId); |
| } |
| }); |
| } |
| |
| /** See spec in implementation notes. */ |
| public static Object toLazyCompactString(final RegistrationSummary regSummary) { |
| return LazyString.toLazyCompactString(regSummary, new Receiver<TextBuilder>() { |
| @Override |
| public void accept(TextBuilder builder) { |
| toCompactString(builder, regSummary); |
| } |
| }); |
| } |
| |
| /** See spec in implementation notes. */ |
| public static Object toLazyCompactString(final InfoMessage infoMessage) { |
| return LazyString.toLazyCompactString(infoMessage, new Receiver<TextBuilder>() { |
| @Override |
| public void accept(TextBuilder builder) { |
| toCompactString(builder, infoMessage); |
| } |
| }); |
| } |
| |
| /** See spec in implementation notes. */ |
| public static Object toLazyCompactString(final RegistrationSyncMessage syncMessage) { |
| return LazyString.toLazyCompactString(syncMessage, new Receiver<TextBuilder>() { |
| @Override |
| public void accept(TextBuilder builder) { |
| toCompactString(builder, syncMessage); |
| } |
| }); |
| } |
| |
| /** See spec in implementation notes and toCompactString for ClientToServerMessage. */ |
| public static Object toLazyCompactString(final ClientToServerMessage message, |
| final boolean printHighFrequencyMessages) { |
| return LazyString.toLazyCompactString(message, new Receiver<TextBuilder>() { |
| @Override |
| public void accept(TextBuilder builder) { |
| toCompactString(builder, message, printHighFrequencyMessages); |
| } |
| }); |
| } |
| |
| /** See spec in implementation notes and toCompactString for ServerToClientMessage. */ |
| public static Object toLazyCompactString(final ServerToClientMessage message, |
| final boolean printHighFrequencyMessages) { |
| return LazyString.toLazyCompactString(message, new Receiver<TextBuilder>() { |
| @Override |
| public void accept(TextBuilder builder) { |
| toCompactString(builder, message, printHighFrequencyMessages); |
| } |
| }); |
| } |
| |
| |
| /** See spec in implementation notes. */ |
| public static Object toLazyCompactStringForObjectIds( |
| final Collection<ObjectIdP> objectIds) { |
| return LazyString.toLazyCompactString(objectIds, new Receiver<TextBuilder>() { |
| @Override |
| public void accept(TextBuilder builder) { |
| toCompactStringForObjectIds(builder, objectIds); |
| } |
| }); |
| } |
| |
| /** See spec in implementation notes. */ |
| public static Object toLazyCompactStringForInvalidations( |
| final Collection<InvalidationP> invalidations) { |
| return LazyString.toLazyCompactString(invalidations, new Receiver<TextBuilder>() { |
| @Override |
| public void accept(TextBuilder builder) { |
| toCompactStringForInvalidations(builder, invalidations); |
| } |
| }); |
| } |
| |
| /** See spec in implementation notes. */ |
| public static Object toLazyCompactStringForRegistrations( |
| final Collection<RegistrationP> registrations) { |
| return LazyString.toLazyCompactString(registrations, new Receiver<TextBuilder>() { |
| @Override |
| public void accept(TextBuilder builder) { |
| toCompactStringForRegistrations(builder, registrations); |
| } |
| }); |
| } |
| |
| // |
| // Implementation notes: The following helper methods do the actual conversion of the proto into |
| // the compact representation in the given builder. Each method has the following spec: |
| // Adds a compact representation for {@code <parameter-name>} to {@code builder} and |
| // returns {@code builder}. |
| // TODO: Look into building indirection tables for the collections to avoid |
| // code duplication. |
| // |
| |
| /** See spec in implementation notes. */ |
| public static TextBuilder toCompactString(TextBuilder builder, ByteString byteString) { |
| if (byteString == null) { |
| return builder; |
| } |
| return Bytes.toCompactString(builder, byteString.toByteArray()); |
| } |
| |
| /** See spec in implementation notes. */ |
| public static TextBuilder toCompactString(TextBuilder builder, ObjectIdP objectId) { |
| if (objectId == null) { |
| return builder; |
| } |
| builder.appendFormat("(Obj: %s, ", objectId.getSource()); |
| toCompactString(builder, objectId.getName()); |
| builder.append(')'); |
| return builder; |
| } |
| |
| /** See spec in implementation notes. */ |
| public static TextBuilder toCompactString(TextBuilder builder, |
| InvalidationP invalidation) { |
| if (invalidation == null) { |
| return builder; |
| } |
| builder.append("(Inv: "); |
| toCompactString(builder, invalidation.getObjectId()); |
| builder.append(", "); |
| if (invalidation.getIsTrickleRestart()) { |
| builder.append("<"); |
| } |
| builder.append(invalidation.getVersion()); |
| if (invalidation.hasPayload()) { |
| builder.append(", P:"); |
| toCompactString(builder, invalidation.getPayload()); |
| } |
| builder.append(')'); |
| return builder; |
| } |
| |
| /** See spec in implementation notes. */ |
| public static TextBuilder toCompactStringForInvalidations(TextBuilder builder, |
| final Collection<InvalidationP> invalidations) { |
| if (invalidations == null) { |
| return builder; |
| } |
| boolean first = true; |
| for (InvalidationP invalidation : invalidations) { |
| if (!first) { |
| builder.append(", "); |
| } |
| toCompactString(builder, invalidation); |
| first = false; |
| } |
| return builder; |
| } |
| |
| /** See spec in implementation notes. */ |
| public static TextBuilder toCompactString(TextBuilder builder, StatusP status) { |
| if (status == null) { |
| return builder; |
| } |
| builder.appendFormat("Status: %s", status.getCode()); |
| if (status.hasDescription()) { |
| builder.appendFormat(", Desc: %s", status.getDescription()); |
| } |
| return builder; |
| } |
| |
| |
| /** See spec in implementation notes. */ |
| public static TextBuilder toCompactString(TextBuilder builder, RegistrationP regOp) { |
| if (regOp == null) { |
| return builder; |
| } |
| builder.appendFormat("RegOp: %s, ", |
| regOp.getOpType() == RegistrationP.OpType.REGISTER ? "R" : "U"); |
| toCompactString(builder, regOp.getObjectId()); |
| return builder; |
| } |
| |
| public static TextBuilder toCompactString(TextBuilder builder, |
| RegistrationStatus regStatus) { |
| if (regStatus == null) { |
| return builder; |
| } |
| builder.append('<'); |
| toCompactString(builder, regStatus.getRegistration()); |
| builder.append(", "); |
| toCompactString(builder, regStatus.getStatus()); |
| builder.append('>'); |
| return builder; |
| } |
| |
| /** See spec in implementation notes. */ |
| public static TextBuilder toCompactStringForRegistrations(TextBuilder builder, |
| Collection<RegistrationP> registrations) { |
| if (registrations == null) { |
| return builder; |
| } |
| |
| boolean first = true; |
| builder.append("RegOps: "); |
| for (RegistrationP registration : registrations) { |
| if (!first) { |
| builder.append(", "); |
| } |
| toCompactString(builder, registration); |
| first = false; |
| } |
| return builder; |
| } |
| |
| /** See spec in implementation notes. */ |
| public static TextBuilder toCompactStringForRegistrationStatuses(TextBuilder builder, |
| Collection<RegistrationStatus> registrationStatuses) { |
| if (registrationStatuses == null) { |
| return builder; |
| } |
| |
| boolean first = true; |
| builder.append("RegOps: "); |
| for (RegistrationStatus registrationStatus : registrationStatuses) { |
| if (!first) { |
| builder.append(", "); |
| } |
| toCompactString(builder, registrationStatus); |
| first = false; |
| } |
| return builder; |
| } |
| |
| /** See spec in implementation notes. */ |
| public static TextBuilder toCompactStringForObjectIds(TextBuilder builder, |
| Collection<ObjectIdP> objectIds) { |
| if (objectIds == null) { |
| return builder; |
| } |
| boolean first = true; |
| builder.append("ObjectIds: "); |
| for (ObjectIdP objectId : objectIds) { |
| if (!first) { |
| builder.append(", "); |
| } |
| toCompactString(builder, objectId); |
| first = false; |
| } |
| return builder; |
| } |
| |
| /** See spec in implementation notes. */ |
| private static TextBuilder toCompactString(TextBuilder builder, |
| ApplicationClientIdP applicationClientId) { |
| if (applicationClientId == null) { |
| return builder; |
| } |
| builder.appendFormat("(Ceid: "); |
| toCompactString(builder, applicationClientId.getClientName()); |
| builder.append(')'); |
| return builder; |
| } |
| |
| /** See spec in implementation notes. */ |
| public static TextBuilder toCompactString(TextBuilder builder, |
| RegistrationSummary regSummary) { |
| if (regSummary == null) { |
| return builder; |
| } |
| |
| builder.appendFormat("<RegSummary: Num = %d, Hash = ", regSummary.getNumRegistrations()); |
| CommonProtoStrings2.toCompactString(builder, regSummary.getRegistrationDigest()); |
| builder.append('>'); |
| return builder; |
| } |
| |
| public static TextBuilder toCompactString(TextBuilder builder, |
| ProtocolVersion protocolVersion) { |
| if (protocolVersion == null) { |
| return builder; |
| } |
| builder.appendFormat("%d.%d", protocolVersion.getVersion().getMajorVersion(), |
| protocolVersion.getVersion().getMinorVersion()); |
| return builder; |
| } |
| |
| // Print methods for every client-to-server message type. |
| |
| /** See spec in implementation notes. */ |
| public static TextBuilder toCompactString(TextBuilder builder, ClientHeader header) { |
| if (header == null) { |
| return builder; |
| } |
| builder.append("C2S: "); |
| toCompactString(builder, header.getProtocolVersion()); |
| builder.appendFormat(", MsgId: %s, Num regs = %s, Token = ", header.getMessageId(), |
| header.getRegistrationSummary().getNumRegistrations()); |
| toCompactString(builder, header.getClientToken()); |
| return builder; |
| } |
| |
| /** See spec in implementation notes. */ |
| public static TextBuilder toCompactString(TextBuilder builder, |
| InitializeMessage initializeMessage) { |
| if (initializeMessage == null) { |
| return builder; |
| } |
| builder.appendFormat("InitMsg: Client Type: %d, ", initializeMessage.getClientType()); |
| toCompactString(builder, initializeMessage.getApplicationClientId()); |
| return builder; |
| } |
| |
| /** See spec in implementation notes. */ |
| public static TextBuilder toCompactString(TextBuilder builder, |
| RegistrationMessage registrationMessage) { |
| if (registrationMessage == null) { |
| return builder; |
| } |
| builder.appendFormat("RegMsg: "); |
| toCompactStringForRegistrations(builder, registrationMessage.getRegistrationList()); |
| return builder; |
| } |
| |
| /** See spec in implementation notes. */ |
| public static TextBuilder toCompactString(TextBuilder builder, |
| RegistrationSyncMessage syncMessage) { |
| if (syncMessage == null) { |
| return builder; |
| } |
| RegistrationSubtree subtree = syncMessage.getSubtree(0); |
| builder.appendFormat("RegSyncMsg: Num regs: %d, Regs: ", subtree.getRegisteredObjectCount()); |
| toCompactStringForObjectIds(builder, subtree.getRegisteredObjectList()); |
| return builder; |
| } |
| |
| /** See spec in implementation notes. */ |
| public static TextBuilder toCompactString(TextBuilder builder, |
| InfoMessage infoMessage) { |
| if (infoMessage == null) { |
| return builder; |
| } |
| builder.appendFormat("InfoMsg: Platform = %s, Is_summary_requested = %s, Perf counters: ", |
| infoMessage.getClientVersion().getPlatform(), |
| infoMessage.getServerRegistrationSummaryRequested()); |
| boolean first = true; |
| for (PropertyRecord record : infoMessage.getPerformanceCounterList()) { |
| if (!first) { |
| builder.append(", "); |
| } |
| builder.appendFormat("%s = %d", record.getName(), record.getValue()); |
| first = false; |
| } |
| return builder; |
| } |
| |
| /** See spec in implementation notes. */ |
| public static TextBuilder toCompactString(TextBuilder builder, |
| InvalidationMessage invMessage) { |
| if (invMessage == null) { |
| return builder; |
| } |
| builder.appendFormat("InvMsg: "); |
| toCompactStringForInvalidations(builder, invMessage.getInvalidationList()); |
| return builder; |
| } |
| |
| // Print methods for every server-to-client message type. |
| |
| public static TextBuilder toCompactString(TextBuilder builder, ServerHeader header) { |
| if (header == null) { |
| return builder; |
| } |
| builder.append("S2C: "); |
| toCompactString(builder, header.getProtocolVersion()); |
| builder.appendFormat(", MsgId: %s, Num regs = %s, Token = ", header.getMessageId(), |
| header.getRegistrationSummary().getNumRegistrations()); |
| toCompactString(builder, header.getClientToken()); |
| return builder; |
| } |
| |
| /** See spec in implementation notes. */ |
| public static TextBuilder toCompactString(TextBuilder builder, |
| TokenControlMessage tokenControlMessage) { |
| if (tokenControlMessage == null) { |
| return builder; |
| } |
| builder.append("TokenMsg: "); |
| toCompactString(builder, tokenControlMessage.getNewToken()); |
| return builder; |
| } |
| |
| /** See spec in implementation notes. */ |
| public static TextBuilder toCompactString(TextBuilder builder, |
| RegistrationStatusMessage regStatusMessage) { |
| if (regStatusMessage == null) { |
| return builder; |
| } |
| builder.append("RegStatusMsg: "); |
| toCompactStringForRegistrationStatuses(builder, regStatusMessage.getRegistrationStatusList()); |
| return builder; |
| } |
| |
| /** See spec in implementation notes. */ |
| public static TextBuilder toCompactString(TextBuilder builder, |
| RegistrationSyncRequestMessage regSyncRequestMessage) { |
| if (regSyncRequestMessage == null) { |
| return builder; |
| } |
| builder.append("RegSyncRequestMsg: "); |
| return builder; |
| } |
| |
| /** See spec in implementation notes. */ |
| public static TextBuilder toCompactString(TextBuilder builder, |
| InfoRequestMessage infoRequestMessage) { |
| if (infoRequestMessage == null) { |
| return builder; |
| } |
| builder.append("InfoRequestMsg:"); |
| return builder; |
| } |
| |
| /** See spec in implementation notes. */ |
| public static TextBuilder toCompactString(TextBuilder builder, |
| ConfigChangeMessage configChangeMessage) { |
| if (configChangeMessage == null) { |
| return builder; |
| } |
| builder.appendFormat("ConfigChangeMsg: %d", configChangeMessage.getNextMessageDelayMs()); |
| return builder; |
| } |
| |
| /** See spec in implementation notes. */ |
| public static TextBuilder toCompactString(TextBuilder builder, |
| ErrorMessage errorMessage) { |
| if (errorMessage == null) { |
| return builder; |
| } |
| builder.appendFormat("ErrorMsg: %s, %s", errorMessage.getCode(), errorMessage.getDescription()); |
| return builder; |
| } |
| |
| /** |
| * If {@code printHighFrequencyMessages} is true, logs sub-messages that are exchanged at a high |
| * frequency between the client and the registrar, e.g., invalidation ack message, heartbeat |
| * message. |
| */ |
| public static TextBuilder toCompactString(TextBuilder builder, |
| ClientToServerMessage msg, boolean printHighFrequencyMessages) { |
| // Print the header and any sub-messages in the message. |
| |
| toCompactString(builder, msg.getHeader()); |
| builder.append(','); |
| |
| if (msg.hasInitializeMessage()) { |
| toCompactString(builder, msg.getInitializeMessage()); |
| builder.append(','); |
| } |
| if (msg.hasRegistrationMessage()) { |
| toCompactString(builder, msg.getRegistrationMessage()); |
| builder.append(','); |
| } |
| if (msg.hasRegistrationSyncMessage()) { |
| toCompactString(builder, msg.getRegistrationSyncMessage()); |
| builder.append(','); |
| } |
| if (printHighFrequencyMessages && msg.hasInvalidationAckMessage()) { |
| toCompactString(builder, msg.getInvalidationAckMessage()); |
| builder.append(','); |
| } |
| if (printHighFrequencyMessages && msg.hasInfoMessage()) { |
| toCompactString(builder, msg.getInfoMessage()); |
| builder.append(','); |
| } |
| return builder; |
| } |
| |
| /** |
| * If {@code printHighFrequencyMessages} is true, logs sub-messages that are exchanged at a high |
| * frequency between the client and the registrar (if they are the only messages present), |
| * e.g., invalidation message. |
| */ |
| public static TextBuilder toCompactString(TextBuilder builder, |
| ServerToClientMessage msg, boolean printHighFrequencyMessages) { |
| // Print the header and any sub-messages in the message. |
| |
| toCompactString(builder, msg.getHeader()); |
| builder.append(','); |
| |
| if (msg.hasTokenControlMessage()) { |
| toCompactString(builder, msg.getTokenControlMessage()); |
| builder.append(','); |
| } |
| if (printHighFrequencyMessages && msg.hasInvalidationMessage()) { |
| toCompactString(builder, msg.getInvalidationMessage()); |
| builder.append(','); |
| } |
| if (msg.hasErrorMessage()) { |
| toCompactString(builder, msg.getErrorMessage()); |
| builder.append(','); |
| } |
| if (msg.hasRegistrationSyncRequestMessage()) { |
| toCompactString(builder, msg.getRegistrationSyncRequestMessage()); |
| builder.append(','); |
| } |
| if (msg.hasRegistrationStatusMessage()) { |
| toCompactString(builder, msg.getRegistrationStatusMessage()); |
| builder.append(','); |
| } |
| if (msg.hasInfoRequestMessage()) { |
| toCompactString(builder, msg.getInfoRequestMessage()); |
| builder.append(','); |
| } |
| if (msg.hasConfigChangeMessage()) { |
| toCompactString(builder, msg.getConfigChangeMessage()); |
| builder.append(','); |
| } |
| return builder; |
| } |
| |
| private CommonProtoStrings2() { // To prevent instantiation |
| } |
| } |