Add original URI.java source
This commit is contained in:
982
apps/jetty/java/src/org/mortbay/util/URI.java
Normal file
982
apps/jetty/java/src/org/mortbay/util/URI.java
Normal file
@ -0,0 +1,982 @@
|
||||
// ========================================================================
|
||||
// $Id: URI.java,v 1.40 2009/05/16 02:02:00 gregwilkins Exp $
|
||||
// Copyright 199-2004 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// 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.mortbay.util;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.mortbay.log.LogFactory;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** URI Holder.
|
||||
* This class assists with the decoding and encoding or HTTP URI's.
|
||||
* It differs from the java.net.URL class as it does not provide
|
||||
* communications ability, but it does assist with query string
|
||||
* formatting.
|
||||
* <P>ISO_8859_1 encoding is used by default for % encoded characters. This
|
||||
* may be overridden with the org.mortbay.util.URI.charset system property.
|
||||
* @see UrlEncoded
|
||||
* @version $Id: URI.java,v 1.40 2009/05/16 02:02:00 gregwilkins Exp $
|
||||
* @author Greg Wilkins (gregw)
|
||||
*/
|
||||
public class URI
|
||||
implements Cloneable
|
||||
{
|
||||
private static Log log = LogFactory.getLog(URI.class);
|
||||
|
||||
public static final String __CHARSET=System.getProperty("org.mortbay.util.URI.charset",StringUtil.__UTF_8);
|
||||
public static final boolean __CHARSET_IS_DEFAULT=__CHARSET.equals(StringUtil.__UTF_8);
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
private String _uri;
|
||||
private String _scheme;
|
||||
private String _host;
|
||||
private int _port;
|
||||
private String _path;
|
||||
private String _encodedPath;
|
||||
private String _query;
|
||||
private UrlEncoded _parameters;
|
||||
private boolean _dirty;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Copy Constructor .
|
||||
* @param uri
|
||||
*/
|
||||
public URI(URI uri)
|
||||
throws IllegalArgumentException
|
||||
{
|
||||
_uri=uri.toString();
|
||||
_scheme=uri._scheme;
|
||||
_host=uri._host;
|
||||
_port=uri._port;
|
||||
_path=uri._path;
|
||||
_encodedPath=uri._encodedPath;
|
||||
_query=uri._query;
|
||||
if (uri._parameters!=null)
|
||||
_parameters=(UrlEncoded)uri._parameters.clone();
|
||||
_dirty=false;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Construct from a String.
|
||||
* The string must contain a URI path, but optionaly may contain a
|
||||
* scheme, host, port and query string.
|
||||
*
|
||||
* @param uri [scheme://host[:port]]/path[?query]
|
||||
*/
|
||||
public URI(String uri)
|
||||
throws IllegalArgumentException
|
||||
{
|
||||
setURI(uri);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setURI(String uri)
|
||||
throws IllegalArgumentException
|
||||
{
|
||||
try
|
||||
{
|
||||
_uri=uri;
|
||||
_scheme=null;
|
||||
_host=null;
|
||||
_port=0;
|
||||
_path=null;
|
||||
_encodedPath=null;
|
||||
_query=null;
|
||||
if (_parameters!=null)
|
||||
_parameters.clear();
|
||||
|
||||
// Scan _uri for host, port, path & query
|
||||
int maxi=uri.length()-1;
|
||||
int mark=0;
|
||||
int state=0;
|
||||
int i=0;
|
||||
|
||||
if (maxi==0 || uri.charAt(0)=='/' && uri.charAt(1)!='/')
|
||||
{
|
||||
state=3;
|
||||
_scheme=null;
|
||||
_host=null;
|
||||
_port=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i=0;state<3 && i<=maxi;i++)
|
||||
{
|
||||
char c=uri.charAt(i);
|
||||
switch(state)
|
||||
{
|
||||
case 0: // looking for scheme or path
|
||||
if (c==':' &&
|
||||
uri.charAt(i+1)=='/' &&
|
||||
uri.charAt(i+2)=='/')
|
||||
{
|
||||
// found end of scheme & start of host
|
||||
_scheme=uri.substring(mark,i);
|
||||
i+=2;
|
||||
mark=i+1;
|
||||
state=1;
|
||||
}
|
||||
else if (i==0 && c=='/')
|
||||
{
|
||||
// Found path
|
||||
state=3;
|
||||
}
|
||||
else if (i==0 && c=='*')
|
||||
{
|
||||
state=5;
|
||||
_path="*";
|
||||
_encodedPath="*";
|
||||
}
|
||||
continue;
|
||||
|
||||
case 1: // Get host & look for port or path
|
||||
if (c==':')
|
||||
{
|
||||
// found port
|
||||
_host=uri.substring(mark,i);
|
||||
mark=i+1;
|
||||
state=2;
|
||||
}
|
||||
else if (c=='/')
|
||||
{
|
||||
// found path
|
||||
_host=uri.substring(mark,i);
|
||||
mark=i;
|
||||
state=3;
|
||||
}
|
||||
continue;
|
||||
|
||||
case 2: // Get port & look for path
|
||||
if (c=='/')
|
||||
{
|
||||
_port=TypeUtil.parseInt(uri,mark,i-mark,10);
|
||||
mark=i;
|
||||
state=3;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// State 3 - Get path & look for query
|
||||
_query=null;
|
||||
for (i++;i<=maxi;i++)
|
||||
{
|
||||
char c=uri.charAt(i);
|
||||
if (c=='?')
|
||||
{
|
||||
// Found query
|
||||
_encodedPath=uri.substring(mark,i);
|
||||
_path=decodePath(_encodedPath);
|
||||
|
||||
mark=i+1;
|
||||
state=4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// complete last state
|
||||
switch(state)
|
||||
{
|
||||
case 0:
|
||||
_dirty=false;
|
||||
_encodedPath=_uri;
|
||||
_path=decodePath(_encodedPath);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
_dirty=true;
|
||||
_encodedPath="/";
|
||||
_path=_encodedPath;
|
||||
_host=uri.substring(mark);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
_dirty=true;
|
||||
_encodedPath="/";
|
||||
_path=_encodedPath;
|
||||
_port=TypeUtil.parseInt(uri,mark,-1,10);
|
||||
break;
|
||||
case 3:
|
||||
_dirty=(mark==maxi);
|
||||
_encodedPath=uri.substring(mark);
|
||||
_path=decodePath(_encodedPath);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
_dirty=false;
|
||||
if (mark<=maxi)
|
||||
_query=uri.substring(mark);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
_dirty=false;
|
||||
}
|
||||
|
||||
if (_query!=null && _query.length()>0)
|
||||
{
|
||||
if (_parameters==null)
|
||||
_parameters= new UrlEncoded();
|
||||
else
|
||||
_parameters.clear();
|
||||
_parameters.decode(_query,__CHARSET);
|
||||
}
|
||||
else
|
||||
_query=null;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LogSupport.ignore(log,e);
|
||||
throw new IllegalArgumentException("Malformed URI '"+uri+
|
||||
"' : "+e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Is the URI an absolute URL?
|
||||
* @return True if the URI has a scheme or host
|
||||
*/
|
||||
public boolean isAbsolute()
|
||||
{
|
||||
return _scheme!=null || _host!=null;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get the uri scheme.
|
||||
* @return the URI scheme
|
||||
*/
|
||||
public String getScheme()
|
||||
{
|
||||
return _scheme;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Set the uri scheme.
|
||||
* @param scheme the uri scheme
|
||||
*/
|
||||
public void setScheme(String scheme)
|
||||
{
|
||||
_scheme=scheme;
|
||||
_dirty=true;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get the uri host.
|
||||
* @return the URI host
|
||||
*/
|
||||
public String getHost()
|
||||
{
|
||||
return _host;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Set the uri host.
|
||||
* @param host the uri host
|
||||
*/
|
||||
public void setHost(String host)
|
||||
{
|
||||
_host=host;
|
||||
_dirty=true;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get the uri port.
|
||||
* @return the URI port
|
||||
*/
|
||||
public int getPort()
|
||||
{
|
||||
return _port;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Set the uri port.
|
||||
* A port of 0 implies use the default port.
|
||||
* @param port the uri port
|
||||
*/
|
||||
public void setPort(int port)
|
||||
{
|
||||
_port=port;
|
||||
_dirty=true;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get the uri path.
|
||||
* @return the URI path
|
||||
*/
|
||||
public String getPath()
|
||||
{
|
||||
return _path;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get the encoded uri path.
|
||||
* @return the URI path
|
||||
*/
|
||||
public String getEncodedPath()
|
||||
{
|
||||
return _encodedPath;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Set the uri path.
|
||||
* @param path the URI path
|
||||
*/
|
||||
public void setPath(String path)
|
||||
{
|
||||
_path=path;
|
||||
_encodedPath=encodePath(_path);
|
||||
_dirty=true;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get the uri query String.
|
||||
* @return the URI query string
|
||||
*/
|
||||
public String getQuery()
|
||||
{
|
||||
if (_dirty && _parameters!=null)
|
||||
{
|
||||
_query = _parameters.encode(__CHARSET);
|
||||
if (_query!=null && _query.length()==0)
|
||||
_query=null;
|
||||
}
|
||||
return _query;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Set the uri query String.
|
||||
* @param query the URI query string
|
||||
*/
|
||||
public void setQuery(String query)
|
||||
{
|
||||
_query=query;
|
||||
|
||||
if (_parameters!=null)
|
||||
_parameters.clear();
|
||||
else if (query!=null)
|
||||
_parameters=new UrlEncoded();
|
||||
|
||||
if (query!=null)
|
||||
_parameters.decode(query,__CHARSET);
|
||||
|
||||
cleanURI();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get the uri query _parameters names.
|
||||
* @return Unmodifiable set of URI query _parameters names
|
||||
*/
|
||||
public Set getParameterNames()
|
||||
{
|
||||
if (_parameters==null)
|
||||
return Collections.EMPTY_SET;
|
||||
return _parameters.keySet();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get the uri query _parameters.
|
||||
* @return the URI query _parameters
|
||||
*/
|
||||
public MultiMap getParameters()
|
||||
{
|
||||
if (_parameters==null)
|
||||
_parameters=new UrlEncoded();
|
||||
_dirty=true;
|
||||
return _parameters;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get the uri query _parameters.
|
||||
* @return the URI query _parameters in an unmodifiable map.
|
||||
*/
|
||||
public Map getUnmodifiableParameters()
|
||||
{
|
||||
if (_parameters==null)
|
||||
return Collections.EMPTY_MAP;
|
||||
return Collections.unmodifiableMap(_parameters);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Add the uri query _parameters to a MultiMap
|
||||
*/
|
||||
public void putParametersTo(MultiMap map)
|
||||
{
|
||||
if (_parameters!=null && _parameters.size()>0)
|
||||
map.putAll(_parameters);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Clear the URI _parameters.
|
||||
*/
|
||||
public void clearParameters()
|
||||
{
|
||||
if (_parameters!=null)
|
||||
{
|
||||
_dirty=true;
|
||||
_parameters.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Add encoded _parameters.
|
||||
* @param encoded A HTTP encoded string of _parameters: e.g.. "a=1&b=2"
|
||||
*/
|
||||
public void put(String encoded)
|
||||
{
|
||||
UrlEncoded params = new UrlEncoded(encoded);
|
||||
put(params);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Add name value pair to the uri query _parameters.
|
||||
* @param name name of value
|
||||
* @param value The value, which may be a multi valued list or
|
||||
* String array.
|
||||
*/
|
||||
public Object put(Object name, Object value)
|
||||
{
|
||||
return getParameters().put(name,value);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Add dictionary to the uri query _parameters.
|
||||
*/
|
||||
public void put(Map values)
|
||||
{
|
||||
getParameters().putAll(values);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get named value
|
||||
*/
|
||||
public String get(String name)
|
||||
{
|
||||
if (_parameters==null)
|
||||
return null;
|
||||
return (String)_parameters.get(name);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get named multiple values.
|
||||
* @param name The parameter name
|
||||
* @return Umodifiable list of values or null
|
||||
*/
|
||||
public List getValues(String name)
|
||||
{
|
||||
if (_parameters==null)
|
||||
return null;
|
||||
return _parameters.getValues(name);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Remove named value
|
||||
*/
|
||||
public void remove(String name)
|
||||
{
|
||||
if (_parameters!=null)
|
||||
{
|
||||
_dirty=
|
||||
_parameters.remove(name)!=null;
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** @return the URI string encoded.
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
if (_dirty)
|
||||
{
|
||||
getQuery();
|
||||
cleanURI();
|
||||
}
|
||||
return _uri;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
private void cleanURI()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(_uri.length()*2);
|
||||
synchronized(buf)
|
||||
{
|
||||
if (_scheme!=null)
|
||||
{
|
||||
buf.append(_scheme);
|
||||
buf.append("://");
|
||||
buf.append(_host);
|
||||
if (_port>0)
|
||||
{
|
||||
buf.append(':');
|
||||
buf.append(_port);
|
||||
}
|
||||
}
|
||||
|
||||
buf.append(_encodedPath);
|
||||
|
||||
if (_query!=null && _query.length()>0)
|
||||
{
|
||||
buf.append('?');
|
||||
buf.append(_query);
|
||||
}
|
||||
_uri=buf.toString();
|
||||
_dirty=false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Encode a URI path.
|
||||
* This is the same encoding offered by URLEncoder, except that
|
||||
* the '/' character is not encoded.
|
||||
* @param path The path the encode
|
||||
* @return The encoded path
|
||||
*/
|
||||
public static String encodePath(String path)
|
||||
{
|
||||
if (path==null || path.length()==0)
|
||||
return path;
|
||||
|
||||
StringBuffer buf = encodePath(null,path);
|
||||
return buf==null?path:buf.toString();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Encode a URI path.
|
||||
* @param path The path the encode
|
||||
* @param buf StringBuffer to encode path into (or null)
|
||||
* @return The StringBuffer or null if no substitutions required.
|
||||
*/
|
||||
public static StringBuffer encodePath(StringBuffer buf, String path)
|
||||
{
|
||||
if (buf==null)
|
||||
{
|
||||
loop:
|
||||
for (int i=0;i<path.length();i++)
|
||||
{
|
||||
char c=path.charAt(i);
|
||||
switch(c)
|
||||
{
|
||||
case '%':
|
||||
case '?':
|
||||
case ';':
|
||||
case '#':
|
||||
case ' ':
|
||||
buf=new StringBuffer(path.length()<<1);
|
||||
break loop;
|
||||
}
|
||||
}
|
||||
if (buf==null)
|
||||
return null;
|
||||
}
|
||||
|
||||
synchronized(buf)
|
||||
{
|
||||
for (int i=0;i<path.length();i++)
|
||||
{
|
||||
char c=path.charAt(i);
|
||||
switch(c)
|
||||
{
|
||||
case '%':
|
||||
buf.append("%25");
|
||||
continue;
|
||||
case '?':
|
||||
buf.append("%3F");
|
||||
continue;
|
||||
case ';':
|
||||
buf.append("%3B");
|
||||
continue;
|
||||
case '#':
|
||||
buf.append("%23");
|
||||
continue;
|
||||
case ' ':
|
||||
buf.append("%20");
|
||||
continue;
|
||||
default:
|
||||
buf.append(c);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Encode a URI path.
|
||||
* @param path The path the encode
|
||||
* @param buf StringBuffer to encode path into (or null)
|
||||
* @param encode String of characters to encode. % is always encoded.
|
||||
* @return The StringBuffer or null if no substitutions required.
|
||||
*/
|
||||
public static StringBuffer encodeString(StringBuffer buf,
|
||||
String path,
|
||||
String encode)
|
||||
{
|
||||
if (buf==null)
|
||||
{
|
||||
loop:
|
||||
for (int i=0;i<path.length();i++)
|
||||
{
|
||||
char c=path.charAt(i);
|
||||
if (c=='%' || encode.indexOf(c)>=0)
|
||||
{
|
||||
buf=new StringBuffer(path.length()<<1);
|
||||
break loop;
|
||||
}
|
||||
}
|
||||
if (buf==null)
|
||||
return null;
|
||||
}
|
||||
|
||||
synchronized(buf)
|
||||
{
|
||||
for (int i=0;i<path.length();i++)
|
||||
{
|
||||
char c=path.charAt(i);
|
||||
if (c=='%' || encode.indexOf(c)>=0)
|
||||
{
|
||||
buf.append('%');
|
||||
StringUtil.append(buf,(byte)(0xff&c),16);
|
||||
}
|
||||
else
|
||||
buf.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* Decode a URI path.
|
||||
* @param path The path the encode
|
||||
* @param buf StringBuffer to encode path into
|
||||
*/
|
||||
public static String decodePath(String path)
|
||||
{
|
||||
int len=path.length();
|
||||
byte[] bytes=null;
|
||||
int n=0;
|
||||
boolean noDecode=true;
|
||||
|
||||
for (int i=0;i<len;i++)
|
||||
{
|
||||
char c = path.charAt(i);
|
||||
|
||||
byte b = (byte)(0xff & c);
|
||||
|
||||
if (c=='%' && (i+2)<len)
|
||||
{
|
||||
noDecode=false;
|
||||
b=(byte)(0xff&TypeUtil.parseInt(path,i+1,2,16));
|
||||
i+=2;
|
||||
}
|
||||
else if (bytes==null)
|
||||
{
|
||||
n++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bytes==null)
|
||||
{
|
||||
noDecode=false;
|
||||
bytes=new byte[len];
|
||||
for (int j=0;j<n;j++)
|
||||
bytes[j]=(byte)(0xff & path.charAt(j));
|
||||
}
|
||||
|
||||
bytes[n++]=b;
|
||||
}
|
||||
|
||||
if (noDecode)
|
||||
return path;
|
||||
|
||||
try
|
||||
{
|
||||
return new String(bytes,0,n,__CHARSET);
|
||||
}
|
||||
catch(UnsupportedEncodingException e)
|
||||
{
|
||||
log.warn(LogSupport.EXCEPTION,e);
|
||||
return new String(bytes,0,n);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Clone URI.
|
||||
* @return cloned URI
|
||||
*/
|
||||
public Object clone()
|
||||
throws CloneNotSupportedException
|
||||
{
|
||||
URI u = (URI)super.clone();
|
||||
if (_parameters!=null)
|
||||
u._parameters=(UrlEncoded)_parameters.clone();
|
||||
_dirty=false;
|
||||
|
||||
return u;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Add two URI path segments.
|
||||
* Handles null and empty paths, path and query params (eg ?a=b or
|
||||
* ;JSESSIONID=xxx) and avoids duplicate '/'
|
||||
* @param p1 URI path segment
|
||||
* @param p2 URI path segment
|
||||
* @return Legally combined path segments.
|
||||
*/
|
||||
public static String addPaths(String p1, String p2)
|
||||
{
|
||||
if (p1==null || p1.length()==0)
|
||||
{
|
||||
if (p2==null || p2.length()==0)
|
||||
return p1;
|
||||
return p2;
|
||||
}
|
||||
if (p2==null || p2.length()==0)
|
||||
return p1;
|
||||
|
||||
int split=p1.indexOf(';');
|
||||
if (split<0)
|
||||
split=p1.indexOf('?');
|
||||
if (split==0)
|
||||
return p2+p1;
|
||||
if (split<0)
|
||||
split=p1.length();
|
||||
|
||||
StringBuffer buf = new StringBuffer(p1.length()+p2.length()+2);
|
||||
buf.append(p1);
|
||||
|
||||
if (buf.charAt(split-1)=='/')
|
||||
{
|
||||
if (p2.startsWith("/"))
|
||||
{
|
||||
buf.deleteCharAt(split-1);
|
||||
buf.insert(split-1,p2);
|
||||
}
|
||||
else
|
||||
buf.insert(split,p2);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (p2.startsWith("/"))
|
||||
buf.insert(split,p2);
|
||||
else
|
||||
{
|
||||
buf.insert(split,'/');
|
||||
buf.insert(split+1,p2);
|
||||
}
|
||||
}
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Return the parent Path.
|
||||
* Treat a URI like a directory path and return the parent directory.
|
||||
*/
|
||||
public static String parentPath(String p)
|
||||
{
|
||||
if (p==null || "/".equals(p))
|
||||
return null;
|
||||
int slash=p.lastIndexOf('/',p.length()-2);
|
||||
if (slash>=0)
|
||||
return p.substring(0,slash+1);
|
||||
return null;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Strip parameters from a path.
|
||||
* Return path upto any semicolon parameters.
|
||||
*/
|
||||
public static String stripPath(String path)
|
||||
{
|
||||
if (path==null)
|
||||
return null;
|
||||
int semi=path.indexOf(';');
|
||||
if (semi<0)
|
||||
return path;
|
||||
return path.substring(0,semi);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Convert a path to a cananonical form.
|
||||
* All instances of "." and ".." are factored out. Null is returned
|
||||
* if the path tries to .. above it's root.
|
||||
* @param path
|
||||
* @return path or null.
|
||||
*/
|
||||
public static String canonicalPath(String path)
|
||||
{
|
||||
if (path==null || path.length()==0)
|
||||
return path;
|
||||
|
||||
int end=path.length();
|
||||
int start = path.lastIndexOf('/', end);
|
||||
|
||||
search:
|
||||
while (end>0)
|
||||
{
|
||||
switch(end-start)
|
||||
{
|
||||
case 2: // possible single dot
|
||||
if (path.charAt(start+1)!='.')
|
||||
break;
|
||||
break search;
|
||||
case 3: // possible double dot
|
||||
if (path.charAt(start+1)!='.' || path.charAt(start+2)!='.')
|
||||
break;
|
||||
break search;
|
||||
}
|
||||
|
||||
end=start;
|
||||
start=path.lastIndexOf('/',end-1);
|
||||
}
|
||||
|
||||
// If we have checked the entire string
|
||||
if (start>=end)
|
||||
return path;
|
||||
|
||||
StringBuffer buf = new StringBuffer(path);
|
||||
int delStart=-1;
|
||||
int delEnd=-1;
|
||||
int skip=0;
|
||||
|
||||
while (end>0)
|
||||
{
|
||||
switch(end-start)
|
||||
{
|
||||
case 2: // possible single dot
|
||||
if (buf.charAt(start+1)!='.')
|
||||
{
|
||||
if (skip>0 && --skip==0)
|
||||
{
|
||||
delStart=start>=0?start:0;
|
||||
if(delStart>0 && delEnd==buf.length() && buf.charAt(delEnd-1)=='.')
|
||||
delStart++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(start<0 && buf.length()>2 && buf.charAt(1)=='/' && buf.charAt(2)=='/')
|
||||
break;
|
||||
|
||||
if(delEnd<0)
|
||||
delEnd=end;
|
||||
delStart=start;
|
||||
if (delStart<0 || delStart==0&&buf.charAt(delStart)=='/')
|
||||
{
|
||||
delStart++;
|
||||
if (delEnd<buf.length() && buf.charAt(delEnd)=='/')
|
||||
delEnd++;
|
||||
break;
|
||||
}
|
||||
if (end==buf.length())
|
||||
delStart++;
|
||||
|
||||
end=start--;
|
||||
while (start>=0 && buf.charAt(start)!='/')
|
||||
start--;
|
||||
continue;
|
||||
|
||||
case 3: // possible double dot
|
||||
if (buf.charAt(start+1)!='.' || buf.charAt(start+2)!='.')
|
||||
{
|
||||
if (skip>0 && --skip==0)
|
||||
{ delStart=start>=0?start:0;
|
||||
if(delStart>0 && delEnd==buf.length() && buf.charAt(delEnd-1)=='.')
|
||||
delStart++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
delStart=start;
|
||||
if (delEnd<0)
|
||||
delEnd=end;
|
||||
|
||||
skip++;
|
||||
end=start--;
|
||||
while (start>=0 && buf.charAt(start)!='/')
|
||||
start--;
|
||||
continue;
|
||||
|
||||
default:
|
||||
if (skip>0 && --skip==0)
|
||||
{
|
||||
delStart=start>=0?start:0;
|
||||
if(delEnd==buf.length() && buf.charAt(delEnd-1)=='.')
|
||||
delStart++;
|
||||
}
|
||||
}
|
||||
|
||||
// Do the delete
|
||||
if (skip<=0 && delStart>=0 && delStart>=0)
|
||||
{
|
||||
buf.delete(delStart,delEnd);
|
||||
delStart=delEnd=-1;
|
||||
if (skip>0)
|
||||
delEnd=end;
|
||||
}
|
||||
|
||||
end=start--;
|
||||
while (start>=0 && buf.charAt(start)!='/')
|
||||
start--;
|
||||
}
|
||||
|
||||
// Too many ..
|
||||
if (skip>0)
|
||||
return null;
|
||||
|
||||
// Do the delete
|
||||
if (delEnd>=0)
|
||||
buf.delete(delStart,delEnd);
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param uri URI
|
||||
* @return True if the uri has a scheme
|
||||
*/
|
||||
public static boolean hasScheme(String uri)
|
||||
{
|
||||
for (int i=0;i<uri.length();i++)
|
||||
{
|
||||
char c=uri.charAt(i);
|
||||
if (c==':')
|
||||
return true;
|
||||
if (!(c>='a'&&c<='z' ||
|
||||
c>='A'&&c<='Z' ||
|
||||
(i>0 &&(c>='0'&&c<='9' ||
|
||||
c=='.' ||
|
||||
c=='+' ||
|
||||
c=='-'))
|
||||
))
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user