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    public static class NotFoundException extends Exception {
039        private static final long serialVersionUID = 8744022794646381475L;
040
041        public NotFoundException() {
042            super();
043        }
044
045        public NotFoundException(String detail) {
046            super(detail);
047        }
048    }
049
050    private NameRegistrar() {
051        super();
052    }
053
054    public static TSpace<String, Object> getSpace() {
055        return sp;
056    }
057
058    /**
059     * @return a copy of the NameRegistrar's entries as a Map
060     */
061    public static Map<String,Object> getAsMap() {
062        Map<String,Object> map = new HashMap<String,Object>();
063        for (String k : sp.getKeySet()) {
064            Object v  = sp.rdp(k);
065            if (v != null)
066                map.put(k,v);
067        }
068        return map;
069    }
070
071    /**
072     * @return singleton instance
073     */
074    public static NameRegistrar getInstance() {
075        return instance;
076    }
077
078    /**
079     * register object
080     *
081     * @param key
082     *            - key with which the specified value is to be associated.
083     * @param value
084     *            - value to be associated with the specified key
085     */
086    public static void register(String key, Object value) {
087        sp.put(key, value);
088    }
089
090    /**
091     * @param key
092     *            key whose mapping is to be removed from registrar.
093     */
094    public static void unregister(String key) {
095        SpaceUtil.wipe(sp, key);
096    }
097
098    /**
099     * Get a value from the registry.
100     *
101     * @param <T> desired type of entry value.
102     * @param key the key whose associated value is to be returned.
103     * @return a value
104     * @throws NotFoundException if key not present in registrar
105     */
106    public static <T> T get(String key) throws NotFoundException {
107        @SuppressWarnings("unchecked")
108        T obj = (T) sp.rdp(key);
109        if (obj == null) {
110            throw new NotFoundException(key);
111        }
112        return obj;
113    }
114
115    /**
116     * Get a value from the registry - wait for it specified time.
117     *
118     * @param <T> desired type of value.
119     * @param key the key whose associated value is to be returned.
120     * @param timeout the maximum waiting time (in miliseconds) for
121     * the appearance of value in the registry.
122     * @return a value or {@code null} if it does not exist
123     */
124    public static <T> T get(String key, long timeout) {
125        return (T) sp.rd(key, timeout);
126    }
127
128    /**
129     * Get a value from the registry - without casting {@code NotFoundException}.
130     *
131     * @param <T> desired type of value.
132     * @param key the key whose associated value is to be returned.
133     * @return a value or {@code null} if it does not exist
134     */
135    public static <T> T getIfExists(String key) {
136        @SuppressWarnings("unchecked")
137        T obj = (T) sp.rdp(key);
138        return obj;
139    }
140
141    public void dump(PrintStream p, String indent) {
142        dump(p, indent, false);
143    }
144
145    public void dump(PrintStream p, String indent, boolean detail) {
146        String inner = indent + "  ";
147        p.println(indent + "name-registrar:");
148        for (String key : sp.getKeySet()) {
149            Object obj = sp.rdp(key);
150            String objectClassName = obj == null ? "<NULL>" : obj.getClass().getName();
151            p.println(inner + key + ": " + objectClassName);
152            if (detail && obj instanceof Loggeable) {
153                try {
154                    ((Loggeable) obj).dump(p, inner + "  ");
155                } catch (Exception e) {         // typically a NPE may be thrown from badly-initialized objects
156                    p.println(e.getMessage());
157                }
158            }
159        }
160    }
161}