001/* 002 * jPOS Project [http://jpos.org] 003 * Copyright (C) 2000-2026 jPOS Software SRL 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Affero General Public License as 007 * published by the Free Software Foundation, either version 3 of the 008 * License, or (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Affero General Public License for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018 019package org.jpos.util; 020 021import org.jpos.space.SpaceUtil; 022import org.jpos.space.TSpace; 023 024import java.io.PrintStream; 025import java.util.HashMap; 026import java.util.Map; 027 028/** 029 * Allow runtime binding of jPOS's components (ISOChannels, Logger, MUXes, etc) 030 * 031 * @author <a href="mailto:apr@cs.com.uy">Alejandro P. Revilla</a> 032 * @version $Revision$ $Date$ 033 */ 034public class NameRegistrar implements Loggeable { 035 private static final NameRegistrar instance = new NameRegistrar(); 036 private static final TSpace<String, Object> sp = new TSpace<String,Object>(); 037 038 /** Thrown when a requested name is not found in the registrar. */ 039 public static class NotFoundException extends Exception { 040 private static final long serialVersionUID = 8744022794646381475L; 041 042 /** Default constructor. */ 043 public NotFoundException() { 044 super(); 045 } 046 047 /** Constructs a NotFoundException with the given detail message. 048 * @param detail the missing key or detail message 049 */ 050 public NotFoundException(String detail) { 051 super(detail); 052 } 053 } 054 055 /** Private constructor — use the singleton. */ 056 private NameRegistrar() { 057 super(); 058 } 059 060 /** Returns the underlying TSpace used for name registration. 061 * @return the shared TSpace instance 062 */ 063 public static TSpace<String, Object> getSpace() { 064 return sp; 065 } 066 067 /** 068 * Returns a copy of the NameRegistrar's entries as a Map. 069 * @return a copy of the NameRegistrar's entries as a Map 070 */ 071 public static Map<String,Object> getAsMap() { 072 Map<String,Object> map = new HashMap<String,Object>(); 073 for (String k : sp.getKeySet()) { 074 Object v = sp.rdp(k); 075 if (v != null) 076 map.put(k,v); 077 } 078 return map; 079 } 080 081 /** 082 * Returns the singleton NameRegistrar instance. 083 * @return singleton instance 084 */ 085 public static NameRegistrar getInstance() { 086 return instance; 087 } 088 089 /** 090 * register object 091 * 092 * @param key 093 * - key with which the specified value is to be associated. 094 * @param value 095 * - value to be associated with the specified key 096 */ 097 public static void register(String key, Object value) { 098 sp.put(key, value); 099 } 100 101 /** 102 * Removes the mapping for the given key from the registrar. 103 * @param key 104 * key whose mapping is to be removed from registrar. 105 */ 106 public static void unregister(String key) { 107 SpaceUtil.wipe(sp, key); 108 } 109 110 /** 111 * Get a value from the registry. 112 * 113 * @param <T> desired type of entry value. 114 * @param key the key whose associated value is to be returned. 115 * @return a value 116 * @throws NotFoundException if key not present in registrar 117 */ 118 public static <T> T get(String key) throws NotFoundException { 119 @SuppressWarnings("unchecked") 120 T obj = (T) sp.rdp(key); 121 if (obj == null) { 122 throw new NotFoundException(key); 123 } 124 return obj; 125 } 126 127 /** 128 * Get a value from the registry - wait for it specified time. 129 * 130 * @param <T> desired type of value. 131 * @param key the key whose associated value is to be returned. 132 * @param timeout the maximum waiting time (in miliseconds) for 133 * the appearance of value in the registry. 134 * @return a value or {@code null} if it does not exist 135 */ 136 public static <T> T get(String key, long timeout) { 137 return (T) sp.rd(key, timeout); 138 } 139 140 /** 141 * Get a value from the registry - without casting {@code NotFoundException}. 142 * 143 * @param <T> desired type of value. 144 * @param key the key whose associated value is to be returned. 145 * @return a value or {@code null} if it does not exist 146 */ 147 public static <T> T getIfExists(String key) { 148 @SuppressWarnings("unchecked") 149 T obj = (T) sp.rdp(key); 150 return obj; 151 } 152 153 /** Dumps a summary of registered names to the given stream. 154 * @param p output stream 155 * @param indent indent prefix 156 */ 157 public void dump(PrintStream p, String indent) { 158 dump(p, indent, false); 159 } 160 161 /** Dumps registered names to the given stream, optionally including object detail. 162 * @param p output stream 163 * @param indent indent prefix 164 * @param detail if true, also dumps Loggeable objects 165 */ 166 public void dump(PrintStream p, String indent, boolean detail) { 167 String inner = indent + " "; 168 p.println(indent + "name-registrar:"); 169 for (String key : sp.getKeySet()) { 170 Object obj = sp.rdp(key); 171 String objectClassName = obj == null ? "<NULL>" : obj.getClass().getName(); 172 p.println(inner + key + ": " + objectClassName); 173 if (detail && obj instanceof Loggeable) { 174 try { 175 ((Loggeable) obj).dump(p, inner + " "); 176 } catch (Exception e) { // typically a NPE may be thrown from badly-initialized objects 177 p.println(e.getMessage()); 178 } 179 } 180 } 181 } 182}