1818import com .github .os72 .protocjar .Protoc ;
1919import com .google .protobuf .DescriptorProtos ;
2020import com .google .protobuf .DescriptorProtos .FileDescriptorProto ;
21+ import com .google .protobuf .DescriptorProtos .FileDescriptorSet ;
22+ import com .google .protobuf .Descriptors .DescriptorValidationException ;
23+ import com .google .protobuf .Descriptors .FileDescriptor ;
24+ import com .google .protobuf .ProtocolStringList ;
2125import io .serverlessworkflow .impl .resources .ExternalResourceHandler ;
2226import java .io .FileNotFoundException ;
2327import java .io .IOException ;
2832import java .nio .file .Path ;
2933import java .nio .file .SimpleFileVisitor ;
3034import java .nio .file .attribute .BasicFileAttributes ;
35+ import java .util .ArrayList ;
36+ import java .util .HashMap ;
37+ import java .util .Iterator ;
38+ import java .util .List ;
39+ import java .util .Map ;
40+ import java .util .Objects ;
3141import org .slf4j .Logger ;
3242import org .slf4j .LoggerFactory ;
3343
3444class FileDescriptorReader {
3545
3646 private static final Logger logger = LoggerFactory .getLogger (FileDescriptorReader .class );
3747
38- static FileDescriptorProto readDescriptor (ExternalResourceHandler externalResourceHandler ) {
39-
48+ static FileDescriptor readDescriptor (ExternalResourceHandler externalResourceHandler ) {
4049 Path grpcDir = null ;
4150 try (InputStream inputStream = externalResourceHandler .open ()) {
4251 grpcDir = Files .createTempDirectory ("serverless-workflow-" );
@@ -46,21 +55,14 @@ static FileDescriptorProto readDescriptor(ExternalResourceHandler externalResour
4655 Files .copy (inputStream , protoFile );
4756 Path descriptorOutput = grpcDir .resolve ("descriptor.protobin" );
4857 generateFileDescriptor (grpcDir , protoFile , descriptorOutput );
49- return DescriptorProtos .FileDescriptorSet .newBuilder ()
50- .mergeFrom (Files .readAllBytes (descriptorOutput ))
51- .build ()
52- .getFileList ()
53- .stream ()
54- .filter (n -> n .getName ().equals (name ))
55- .findAny ()
56- .orElseThrow (
57- () ->
58- new IllegalStateException (
59- "There was something really wrong generating the protoc descriptor, it does not included a file named "
60- + name ));
58+ return toFileDescriptor (
59+ DescriptorProtos .FileDescriptorSet .newBuilder ()
60+ .mergeFrom (Files .readAllBytes (descriptorOutput ))
61+ .build (),
62+ name );
6163 } catch (IOException e ) {
6264 throw new UncheckedIOException (
63- "Unable to process gRPC proto file associated with resource "
65+ "Unable to process gRPC proto file associated with resource: "
6466 + externalResourceHandler .name (),
6567 e );
6668 } finally {
@@ -70,6 +72,54 @@ static FileDescriptorProto readDescriptor(ExternalResourceHandler externalResour
7072 }
7173 }
7274
75+ private static FileDescriptor toFileDescriptor (FileDescriptorSet set , String name ) {
76+ List <FileDescriptorProto > remainingProtos = new ArrayList <>(set .getFileList ());
77+ Map <String , FileDescriptor > builtDescriptors = new HashMap <>();
78+ while (!remainingProtos .isEmpty ()) {
79+ Iterator <FileDescriptorProto > iterator = remainingProtos .iterator ();
80+ boolean modified = false ;
81+ while (iterator .hasNext ()) {
82+ FileDescriptorProto proto = iterator .next ();
83+ ProtocolStringList requiredDependencies = proto .getDependencyList ();
84+ List <FileDescriptor > currentDependencies =
85+ requiredDependencies .stream ()
86+ .map (builtDescriptors ::get )
87+ .filter (Objects ::nonNull )
88+ .toList ();
89+ if (requiredDependencies .size () == currentDependencies .size ()) {
90+ FileDescriptor fileDescriptor = buildFileDescriptor (proto , currentDependencies );
91+ String protoName = proto .getName ();
92+ if (protoName .equals (name )) {
93+ return fileDescriptor ;
94+ }
95+ builtDescriptors .put (protoName , fileDescriptor );
96+ iterator .remove ();
97+ modified = true ;
98+ }
99+ }
100+ if (!modified ) {
101+ throw new IllegalStateException (
102+ "Unable to build valid gRPC descriptor from proto file associated with resource: "
103+ + name
104+ + ". There are missing or circular dependencies" );
105+ }
106+ }
107+ throw new IllegalStateException ("Cannot build FileDescriptor for name: " + name );
108+ }
109+
110+ private static FileDescriptor buildFileDescriptor (
111+ FileDescriptorProto proto , List <FileDescriptor > currentDependencies ) {
112+ try {
113+ return FileDescriptor .buildFrom (
114+ proto , currentDependencies .toArray (new FileDescriptor [currentDependencies .size ()]));
115+ } catch (DescriptorValidationException e ) {
116+ throw new IllegalStateException (
117+ "Unable to build valid gRPC descriptor from proto file associated with resource: "
118+ + proto .getName (),
119+ e );
120+ }
121+ }
122+
73123 private static void deleteTempFiles (Path grpcDir ) {
74124 try {
75125 Files .walkFileTree (
@@ -142,15 +192,10 @@ private static void generateFileDescriptorWithProcessBuilder(String[] protocArgs
142192 String [] command = new String [protocArgs .length + 1 ];
143193 command [0 ] = "protoc" ;
144194 System .arraycopy (protocArgs , 0 , command , 1 , protocArgs .length );
145-
146195 ProcessBuilder processBuilder = new ProcessBuilder (command );
147-
148196 processBuilder .redirectErrorStream (true );
149-
150197 Process process = processBuilder .start ();
151-
152198 int exitCode = process .waitFor ();
153-
154199 if (exitCode != 0 ) {
155200 throw new IOException (
156201 "Unable to generate file descriptor using system protoc. Exit code: " + exitCode );
0 commit comments