001/* 002 * Copyright (c) 2025 Tada AB and other contributors, as listed below. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the The BSD 3-Clause License 006 * which accompanies this distribution, and is available at 007 * http://opensource.org/licenses/BSD-3-Clause 008 * 009 * Contributors: 010 * Chapman Flack 011 */ 012package org.postgresql.pljava.example.annotation; 013 014import java.lang.module.ModuleDescriptor; 015 016import java.sql.ResultSet; 017import java.sql.SQLException; 018 019import java.util.Iterator; 020import java.util.Objects; 021 022import java.util.stream.Stream; 023 024import org.postgresql.pljava.ResultSetProvider; 025import org.postgresql.pljava.annotation.Function; 026import static org.postgresql.pljava.annotation.Function.Effects.STABLE; 027 028/** 029 * Example code to support querying for the modules in Java's boot layer. 030 */ 031public class Modules implements ResultSetProvider.Large { 032 /** 033 * Returns information on the named modules in Java's boot module layer. 034 */ 035 @Function( 036 effects = STABLE, 037 out = { 038 "name pg_catalog.text", 039 "any_unqualified_exports boolean", 040 "any_unqualified_opens boolean" 041 } 042 ) 043 public static ResultSetProvider java_modules() 044 { 045 return new Modules( 046 ModuleLayer.boot().modules().stream().map(Module::getDescriptor) 047 .filter(Objects::nonNull)); 048 } 049 050 private final Iterator<ModuleDescriptor> iterator; 051 private final Runnable closer; 052 053 private Modules(Stream<ModuleDescriptor> s) 054 { 055 iterator = s.iterator(); 056 closer = s::close; 057 } 058 059 @Override 060 public boolean assignRowValues(ResultSet receiver, long currentRow) 061 throws SQLException 062 { 063 if ( ! iterator.hasNext() ) 064 return false; 065 066 ModuleDescriptor md = iterator.next(); 067 068 receiver.updateString(1, md.name()); 069 070 receiver.updateBoolean(2, 071 md.exports().stream().anyMatch(e -> ! e.isQualified())); 072 073 receiver.updateBoolean(3, 074 md.isOpen() || 075 md.opens().stream().anyMatch(o -> ! o.isQualified())); 076 077 return true; 078 } 079 080 @Override 081 public void close() 082 { 083 closer.run(); 084 } 085}