Skip to content

Commit

Permalink
Add CelDescriptorPool and ProtoMessageFactory.
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 572023058
  • Loading branch information
l46kok authored and copybara-github committed Oct 12, 2023
1 parent 67053b3 commit 1ba80a0
Show file tree
Hide file tree
Showing 11 changed files with 768 additions and 2 deletions.
26 changes: 25 additions & 1 deletion common/internal/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,35 @@ java_library(

java_library(
name = "errors",
visibility = ["//visibility:public"],
exports = ["//common/src/main/java/dev/cel/common/internal:errors"],
)

java_library(
name = "env_visitor",
exports = ["//common/src/main/java/dev/cel/common/internal:env_visitor"],
)

java_library(
name = "default_instance_message_factory",
exports = ["//common/src/main/java/dev/cel/common/internal:default_instance_message_factory"],
)

java_library(
name = "well_known_proto",
exports = ["//common/src/main/java/dev/cel/common/internal:well_known_proto"],
)

java_library(
name = "proto_message_factory",
exports = ["//common/src/main/java/dev/cel/common/internal:proto_message_factory"],
)

java_library(
name = "default_message_factory",
exports = ["//common/src/main/java/dev/cel/common/internal:default_message_factory"],
)

java_library(
name = "cel_descriptor_pools",
exports = ["//common/src/main/java/dev/cel/common/internal:cel_descriptor_pools"],
)
76 changes: 75 additions & 1 deletion common/src/main/java/dev/cel/common/internal/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ ENV_VISITOR_SOURCES = [
"EnvVisitor.java",
]

# keep sorted
CEL_DESCRIPTOR_POOL_SOURCES = [
"CelDescriptorPool.java",
"CombinedDescriptorPool.java",
"DefaultDescriptorPool.java",
]

java_library(
name = "internal",
srcs = INTERNAL_SOURCES,
Expand Down Expand Up @@ -86,19 +93,33 @@ java_library(

# keep sorted
DYNAMIC_PROTO_SOURCES = [
"DefaultInstanceMessageFactory.java",
"DynamicProto.java",
"ProtoAdapter.java",
"ProtoRegistryProvider.java",
]

java_library(
name = "default_instance_message_factory",
srcs = ["DefaultInstanceMessageFactory.java"],
tags = [
],
deps = [
"//common/annotations",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
],
)

# keep sorted

java_library(
name = "dynamic_proto",
srcs = DYNAMIC_PROTO_SOURCES,
tags = [
],
deps = [
":converter",
":default_instance_message_factory",
"//:auto_value",
"//common",
"//common:error_codes",
Expand Down Expand Up @@ -155,3 +176,56 @@ java_library(
"@cel_spec//proto/cel/expr:expr_java_proto",
],
)

java_library(
name = "well_known_proto",
srcs = ["WellKnownProto.java"],
tags = [
],
deps = [
"//common/annotations",
"@maven//:com_google_protobuf_protobuf_java",
],
)

java_library(
name = "default_message_factory",
srcs = ["DefaultMessageFactory.java"],
tags = [
],
deps = [
":cel_descriptor_pools",
":default_instance_message_factory",
":proto_message_factory",
"//common/annotations",
"@maven//:com_google_protobuf_protobuf_java",
],
)

java_library(
name = "proto_message_factory",
srcs = ["ProtoMessageFactory.java"],
tags = [
],
deps = [
":cel_descriptor_pools",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
],
)

java_library(
name = "cel_descriptor_pools",
srcs = CEL_DESCRIPTOR_POOL_SOURCES,
tags = [
],
deps = [
":well_known_proto",
"//common",
"//common/annotations",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven//:com_google_guava_guava",
"@maven//:com_google_protobuf_protobuf_java",
],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright 2023 Google LLC
//
// 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
//
// https://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 dev.cel.common.internal;

import com.google.errorprone.annotations.Immutable;
import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.ExtensionRegistry;
import dev.cel.common.annotations.Internal;
import java.util.Optional;

/**
* {@link CelDescriptorPool} allows lookup of descriptors for message types and field descriptors
* for Proto2 extension messages.
*
* <p>CEL Library Internals. Do Not Use.
*/
@Immutable
@Internal
public interface CelDescriptorPool {

/** Finds the descriptor by fully qualified message type. */
Optional<Descriptor> findDescriptor(String name);

/** Finds the corresponding field descriptor for an extension field on a message. */
Optional<FieldDescriptor> findExtensionDescriptor(
Descriptor containingDescriptor, String fieldName);

/**
* Retrieves the registered extension registry. This is specifically needed to handle unpacking
* Any messages containing Proto2 extension messages.
*/
ExtensionRegistry getExtensionRegistry();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Copyright 2023 Google LLC
//
// 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
//
// https://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 dev.cel.common.internal;

import com.google.common.collect.ImmutableList;
import com.google.errorprone.annotations.Immutable;
import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.ExtensionRegistry;
import dev.cel.common.annotations.Internal;
import java.util.Optional;

/**
* The {@link CombinedDescriptorPool} takes one or more {@link CelDescriptorPool} instances and
* supports descriptor lookups in the order the descriptor pools are added to the constructor.
*
* <p>CEL Library Internals. Do Not Use.
*/
@Immutable
@Internal
public final class CombinedDescriptorPool implements CelDescriptorPool {
private final ImmutableList<CelDescriptorPool> descriptorPools;

@SuppressWarnings("Immutable") // ExtensionRegistry is immutable, just not marked as such.
private final ExtensionRegistry extensionRegistry;

public static CombinedDescriptorPool create(ImmutableList<CelDescriptorPool> descriptorPools) {
return new CombinedDescriptorPool(descriptorPools);
}

@Override
public Optional<Descriptor> findDescriptor(String name) {
for (CelDescriptorPool descriptorPool : descriptorPools) {
Optional<Descriptor> maybeDescriptor = descriptorPool.findDescriptor(name);
if (maybeDescriptor.isPresent()) {
return maybeDescriptor;
}
}

return Optional.empty();
}

@Override
public Optional<FieldDescriptor> findExtensionDescriptor(
Descriptor containingDescriptor, String fieldName) {
for (CelDescriptorPool descriptorPool : descriptorPools) {
Optional<FieldDescriptor> maybeExtensionDescriptor =
descriptorPool.findExtensionDescriptor(containingDescriptor, fieldName);
if (maybeExtensionDescriptor.isPresent()) {
return maybeExtensionDescriptor;
}
}

return Optional.empty();
}

@Override
public ExtensionRegistry getExtensionRegistry() {
return extensionRegistry;
}

private CombinedDescriptorPool(ImmutableList<CelDescriptorPool> descriptorPools) {
this.descriptorPools = descriptorPools;
// TODO: Combine the extension registry. This will become necessary once we accept
// ExtensionRegistry through runtime builder.
this.extensionRegistry =
descriptorPools.stream()
.map(CelDescriptorPool::getExtensionRegistry)
.filter(e -> !e.equals(ExtensionRegistry.getEmptyRegistry()))
.findFirst()
.orElse(ExtensionRegistry.getEmptyRegistry());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// Copyright 2023 Google LLC
//
// 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
//
// https://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 dev.cel.common.internal;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.ImmutableMap.toImmutableMap;
import static java.util.Arrays.stream;

import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap;
import com.google.errorprone.annotations.Immutable;
import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.ExtensionRegistry;
import dev.cel.common.CelDescriptors;
import dev.cel.common.annotations.Internal;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
* A descriptor pool that has descriptors pre-loaded for well-known types defined by {@link
* WellKnownProto}.
*
* <p>CEL Library Internals. Do Not Use.
*/
@Immutable
@Internal
public final class DefaultDescriptorPool implements CelDescriptorPool {
private static final ImmutableMap<String, Descriptor> WELL_KNOWN_TYPE_DESCRIPTORS =
stream(WellKnownProto.values())
.collect(toImmutableMap(WellKnownProto::typeName, WellKnownProto::descriptor));

/** A DefaultDescriptorPool instance with just well known types loaded. */
public static final DefaultDescriptorPool INSTANCE =
new DefaultDescriptorPool(WELL_KNOWN_TYPE_DESCRIPTORS, ImmutableMultimap.of());

// K: Fully qualified message type name, V: Message descriptor
private final ImmutableMap<String, Descriptor> descriptorMap;

// K: Fully qualified message type name (of containing descriptor)
// V: Field descriptor for the extension message
private final ImmutableMultimap<String, FieldDescriptor> extensionDescriptorMap;

public static DefaultDescriptorPool create(CelDescriptors celDescriptors) {
Map<String, Descriptor> descriptorMap = new HashMap<>(); // Using a hashmap to allow deduping
stream(WellKnownProto.values()).forEach(d -> descriptorMap.put(d.typeName(), d.descriptor()));

for (Descriptor descriptor : celDescriptors.messageTypeDescriptors()) {
descriptorMap.putIfAbsent(descriptor.getFullName(), descriptor);
}

return new DefaultDescriptorPool(
ImmutableMap.copyOf(descriptorMap), celDescriptors.extensionDescriptors());
}

@Override
public Optional<Descriptor> findDescriptor(String name) {
return Optional.ofNullable(descriptorMap.get(name));
}

@Override
public Optional<FieldDescriptor> findExtensionDescriptor(
Descriptor containingDescriptor, String fieldName) {
String typeName = containingDescriptor.getFullName();
ImmutableCollection<FieldDescriptor> fieldDescriptors = extensionDescriptorMap.get(typeName);

return fieldDescriptors.stream().filter(d -> d.getFullName().equals(fieldName)).findFirst();
}

@Override
public ExtensionRegistry getExtensionRegistry() {
// TODO: Populate one from runtime builder.
return ExtensionRegistry.getEmptyRegistry();
}

private DefaultDescriptorPool(
ImmutableMap<String, Descriptor> descriptorMap,
ImmutableMultimap<String, FieldDescriptor> extensionDescriptorMap) {
this.descriptorMap = checkNotNull(descriptorMap);
this.extensionDescriptorMap = checkNotNull(extensionDescriptorMap);
}
}
Loading

0 comments on commit 1ba80a0

Please sign in to comment.