Added: tomcat/sandbox/java/org/apache/tomcat/util/net/SSLSupport.java URL: http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/tomcat/util/net/SSLSupport.java?rev=345653&view=auto ============================================================================== --- tomcat/sandbox/java/org/apache/tomcat/util/net/SSLSupport.java (added) +++ tomcat/sandbox/java/org/apache/tomcat/util/net/SSLSupport.java Sat Nov 19 08:50:47 2005 @@ -0,0 +1,127 @@ +/* + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.tomcat.util.net; + +import java.io.IOException; + +/* SSLSupport + + Interface for SSL-specific functions + + @author EKR +*/ + +public interface SSLSupport { + /** + * The Request attribute key for the cipher suite. + */ + public static final String CIPHER_SUITE_KEY = "javax.servlet.request.cipher_suite"; + + /** + * The Request attribute key for the key size. + */ + public static final String KEY_SIZE_KEY = "javax.servlet.request.key_size"; + + /** + * The Request attribute key for the client certificate chain. + */ + public static final String CERTIFICATE_KEY = "javax.servlet.request.X509Certificate"; + + /** + * The Request attribute key for the session id. + * This one is a Tomcat extension to the Servlet spec. + */ + public static final String SESSION_ID_KEY = "javax.servlet.request.ssl_session"; + + /** + * A mapping table to determine the number of effective bits in the key + * when using a cipher suite containing the specified cipher name. The + * underlying data came from the TLS Specification (RFC 2246), Appendix C. + */ + static final CipherData ciphers[] = { + new CipherData("_WITH_NULL_", 0), + new CipherData("_WITH_IDEA_CBC_", 128), + new CipherData("_WITH_RC2_CBC_40_", 40), + new CipherData("_WITH_RC4_40_", 40), + new CipherData("_WITH_RC4_128_", 128), + new CipherData("_WITH_DES40_CBC_", 40), + new CipherData("_WITH_DES_CBC_", 56), + new CipherData("_WITH_3DES_EDE_CBC_", 168) + }; + + /** + * The cipher suite being used on this connection. + */ + public String getCipherSuite() throws IOException; + + /** + * The client certificate chain (if any). + */ + public Object[] getPeerCertificateChain() + throws IOException; + + /** + * The client certificate chain (if any). + * @param force If <code>true</code>, then re-negotiate the + * connection if necessary. + */ + public Object[] getPeerCertificateChain(boolean force) + throws IOException; + + /** + * Get the keysize. + * + * What we're supposed to put here is ill-defined by the + * Servlet spec (S 4.7 again). There are at least 4 potential + * values that might go here: + * + * (a) The size of the encryption key + * (b) The size of the MAC key + * (c) The size of the key-exchange key + * (d) The size of the signature key used by the server + * + * Unfortunately, all of these values are nonsensical. + **/ + public Integer getKeySize() + throws IOException; + + /** + * The current session Id. + */ + public String getSessionId() + throws IOException; + /** + * Simple data class that represents the cipher being used, along with the + * corresponding effective key size. The specified phrase must appear in the + * name of the cipher suite to be recognized. + */ + + final class CipherData { + + public String phrase = null; + + public int keySize = 0; + + public CipherData(String phrase, int keySize) { + this.phrase = phrase; + this.keySize = keySize; + } + + } + +} +
Added: tomcat/sandbox/java/org/apache/tomcat/util/net/ServerSocketFactory.java URL: http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/tomcat/util/net/ServerSocketFactory.java?rev=345653&view=auto ============================================================================== --- tomcat/sandbox/java/org/apache/tomcat/util/net/ServerSocketFactory.java (added) +++ tomcat/sandbox/java/org/apache/tomcat/util/net/ServerSocketFactory.java Sat Nov 19 08:50:47 2005 @@ -0,0 +1,172 @@ +/* + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.tomcat.util.net; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.Hashtable; + +/** + * This class creates server sockets. It may be subclassed by other + * factories, which create particular types of server sockets. This + * provides a general framework for the addition of public socket-level + * functionality. It it is the server side analogue of a socket factory, + * and similarly provides a way to capture a variety of policies related + * to the sockets being constructed. + * + * <P> Like socket factories, Server Socket factory instances have two + * categories of methods. First are methods used to create sockets. + * Second are methods which set properties used in the production of + * sockets, such as networking options. There is also an environment + * specific default server socket factory; frameworks will often use + * their own customized factory. + * + * <P><hr><em> It may be desirable to move this interface into the + * <b>java.net</b> package, so that is not an extension but the preferred + * interface. Should this be serializable, making it a JavaBean which can + * be saved along with its networking configuration? + * </em> + * + * @author [EMAIL PROTECTED] + * @author Harish Prabandham + */ +public abstract class ServerSocketFactory implements Cloneable { + + // + // NOTE: JDK 1.1 bug in class GC, this can get collected + // even though it's always accessible via getDefault(). + // + + private static ServerSocketFactory theFactory; + protected Hashtable attributes=new Hashtable(); + + /** + * Constructor is used only by subclasses. + */ + + protected ServerSocketFactory () { + /* NOTHING */ + } + + /** General mechanism to pass attributes from the + * ServerConnector to the socket factory. + * + * Note that the "prefered" mechanism is to + * use bean setters and explicit methods, but + * this allows easy configuration via server.xml + * or simple Properties + */ + public void setAttribute( String name, Object value ) { + if( name!=null && value !=null) + attributes.put( name, value ); + } + + /** + * Returns a copy of the environment's default socket factory. + */ + public static synchronized ServerSocketFactory getDefault () { + // + // optimize typical case: no synch needed + // + + if (theFactory == null) { + // + // Different implementations of this method could + // work rather differently. For example, driving + // this from a system property, or using a different + // implementation than JavaSoft's. + // + + theFactory = new DefaultServerSocketFactory (); + } + + try { + return (ServerSocketFactory) theFactory.clone (); + } catch (CloneNotSupportedException e) { + throw new RuntimeException (e.getMessage ()); + } + } + + /** + * Returns a server socket which uses all network interfaces on + * the host, and is bound to a the specified port. The socket is + * configured with the socket options (such as accept timeout) + * given to this factory. + * + * @param port the port to listen to + * @exception IOException for networking errors + * @exception InstantiationException for construction errors + */ + public abstract ServerSocket createSocket (int port) + throws IOException, InstantiationException; + + /** + * Returns a server socket which uses all network interfaces on + * the host, is bound to a the specified port, and uses the + * specified connection backlog. The socket is configured with + * the socket options (such as accept timeout) given to this factory. + * + * @param port the port to listen to + * @param backlog how many connections are queued + * @exception IOException for networking errors + * @exception InstantiationException for construction errors + */ + + public abstract ServerSocket createSocket (int port, int backlog) + throws IOException, InstantiationException; + + /** + * Returns a server socket which uses only the specified network + * interface on the local host, is bound to a the specified port, + * and uses the specified connection backlog. The socket is configured + * with the socket options (such as accept timeout) given to this factory. + * + * @param port the port to listen to + * @param backlog how many connections are queued + * @param ifAddress the network interface address to use + * @exception IOException for networking errors + * @exception InstantiationException for construction errors + */ + + public abstract ServerSocket createSocket (int port, + int backlog, InetAddress ifAddress) + throws IOException, InstantiationException; + + public void initSocket( Socket s ) { + } + + /** + Wrapper function for accept(). This allows us to trap and + translate exceptions if necessary + + @exception IOException; + */ + public abstract Socket acceptSocket(ServerSocket socket) + throws IOException; + + /** + Extra function to initiate the handshake. Sometimes necessary + for SSL + + @exception IOException; + */ + public abstract void handshake(Socket sock) + throws IOException; +} + Added: tomcat/sandbox/java/org/apache/tomcat/util/net/TcpConnection.java URL: http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/tomcat/util/net/TcpConnection.java?rev=345653&view=auto ============================================================================== --- tomcat/sandbox/java/org/apache/tomcat/util/net/TcpConnection.java (added) +++ tomcat/sandbox/java/org/apache/tomcat/util/net/TcpConnection.java Sat Nov 19 08:50:47 2005 @@ -0,0 +1,109 @@ +/* + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.tomcat.util.net; + +import java.io.IOException; +import java.io.InputStream; +import java.net.Socket; + +/** + * + */ +public class TcpConnection { // implements Endpoint { + /** + * Maxium number of times to clear the socket input buffer. + */ + static int MAX_SHUTDOWN_TRIES=20; + + public TcpConnection() { + } + + // -------------------- Properties -------------------- + + PoolTcpEndpoint endpoint; + Socket socket; + + public static void setMaxShutdownTries(int mst) { + MAX_SHUTDOWN_TRIES = mst; + } + public void setEndpoint(PoolTcpEndpoint endpoint) { + this.endpoint = endpoint; + } + + public PoolTcpEndpoint getEndpoint() { + return endpoint; + } + + public void setSocket(Socket socket) { + this.socket=socket; + } + + public Socket getSocket() { + return socket; + } + + public void recycle() { + endpoint = null; + socket = null; + } + + // Another frequent repetition + public static int readLine(InputStream in, byte[] b, int off, int len) + throws IOException + { + if (len <= 0) { + return 0; + } + int count = 0, c; + + while ((c = in.read()) != -1) { + b[off++] = (byte)c; + count++; + if (c == '\n' || count == len) { + break; + } + } + return count > 0 ? count : -1; + } + + + // Usefull stuff - avoid having it replicated everywhere + public static void shutdownInput(Socket socket) + throws IOException + { + try { + InputStream is = socket.getInputStream(); + int available = is.available (); + int count=0; + + // XXX on JDK 1.3 just socket.shutdownInput () which + // was added just to deal with such issues. + + // skip any unread (bogus) bytes + while (available > 0 && count++ < MAX_SHUTDOWN_TRIES) { + is.skip (available); + available = is.available(); + } + }catch(NullPointerException npe) { + // do nothing - we are just cleaning up, this is + // a workaround for Netscape \n\r in POST - it is supposed + // to be ignored + } + } +} + + Added: tomcat/sandbox/java/org/apache/tomcat/util/net/TcpConnectionHandler.java URL: http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/tomcat/util/net/TcpConnectionHandler.java?rev=345653&view=auto ============================================================================== --- tomcat/sandbox/java/org/apache/tomcat/util/net/TcpConnectionHandler.java (added) +++ tomcat/sandbox/java/org/apache/tomcat/util/net/TcpConnectionHandler.java Sat Nov 19 08:50:47 2005 @@ -0,0 +1,65 @@ +/* + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.tomcat.util.net; + + +/** + * This interface will be implemented by any object that + * uses TcpConnections. It is supported by the pool tcp + * connection manager and should be supported by future + * managers. + * The goal is to decouple the connection handler from + * the thread, socket and pooling complexity. + */ +public interface TcpConnectionHandler { + + /** Add informations about the a "controler" object + * specific to the server. In tomcat it will be a + * ContextManager. + * @deprecated This has nothing to do with TcpHandling, + * was used as a workaround + */ + public void setServer(Object manager); + + + /** Used to pass config informations to the handler. + * + * @deprecated This has nothing to do with Tcp, + * was used as a workaround. + */ + public void setAttribute(String name, Object value ); + + /** Called before the call to processConnection. + * If the thread is reused, init() should be called once per thread. + * + * It may look strange, but it's a _very_ good way to avoid synchronized + * methods and keep per thread data. + * + * Assert: the object returned from init() will be passed to + * all processConnection() methods happening in the same thread. + * + */ + public Object[] init( ); + + /** + * Assert: connection!=null + * Assert: connection.getSocket() != null + * Assert: thData != null and is the result of calling init() + * Assert: thData is preserved per Thread. + */ + public void processConnection(TcpConnection connection, Object thData[]); +} Added: tomcat/sandbox/java/org/apache/tomcat/util/net/URL.java URL: http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/tomcat/util/net/URL.java?rev=345653&view=auto ============================================================================== --- tomcat/sandbox/java/org/apache/tomcat/util/net/URL.java (added) +++ tomcat/sandbox/java/org/apache/tomcat/util/net/URL.java Sat Nov 19 08:50:47 2005 @@ -0,0 +1,731 @@ +/* + * Copyright 1999-2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.tomcat.util.net; + + +import java.io.Serializable; +import java.net.MalformedURLException; + + +/** + * <p><strong>URL</strong> is designed to provide public APIs for parsing + * and synthesizing Uniform Resource Locators as similar as possible to the + * APIs of <code>java.net.URL</code>, but without the ability to open a + * stream or connection. One of the consequences of this is that you can + * construct URLs for protocols for which a URLStreamHandler is not + * available (such as an "https" URL when JSSE is not installed).</p> + * + * <p><strong>WARNING</strong> - This class assumes that the string + * representation of a URL conforms to the <code>spec</code> argument + * as described in RFC 2396 "Uniform Resource Identifiers: Generic Syntax": + * <pre> + * <scheme>//<authority><path>?<query>#<fragment> + * </pre></p> + * + * <p><strong>FIXME</strong> - This class really ought to end up in a Commons + * package someplace.</p> + * + * @author Craig R. McClanahan + * @version $Revision: 299472 $ $Date: 2004-06-19 17:08:15 -0700 (Sat, 19 Jun 2004) $ + */ + +public final class URL implements Serializable { + + + // ----------------------------------------------------------- Constructors + + + /** + * Create a URL object from the specified String representation. + * + * @param spec String representation of the URL + * + * @exception MalformedURLException if the string representation + * cannot be parsed successfully + */ + public URL(String spec) throws MalformedURLException { + + this(null, spec); + + } + + + /** + * Create a URL object by parsing a string representation relative + * to a specified context. Based on logic from JDK 1.3.1's + * <code>java.net.URL</code>. + * + * @param context URL against which the relative representation + * is resolved + * @param spec String representation of the URL (usually relative) + * + * @exception MalformedURLException if the string representation + * cannot be parsed successfully + */ + public URL(URL context, String spec) throws MalformedURLException { + + String original = spec; + int i, limit, c; + int start = 0; + String newProtocol = null; + boolean aRef = false; + + try { + + // Eliminate leading and trailing whitespace + limit = spec.length(); + while ((limit > 0) && (spec.charAt(limit - 1) <= ' ')) { + limit--; + } + while ((start < limit) && (spec.charAt(start) <= ' ')) { + start++; + } + + // If the string representation starts with "url:", skip it + if (spec.regionMatches(true, start, "url:", 0, 4)) { + start += 4; + } + + // Is this a ref relative to the context URL? + if ((start < spec.length()) && (spec.charAt(start) == '#')) { + aRef = true; + } + + // Parse out the new protocol + for (i = start; !aRef && (i < limit) ; i++) { + c = spec.charAt(i); + if (c == ':') { + String s = spec.substring(start, i).toLowerCase(); + // Assume all protocols are valid + newProtocol = s; + start = i + 1; + break; + } else if( c == '#' ) { + aRef = true; + } else if( !isSchemeChar((char)c) ) { + break; + } + } + + // Only use our context if the protocols match + protocol = newProtocol; + if ((context != null) && ((newProtocol == null) || + newProtocol.equalsIgnoreCase(context.getProtocol()))) { + // If the context is a hierarchical URL scheme and the spec + // contains a matching scheme then maintain backwards + // compatibility and treat it as if the spec didn't contain + // the scheme; see 5.2.3 of RFC2396 + if ((context.getPath() != null) && + (context.getPath().startsWith("/"))) + newProtocol = null; + if (newProtocol == null) { + protocol = context.getProtocol(); + authority = context.getAuthority(); + userInfo = context.getUserInfo(); + host = context.getHost(); + port = context.getPort(); + file = context.getFile(); + int question = file.lastIndexOf("?"); + if (question < 0) + path = file; + else + path = file.substring(0, question); + } + } + + if (protocol == null) + throw new MalformedURLException("no protocol: " + original); + + // Parse out any ref portion of the spec + i = spec.indexOf('#', start); + if (i >= 0) { + ref = spec.substring(i + 1, limit); + limit = i; + } + + // Parse the remainder of the spec in a protocol-specific fashion + parse(spec, start, limit); + if (context != null) + normalize(); + + + } catch (MalformedURLException e) { + throw e; + } catch (Exception e) { + throw new MalformedURLException(e.toString()); + } + + } + + + + + + /** + * Create a URL object from the specified components. The default port + * number for the specified protocol will be used. + * + * @param protocol Name of the protocol to use + * @param host Name of the host addressed by this protocol + * @param file Filename on the specified host + * + * @exception MalformedURLException is never thrown, but present for + * compatible APIs + */ + public URL(String protocol, String host, String file) + throws MalformedURLException { + + this(protocol, host, -1, file); + + } + + + /** + * Create a URL object from the specified components. Specifying a port + * number of -1 indicates that the URL should use the default port for + * that protocol. Based on logic from JDK 1.3.1's + * <code>java.net.URL</code>. + * + * @param protocol Name of the protocol to use + * @param host Name of the host addressed by this protocol + * @param port Port number, or -1 for the default port for this protocol + * @param file Filename on the specified host + * + * @exception MalformedURLException is never thrown, but present for + * compatible APIs + */ + public URL(String protocol, String host, int port, String file) + throws MalformedURLException { + + this.protocol = protocol; + this.host = host; + this.port = port; + + int hash = file.indexOf('#'); + this.file = hash < 0 ? file : file.substring(0, hash); + this.ref = hash < 0 ? null : file.substring(hash + 1); + int question = file.lastIndexOf('?'); + if (question >= 0) { + query = file.substring(question + 1); + path = file.substring(0, question); + } else + path = file; + + if ((host != null) && (host.length() > 0)) + authority = (port == -1) ? host : host + ":" + port; + + } + + + // ----------------------------------------------------- Instance Variables + + + /** + * The authority part of the URL. + */ + private String authority = null; + + + /** + * The filename part of the URL. + */ + private String file = null; + + + /** + * The host name part of the URL. + */ + private String host = null; + + + /** + * The path part of the URL. + */ + private String path = null; + + + /** + * The port number part of the URL. + */ + private int port = -1; + + + /** + * The protocol name part of the URL. + */ + private String protocol = null; + + + /** + * The query part of the URL. + */ + private String query = null; + + + /** + * The reference part of the URL. + */ + private String ref = null; + + + /** + * The user info part of the URL. + */ + private String userInfo = null; + + + // --------------------------------------------------------- Public Methods + + + /** + * Compare two URLs for equality. The result is <code>true</code> if and + * only if the argument is not null, and is a <code>URL</code> object + * that represents the same <code>URL</code> as this object. Two + * <code>URLs</code> are equal if they have the same protocol and + * reference the same host, the same port number on the host, + * and the same file and anchor on the host. + * + * @param obj The URL to compare against + */ + public boolean equals(Object obj) { + + if (obj == null) + return (false); + if (!(obj instanceof URL)) + return (false); + URL other = (URL) obj; + if (!sameFile(other)) + return (false); + return (compare(ref, other.getRef())); + + } + + + /** + * Return the authority part of the URL. + */ + public String getAuthority() { + + return (this.authority); + + } + + + /** + * Return the filename part of the URL. <strong>NOTE</strong> - For + * compatibility with <code>java.net.URL</code>, this value includes + * the query string if there was one. For just the path portion, + * call <code>getPath()</code> instead. + */ + public String getFile() { + + if (file == null) + return (""); + return (this.file); + + } + + + /** + * Return the host name part of the URL. + */ + public String getHost() { + + return (this.host); + + } + + + /** + * Return the path part of the URL. + */ + public String getPath() { + + if (this.path == null) + return (""); + return (this.path); + + } + + + /** + * Return the port number part of the URL. + */ + public int getPort() { + + return (this.port); + + } + + + /** + * Return the protocol name part of the URL. + */ + public String getProtocol() { + + return (this.protocol); + + } + + + /** + * Return the query part of the URL. + */ + public String getQuery() { + + return (this.query); + + } + + + /** + * Return the reference part of the URL. + */ + public String getRef() { + + return (this.ref); + + } + + + /** + * Return the user info part of the URL. + */ + public String getUserInfo() { + + return (this.userInfo); + + } + + + /** + * Normalize the <code>path</code> (and therefore <code>file</code>) + * portions of this URL. + * <p> + * <strong>NOTE</strong> - This method is not part of the public API + * of <code>java.net.URL</code>, but is provided as a value added + * service of this implementation. + * + * @exception MalformedURLException if a normalization error occurs, + * such as trying to move about the hierarchical root + */ + public void normalize() throws MalformedURLException { + + // Special case for null path + if (path == null) { + if (query != null) + file = "?" + query; + else + file = ""; + return; + } + + // Create a place for the normalized path + String normalized = path; + if (normalized.equals("/.")) { + path = "/"; + if (query != null) + file = path + "?" + query; + else + file = path; + return; + } + + // Normalize the slashes and add leading slash if necessary + if (normalized.indexOf('\\') >= 0) + normalized = normalized.replace('\\', '/'); + if (!normalized.startsWith("/")) + normalized = "/" + normalized; + + // Resolve occurrences of "//" in the normalized path + while (true) { + int index = normalized.indexOf("//"); + if (index < 0) + break; + normalized = normalized.substring(0, index) + + normalized.substring(index + 1); + } + + // Resolve occurrences of "/./" in the normalized path + while (true) { + int index = normalized.indexOf("/./"); + if (index < 0) + break; + normalized = normalized.substring(0, index) + + normalized.substring(index + 2); + } + + // Resolve occurrences of "/../" in the normalized path + while (true) { + int index = normalized.indexOf("/../"); + if (index < 0) + break; + if (index == 0) + throw new MalformedURLException + ("Invalid relative URL reference"); + int index2 = normalized.lastIndexOf('/', index - 1); + normalized = normalized.substring(0, index2) + + normalized.substring(index + 3); + } + + // Resolve occurrences of "/." at the end of the normalized path + if (normalized.endsWith("/.")) + normalized = normalized.substring(0, normalized.length() - 1); + + // Resolve occurrences of "/.." at the end of the normalized path + if (normalized.endsWith("/..")) { + int index = normalized.length() - 3; + int index2 = normalized.lastIndexOf('/', index - 1); + if (index2 < 0) + throw new MalformedURLException + ("Invalid relative URL reference"); + normalized = normalized.substring(0, index2 + 1); + } + + // Return the normalized path that we have completed + path = normalized; + if (query != null) + file = path + "?" + query; + else + file = path; + + } + + + /** + * Compare two URLs, excluding the "ref" fields. Returns <code>true</code> + * if this <code>URL</code> and the <code>other</code> argument both refer + * to the same resource. The two <code>URLs</code> might not both contain + * the same anchor. + */ + public boolean sameFile(URL other) { + + if (!compare(protocol, other.getProtocol())) + return (false); + if (!compare(host, other.getHost())) + return (false); + if (port != other.getPort()) + return (false); + if (!compare(file, other.getFile())) + return (false); + return (true); + + } + + + /** + * Return a string representation of this URL. This follow the rules in + * RFC 2396, Section 5.2, Step 7. + */ + public String toExternalForm() { + + StringBuffer sb = new StringBuffer(); + if (protocol != null) { + sb.append(protocol); + sb.append(":"); + } + if (authority != null) { + sb.append("//"); + sb.append(authority); + } + if (path != null) + sb.append(path); + if (query != null) { + sb.append('?'); + sb.append(query); + } + if (ref != null) { + sb.append('#'); + sb.append(ref); + } + return (sb.toString()); + + } + + + /** + * Return a string representation of this object. + */ + public String toString() { + + StringBuffer sb = new StringBuffer("URL["); + sb.append("authority="); + sb.append(authority); + sb.append(", file="); + sb.append(file); + sb.append(", host="); + sb.append(host); + sb.append(", port="); + sb.append(port); + sb.append(", protocol="); + sb.append(protocol); + sb.append(", query="); + sb.append(query); + sb.append(", ref="); + sb.append(ref); + sb.append(", userInfo="); + sb.append(userInfo); + sb.append("]"); + return (sb.toString()); + + // return (toExternalForm()); + + } + + + // -------------------------------------------------------- Private Methods + + + /** + * Compare to String values for equality, taking appropriate care if one + * or both of the values are <code>null</code>. + * + * @param first First string + * @param second Second string + */ + private boolean compare(String first, String second) { + + if (first == null) { + if (second == null) + return (true); + else + return (false); + } else { + if (second == null) + return (false); + else + return (first.equals(second)); + } + + } + + + /** + * Parse the specified portion of the string representation of a URL, + * assuming that it has a format similar to that for <code>http</code>. + * + * <p><strong>FIXME</strong> - This algorithm can undoubtedly be optimized + * for performance. However, that needs to wait until after sufficient + * unit tests are implemented to guarantee correct behavior with no + * regressions.</p> + * + * @param spec String representation being parsed + * @param start Starting offset, which will be just after the ':' (if + * there is one) that determined the protocol name + * @param limit Ending position, which will be the position of the '#' + * (if there is one) that delimited the anchor + * + * @exception MalformedURLException if a parsing error occurs + */ + private void parse(String spec, int start, int limit) + throws MalformedURLException { + + // Trim the query string (if any) off the tail end + int question = spec.lastIndexOf('?', limit - 1); + if ((question >= 0) && (question < limit)) { + query = spec.substring(question + 1, limit); + limit = question; + } else { + query = null; + } + + // Parse the authority section + if (spec.indexOf("//", start) == start) { + int pathStart = spec.indexOf("/", start + 2); + if ((pathStart >= 0) && (pathStart < limit)) { + authority = spec.substring(start + 2, pathStart); + start = pathStart; + } else { + authority = spec.substring(start + 2, limit); + start = limit; + } + if (authority.length() > 0) { + int at = authority.indexOf('@'); + if( at >= 0 ) { + userInfo = authority.substring(0,at); + } + int ipv6 = authority.indexOf('[',at+1); + int hStart = at+1; + if( ipv6 >= 0 ) { + hStart = ipv6; + ipv6 = authority.indexOf(']', ipv6); + if( ipv6 < 0 ) { + throw new MalformedURLException( + "Closing ']' not found in IPV6 address: " + authority); + } else { + at = ipv6-1; + } + } + + int colon = authority.indexOf(':', at+1); + if (colon >= 0) { + try { + port = + Integer.parseInt(authority.substring(colon + 1)); + } catch (NumberFormatException e) { + throw new MalformedURLException(e.toString()); + } + host = authority.substring(hStart, colon); + } else { + host = authority.substring(hStart); + port = -1; + } + } + } + + // Parse the path section + if (spec.indexOf("/", start) == start) { // Absolute path + path = spec.substring(start, limit); + if (query != null) + file = path + "?" + query; + else + file = path; + return; + } + + // Resolve relative path against our context's file + if (path == null) { + if (query != null) + file = "?" + query; + else + file = null; + return; + } + if (!path.startsWith("/")) + throw new MalformedURLException + ("Base path does not start with '/'"); + if (!path.endsWith("/")) + path += "/../"; + path += spec.substring(start, limit); + if (query != null) + file = path + "?" + query; + else + file = path; + return; + + } + + /** + * Determine if the character is allowed in the scheme of a URI. + * See RFC 2396, Section 3.1 + */ + public static boolean isSchemeChar(char c) { + return Character.isLetterOrDigit(c) || + c == '+' || c == '-' || c == '.'; + } + +} Added: tomcat/sandbox/java/org/apache/tomcat/util/net/res/LocalStrings.properties URL: http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/tomcat/util/net/res/LocalStrings.properties?rev=345653&view=auto ============================================================================== --- tomcat/sandbox/java/org/apache/tomcat/util/net/res/LocalStrings.properties (added) +++ tomcat/sandbox/java/org/apache/tomcat/util/net/res/LocalStrings.properties Sat Nov 19 08:50:47 2005 @@ -0,0 +1,24 @@ +# net resources +endpoint.err.fatal=Endpoint {0} shutdown due to exception: {1} +endpoint.err.nonfatal=Endpoint {0} ignored exception: {1} +endpoint.warn.reinit=Reinitializing ServerSocket +endpoint.warn.restart=Restarting endpoint +endpoint.warn.security=Endpoint {0} security exception: {1} +endpoint.err.socket=Socket error caused by remote host {0} +endpoint.err.handshake=Handshake failed +endpoint.err.unexpected=Unexpected error processing socket +endpoint.warn.nullSocket=Null socket returned by accept +endpoint.debug.unlock=Caught exception trying to unlock accept on port {0} +endpoint.err.close=Caught exception trying to close socket +endpoint.noProcessor=No Processors - worker thread dead! +endpoint.init.bind=Socket bind failed: {0} +endpoint.init.listen=Socket listen failed: {0} + +endpoint.accept.fail=Socket accept failed +endpoint.poll.limitedpollsize=Failed to create poller with specified size, uses 62 instead +endpoint.poll.initfail=Poller creation failed +endpoint.poll.fail=Critical poller failure ({0}), restarting poller +endpoint.poll.error=Unexpected poller error +endpoint.sendfile.error=Unexpected sendfile error +endpoint.sendfile.addfail=Sednfile failure with status {0} +endpoint.sendfile.nosupport=Disabling sendfile, since either the APR version or the system doesn't support it Added: tomcat/sandbox/java/org/apache/tomcat/util/net/res/LocalStrings_es.properties URL: http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/tomcat/util/net/res/LocalStrings_es.properties?rev=345653&view=auto ============================================================================== --- tomcat/sandbox/java/org/apache/tomcat/util/net/res/LocalStrings_es.properties (added) +++ tomcat/sandbox/java/org/apache/tomcat/util/net/res/LocalStrings_es.properties Sat Nov 19 08:50:47 2005 @@ -0,0 +1,6 @@ +# net resources +endpoint.err.fatal=Punto Final (Endpoint) {0} parado debido a excepción: {1} +endpoint.err.nonfatal=El Punto Final (Endpoint) {0} ignoró excepción: {1} +endpoint.warn.reinit=Reinicializando ServerSocket +endpoint.warn.restart=Rearrancando punto final (endpoint) +endpoint.warn.security=Punto Final (Endpoint) {0} con excepción de seguridad: {1} Added: tomcat/sandbox/java/org/apache/tomcat/util/net/res/LocalStrings_fr.properties URL: http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/tomcat/util/net/res/LocalStrings_fr.properties?rev=345653&view=auto ============================================================================== --- tomcat/sandbox/java/org/apache/tomcat/util/net/res/LocalStrings_fr.properties (added) +++ tomcat/sandbox/java/org/apache/tomcat/util/net/res/LocalStrings_fr.properties Sat Nov 19 08:50:47 2005 @@ -0,0 +1,6 @@ +# net resources +endpoint.err.fatal=Le point de contact {0} a été éteint suite à l''exception{1} +endpoint.err.nonfatal=Le point de contact {0} a ignoré l''exception: {1} +endpoint.warn.reinit=Réinitialisation du ServerSocket +endpoint.warn.restart=Redémarrage du point de contact + Added: tomcat/sandbox/java/org/apache/tomcat/util/net/res/LocalStrings_ja.properties URL: http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/tomcat/util/net/res/LocalStrings_ja.properties?rev=345653&view=auto ============================================================================== --- tomcat/sandbox/java/org/apache/tomcat/util/net/res/LocalStrings_ja.properties (added) +++ tomcat/sandbox/java/org/apache/tomcat/util/net/res/LocalStrings_ja.properties Sat Nov 19 08:50:47 2005 @@ -0,0 +1,6 @@ +# net resources +endpoint.err.fatal=\u4f8b\u5916\u306e\u305f\u3081\u306b\u30a8\u30f3\u30c9\u30dd\u30a4\u30f3\u30c8 {0} \u306f\u30b7\u30e3\u30c3\u30c8\u30c0\u30a6\u30f3\u3057\u307e\u3059: {1} +endpoint.err.nonfatal=\u30a8\u30f3\u30c9\u30dd\u30a4\u30f3\u30c8 {0} \u306f\u4f8b\u5916\u3092\u7121\u8996\u3057\u307e\u3057\u305f: {1} +endpoint.warn.reinit=ServerSocket\u3092\u518d\u521d\u671f\u5316\u3057\u307e\u3059 +endpoint.warn.restart=\u30a8\u30f3\u30c9\u30dd\u30a4\u30f3\u30c8\u3092\u518d\u8d77\u52d5\u3057\u307e\u3059 +endpoint.warn.security=\u30a8\u30f3\u30c9\u30dd\u30a4\u30f3\u30c8 {0} \u306e\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u4f8b\u5916\u3067\u3059: {1} --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]