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.space;
020
021import org.jpos.core.Configuration;
022import org.jpos.core.ConfigurationException;
023import org.jpos.core.Configurable;
024
025import javax.naming.InitialContext;
026import javax.naming.NamingException;
027import java.io.Serializable;
028import java.rmi.RemoteException;
029import java.rmi.registry.LocateRegistry;
030import java.rmi.registry.Registry;
031import java.rmi.server.*;
032import java.util.Set;
033
034/**
035 * RMI Space Proxy 
036 * @author Alejandro Revilla
037 * @author Niclas Hedhman
038 * @version $Revision$ $Date$
039 * @since 1.4.9
040 */
041@SuppressWarnings("unchecked")
042public class SpaceProxy implements RemoteSpace, Configurable {
043    Space sp;
044    Configuration cfg;
045    private RemoteRef ref;
046    private RemoteStub stub;
047    /**
048     * Constructs a proxy backed by the default jPOS space.
049     *
050     * @throws RemoteException if RMI export fails
051     */
052    public SpaceProxy () throws RemoteException {
053        super();
054        sp = SpaceFactory.getSpace ();
055        startService ();
056    }
057    /**
058     * Constructs a proxy backed by the space resolved from {@code spaceUri}.
059     *
060     * @param spaceUri SpaceFactory-style space URI
061     * @throws RemoteException if RMI export fails
062     */
063    public SpaceProxy (String spaceUri) throws RemoteException {
064        super ();
065        sp = SpaceFactory.getSpace (spaceUri);
066        startService ();
067    }
068
069    private void startService () throws RemoteException 
070    {
071        try {
072            LocateRegistry.createRegistry (Registry.REGISTRY_PORT);
073        } catch (ExportException ignored) {
074            // NOPMD: ok to happen
075        }
076        stub = UnicastRemoteObject.exportObject (this);
077        ref  = stub.getRef();
078    }
079
080    public void out (Serializable key, Serializable value) 
081        throws RemoteException
082    {
083        sp.out (key, value);
084    }
085    public void out (Serializable key, Serializable value, long timeout)
086        throws RemoteException
087    {
088        sp.out (key, value, timeout);
089    }
090    public Serializable in (Serializable key)
091        throws RemoteException
092    {
093        return (Serializable) sp.in (key);
094    }
095    public Serializable rd  (Serializable key)
096        throws RemoteException
097    {
098        return (Serializable) sp.rd (key);
099    }
100    public Serializable in  (Serializable key, long timeout)
101        throws RemoteException
102    {
103        return (Serializable) sp.in (key, timeout);
104    }
105    public Serializable rd  (Serializable key, long timeout)
106        throws RemoteException
107    {
108        return (Serializable) sp.rd (key, timeout);
109    }
110    public Serializable inp (Serializable key)
111        throws RemoteException
112    {
113        return (Serializable) sp.inp (key);
114    }
115    public Serializable rdp (Serializable key)
116        throws RemoteException
117    {
118        return (Serializable) sp.rdp (key);
119    }
120    /** Unexports this proxy from the RMI runtime, retrying once after a brief delay. */
121    public void shutdown() {
122        try {
123            if (UnicastRemoteObject.unexportObject (this, false)) 
124                return;
125            Thread.sleep (5000);
126            UnicastRemoteObject.unexportObject (this, true);
127        } catch (Exception ignored) {
128            // NOPMD: nothing to do .. we're shutting down ...
129        }
130    }
131    public void setConfiguration (Configuration cfg) 
132        throws ConfigurationException
133    {
134        this.cfg = cfg;
135        try {
136            InitialContext ctx = new InitialContext ();
137            ctx.rebind (cfg.get ("name"), stub);
138        } catch (NamingException e) {
139            throw new ConfigurationException (e);
140        }
141    }
142    /**
143     * Returns the underlying local-space key set when available.
144     *
145     * @return the live key set, or {@code null} when the proxied space is not local
146     */
147    public Set getKeySet () {
148        if (sp instanceof LocalSpace)
149            return ((LocalSpace)sp).getKeySet ();
150        else
151            return null;
152    }
153    public String toString() {
154        if (ref == null)
155            return getClass().getName() + "[<unexported>]";
156        else
157            return getClass().getName() + "[" + ref.remoteToString() + "]";
158    }
159    public int hashCode() {
160        if (ref == null )
161            return super.hashCode();
162        else
163            return ref.remoteHashCode();
164    }
165    public boolean equals (Object obj) {
166        if (obj instanceof RemoteObject) {
167            if (ref == null) {
168                return obj == this;
169            } else {
170                RemoteRef otherRef = ((RemoteObject)obj).getRef();
171                return ref.remoteEquals (otherRef);
172            }
173        } else if (obj != null) {
174            return obj.equals (this);
175        } else {
176            return false;
177        }
178    }
179}
180