| /* |
| * 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.Preconditions; |
| import com.google.protobuf.ByteString; |
| import com.google.protos.ipc.invalidation.AndroidChannel; |
| import com.google.protos.ipc.invalidation.ChannelCommon.NetworkEndpointId; |
| import com.google.protos.ipc.invalidation.ChannelCommon.NetworkEndpointId.NetworkAddress; |
| import com.google.protos.ipc.invalidation.Client.AckHandleP; |
| import com.google.protos.ipc.invalidation.Client.PersistentStateBlob; |
| import com.google.protos.ipc.invalidation.Client.PersistentTiclState; |
| import com.google.protos.ipc.invalidation.ClientProtocol.ApplicationClientIdP; |
| import com.google.protos.ipc.invalidation.ClientProtocol.ClientVersion; |
| import com.google.protos.ipc.invalidation.ClientProtocol.ConfigChangeMessage; |
| import com.google.protos.ipc.invalidation.ClientProtocol.ErrorMessage; |
| import com.google.protos.ipc.invalidation.ClientProtocol.InfoRequestMessage; |
| import com.google.protos.ipc.invalidation.ClientProtocol.InitializeMessage; |
| import com.google.protos.ipc.invalidation.ClientProtocol.InitializeMessage.DigestSerializationType; |
| 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.RateLimitP; |
| 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 com.google.protos.ipc.invalidation.ClientProtocol.Version; |
| |
| import java.util.Collection; |
| import java.util.List; |
| |
| |
| /** |
| * Utilities for creating protocol buffers. |
| * |
| */ |
| public class CommonProtos2 { |
| |
| |
| /** Returns true iff status corresponds to success. */ |
| public static boolean isSuccess(StatusP status) { |
| return status.getCode() == StatusP.Code.SUCCESS; |
| } |
| |
| /** Returns true iff status corresponds to transient failure. */ |
| public static boolean isTransientFailure(StatusP status) { |
| return status.getCode() == StatusP.Code.TRANSIENT_FAILURE; |
| } |
| |
| /** Returns true iff status corresponds to permanent failure. */ |
| public static boolean isPermanentFailure(StatusP status) { |
| return status.getCode() == StatusP.Code.PERMANENT_FAILURE; |
| } |
| |
| // The following methods help in creating a protobuf object given its components. A Nullable |
| // parameter implies that the particular field will not be set for that proto. |
| // For the specs, please see the corresponding Proto file (to avoid inconsistency due to |
| // duplication). |
| |
| public static Version newVersion(int majorVersion, int minorVersion) { |
| return Version.newBuilder().setMajorVersion(majorVersion).setMinorVersion(minorVersion).build(); |
| } |
| |
| public static ClientVersion newClientVersion(String platform, String language, |
| String applicationInfo) { |
| return ClientVersion.newBuilder() |
| .setVersion(CommonInvalidationConstants2.CLIENT_VERSION_VALUE) |
| .setPlatform(platform) |
| .setLanguage(language) |
| .setApplicationInfo(applicationInfo) |
| .build(); |
| } |
| |
| public static ObjectIdP newObjectIdP(int source, ByteString name) { |
| return ObjectIdP.newBuilder().setSource(source).setName(name).build(); |
| } |
| |
| public static ObjectIdP newObjectIdP(int source, byte[] name) { |
| return newObjectIdP(source, ByteString.copyFrom(name)); |
| } |
| |
| public static boolean isAllObjectId(ObjectIdP objectId) { |
| return (objectId != null) && |
| (CommonInvalidationConstants2.ALL_OBJECT_ID.getSource() == objectId.getSource()) && |
| (CommonInvalidationConstants2.ALL_OBJECT_ID.getName().equals(objectId.getName())); |
| |
| } |
| |
| public static RateLimitP newRateLimitP(int windowMs, int count) { |
| return RateLimitP.newBuilder() |
| .setWindowMs(windowMs) |
| .setCount(count) |
| .build(); |
| } |
| |
| public static ApplicationClientIdP newApplicationClientIdP(int clientType, |
| ByteString clientName) { |
| return ApplicationClientIdP.newBuilder() |
| .setClientType(clientType) |
| .setClientName(clientName) |
| .build(); |
| } |
| |
| public static InvalidationP newInvalidationP(ObjectIdP oid, long version, |
| TrickleState trickleState) { |
| return newInvalidationP(oid, version, trickleState, null); |
| } |
| |
| public static InvalidationP newInvalidationP(ObjectIdP oid, long version, |
| TrickleState trickleState, ByteString payload) { |
| InvalidationP.Builder builder = InvalidationP.newBuilder() |
| .setObjectId(oid) |
| .setIsKnownVersion(true) |
| .setVersion(version) |
| .setIsTrickleRestart(trickleState == TrickleState.RESTART); |
| if (payload != null) { |
| builder.setPayload(payload); |
| } |
| return builder.build(); |
| } |
| |
| public static InvalidationP newInvalidationPForUnknownVersion(ObjectIdP oid, |
| long sequenceNumber) { |
| return InvalidationP.newBuilder() |
| .setObjectId(oid) |
| .setIsKnownVersion(false) |
| .setIsTrickleRestart(true) |
| .setVersion(sequenceNumber) |
| .build(); |
| } |
| |
| /** |
| * Returns an invalidation that is identical to {@code invalidation} but with the |
| * {@code is_trickle_restart} flag set to true. If the input {@invalidation} is already restarted, |
| * it is returned directly. Otherwise, a new invalidation is created. |
| */ |
| public static InvalidationP toRestartedInvalidation(InvalidationP invalidation) { |
| if (invalidation.hasIsTrickleRestart() && invalidation.getIsTrickleRestart()) { |
| return invalidation; |
| } |
| return invalidation.toBuilder().setIsTrickleRestart(true).build(); |
| } |
| |
| /** |
| * Returns an invalidation that is identical to {@code invalidation} but with the |
| * {@code is_trickle_restart} flag set to false. If the input {@invalidation} is already |
| * a continuous invalidation, it is returned directly. Otherwise, a new invalidation is created. |
| */ |
| public static InvalidationP toContinuousInvalidation(InvalidationP invalidation) { |
| if (invalidation.hasIsTrickleRestart() && !invalidation.getIsTrickleRestart()) { |
| return invalidation; |
| } |
| return invalidation.toBuilder().setIsTrickleRestart(false).build(); |
| } |
| |
| public static RegistrationP newRegistrationP(ObjectIdP oid, boolean isReg) { |
| RegistrationP registration = RegistrationP.newBuilder() |
| .setObjectId(oid) |
| .setOpType(isReg ? RegistrationP.OpType.REGISTER : RegistrationP.OpType.UNREGISTER) |
| .build(); |
| return registration; |
| } |
| |
| public static RegistrationP newRegistrationPForRegistration(ObjectIdP oid) { |
| return newRegistrationP(oid, true); |
| } |
| |
| public static RegistrationP newRegistrationPForUnregistration(ObjectIdP oid) { |
| return newRegistrationP(oid, false); |
| } |
| |
| public static StatusP newSuccessStatus() { |
| return StatusP.newBuilder().setCode(StatusP.Code.SUCCESS).build(); |
| } |
| |
| public static StatusP newFailureStatus(boolean isTransient, String description) { |
| return StatusP.newBuilder() |
| .setCode(isTransient ? StatusP.Code.TRANSIENT_FAILURE : StatusP.Code.PERMANENT_FAILURE) |
| .setDescription(description) |
| .build(); |
| } |
| |
| public static RegistrationSummary newRegistrationSummary(int numRegistrations, byte[] regDigest) { |
| RegistrationSummary regSummary = RegistrationSummary.newBuilder() |
| .setNumRegistrations(numRegistrations) |
| .setRegistrationDigest(ByteString.copyFrom(regDigest)) |
| .build(); |
| return regSummary; |
| } |
| |
| public static RegistrationStatus newRegistrationStatus(RegistrationP registration, |
| StatusP status) { |
| return RegistrationStatus.newBuilder() |
| .setRegistration(registration) |
| .setStatus(status) |
| .build(); |
| } |
| |
| public static RegistrationStatus newSuccessRegistrationStatus(RegistrationP registration) { |
| return RegistrationStatus.newBuilder() |
| .setRegistration(registration) |
| .setStatus(newSuccessStatus()) |
| .build(); |
| } |
| |
| public static RegistrationStatus newTransientFailureRegistrationStatus( |
| RegistrationP registration, String description) { |
| return RegistrationStatus.newBuilder() |
| .setRegistration(registration) |
| .setStatus(newFailureStatus(true, description)) |
| .build(); |
| } |
| |
| public static PersistentTiclState newPersistentTiclState(ByteString clientToken, |
| long lastMessageSendTimeMs) { |
| return PersistentTiclState.newBuilder() |
| .setClientToken(clientToken) |
| .setLastMessageSendTimeMs(lastMessageSendTimeMs) |
| .build(); |
| } |
| |
| public static AckHandleP newAckHandleP(InvalidationP invalidation) { |
| return AckHandleP.newBuilder().setInvalidation(invalidation).build(); |
| } |
| |
| public static PersistentStateBlob newPersistentStateBlob(PersistentTiclState state, |
| ByteString mac) { |
| return PersistentStateBlob.newBuilder() |
| .setTiclState(state) |
| .setAuthenticationCode(mac) |
| .build(); |
| } |
| |
| // Methods to create ClientToServerMessages. |
| |
| public static InitializeMessage newInitializeMessage(int clientType, |
| ApplicationClientIdP applicationClientId, ByteString nonce, |
| DigestSerializationType digestSerializationType) { |
| return InitializeMessage.newBuilder() |
| .setClientType(clientType) |
| .setApplicationClientId(applicationClientId) |
| .setDigestSerializationType(digestSerializationType) |
| .setNonce(nonce) |
| .build(); |
| } |
| |
| public static PropertyRecord newPropertyRecord(String name, int value) { |
| return PropertyRecord.newBuilder().setName(name).setValue(value).build(); |
| } |
| |
| // Methods to create ServerToClientMessages. |
| |
| public static ServerHeader newServerHeader(ByteString clientToken, long currentTimeMs, |
| RegistrationSummary registrationSummary, String messageId) { |
| ServerHeader.Builder builder = ServerHeader.newBuilder() |
| .setProtocolVersion(CommonInvalidationConstants2.PROTOCOL_VERSION) |
| .setClientToken(clientToken) |
| .setServerTimeMs(currentTimeMs); |
| if (registrationSummary != null) { |
| builder.setRegistrationSummary(registrationSummary); |
| } |
| if (messageId != null) { |
| builder.setMessageId(messageId); |
| } |
| return builder.build(); |
| } |
| |
| public static ErrorMessage newErrorMessage(ErrorMessage.Code code, String description) { |
| return ErrorMessage.newBuilder() |
| .setCode(code) |
| .setDescription(description) |
| .build(); |
| } |
| |
| public static InvalidationMessage newInvalidationMessage(Iterable<InvalidationP> invalidations) { |
| return InvalidationMessage.newBuilder().addAllInvalidation(invalidations).build(); |
| } |
| |
| public static RegistrationSyncRequestMessage newRegistrationSyncRequestMessage() { |
| return RegistrationSyncRequestMessage.getDefaultInstance(); |
| } |
| |
| public static RegistrationSyncMessage newRegistrationSyncMessage( |
| List<RegistrationSubtree> subtrees) { |
| return RegistrationSyncMessage.newBuilder().addAllSubtree(subtrees).build(); |
| } |
| |
| public static RegistrationSubtree newRegistrationSubtree(List<ObjectIdP> registeredOids) { |
| return RegistrationSubtree.newBuilder().addAllRegisteredObject(registeredOids).build(); |
| } |
| |
| public static InfoRequestMessage newPerformanceCounterRequestMessage() { |
| return InfoRequestMessage.newBuilder() |
| .addInfoType(InfoRequestMessage.InfoType.GET_PERFORMANCE_COUNTERS) |
| .build(); |
| } |
| |
| public static ConfigChangeMessage newConfigChangeMessage(long nextMessageDelayMs) { |
| return ConfigChangeMessage.newBuilder().setNextMessageDelayMs(nextMessageDelayMs).build(); |
| } |
| |
| public static ServerToClientMessage newServerToClientMessage(ServerHeader scHeader) { |
| return ServerToClientMessage.newBuilder() |
| .setHeader(scHeader) |
| .build(); |
| } |
| |
| public static ServerToClientMessage.Builder newServerToClientMessage(ServerHeader scHeader, |
| TokenControlMessage tokenControlMessage) { |
| return ServerToClientMessage.newBuilder() |
| .setHeader(scHeader) |
| .setTokenControlMessage(tokenControlMessage); |
| } |
| |
| public static ServerToClientMessage newServerToClientMessage(ServerHeader scHeader, |
| RegistrationSyncRequestMessage syncRequestionMessage) { |
| return ServerToClientMessage.newBuilder() |
| .setHeader(scHeader) |
| .setRegistrationSyncRequestMessage(syncRequestionMessage) |
| .build(); |
| } |
| |
| public static ServerToClientMessage newServerToClientMessage(ServerHeader scHeader, |
| InvalidationMessage invalidationMessage) { |
| return ServerToClientMessage.newBuilder() |
| .setHeader(scHeader) |
| .setInvalidationMessage(invalidationMessage) |
| .build(); |
| } |
| |
| public static ServerToClientMessage newServerToClientMessage(ServerHeader scHeader, |
| RegistrationStatusMessage registrationStatusMessage) { |
| return ServerToClientMessage.newBuilder() |
| .setHeader(scHeader) |
| .setRegistrationStatusMessage(registrationStatusMessage) |
| .build(); |
| } |
| |
| public static ServerToClientMessage newServerToClientMessage(ServerHeader scHeader, |
| InfoRequestMessage infoRequestMessage) { |
| return ServerToClientMessage.newBuilder() |
| .setHeader(scHeader) |
| .setInfoRequestMessage(infoRequestMessage) |
| .build(); |
| } |
| |
| public static ServerToClientMessage newServerToClientMessage(ServerHeader scHeader, |
| ConfigChangeMessage configChangeMessage) { |
| return ServerToClientMessage.newBuilder() |
| .setHeader(scHeader) |
| .setConfigChangeMessage(configChangeMessage) |
| .build(); |
| } |
| |
| public static ServerToClientMessage newServerToClientMessage(ServerHeader scHeader, |
| ErrorMessage errorMessage) { |
| return ServerToClientMessage.newBuilder() |
| .setHeader(scHeader) |
| .setErrorMessage(errorMessage) |
| .build(); |
| } |
| |
| /** |
| * Constructs a network endpoint id for an Android client with the given {@code registrationId}, |
| * {@code clientKey}, and {@code packageName}. |
| */ |
| public static NetworkEndpointId newAndroidEndpointId(String registrationId, String clientKey, |
| String packageName, Version channelVersion) { |
| Preconditions.checkNotNull(registrationId, "Null registration id"); |
| Preconditions.checkNotNull(clientKey, "Null client key"); |
| Preconditions.checkNotNull(packageName, "Null package name"); |
| Preconditions.checkNotNull(channelVersion, "Null channel version"); |
| |
| AndroidChannel.EndpointId.Builder endpointBuilder = AndroidChannel.EndpointId.newBuilder() |
| .setC2DmRegistrationId(registrationId) |
| .setClientKey(clientKey) |
| .setPackageName(packageName) |
| .setChannelVersion(channelVersion); |
| return newNetworkEndpointId(NetworkAddress.ANDROID, endpointBuilder.build().toByteString()); |
| } |
| |
| public static NetworkEndpointId newNetworkEndpointId(NetworkAddress networkAddr, |
| ByteString clientAddr) { |
| return NetworkEndpointId.newBuilder() |
| .setNetworkAddress(networkAddr) |
| .setClientAddress(clientAddr) |
| .build(); |
| } |
| |
| /** |
| * Returns an endpoint id that is identical to the given {@code endpointId} except with |
| * {@link NetworkEndpointId#getIsOffline} set to {@code true}. |
| */ |
| public static NetworkEndpointId endpointIdToOfflineEndpointId(NetworkEndpointId endpointId) { |
| // If the endpoint is already marked offline, there's no need to build a new one. |
| return isOnline(endpointId) ? endpointId.toBuilder().setIsOffline(true).build() : endpointId; |
| } |
| |
| /** |
| * Indicates whether the optional {@code endpointId} is for an online client. If the id is |
| * {@code null}, it means the client has no endpoint associated with it and it is considered |
| * offline. If the endpoint is known, it is considered online if the {@code is_offline} field is |
| * not defined or if the field is {@code false}. |
| */ |
| public static boolean isOnline(NetworkEndpointId endpointId) { |
| // NetworkEndpointId has an optional is_offline field. The client is online if the field's value |
| // is either undefined or false. |
| return (endpointId != null) && (!endpointId.hasIsOffline() || !endpointId.getIsOffline()); |
| } |
| |
| public static TokenControlMessage newTokenControlMessage(ByteString newToken) { |
| TokenControlMessage.Builder builder = TokenControlMessage.newBuilder(); |
| if (newToken != null) { |
| builder.setNewToken(newToken); |
| } |
| return builder.build(); |
| } |
| |
| public static RegistrationStatusMessage newRegistrationStatusMessage( |
| Collection<RegistrationStatus> statuses) { |
| Preconditions.checkArgument(!statuses.isEmpty(), "Empty statuses"); |
| return RegistrationStatusMessage.newBuilder().addAllRegistrationStatus(statuses).build(); |
| } |
| |
| public static RegistrationMessage newRegistrationMessage( |
| Collection<RegistrationP> registrations) { |
| Preconditions.checkArgument(!registrations.isEmpty(), "Empty registrations"); |
| return RegistrationMessage.newBuilder().addAllRegistration(registrations).build(); |
| } |
| |
| private CommonProtos2() { // To prevent instantiation |
| } |
| } |