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

Reply via email to