| /*=============================================================================# |
| # Copyright (c) 2009, 2021 Stephan Wahlbrink and others. |
| # |
| # This program and the accompanying materials are made available under the |
| # terms of the Eclipse Public License 2.0 which is available at |
| # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 |
| # which is available at https://www.apache.org/licenses/LICENSE-2.0. |
| # |
| # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| # |
| # Contributors: |
| # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation |
| #=============================================================================*/ |
| |
| package org.eclipse.statet.jcommons.rmi; |
| |
| import java.net.InetAddress; |
| import java.net.MalformedURLException; |
| import java.net.UnknownHostException; |
| import java.rmi.AccessException; |
| import java.rmi.NotBoundException; |
| import java.rmi.Remote; |
| import java.rmi.RemoteException; |
| import java.rmi.registry.Registry; |
| |
| import org.eclipse.statet.jcommons.lang.NonNullByDefault; |
| import org.eclipse.statet.jcommons.lang.Nullable; |
| import org.eclipse.statet.jcommons.net.Port; |
| |
| |
| /** |
| * Address for RMI naming |
| */ |
| @NonNullByDefault |
| public class RMIAddress { |
| |
| |
| public static void validate(final String address) throws MalformedURLException { |
| try { |
| new RMIAddress(address, false); |
| } |
| catch (final UnknownHostException e) { |
| } |
| } |
| |
| private static final int DEFAULT_PORT_NUM= Registry.REGISTRY_PORT; |
| public static final Port DEFAULT_PORT= new Port(DEFAULT_PORT_NUM); |
| |
| public static final String REGISTRY_NAME= ""; //$NON-NLS-1$ |
| |
| |
| private static String checkChars(final String s) throws MalformedURLException { |
| for (int i= 0; i < s.length(); i++) { |
| final char c= s.charAt(i); |
| if (c == '?' || c == '#' || c == '[' || c == ']' || c == '@' |
| || c == '!' || c == '$' || c == '&' || c == '\'' || c == '(' || c == ')' |
| || c == '*' || c == '+' || c == ',' || c == ';' || c == '=' |
| || c == '"' || c == '\\') { |
| throw new MalformedURLException("Character '" + c+"' is not allowed."); |
| } |
| } |
| return s; |
| } |
| |
| private static String checkNameChars(final String s) throws IllegalArgumentException { |
| for (int i= 0; i < s.length(); i++) { |
| final char c= s.charAt(i); |
| if (c == '?' || c == '#' || c == '[' || c == ']' || c == '@' |
| || c == '!' || c == '$' || c == '&' || c == '\'' || c == '(' || c == ')' |
| || c == '*' || c == '+' || c == ',' || c == ';' || c == '=' |
| || c == '"' || c == '\\') { |
| throw new IllegalArgumentException("Character '" + c + "' is not allowed."); |
| } |
| } |
| return s; |
| } |
| |
| private static Port parsePort(final String port) throws MalformedURLException { |
| try { |
| return Port.valueOf(port); |
| } |
| catch (final IllegalArgumentException e) { |
| throw new MalformedURLException("Invalid port: " + e.getLocalizedMessage()); |
| } |
| } |
| |
| private static Port checkPort(final Port port) { |
| return (port.get() == DEFAULT_PORT_NUM) ? DEFAULT_PORT : port; |
| } |
| |
| |
| private static String build(final @Nullable String host, final int portNum, |
| final @Nullable String name) { |
| final StringBuilder sb= new StringBuilder("//"); //$NON-NLS-1$ |
| if (host != null) { |
| sb.append(host); |
| } |
| sb.append(':'); |
| if (portNum >= 0) { |
| sb.append(Integer.toString(portNum)); |
| } |
| sb.append('/'); |
| if (name != null) { |
| sb.append(name); |
| } |
| return sb.toString(); |
| } |
| |
| |
| private final @Nullable String host; |
| private InetAddress hostAddress; |
| private final Port port; |
| private final boolean isSsl; |
| private final String path; |
| |
| private @Nullable String address; |
| private @Nullable String ser; |
| |
| |
| public RMIAddress(final String address) |
| throws UnknownHostException, MalformedURLException { |
| this(address, true); |
| } |
| |
| public RMIAddress(final @Nullable String host, final int portNum, |
| final @Nullable String name) |
| throws UnknownHostException, MalformedURLException { |
| this(build(host, portNum, name), true); |
| } |
| |
| public RMIAddress(final InetAddress address, final int portNum, |
| final @Nullable String name) |
| throws MalformedURLException { |
| this(address.getHostAddress(), address, parsePort(Integer.toString(portNum)), false, |
| (name != null) ? checkChars(name) : "" ); |
| } |
| |
| public RMIAddress(final InetAddress address, final Port port, final boolean isSsl, |
| final String name) { |
| this(address.getHostAddress(), address, checkPort(port), isSsl, |
| checkNameChars(name) ); |
| } |
| |
| public RMIAddress(final InetAddress address, final Port port, |
| final String name) { |
| this(address.getHostAddress(), address, checkPort(port), false, |
| checkNameChars(name) ); |
| } |
| |
| public RMIAddress(final RMIAddress registry, |
| final String name) { |
| this(registry.host, registry.hostAddress, registry.port, registry.isSsl, |
| checkNameChars(name) ); |
| } |
| |
| private RMIAddress(String address, final boolean resolve) |
| throws UnknownHostException, MalformedURLException { |
| address= checkChars(address); |
| |
| if (address.startsWith("ssl:")) { //$NON-NLS-1$ |
| address= address.substring(4); |
| this.isSsl= true; |
| } |
| else { |
| this.isSsl= false; |
| } |
| if (address.startsWith("rmi:")) { //$NON-NLS-1$ |
| address= address.substring(4); |
| } |
| if (!address.startsWith("//")) { //$NON-NLS-1$ |
| address= "//"+address; //$NON-NLS-1$ |
| } |
| |
| final int idxPort= address.indexOf(':', 2); |
| final int idxPath= address.indexOf('/', 2); |
| if (idxPort > 0) { |
| if (idxPath <= idxPort) { |
| throw new IllegalArgumentException(); |
| } |
| this.host= (2 < idxPort) ? address.substring(2, idxPort) : null; |
| this.port= (idxPort + 1 < idxPath) ? |
| checkPort(parsePort(address.substring(idxPort + 1, idxPath))) : |
| DEFAULT_PORT; |
| this.path= address.substring(idxPath+1); |
| } |
| else if (idxPath > 0){ |
| this.host= (2 < idxPath) ? address.substring(2, idxPath) : null; |
| this.port= DEFAULT_PORT; |
| this.path= address.substring(idxPath+1); |
| } |
| else { |
| this.host= null; |
| this.port= DEFAULT_PORT; |
| this.path= address.substring(2); |
| } |
| if (resolve) { |
| this.hostAddress= (this.host != null) ? InetAddress.getByName(this.host) : InetAddress.getLoopbackAddress(); |
| } |
| } |
| |
| private RMIAddress(final @Nullable String host, final InetAddress hostAddress, final Port port, |
| final boolean isSsl, final String path) { |
| this.host= host; |
| this.hostAddress= hostAddress; |
| this.port= port; |
| this.isSsl= isSsl; |
| this.path= path; |
| } |
| |
| |
| /** |
| * @return the host as specified when creating the address |
| */ |
| public String getHost() { |
| return (this.host != null) ? this.host : this.hostAddress.getHostAddress(); |
| } |
| |
| public InetAddress getHostAddress() { |
| return this.hostAddress; |
| } |
| |
| public boolean isLocalHost() { |
| if (this.hostAddress.isLoopbackAddress()) { |
| return true; |
| } |
| try { |
| final InetAddress localhost= InetAddress.getLocalHost(); |
| if (this.hostAddress.equals(localhost)) { |
| return true; |
| } |
| } |
| catch (final UnknownHostException e) {} |
| catch (final ArrayIndexOutOfBoundsException e) { /* JVM bug */ } |
| |
| return false; |
| } |
| |
| public Port getPort() { |
| return this.port; |
| } |
| |
| /** |
| * @return the name |
| */ |
| public String getName() { |
| return this.path; |
| } |
| |
| /** |
| * Standard string presentation to use for rmi |
| * @return |
| */ |
| public String getAddress() { |
| String address= this.address; |
| if (address == null) { |
| final StringBuilder sb= new StringBuilder(32); |
| sb.append("rmi://"); //$NON-NLS-1$ |
| if (this.host != null) { |
| sb.append(this.host); |
| } |
| if (this.port != DEFAULT_PORT) { |
| sb.append(':'); |
| sb.append(this.port); |
| } |
| sb.append('/'); |
| sb.append(this.path); |
| address= sb.toString(); |
| this.address= address; |
| } |
| return address; |
| } |
| |
| public RMIAddress getRegistryAddress() { |
| return new RMIAddress(this.host, this.hostAddress, this.port, this.isSsl, ""); |
| } |
| |
| public Remote lookup() throws RemoteException, NotBoundException, AccessException { |
| final RMIRegistry rmiRegistry= new RMIRegistry(getRegistryAddress(), false); |
| return rmiRegistry.getRegistry().lookup(getName()); |
| } |
| |
| /** |
| * |
| * @return if SSL is enabled |
| * |
| * @since 1.4 |
| */ |
| public boolean isSsl() { |
| return this.isSsl; |
| } |
| |
| |
| @Override |
| public String toString() { |
| String ser= this.ser; |
| if (ser == null) { |
| if (this.isSsl) { |
| ser= "ssl:" + getAddress(); |
| } |
| else { |
| ser= getAddress(); |
| } |
| this.ser= ser; |
| } |
| return ser; |
| } |
| |
| @Override |
| public int hashCode() { |
| return toString().hashCode(); |
| } |
| |
| @Override |
| public boolean equals(final @Nullable Object obj) { |
| if (this == obj) { |
| return true; |
| } |
| if (obj instanceof RMIAddress) { |
| final RMIAddress other= (RMIAddress) obj; |
| return (this.hostAddress.equals(other.hostAddress) |
| && this.port.equals(other.port) |
| && this.isSsl == other.isSsl |
| && this.path.equals(other.path) ); |
| } |
| return false; |
| } |
| |
| } |