| /*=============================================================================# |
| # Copyright (c) 2009, 2018 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.rj.server.srv; |
| |
| import java.net.InetAddress; |
| import java.net.MalformedURLException; |
| import java.net.UnknownHostException; |
| import java.rmi.registry.Registry; |
| |
| |
| /** |
| * Address for RMI naming |
| */ |
| class RMIAddress { |
| |
| |
| public static final InetAddress LOOPBACK; |
| |
| public static void validate(final String address) throws MalformedURLException { |
| try { |
| new RMIAddress(address, false); |
| } |
| catch (final UnknownHostException e) { |
| } |
| } |
| |
| |
| 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 int checkPort(final String port) throws MalformedURLException { |
| final int portNum; |
| try { |
| portNum= (port != null) ? Integer.parseInt(port) : Registry.REGISTRY_PORT; |
| } |
| catch (final NumberFormatException e) { |
| throw new MalformedURLException("Invalid port, " + e.getMessage()); |
| } |
| return checkPort(portNum); |
| } |
| |
| private static int checkPort(final int portNum) throws MalformedURLException { |
| if (portNum < 0 || portNum > 65535) { |
| throw new MalformedURLException("Invalid port, " + "Value must be in range 0-65535"); |
| } |
| return portNum; |
| } |
| |
| private static String build(final String host, final int portNum, final 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(); |
| } |
| |
| |
| static { |
| InetAddress loopbackAddress; |
| try { |
| loopbackAddress= InetAddress.getByAddress("localhost", new byte[] { 127, 0, 0, 1 }); //$NON-NLS-1$ |
| } |
| catch (final UnknownHostException e) { |
| loopbackAddress= null; |
| e.printStackTrace(); |
| } |
| LOOPBACK= loopbackAddress; |
| } |
| |
| |
| private final String host; |
| private InetAddress hostAddress; |
| private final String port; |
| private final int portNum; |
| private final boolean ssl; |
| private final String path; |
| |
| private String address; |
| private String ser; |
| |
| |
| public RMIAddress(final String address) throws UnknownHostException, MalformedURLException { |
| this(address, true); |
| } |
| |
| public RMIAddress(final String host, final int portNum, final String name) throws UnknownHostException, MalformedURLException { |
| this(build(host, portNum, name), true); |
| } |
| |
| public RMIAddress(final InetAddress address, final int port, final String name) |
| throws MalformedURLException { |
| this(address.getHostAddress(), address, Integer.toString(port), checkPort(port), false, |
| (name != null) ? checkChars(name) : ""); |
| } |
| |
| public RMIAddress(final InetAddress address, final int port, final boolean ssl, final String name) |
| throws MalformedURLException { |
| this(address.getHostAddress(), address, Integer.toString(port), checkPort(port), ssl, |
| (name != null) ? checkChars(name) : ""); |
| } |
| |
| public RMIAddress(final RMIAddress registry, final String name) throws MalformedURLException { |
| this(registry.host, registry.hostAddress, registry.port, registry.portNum, registry.ssl, |
| (name != null) ? checkChars(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.ssl= true; |
| } |
| else { |
| this.ssl= 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) ? address.substring(idxPort+1, idxPath) : null; |
| this.path= address.substring(idxPath+1); |
| } |
| else if (idxPath > 0){ |
| this.host= (2 < idxPath) ? address.substring(2, idxPath) : null; |
| this.port= null; |
| this.path= address.substring(idxPath+1); |
| } |
| else { |
| this.host= null; |
| this.port= null; |
| this.path= address.substring(2); |
| } |
| try { |
| this.portNum= checkPort(this.port); |
| } |
| catch (final NumberFormatException e) { |
| throw new MalformedURLException("Invalid port, " + e.getLocalizedMessage()); |
| } |
| if (resolve) { |
| this.hostAddress= (this.host != null) ? InetAddress.getByName(this.host) : LOOPBACK; |
| } |
| } |
| |
| private RMIAddress(final String host, final InetAddress hostAddress, final String port, |
| final int portNum, final boolean ssl, final String path) { |
| this.host= host; |
| this.hostAddress= hostAddress; |
| this.port= port; |
| this.portNum= portNum; |
| this.ssl= ssl; |
| 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; |
| } |
| |
| /** |
| * @return the port |
| */ |
| public String getPort() { |
| return this.port; |
| } |
| |
| public int getPortNum() { |
| return this.portNum; |
| } |
| |
| /** |
| * @return the name |
| */ |
| public String getName() { |
| return this.path; |
| } |
| |
| /** |
| * Standard string presentation to use for rmi |
| * @return |
| */ |
| public String getAddress() { |
| if (this.address == null) { |
| final StringBuilder sb= new StringBuilder(32); |
| sb.append("rmi://"); //$NON-NLS-1$ |
| if (this.host != null) { |
| sb.append(this.host); |
| } |
| if (this.portNum != Registry.REGISTRY_PORT) { |
| sb.append(':'); |
| sb.append(this.port); |
| } |
| sb.append('/'); |
| sb.append(this.path); |
| this.address= sb.toString(); |
| } |
| return this.address; |
| } |
| |
| public RMIAddress getRegistryAddress() { |
| return new RMIAddress(this.host, this.hostAddress, this.port, this.portNum, this.ssl, ""); |
| } |
| |
| /** |
| * |
| * @return if SSL is enabled |
| * |
| * @since 1.4 |
| */ |
| public boolean isSSL() { |
| return this.ssl; |
| } |
| |
| |
| @Override |
| public String toString() { |
| if (this.ser == null) { |
| final String address= getAddress(); |
| if (this.ssl) { |
| this.ser= "ssl:" + address; |
| } |
| else { |
| this.ser= address; |
| } |
| } |
| return this.ser; |
| } |
| |
| @Override |
| public int hashCode() { |
| return toString().hashCode(); |
| } |
| |
| @Override |
| public boolean equals(final Object obj) { |
| if (!(obj instanceof RMIAddress)) { |
| return false; |
| } |
| final RMIAddress other= (RMIAddress) obj; |
| return (this.hostAddress.equals(other.hostAddress) |
| && this.portNum == other.portNum |
| && this.ssl == other.ssl |
| && this.path.equals(other.path) ); |
| } |
| |
| } |