| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
package javax.management.remote.rmi;  | 
 | 
 | 
 | 
import java.io.IOException;  | 
 | 
import java.rmi.NoSuchObjectException;  | 
 | 
import java.rmi.Remote;  | 
 | 
import java.rmi.RemoteException;  | 
 | 
import java.rmi.server.RMIClientSocketFactory;  | 
 | 
import java.rmi.server.RMIServerSocketFactory;  | 
 | 
import java.rmi.server.UnicastRemoteObject;  | 
 | 
import java.rmi.server.RemoteObject;  | 
 | 
import java.util.Map;  | 
 | 
import java.util.Collections;  | 
 | 
import javax.security.auth.Subject;  | 
 | 
 | 
 | 
import com.sun.jmx.remote.internal.RMIExporter;  | 
 | 
import com.sun.jmx.remote.util.EnvHelp;  | 
 | 
import java.io.ObjectStreamClass;  | 
 | 
import java.lang.reflect.Method;  | 
 | 
import java.util.ArrayList;  | 
 | 
import java.util.List;  | 
 | 
import sun.reflect.misc.ReflectUtil;  | 
 | 
import sun.rmi.server.DeserializationChecker;  | 
 | 
import sun.rmi.server.UnicastServerRef;  | 
 | 
import sun.rmi.server.UnicastServerRef2;  | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
public class RMIJRMPServerImpl extends RMIServerImpl { | 
 | 
 | 
 | 
    private final ExportedWrapper exportedWrapper;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public RMIJRMPServerImpl(int port,  | 
 | 
                             RMIClientSocketFactory csf,  | 
 | 
                             RMIServerSocketFactory ssf,  | 
 | 
                             Map<String,?> env)  | 
 | 
            throws IOException { | 
 | 
 | 
 | 
        super(env);  | 
 | 
 | 
 | 
        if (port < 0)  | 
 | 
            throw new IllegalArgumentException("Negative port: " + port); | 
 | 
 | 
 | 
        this.port = port;  | 
 | 
        this.csf = csf;  | 
 | 
        this.ssf = ssf;  | 
 | 
        this.env = (env == null) ? Collections.<String, Object>emptyMap() : env;  | 
 | 
 | 
 | 
        String[] credentialsTypes  | 
 | 
                = (String[]) this.env.get(EnvHelp.CREDENTIAL_TYPES);  | 
 | 
        List<String> types = null;  | 
 | 
        if (credentialsTypes != null) { | 
 | 
            types = new ArrayList<>();  | 
 | 
            for (String type : credentialsTypes) { | 
 | 
                if (type == null) { | 
 | 
                    throw new IllegalArgumentException("A credential type is null."); | 
 | 
                }  | 
 | 
                ReflectUtil.checkPackageAccess(type);  | 
 | 
                types.add(type);  | 
 | 
            }  | 
 | 
        }  | 
 | 
        exportedWrapper = types != null ?  | 
 | 
                new ExportedWrapper(this, types) :  | 
 | 
                null;  | 
 | 
    }  | 
 | 
 | 
 | 
    protected void export() throws IOException { | 
 | 
        if (exportedWrapper != null) { | 
 | 
            export(exportedWrapper);  | 
 | 
        } else { | 
 | 
            export(this);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private void export(Remote obj) throws RemoteException { | 
 | 
        final RMIExporter exporter =  | 
 | 
            (RMIExporter) env.get(RMIExporter.EXPORTER_ATTRIBUTE);  | 
 | 
        final boolean daemon = EnvHelp.isServerDaemon(env);  | 
 | 
 | 
 | 
        if (daemon && exporter != null) { | 
 | 
            throw new IllegalArgumentException("If "+EnvHelp.JMX_SERVER_DAEMON+ | 
 | 
                    " is specified as true, "+RMIExporter.EXPORTER_ATTRIBUTE+  | 
 | 
                    " cannot be used to specify an exporter!");  | 
 | 
        }  | 
 | 
 | 
 | 
        if (daemon) { | 
 | 
            if (csf == null && ssf == null) { | 
 | 
                new UnicastServerRef(port).exportObject(obj, null, true);  | 
 | 
            } else { | 
 | 
                new UnicastServerRef2(port, csf, ssf).exportObject(obj, null, true);  | 
 | 
            }  | 
 | 
        } else if (exporter != null) { | 
 | 
            exporter.exportObject(obj, port, csf, ssf);  | 
 | 
        } else { | 
 | 
            UnicastRemoteObject.exportObject(obj, port, csf, ssf);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private void unexport(Remote obj, boolean force)  | 
 | 
            throws NoSuchObjectException { | 
 | 
        RMIExporter exporter =  | 
 | 
            (RMIExporter) env.get(RMIExporter.EXPORTER_ATTRIBUTE);  | 
 | 
        if (exporter == null)  | 
 | 
            UnicastRemoteObject.unexportObject(obj, force);  | 
 | 
        else  | 
 | 
            exporter.unexportObject(obj, force);  | 
 | 
    }  | 
 | 
 | 
 | 
    protected String getProtocol() { | 
 | 
        return "rmi";  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public Remote toStub() throws IOException { | 
 | 
        if (exportedWrapper != null) { | 
 | 
            return RemoteObject.toStub(exportedWrapper);  | 
 | 
        } else { | 
 | 
            return RemoteObject.toStub(this);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected RMIConnection makeClient(String connectionId, Subject subject)  | 
 | 
            throws IOException { | 
 | 
 | 
 | 
        if (connectionId == null)  | 
 | 
            throw new NullPointerException("Null connectionId"); | 
 | 
 | 
 | 
        RMIConnection client =  | 
 | 
            new RMIConnectionImpl(this, connectionId, getDefaultClassLoader(),  | 
 | 
                                  subject, env);  | 
 | 
        export(client);  | 
 | 
        return client;  | 
 | 
    }  | 
 | 
 | 
 | 
    protected void closeClient(RMIConnection client) throws IOException { | 
 | 
        unexport(client, true);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected void closeServer() throws IOException { | 
 | 
        if (exportedWrapper != null) { | 
 | 
            unexport(exportedWrapper, true);  | 
 | 
        } else { | 
 | 
            unexport(this, true);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private final int port;  | 
 | 
    private final RMIClientSocketFactory csf;  | 
 | 
    private final RMIServerSocketFactory ssf;  | 
 | 
    private final Map<String, ?> env;  | 
 | 
 | 
 | 
    private static class ExportedWrapper implements RMIServer, DeserializationChecker { | 
 | 
        private final RMIServer impl;  | 
 | 
        private final List<String> allowedTypes;  | 
 | 
        private ExportedWrapper(RMIServer impl, List<String> credentialsTypes) { | 
 | 
            this.impl = impl;  | 
 | 
            allowedTypes = credentialsTypes;  | 
 | 
        }  | 
 | 
 | 
 | 
        @Override  | 
 | 
        public String getVersion() throws RemoteException { | 
 | 
            return impl.getVersion();  | 
 | 
        }  | 
 | 
 | 
 | 
        @Override  | 
 | 
        public RMIConnection newClient(Object credentials) throws IOException { | 
 | 
            return impl.newClient(credentials);  | 
 | 
        }  | 
 | 
 | 
 | 
        @Override  | 
 | 
        public void check(Method method, ObjectStreamClass descriptor,  | 
 | 
                int paramIndex, int callID) { | 
 | 
 | 
 | 
            String type = descriptor.getName();  | 
 | 
            if (!allowedTypes.contains(type)) { | 
 | 
                throw new ClassCastException("Unsupported type: " + type); | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        @Override  | 
 | 
        public void checkProxyClass(Method method, String[] ifaces,  | 
 | 
                int paramIndex, int callID) { | 
 | 
            if (ifaces != null && ifaces.length > 0) { | 
 | 
                for (String iface : ifaces) { | 
 | 
                    if (!allowedTypes.contains(iface)) { | 
 | 
                        throw new ClassCastException("Unsupported type: " + iface); | 
 | 
                    }  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
}  |