// Copyright (c) 1996-2002 Brian D. Carlstrom
package bdc.util;
import java.io.File;
import java.io.FileNotFoundException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.logging.Level;
public final class URLUtil
{
/* keep people from creating this class */
private URLUtil ()
{
}
/**
Generate a File for a URL.
@param urlContext a URL to open in a file. Assumes URL is of
type file protocol (e.g. file://) and is not null.
@return a File representing the URL, or null if the file
could not be opened
*/
public static File file (URL urlContext, boolean warning)
{
String protocol = urlContext.getProtocol();
if (!protocol.equals("file")) {
if (warning) {
Log.util.log(
Level.WARNING,
"Invalid protocol for use with URLUtil.file(url): {0}",
urlContext);
}
return null;
}
String filePath = urlContext.getFile();
if (filePath.endsWith("/.")) {
filePath = filePath.substring(0, filePath.length() - 1);
}
// interestingly if one constructs a file with invalid
// separatorChar (e.g. '/' on windows) most File members
// work (e.g. exists()) but getParent() does not. Thus we
// have to flip the separator on Windows.
return new File(filePath.replace('/', File.separatorChar));
}
/**
Returns true if the URL may exist.
If the URL is a file: url, we convert it to a File and call
exists(), which is faster than dealing with a
FileNotFoundException.
This is primarily when the file is likely not to exist, such
as in the ResourceService which probes many possible filenames.
*/
public static boolean maybeURLExists (URL url)
{
File file = URLUtil.file(url, false);
if (file == null) {
// it may exist, we aren't sure.
return true;
}
return file.exists();
}
/**
@param context the context in which to parse the
specification.
@param spec a string representation of a URL.
@return a new URL, or null if there was an exception in
the creation
@see java.net.URL#URL(URL, String)
*/
public static URL asURL (URL context, String spec)
{
// Needed for java 1.2 bug - PR 12590
if ("".equals(spec) &&
context != null &&
"file".equals(context.getProtocol()))
{
spec = "./.";
}
try {
return new URL(context, spec);
}
catch (MalformedURLException e) {
Log.util.log(Level.WARNING,
"Could not create URL for {0}: {1}",
new Object[]{ spec, e}
);
return null;
}
}
/**
Creates a URL relative to the application working directory. This
method should only be used within server code or by command line (i.e.
non-GUI) clients.
If you are in GUI code, use Widgets.url().
If you are in shared code, use Base.service().url().
*/
public static URL url (File file)
{
return url(file.getPath());
}
/**
Creates a URL relative to the application working directory. This
method should only be used within server code or by command line (i.e.
non-GUI) clients.
If you are in GUI code, use Widgets.url().
If you are in shared code, use Base.service().url().
*/
public static URL url (String spec)
{
return asURL(url(), spec);
}
/**
Creates a URL for the application working directory. This method
should only be used within server code or by command line clients.
If you are in GUI code, use Application.codeBase().
*/
public static URL url ()
{
return urlAbsolute(SystemUtil.getCwdFile());
}
/**
Creates a URL that references the given file. This method
should only be used within server code or by command line clients.
*/
public static URL urlAbsolute (File file)
{
String filePath = file.getAbsolutePath();
filePath = filePath.replace(File.separatorChar, '/');
if (file.exists() && file.isDirectory()) {
if (filePath.endsWith("/.")) {
filePath = filePath.substring(0, filePath.length() - 1);
}
if (!filePath.endsWith("/")) {
filePath = Fmt.S("%s/", filePath);
}
}
try {
/*
If the file path starts with "/" then don't prepend
one. Adding the extra slash will yield 'file://..."
which causes the first node of the path to be
considered a hostname not part of the path.
*/
if (filePath.startsWith("/")) {
return new URL("file", null, Fmt.S("%s", filePath));
}
else {
return new URL("file", null, Fmt.S("/%s", filePath));
}
}
catch (MalformedURLException e) {
Log.util.log(Level.WARNING,
"Cannot establish base URL {0}: {1}",
new Object[]{filePath, e}
);
return null;
}
}
/**
Returns whether the specified specification is a
fully-qualified URL. The heuristic that we use is to check
whether it contains the string ":/" before any other
slashes. Note: IFC file codebases a prefixed by "file:/".
This is why we check for only one slash.
*/
public static boolean fullyQualifiedURLSpec (String spec)
{
int slash = spec.indexOf("/");
int colon = spec.indexOf(":");
// We have a complete URL if we have a protocol (the first slash
// is preceded by a colon)
return (slash > 0 && colon == slash - 1);
}
/**
Create a URL to a web server. If the url is absolute (includes
http) use it as is.
Otherwise, assume the URL is relative to the context
.
@param url the URL string we are making a URL object for
@param context the root URL
@return a new URL as requested
@exception MalformedURLException
*/
public static URL formURL (String url, String context)
throws MalformedURLException
{
URL completeURL = null;
if (url.indexOf(HTTP.Protocol) == 0) {
completeURL = new URL(url);
}
else {
completeURL = new URL(new URL(Fmt.S("%s/", context)), url);
}
return completeURL;
}
/**
Create a URL from a path and file name. The resulting URL will
be constructed independently of what VM (1.1 or 1.2) is being
used.
@param path the path (either absolute or relative)
@param file the file name.
@return a new URL as requested
*/
public static URL concatURL (String path, String file)
{
String string = Fmt.S("%s/%s", path, file);
try {
return new URL(string);
}
catch (MalformedURLException e) {
Log.util.log(Level.WARNING,
"Could not create URL for {0}: {1}",
new Object[]{string, e}
);
return null;
}
}
}