blob: 07821788cb2857f990aeb97c14955f0cdb92adc0 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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 org.apache.servicecomb.codec.protobuf.definition;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import javax.ws.rs.core.Response.Status;
import org.apache.servicecomb.codec.protobuf.utils.ScopedProtobufSchemaManager;
import org.apache.servicecomb.core.Invocation;
import org.apache.servicecomb.core.definition.MicroserviceMeta;
import org.apache.servicecomb.swagger.invocation.InvocationType;
import com.fasterxml.jackson.databind.JavaType;
import com.google.common.annotations.VisibleForTesting;
public final class ProtobufManager {
public static final String EXT_ID = "protobuf";
private static final Object LOCK = new Object();
static class RuntimeCacheKey {
final InvocationType invocationType;
final String uniqueOperationId;
// Using response type as the cache key.
// May consider request type as well, but now not implemented
final JavaType responseType;
public RuntimeCacheKey(InvocationType invocationType, String operationId, JavaType responseType) {
this.invocationType = invocationType;
this.uniqueOperationId = operationId;
this.responseType = responseType;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
RuntimeCacheKey that = (RuntimeCacheKey) o;
if (invocationType != that.invocationType) {
return false;
}
if (!uniqueOperationId.equals(that.uniqueOperationId)) {
return false;
}
return Objects.equals(responseType, that.responseType);
}
@Override
public int hashCode() {
int result = invocationType.hashCode();
result = 31 * result + uniqueOperationId.hashCode();
result = 31 * result + (responseType != null ? responseType.hashCode() : 0);
return result;
}
}
private static final Map<RuntimeCacheKey, OperationProtobuf> RUNTIME_CACHE = new HashMap<>();
public static OperationProtobuf getOrCreateOperation(Invocation invocation) {
RuntimeCacheKey cacheKey = new RuntimeCacheKey(invocation.getInvocationType(),
invocation.getOperationMeta().getMicroserviceQualifiedName(),
invocation.findResponseType(Status.OK.getStatusCode()));
OperationProtobuf operationProtobuf = RUNTIME_CACHE.get(cacheKey);
if (operationProtobuf == null) {
synchronized (LOCK) {
MicroserviceMeta microserviceMeta = invocation.getMicroserviceMeta();
ScopedProtobufSchemaManager scopedProtobufSchemaManager = microserviceMeta.getExtData(EXT_ID);
if (scopedProtobufSchemaManager == null) {
scopedProtobufSchemaManager = new ScopedProtobufSchemaManager();
microserviceMeta.putExtData(EXT_ID, scopedProtobufSchemaManager);
}
operationProtobuf = RUNTIME_CACHE.get(cacheKey);
if (operationProtobuf == null) {
operationProtobuf = new OperationProtobuf(scopedProtobufSchemaManager, invocation);
RUNTIME_CACHE.put(cacheKey, operationProtobuf);
}
}
}
return operationProtobuf;
}
@VisibleForTesting
public static void clear() {
RUNTIME_CACHE.clear();
}
}