• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Protocol Buffers - Google's data interchange format
3  * Copyright 2024 Google Inc.  All rights reserved.
4  * https://developers.google.com/protocol-buffers/
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met:
9  *
10  *     * Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  *     * Redistributions in binary form must reproduce the above
13  * copyright notice, this list of conditions and the following disclaimer
14  * in the documentation and/or other materials provided with the
15  * distribution.
16  *     * Neither the name of Google Inc. nor the names of its
17  * contributors may be used to endorse or promote products derived from
18  * this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 package com.google.protobuf.jruby;
34 
35 import com.google.protobuf.CodedInputStream;
36 import com.google.protobuf.Descriptors.MethodDescriptor;
37 import com.google.protobuf.Descriptors.ServiceDescriptor;
38 import java.util.LinkedHashMap;
39 import java.util.Map;
40 import org.jruby.*;
41 import org.jruby.anno.JRubyClass;
42 import org.jruby.anno.JRubyMethod;
43 import org.jruby.runtime.Block;
44 import org.jruby.runtime.ObjectAllocator;
45 import org.jruby.runtime.ThreadContext;
46 import org.jruby.runtime.builtin.IRubyObject;
47 import org.jruby.anno.JRubyClass;
48 import org.jruby.anno.JRubyMethod;
49 
50 @JRubyClass(name = "ServiceDescriptor")
51 public class RubyServiceDescriptor extends RubyObject {
createRubyServiceDescriptor(Ruby runtime)52   public static void createRubyServiceDescriptor(Ruby runtime) {
53     RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf");
54     RubyClass cServiceDescriptor =
55         protobuf.defineClassUnder(
56             "ServiceDescriptor",
57             runtime.getObject(),
58             new ObjectAllocator() {
59               @Override
60               public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
61                 return new RubyServiceDescriptor(runtime, klazz);
62               }
63             });
64     cServiceDescriptor.includeModule(runtime.getEnumerable());
65     cServiceDescriptor.defineAnnotatedMethods(RubyServiceDescriptor.class);
66     cMethodDescriptor = (RubyClass) runtime.getClassFromPath("Google::Protobuf::MethodDescriptor");
67   }
68 
RubyServiceDescriptor(Ruby runtime, RubyClass klazz)69   public RubyServiceDescriptor(Ruby runtime, RubyClass klazz) {
70     super(runtime, klazz);
71   }
72 
73   /*
74    * call-seq:
75    *     ServiceDescriptor.name => name
76    *
77    * Returns the name of this service type as a fully-qualified string (e.g.,
78    * My.Package.Service).
79    */
80   @JRubyMethod(name = "name")
getName(ThreadContext context)81   public IRubyObject getName(ThreadContext context) {
82     return name;
83   }
84 
85   /*
86    * call-seq:
87    *    ServiceDescriptor.file_descriptor
88    *
89    * Returns the FileDescriptor object this service belongs to.
90    */
91   @JRubyMethod(name = "file_descriptor")
getFileDescriptor(ThreadContext context)92   public IRubyObject getFileDescriptor(ThreadContext context) {
93     return RubyFileDescriptor.getRubyFileDescriptor(context, descriptor);
94   }
95 
96   /*
97    * call-seq:
98    *    ServiceDescriptor.options
99    *
100    * Returns the options set on this protobuf service
101    */
102   @JRubyMethod
options(ThreadContext context)103   public IRubyObject options(ThreadContext context) {
104     RubyDescriptorPool pool = (RubyDescriptorPool) RubyDescriptorPool.generatedPool(null, null);
105     RubyDescriptor serviceOptionsDescriptor =
106         (RubyDescriptor)
107             pool.lookup(context, context.runtime.newString("google.protobuf.ServiceOptions"));
108     RubyClass serviceOptionsClass = (RubyClass) serviceOptionsDescriptor.msgclass(context);
109     RubyMessage msg = (RubyMessage) serviceOptionsClass.newInstance(context, Block.NULL_BLOCK);
110     return msg.decodeBytes(
111         context,
112         msg,
113         CodedInputStream.newInstance(
114             descriptor.getOptions().toByteString().toByteArray()), /*freeze*/
115         true);
116   }
117 
118   /*
119    * call-seq:
120    *     ServiceDescriptor.each(&block)
121    *
122    * Iterates over methods in this service, yielding to the block on each one.
123    */
124   @JRubyMethod(name = "each")
each(ThreadContext context, Block block)125   public IRubyObject each(ThreadContext context, Block block) {
126     for (Map.Entry<IRubyObject, RubyMethodDescriptor> entry : methodDescriptors.entrySet()) {
127       block.yield(context, entry.getValue());
128     }
129     return context.nil;
130   }
131 
setDescriptor( ThreadContext context, ServiceDescriptor descriptor, RubyDescriptorPool pool)132   protected void setDescriptor(
133       ThreadContext context, ServiceDescriptor descriptor, RubyDescriptorPool pool) {
134     this.descriptor = descriptor;
135 
136     // Populate the methods (and preserve the order by using LinkedHashMap)
137     methodDescriptors = new LinkedHashMap<IRubyObject, RubyMethodDescriptor>();
138 
139     for (MethodDescriptor methodDescriptor : descriptor.getMethods()) {
140       RubyMethodDescriptor md =
141           (RubyMethodDescriptor) cMethodDescriptor.newInstance(context, Block.NULL_BLOCK);
142       md.setDescriptor(context, methodDescriptor, pool);
143       methodDescriptors.put(context.runtime.newString(methodDescriptor.getName()), md);
144     }
145   }
146 
setName(IRubyObject name)147   protected void setName(IRubyObject name) {
148     this.name = name;
149   }
150 
151   private static RubyClass cMethodDescriptor;
152 
153   private ServiceDescriptor descriptor;
154   private Map<IRubyObject, RubyMethodDescriptor> methodDescriptors;
155   private IRubyObject name;
156 }
157