Revision: 19976 http://sourceforge.net/p/gate/code/19976 Author: markagreenwood Date: 2017-01-23 05:00:32 +0000 (Mon, 23 Jan 2017) Log Message: ----------- creole:// URLs now allow us to refer to resources inside plugins without knowing (or caring) where they actually live on disc, making it easy to refer to files across plugins. This means I should now be able to convert the Twitter plugin -- still need to decide exactly how/when/where to do the init of the handler but this works for now
Modified Paths: -------------- gate/branches/sawdust2/gate-core/src/main/java/gate/Plugin.java Added Paths: ----------- gate/branches/sawdust2/gate-core/src/main/java/sun/ gate/branches/sawdust2/gate-core/src/main/java/sun/net/ gate/branches/sawdust2/gate-core/src/main/java/sun/net/www/ gate/branches/sawdust2/gate-core/src/main/java/sun/net/www/protocol/ gate/branches/sawdust2/gate-core/src/main/java/sun/net/www/protocol/creole/ gate/branches/sawdust2/gate-core/src/main/java/sun/net/www/protocol/creole/Handler.java Modified: gate/branches/sawdust2/gate-core/src/main/java/gate/Plugin.java =================================================================== --- gate/branches/sawdust2/gate-core/src/main/java/gate/Plugin.java 2017-01-23 02:23:21 UTC (rev 19975) +++ gate/branches/sawdust2/gate-core/src/main/java/gate/Plugin.java 2017-01-23 05:00:32 UTC (rev 19976) @@ -22,11 +22,14 @@ import java.io.IOException; import java.io.InputStream; import java.io.Serializable; +import java.lang.reflect.Field; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.net.URLClassLoader; +import java.net.URLStreamHandler; +import java.net.URLStreamHandlerFactory; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.FileVisitResult; @@ -83,13 +86,87 @@ import gate.util.asm.Opcodes; import gate.util.asm.Type; import gate.util.asm.commons.EmptyVisitor; -import gate.util.maven.SimpleMavenCache; import gate.util.maven.SimpleModelResolver; public abstract class Plugin { protected static final Logger log = Logger.getLogger(Plugin.class); + + static { + if(!Plugin.class.getClassLoader() + .equals(ClassLoader.getSystemClassLoader())) { + // we only need to register the factory if the handler classes are not + // already on the system classloader + + log.debug("registering URLStreamHandlerFactory"); + + Field factoryField = null; + + try { + // get the factory field from java.net.URL via reflection + factoryField = URL.class.getDeclaredField("factory"); + + // it's usually package protected but we need access to it + factoryField.setAccessible(true); + + // get the current factory out of the protected field. This will be null + // if a factory hasn't already been set + URLStreamHandlerFactory currentFactory = + (URLStreamHandlerFactory)factoryField.get(null); + + // now we define out custom factory + URLStreamHandlerFactory newFactory = new URLStreamHandlerFactory() { + + @Override + public URLStreamHandler createURLStreamHandler(String protocol) { + if(currentFactory != null) { + // if there was already a factory then delegate to it first to see + // if it can handle the protocol + URLStreamHandler handler = + currentFactory.createURLStreamHandler(protocol); + + // if so our work here is done + if(handler != null) return handler; + } + + // build up the normal classname from the protocol + String className = "sun.net.www.protocol." + protocol + ".Handler"; + + try { + // try to load the class + Class<?> handler = Class.forName(className); + + // create and return an instance of the protocol handler + return (URLStreamHandler)handler.newInstance(); + + } catch(ClassNotFoundException | InstantiationException + | IllegalAccessException e) { + // skip over this to the null return; + } + + // either there is no handler for the protocol or something went + // wrong, either way just return null + return null; + } + }; + + // make sure the factory field is set to null so that setting it won't + // cause an exception + factoryField.set(null, null); + + // register our deligating factory + URL.setURLStreamHandlerFactory(newFactory); + } catch(NoSuchFieldException | IllegalAccessException e) { + //this is a problem as it means our custom protocol handlers aren't going to get used + e.printStackTrace(); + } finally { + // make sure we put the field back the way it was before we started + if(factoryField != null) factoryField.setAccessible(false); + } + } + } + /** * Is the plugin valid (i.e. is the location reachable and the * creole.xml file parsable). @@ -165,7 +242,7 @@ return valid; } - public void copyResources(File dir) throws IOException { + public void copyResources(File dir) throws IOException, URISyntaxException { throw new UnsupportedOperationException("This plugin does not contain any resources that can be copied"); } @@ -417,6 +494,8 @@ private String group, artifact, version; + private transient URL artifactURL; + private WorkspaceReader workspace = null;//new SimpleMavenCache(new File("cache")); public Maven(String group, String artifact, String version) { @@ -459,14 +538,14 @@ } @Override - public void copyResources(File dir) throws IOException { + public void copyResources(File dir) throws URISyntaxException, IOException { if (!hasResources()) throw new UnsupportedOperationException( "this plugin doesn't have any resources you can copy as you would know had you called hasResources first :P"); try (FileSystem zipFs = - FileSystems.newFileSystem(baseURL, new HashMap<>());) { + FileSystems.newFileSystem(artifactURL.toURI(), new HashMap<>());) { Path target = Paths.get(dir.toURI()); Path pathInZip = zipFs.getPath("/resources"); @@ -492,14 +571,22 @@ @Override public boolean hasResources() { - try (FileSystem zipFs = FileSystems.newFileSystem(baseURL, new HashMap<>());) { + try (FileSystem zipFs = FileSystems.newFileSystem(artifactURL.toURI(), new HashMap<>());) { Path pathInZip = zipFs.getPath("/resources"); return Files.isDirectory(pathInZip); } - catch (IOException e) { + catch (URISyntaxException | IOException e) { return false; } } + + public URL getArtifactURL() throws Exception { + if (artifactURL == null) { + getCreoleXML(); + } + + return artifactURL; + } @Override public Document getCreoleXML() throws Exception { @@ -520,20 +607,22 @@ repoSystem.resolveArtifact(repoSession, artifactRequest); - baseURL = - new URI("jar:" + baseURL = new URI("creole://"+group+";"+artifact+";"+version+"/"); + + artifactURL = + new URL("jar:" + artifactResult.getArtifact().getFile().toURI().toURL() + "!/"); // check it has a creole.xml at the root - URL directoryXmlFileUrl = new URL(getBaseURL(), "creole.xml"); + URL directoryXmlFileUrl = new URL(artifactURL, "creole.xml"); InputStream creoleStream = null; try { creoleStream = directoryXmlFileUrl.openStream(); } catch(IOException ioe) { - throw new IOException(directoryXmlFileUrl.toExternalForm() + throw new IOException(getBaseURL().toExternalForm() + " does not exist so this artifact is not a GATE plugin"); } @@ -554,7 +643,7 @@ // jar (marked for scanning) and the dependencies SAXBuilder builder = new SAXBuilder(false); Document jdomDoc = - builder.build(creoleStream, directoryXmlFileUrl.toExternalForm()); + builder.build(creoleStream, getBaseURL().toExternalForm()); Element creoleRoot = jdomDoc.getRootElement(); Added: gate/branches/sawdust2/gate-core/src/main/java/sun/net/www/protocol/creole/Handler.java =================================================================== --- gate/branches/sawdust2/gate-core/src/main/java/sun/net/www/protocol/creole/Handler.java (rev 0) +++ gate/branches/sawdust2/gate-core/src/main/java/sun/net/www/protocol/creole/Handler.java 2017-01-23 05:00:32 UTC (rev 19976) @@ -0,0 +1,58 @@ +package sun.net.www.protocol.creole; + +import java.io.IOException; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLStreamHandler; +import java.util.Set; + +import org.apache.commons.io.IOUtils; + +import gate.Gate; +import gate.Plugin; + +public class Handler extends URLStreamHandler { + + @Override + protected URLConnection openConnection(URL u) throws IOException { + + String[] data = u.getHost().split(";"); + + if (data.length != 3) + throw new IOException(u.getHost()+" does not refer to a CREOLE plugin"); + + Plugin plugin = new Plugin.Maven(data[0], data[1], data[2]); + + Set<Plugin> plugins = Gate.getCreoleRegister().getPlugins(); + + for (Plugin registered : plugins) { + System.out.println(registered.getName()); + if (registered.equals(plugin)) { + + try { + URL baseURL = ((Plugin.Maven)registered).getArtifactURL(); + + URL actualURL = new URL(baseURL,u.getFile()); + return actualURL.openConnection(); + } + catch (Exception e) { + throw new IOException("Unable to access plugin",e); + } + + } + } + + throw new IOException("Plugin specified by URL has not been loaded into GATE"); + } + + public static void main(String args[]) throws Exception { + Gate.init(); + + Plugin plugin = new Plugin.Maven("uk.ac.gate.plugins", "annie", "9.0-SNAPSHOT"); + Gate.getCreoleRegister().registerPlugin(plugin); + + URL url = new URL("creole://uk.ac.gate.plugins;annie;9.0-SNAPSHOT/META-INF/gate/creole.xml"); + System.out.println(IOUtils.toString(url)); + } + +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot _______________________________________________ GATE-cvs mailing list GATE-cvs@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/gate-cvs