From: <mar...@us...> - 2017-01-31 17:40:18
|
Revision: 20033 http://sourceforge.net/p/gate/code/20033 Author: markagreenwood Date: 2017-01-31 17:40:16 +0000 (Tue, 31 Jan 2017) Log Message: ----------- simplified the constructors slightly, updated the tests to match, and added a boat load of documentation Modified Paths: -------------- gate/branches/sawdust2/gate-core/src/main/java/gate/creole/ResourceReference.java gate/branches/sawdust2/gate-core/src/test/java/gate/creole/TestResourceReference.java Modified: gate/branches/sawdust2/gate-core/src/main/java/gate/creole/ResourceReference.java =================================================================== --- gate/branches/sawdust2/gate-core/src/main/java/gate/creole/ResourceReference.java 2017-01-31 17:39:47 UTC (rev 20032) +++ gate/branches/sawdust2/gate-core/src/main/java/gate/creole/ResourceReference.java 2017-01-31 17:40:16 UTC (rev 20033) @@ -17,133 +17,231 @@ import java.io.IOException; import java.io.InputStream; import java.io.Serializable; -import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.net.URLConnection; +import org.apache.log4j.Logger; + import gate.Gate; +/** + * This class provides a common way of referencing a resource regardless of + * where it is located. Specifically it allows resources stored within plugins + * to be referenced without needing to know where the resource is actually + * located as that information is determined when the resource is accessed. + * Previously most GATE components used {@link java.net.URL URL} instances to + * refer to resources and to aid in converting existing code to use + * {@code ResourceReference} instead the public API follows that of {@code URL} + * where possible. + */ public class ResourceReference implements Serializable { private static final long serialVersionUID = 2526144106607856721L; + protected static final Logger log = Logger.getLogger(ResourceReference.class); + + // internal we store the location of the resource as a URI, the exact format + // of the URI will depend on numerous factors and no specific URI scheme is + // assumed private URI uri; + /** + * Create a new instance that references a resource accessible via a known + * {@link java.net.URL URL}. While a useful constructor in it's own right this + * also allows old applications that contain URLs as parameters to PRs that + * now take a {@code ResourceReference} to continue to work as the URL will + * get passed into this constructor automatically as the application is + * reloaded. + * + * @param url + * the {@link java.net.URL URL} of the resource you wish to reference + * @throws URISyntaxException + * if the URL does not strictly conform to RFC 2396 or if it cannot + * be converted to an absolute URI + */ public ResourceReference(URL url) throws URISyntaxException { uri = url.toURI(); + + // we only support absolute URIs as there would be no way to access a + // resource at a relative URI as we wouldn't know what to resolve it against + if(!uri.isAbsolute()) + throw new URISyntaxException(uri.toString(), + "We only support absolute URIs"); } - public ResourceReference(URI uri) { + /** + * Create a new instance that references a resource described by a + * {@link java.net.URI URI}. + * + * @param uri + * the {@link java.net.URI URI} of the resource you wish to reference + * @throws URISyntaxException + * if the URI is not absolute + */ + public ResourceReference(URI uri) throws URISyntaxException { this.uri = uri; - } - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((uri == null) ? 0 : uri.hashCode()); - return result; + // we only support absolute URIs as there would be no way to access a + // resource at a relative URI as we wouldn't know what to resolve it against + if(!uri.isAbsolute()) + throw new URISyntaxException(uri.toString(), + "We only support absolute URIs"); } - @Override - public boolean equals(Object obj) { - if(this == obj) return true; - if(obj == null) return false; - if(getClass() != obj.getClass()) return false; - ResourceReference other = (ResourceReference)obj; - if(uri == null) { - if(other.uri != null) return false; - } else if(!uri.equals(other.uri)) return false; - return true; - } - + /** + * Creates a new instance that references a resource within a given + * {@link gate.creole.Plugin Plugin}. + * + * @param plugin + * a {@link gate.creole.Plugin Plugin} against which to resolve the + * path. Can be null, but only if the path can be parsed as an + * absolute URI + * @param path + * the path to the resource which will be resolved against the + * {@link gate.creole.Plugin Plugin} + * @throws URISyntaxException + * if the reference cannot be converted to an absolute URI + */ public ResourceReference(Plugin plugin, String path) throws URISyntaxException { + + // if the path is null this causes problems later but it's safe to use the + // empty string instead so we'll do that if(path == null) path = ""; if(plugin != null) { + // if the plugin isn't null then we can simply resolve the path against + // it's base URI uri = plugin.getBaseURI().resolve(path); } else { + // there is no plugin so we just use the path to create the URI uri = new URI(path); } + // we only support absolute URIs as there would be no way to access a + // resource at a relative URI as we wouldn't know what to resolve it against if(!uri.isAbsolute()) - throw new URISyntaxException(path, - "Context is null and path is not absolute"); + throw new URISyntaxException(path, "We only support absolute URIs"); } - public ResourceReference(URL context, String path) - throws URISyntaxException, MalformedURLException { + /** + * Creates a new instance that references a resource identified by resolving + * the path against an existing {@code ResourceReference}. + * + * @param context + * a {@code ResourceReference} against which to resolve the path. Can + * be null, but only if the path can be parsed as an absolute URI + * @param path + * the path to the resource which will be resolved against the + * context. + * @throws URISyntaxException + * if the reference cannot be converted to an absolute URI + */ + public ResourceReference(ResourceReference context, String path) + throws URISyntaxException { - // not sure if we need this constructor as we could just assume people can - // do the right thing before calling the constructor - - uri = new URI(path); - - if(context != null && !uri.isAbsolute()) { - uri = (new URL(context, path)).toURI(); - } - - if(!uri.isAbsolute()) - throw new URISyntaxException(path, - "Context is null and path is not absolute"); - } - - public ResourceReference(URI context, String path) throws URISyntaxException { - - // not sure if we need this constructor as we could just assume people can - // do the right thing before calling the constructor - if(context != null) { - uri = context.resolve(path); - } else { - uri = new URI(path); - } - - if(!uri.isAbsolute()) - throw new URISyntaxException(path, - "Context is null and path is not absolute"); - } - - public ResourceReference(ResourceReference context, String path) - throws IOException, URISyntaxException { - if(context != null) { + // if a context is provided then try and resolve the path against the + // encapsulated URI uri = context.uri.resolve(path); } else { + // there is no context so we just use the path to create the URI uri = new URI(path); } + // we only support absolute URIs as there would be no way to access a + // resource at a relative URI as we wouldn't know what to resolve it against if(!uri.isAbsolute()) - throw new URISyntaxException(path, - "Context is null and path is not absolute"); + throw new URISyntaxException(path, "We only support absolute URIs"); } + /** + * Opens a connection to this {@code ResourceReference} and returns an + * {@code InputStream} for reading from that connection. This method is a + * shorthand for: <blockquote> + * + * <pre> + * toURL().openConnection().getInputStream() + * </pre> + * + * </blockquote> + * + * @return an input stream for reading from the URL connection. + * @exception IOException + * if an I/O exception occurs. + */ public InputStream openStream() throws IOException { return toURL().openStream(); } + /** + * Returns a {@link java.net.URLConnection URLConnection} instance that + * represents a connection to the resource referred to by this + * {@code ResourceReference}. + * <P> + * It should be noted that a URLConnection instance does not establish the + * actual network connection on creation. This will happen only when calling + * {@linkplain java.net.URLConnection#connect() URLConnection.connect()}. + * </P> + * This method is a shorthand for: <blockquote> + * + * <pre> + * toURL().openConnection() + * </pre> + * + * </blockquote> + * + * @return a {@link java.net.URLConnection URLConnection} linking to the + * underlying resource. + * @exception IOException + * if an I/O exception occurs. + */ public URLConnection openConnection() throws IOException { return toURL().openConnection(); } + /** + * Creates a {@link java,net.URL URL} instance that can be used to access the + * underlying resource. It should be noted that the result is not guaranteed + * to be valid long term and should never be persisted. If you want persistent + * access then store the {@code ResourceReference} instance instead. + * + * @return a {@link java.net.URL URL} that currently gives access to the + * referenced resource. + * @throws IOException + * if an I/O exception occurs. + */ public URL toURL() throws IOException { + // if the URI scheme is anything but creole then let java handle the + // conversion to a URL as it already knows how to do that if(!uri.getScheme().equals("creole")) return uri.toURL(); try { + // create a URI that should point to the base of the plugin in which this + // resource resides URI base = new URI("creole", uri.getAuthority(), "/", null, null); + for(Plugin plugin : Gate.getCreoleRegister().getPlugins()) { + // go through each plugin we know about until.... + if(plugin.getBaseURI().equals(base)) { - // requiring the additional . seems like a hack but I can't figure out - // any other way of doing it + // ... we find one with the base URI we are expecting and then + + // create a new URL using the base URL of the plugin and the path from + // the URI we know points to the resource + // NOTE: requiring the additional . seems like a hack return new URL(plugin.getBaseURL(), "." + uri.getPath()); } } + + // TODO if we can't find the plugin should we try loading it? + } catch(URISyntaxException e) { // this is impossible so ignore it - e.printStackTrace(); + log.debug("An impossible exception case happened, how?", e); } throw new IOException("Unable to locate URI: " + uri); @@ -161,4 +259,24 @@ public String toExternalForm() { return toString(); } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((uri == null) ? 0 : uri.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if(this == obj) return true; + if(obj == null) return false; + if(getClass() != obj.getClass()) return false; + ResourceReference other = (ResourceReference)obj; + if(uri == null) { + if(other.uri != null) return false; + } else if(!uri.equals(other.uri)) return false; + return true; + } } Modified: gate/branches/sawdust2/gate-core/src/test/java/gate/creole/TestResourceReference.java =================================================================== --- gate/branches/sawdust2/gate-core/src/test/java/gate/creole/TestResourceReference.java 2017-01-31 17:39:47 UTC (rev 20032) +++ gate/branches/sawdust2/gate-core/src/test/java/gate/creole/TestResourceReference.java 2017-01-31 17:40:16 UTC (rev 20033) @@ -124,17 +124,14 @@ URL creoleURL = new URL(TestDocument.getTestServerName() + "tests/creole.xml"); - ResourceReference rr = new ResourceReference(testURL, "./creole.xml"); + ResourceReference context = new ResourceReference(testURL); + ResourceReference rr = new ResourceReference(context, "./creole.xml"); assertEquals("References do not match (1)", creoleURL, rr.toURL()); - ResourceReference context = new ResourceReference(testURL); - rr = new ResourceReference(context, "./creole.xml"); - assertEquals("References do not match (2)", creoleURL, rr.toURL()); - Plugin plugin = new Plugin.Directory(testURL); context = new ResourceReference(plugin, "abc"); rr = new ResourceReference(context, "./creole.xml"); - assertEquals("References do not match (3)", creoleURL, rr.toURL()); + assertEquals("References do not match (2)", creoleURL, rr.toURL()); context = new ResourceReference(plugin, "html/"); rr = new ResourceReference(context, "../creole.xml"); @@ -154,27 +151,15 @@ ResourceReference rr = new ResourceReference((ResourceReference)null, path); assertEquals("String representations don't match (1)", path, rr.toString()); - rr = new ResourceReference((URL)null, path); + rr = new ResourceReference((Plugin)null, path); assertEquals("String representations don't match (2)", path, rr.toString()); - rr = new ResourceReference((URI)null, path); - assertEquals("String representations don't match (3)", path, rr.toString()); - - rr = new ResourceReference((Plugin)null, path); - assertEquals("String representations don't match (4)", path, rr.toString()); - rr = new ResourceReference( new ResourceReference(new URL("http://gate.ac.uk")), path); - assertEquals("String representations don't match (5)", path, rr.toString()); + assertEquals("String representations don't match (3)", path, rr.toString()); - rr = new ResourceReference(new URL("http://gate.ac.uk"), path); - assertEquals("String representations don't match (6)", path, rr.toString()); - - rr = new ResourceReference(new URI("http://gate.ac.uk"), path); - assertEquals("String representations don't match (7)", path, rr.toString()); - rr = new ResourceReference(creolePlugin, path); - assertEquals("String representations don't match (8)", path, rr.toString()); + assertEquals("String representations don't match (4)", path, rr.toString()); } public void testDefaultValue() throws Exception { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |