Revision: 20014
          http://sourceforge.net/p/gate/code/20014
Author:   markagreenwood
Date:     2017-01-30 11:28:58 +0000 (Mon, 30 Jan 2017)
Log Message:
-----------
ResourceReference params can now be persisted into xgapp files and any that 
refer to objects by file URL are handled in the same was as saving file: URLs 
already are so $ etc. works. Note that reading these back doesn't work yet

Modified Paths:
--------------
    
gate/branches/sawdust2/gate-core/src/main/java/gate/creole/ResourceReference.java
    
gate/branches/sawdust2/gate-core/src/main/java/gate/util/persistence/PersistenceManager.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-30 02:23:19 UTC (rev 20013)
+++ 
gate/branches/sawdust2/gate-core/src/main/java/gate/creole/ResourceReference.java
   2017-01-30 11:28:58 UTC (rev 20014)
@@ -16,6 +16,7 @@
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.Serializable;
 import java.net.MalformedURLException;
 import java.net.URI;
 import java.net.URISyntaxException;
@@ -24,8 +25,10 @@
 
 import gate.Gate;
 
-public class ResourceReference {
+public class ResourceReference implements Serializable {
 
+  private static final long serialVersionUID = 2526144106607856721L;
+
   private URI uri;
 
   public ResourceReference(URL url) throws URISyntaxException {

Modified: 
gate/branches/sawdust2/gate-core/src/main/java/gate/util/persistence/PersistenceManager.java
===================================================================
--- 
gate/branches/sawdust2/gate-core/src/main/java/gate/util/persistence/PersistenceManager.java
        2017-01-30 02:23:19 UTC (rev 20013)
+++ 
gate/branches/sawdust2/gate-core/src/main/java/gate/util/persistence/PersistenceManager.java
        2017-01-30 11:28:58 UTC (rev 20014)
@@ -76,6 +76,7 @@
 import gate.creole.ConditionalSerialAnalyserController;
 import gate.creole.Plugin;
 import gate.creole.ResourceInstantiationException;
+import gate.creole.ResourceReference;
 import gate.creole.SerialAnalyserController;
 import gate.event.ProgressListener;
 import gate.event.StatusListener;
@@ -159,7 +160,66 @@
 
     static final long serialVersionUID = -8665414981783519937L;
   }
+  
+  public static class RRPersistence implements Persistence {
+    
+    String uriString;
+    
+    @Override
+    public String toString() {
+      return uriString;
+    }
 
+    @Override
+    public void extractDataFromSource(Object source)
+        throws PersistenceException {
+      
+      try {
+        URI uri = null;
+        
+        if (source instanceof ResourceReference) {
+          uri = ((ResourceReference)source).toURI();
+        }
+        
+        if (uri == null) throw new UnsupportedOperationException("Whatever you 
are trying to persist isn't a URL");
+        
+        if(uri.getScheme() != null && uri.getScheme().equals("file")) {
+            // url is what we want to convert to something that is relative to 
$relpath$, 
+            // $resourceshome$ or $gatehome$ 
+            
+            // The file in which the URL should get persisted, the directory 
this file is in
+            // is the location to which we want to make the URL relative, 
unless we want to 
+            // use $gatehome$ or $resourceshome$
+            File outFile = currentPersistenceFile();
+            //File outFileReal = getCanonicalFileIfPossible(outFile);
+            
+            File urlFile = new File(uri);//Files.fileFromURL(url);
+            //File urlFileReal = getCanonicalFileIfPossible(urlFile);
+            
+            //logger.debug("Trying to persist "+uri+" for "+outFile);
+            
+            uriString = URLHolder.relativize(outFile, urlFile);
+            
+        } // if protocol is file
+        else {
+          // protocol was not file:
+          uriString = ((URI)source).toString();
+        }
+      }
+      catch(ClassCastException | URISyntaxException e) {
+        throw new PersistenceException(e);
+      }
+    }
+
+    @Override
+    public Object createObject()
+        throws PersistenceException, ResourceInstantiationException {
+      // TODO Auto-generated method stub
+      return null;
+    }
+    
+  }
+
   /**
    * URLs get upset when serialised and deserialised so we need to
    * convert them to strings for storage. 
@@ -198,6 +258,152 @@
      * from the original source object.
      */
     static final Logger logger = Logger.getLogger(URLHolder.class);
+    
+    public static String relativize(File outFile, File urlFile) throws 
URISyntaxException {
+          
+      File outFileReal = getCanonicalFileIfPossible(outFile);
+      File urlFileReal = getCanonicalFileIfPossible(urlFile);
+   // Note: the outDir will be correct if the application file itself is not a 
link
+      // If the application file is a link than its parent is the parent of 
the real
+      // path. 
+      File outDir = outFile.getParentFile(); 
+      File outDirReal = getCanonicalFileIfPossible(outDir);
+      File outDirOfReal = 
getCanonicalFileIfPossible(outFileReal.getParentFile());            
+      
+      
+      logger.debug("urlFile="+urlFile+", urlFileReal"+urlFileReal);
+      logger.debug("outDir="+outDir+", outDirReal"+outDirReal);
+      
+      // by default, use just the relative path
+      String pathMarker = relativePathMarker;
+      
+        // - this returns the canonical path to GATE_HOME
+      File gateHomePathReal = getGateHomePath();
+
+      // get the canonical path of the resources home directory, if set, 
otherwise null
+      File resourceshomeDirReal = getResourceshomePath();
+      
+      // Only if we actually *want* to consider GATE_HOME and other special 
directories,
+      // do all of this ...
+      // Note: the semantics of this has slightly changed to what it was 
before: we only
+      // do this is the use gatehome flag is set, not if it is not set but the 
warn flag
+      // is set (previsouly, the warn flag alone was sufficient too).
+      if(currentUseGateHome()) {
+        // First of all, check if we want to use GATE_HOME instead: this 
happens 
+        // if the real location of the url is inside the real location of 
GATE_HOME            
+        // and the location of the outfile is outside of GATE_HOME
+
+        if (!isContainedWithin(outFileReal, gateHomePathReal) &&
+            isContainedWithin(urlFileReal, gateHomePathReal)) {
+          logger.debug("Setting path marker to "+gatehomePathMarker);
+          if(currentWarnAboutGateHome()) {
+            if(!currentHaveWarnedAboutGateHome().getValue()) {
+              logger.warn(
+                    "\nYour application is using some of the resources/plugins 
"+
+                    "distributed with GATE, and may not work as expected "+
+                    "with different versions of GATE. You should consider "+
+                    "making private local copies of the plug-ins, and "+
+                    "distributing those with your application.");
+              currentHaveWarnedAboutGateHome().setValue(true);
+            }
+            // the actual URL is shown every time
+            //logger.warn("GATE resource referenced: "+url);
+          }
+          if(currentUseGateHome()) {
+            pathMarker = gatehomePathMarker;
+          }
+        } else 
+          // Otherwise, do the same check for the resources home path, but 
only if it
+          // is actuallys set
+          if(resourceshomeDirReal != null &&
+            !isContainedWithin(outFileReal, resourceshomeDirReal) &&
+            isContainedWithin(urlFileReal, resourceshomeDirReal)) {
+           if(currentWarnAboutGateHome()) {
+            if(!currentHaveWarnedAboutResourceshome().getValue()) {
+              logger.warn(
+                    "\nYour application is using resources from your project "+
+                    "path at "+getResourceshomePath()+". Restoring the 
application "+
+                    "will only work if the same project path is set.");
+              currentHaveWarnedAboutResourceshome().setValue(true);
+            }
+            // the actual URL is shown every time
+            //logger.warn("Resource referenced: "+url);
+          }
+          if(currentUseGateHome()) {
+            pathMarker = resourceshomePathMarker;
+          }
+         
+        }
+      }
+
+      String relPath = null;
+                  
+      if(pathMarker.equals(relativePathMarker)) {
+        // In theory we should just relativize here using the original paths, 
without
+        // following any symbolic links. We do not want to follow symbolic 
links because 
+        // somebody may want to use a symbolic link to a completely different 
location
+        // to include some resources into the project directory that contains 
the 
+        // pipeline (and the link to the resource).
+        // However, if the project directory itself is within a linked 
location, then 
+        // GATE will sometimes use the linked and sometimes the non-linked 
path 
+        // (for some reason it uses the non-linked path in the plugin manager 
but it uses
+        // the linked path when the application file is choosen). This means 
that 
+        // in those cases, there would be a large number of unwanted 
../../../../some/dir/to/get/back
+        // If we solve this by using the canonical paths, it will do the wrong 
thing for 
+        // links to resources. So we choose to make a compromise: if we can 
create a relative
+        // path that does not generate any ../ at the beginning of the 
relative part, then
+        // we use that, otherwise we use the real paths 
+        
+        relPath = getRelativeFilePathString(outDir, urlFile);
+        logger.debug("First relative path string attempt got "+relPath);
+        if(relPath.startsWith("../")) {
+          // if we want to actually use the real path, we have to be careful 
which is the 
+          // real parent of the out file: if outFile is a symbolic link then 
it is 
+          // outDirOfReal otherwise it is outDirReal
+          logger.debug("upslength is "+upsLength(relPath));
+          String tmpPath = relPath;
+          if(java.nio.file.Files.isSymbolicLink(outFile.toPath())) {
+            tmpPath = getRelativeFilePathString(outDirOfReal, urlFileReal);
+            logger.debug("trying outDirOfReal "+tmpPath);
+            logger.debug("upslength is "+upsLength(tmpPath));
+          } else {
+            tmpPath = getRelativeFilePathString(outDirReal, urlFileReal);      
                            
+            logger.debug("trying outDirReal "+tmpPath);
+            logger.debug("upslength is "+upsLength(tmpPath));
+          }
+          if(upsLength(tmpPath) < upsLength(relPath)) {
+            relPath = tmpPath;
+          }
+          logger.debug("Using tmpPath "+relPath);
+        }
+        // if we still get something that starts with ../ then our only 
remaining option is
+        // to find if a parent 
+      } else if(pathMarker.equals(gatehomePathMarker)) {
+        relPath = getRelativeFilePathString(gateHomePathReal, urlFileReal);
+      } else if(pathMarker.equals(resourceshomePathMarker)) {
+        relPath = getRelativeFilePathString(resourceshomeDirReal, urlFileReal);
+      } else {
+        // this should really never happen!
+        throw new GateRuntimeException("Unexpected error when persisting URL 
"+urlFile);
+      }
+
+      Path rel = Paths.get(relPath);
+      String uriPath = "";
+      boolean first = true;
+      for(Path component : rel) {
+        if(!first) uriPath += "/";
+        uriPath += component.toString();
+        first = false;
+      }
+      if(urlFile.isDirectory()) {
+        // trailing slash
+        uriPath += "/";
+      }
+      // construct the final properly encoded relative URI
+      URI finalRelUri = new URI(null, null, uriPath, null);
+      return pathMarker + finalRelUri.getRawPath();
+    }
+    
     @Override
     public void extractDataFromSource(Object source)
             throws PersistenceException {
@@ -221,149 +427,15 @@
             // is the location to which we want to make the URL relative, 
unless we want to 
             // use $gatehome$ or $resourceshome$
             File outFile = currentPersistenceFile();
-            File outFileReal = getCanonicalFileIfPossible(outFile);
-            // Note: the outDir will be correct if the application file itself 
is not a link
-            // If the application file is a link than its parent is the parent 
of the real
-            // path. 
-            File outDir = outFile.getParentFile(); 
-            File outDirReal = getCanonicalFileIfPossible(outDir);
-            File outDirOfReal = 
getCanonicalFileIfPossible(outFileReal.getParentFile());
+            //File outFileReal = getCanonicalFileIfPossible(outFile);
             
             File urlFile = Files.fileFromURL(url);
-            File urlFileReal = getCanonicalFileIfPossible(urlFile);
+            //File urlFileReal = getCanonicalFileIfPossible(urlFile);
             
             logger.debug("Trying to persist "+url+" for "+outFile);
-            logger.debug("urlFile="+urlFile+", urlFileReal"+urlFileReal);
-            logger.debug("outDir="+outDir+", outDirReal"+outDirReal);
             
-            // by default, use just the relative path
-            String pathMarker = relativePathMarker;
+            urlString = relativize(outFile, urlFile);
             
-              // - this returns the canonical path to GATE_HOME
-            File gateHomePathReal = getGateHomePath();
-
-            // get the canonical path of the resources home directory, if set, 
otherwise null
-            File resourceshomeDirReal = getResourceshomePath();
-            
-            // Only if we actually *want* to consider GATE_HOME and other 
special directories,
-            // do all of this ...
-            // Note: the semantics of this has slightly changed to what it was 
before: we only
-            // do this is the use gatehome flag is set, not if it is not set 
but the warn flag
-            // is set (previsouly, the warn flag alone was sufficient too).
-            if(currentUseGateHome()) {
-              // First of all, check if we want to use GATE_HOME instead: this 
happens 
-              // if the real location of the url is inside the real location 
of GATE_HOME            
-              // and the location of the outfile is outside of GATE_HOME
-
-              if (!isContainedWithin(outFileReal, gateHomePathReal) &&
-                  isContainedWithin(urlFileReal, gateHomePathReal)) {
-                logger.debug("Setting path marker to "+gatehomePathMarker);
-                if(currentWarnAboutGateHome()) {
-                  if(!currentHaveWarnedAboutGateHome().getValue()) {
-                    logger.warn(
-                          "\nYour application is using some of the 
resources/plugins "+
-                          "distributed with GATE, and may not work as expected 
"+
-                          "with different versions of GATE. You should 
consider "+
-                          "making private local copies of the plug-ins, and "+
-                          "distributing those with your application.");
-                    currentHaveWarnedAboutGateHome().setValue(true);
-                  }
-                  // the actual URL is shown every time
-                  logger.warn("GATE resource referenced: "+url);
-                }
-                if(currentUseGateHome()) {
-                  pathMarker = gatehomePathMarker;
-                }
-              } else 
-                // Otherwise, do the same check for the resources home path, 
but only if it
-                // is actuallys set
-                if(resourceshomeDirReal != null &&
-                  !isContainedWithin(outFileReal, resourceshomeDirReal) &&
-                  isContainedWithin(urlFileReal, resourceshomeDirReal)) {
-                 if(currentWarnAboutGateHome()) {
-                  if(!currentHaveWarnedAboutResourceshome().getValue()) {
-                    logger.warn(
-                          "\nYour application is using resources from your 
project "+
-                          "path at "+getResourceshomePath()+". Restoring the 
application "+
-                          "will only work if the same project path is set.");
-                    currentHaveWarnedAboutResourceshome().setValue(true);
-                  }
-                  // the actual URL is shown every time
-                  logger.warn("Resource referenced: "+url);
-                }
-                if(currentUseGateHome()) {
-                  pathMarker = resourceshomePathMarker;
-                }
-               
-              }
-            }
-
-            String relPath = null;
-                        
-            if(pathMarker.equals(relativePathMarker)) {
-              // In theory we should just relativize here using the original 
paths, without
-              // following any symbolic links. We do not want to follow 
symbolic links because 
-              // somebody may want to use a symbolic link to a completely 
different location
-              // to include some resources into the project directory that 
contains the 
-              // pipeline (and the link to the resource).
-              // However, if the project directory itself is within a linked 
location, then 
-              // GATE will sometimes use the linked and sometimes the 
non-linked path 
-              // (for some reason it uses the non-linked path in the plugin 
manager but it uses
-              // the linked path when the application file is choosen). This 
means that 
-              // in those cases, there would be a large number of unwanted 
../../../../some/dir/to/get/back
-              // If we solve this by using the canonical paths, it will do the 
wrong thing for 
-              // links to resources. So we choose to make a compromise: if we 
can create a relative
-              // path that does not generate any ../ at the beginning of the 
relative part, then
-              // we use that, otherwise we use the real paths 
-              
-              relPath = getRelativeFilePathString(outDir, urlFile);
-              logger.debug("First relative path string attempt got "+relPath);
-              if(relPath.startsWith("../")) {
-                // if we want to actually use the real path, we have to be 
careful which is the 
-                // real parent of the out file: if outFile is a symbolic link 
then it is 
-                // outDirOfReal otherwise it is outDirReal
-                logger.debug("upslength is "+upsLength(relPath));
-                String tmpPath = relPath;
-                if(java.nio.file.Files.isSymbolicLink(outFile.toPath())) {
-                  tmpPath = getRelativeFilePathString(outDirOfReal, 
urlFileReal);
-                  logger.debug("trying outDirOfReal "+tmpPath);
-                  logger.debug("upslength is "+upsLength(tmpPath));
-                } else {
-                  tmpPath = getRelativeFilePathString(outDirReal, 
urlFileReal);                                  
-                  logger.debug("trying outDirReal "+tmpPath);
-                  logger.debug("upslength is "+upsLength(tmpPath));
-                }
-                if(upsLength(tmpPath) < upsLength(relPath)) {
-                  relPath = tmpPath;
-                }
-                logger.debug("Using tmpPath "+relPath);
-              }
-              // if we still get something that starts with ../ then our only 
remaining option is
-              // to find if a parent 
-            } else if(pathMarker.equals(gatehomePathMarker)) {
-              relPath = getRelativeFilePathString(gateHomePathReal, 
urlFileReal);
-            } else if(pathMarker.equals(resourceshomePathMarker)) {
-              relPath = getRelativeFilePathString(resourceshomeDirReal, 
urlFileReal);
-            } else {
-              // this should really never happen!
-              throw new GateRuntimeException("Unexpected error when persisting 
URL "+url);
-            }
-
-            Path rel = Paths.get(relPath);
-            String uriPath = "";
-            boolean first = true;
-            for(Path component : rel) {
-              if(!first) uriPath += "/";
-              uriPath += component.toString();
-              first = false;
-            }
-            if(urlFile.isDirectory()) {
-              // trailing slash
-              uriPath += "/";
-            }
-            // construct the final properly encoded relative URI
-            URI finalRelUri = new URI(null, null, uriPath, null);
-            urlString = pathMarker + finalRelUri.getRawPath();
         } // if protocol is file
         else {
           // protocol was not file:
@@ -493,7 +565,7 @@
     }
     
     
-    private File getGateHomePath() {
+    private static File getGateHomePath() {
       if(gatehomePath != null) {
         return gatehomePath;
       } else {
@@ -502,7 +574,7 @@
       }
     }
     
-    private File getResourceshomePath() {
+    private static File getResourceshomePath() {
       if(haveResourceshomePath == null) {
         String resourceshomeString = 
System.getProperty(resourceshomePropertyName);
         if(resourceshomeString == null) {
@@ -521,7 +593,7 @@
     }
 
 
-    private File getCanonicalFileIfPossible(File file) {
+    private static File getCanonicalFileIfPossible(File file) {
       if (file == null) return file;
       File tmp = file;
       try {
@@ -544,7 +616,7 @@
      * @param file the file we want to reference
      * @return the path appended to dir to get to file
      */
-    private String getRelativeFilePathString(File dir, File file) {
+    private static String getRelativeFilePathString(File dir, File file) {
       Path dirPath = dir.toPath();
       Path filePath = file.toPath();
       try {
@@ -561,7 +633,7 @@
       return dirPath.relativize(filePath).toString();
     }
 
-    private int upsLength(String path) {
+    private static int upsLength(String path) {
       Matcher m = goUpPattern.matcher(path);
       if(m.matches()) {
         return m.group(1).length();
@@ -1421,6 +1493,7 @@
       registerPersistentEquivalent(VisualResource.class, 
SlashDevSlashNull.class);
 
       registerPersistentEquivalent(URL.class, URLHolder.class);
+      registerPersistentEquivalent(ResourceReference.class, 
RRPersistence.class);
       
       //for compatibility reasons we treat Plugins loaded from a directory URL 
as a URL
       registerPersistentEquivalent(Plugin.Directory.class, URLHolder.class);

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-30 02:23:19 UTC (rev 20013)
+++ 
gate/branches/sawdust2/gate-core/src/test/java/gate/creole/TestResourceReference.java
       2017-01-30 11:28:58 UTC (rev 20014)
@@ -1,20 +1,25 @@
 package gate.creole;
 
+import java.io.File;
 import java.io.InputStream;
 import java.net.URI;
 import java.net.URL;
 
 import org.apache.commons.io.IOUtils;
+import org.jdom.Content;
 import org.jdom.Document;
 import org.jdom.Element;
 import org.jdom.JDOMException;
+import org.jdom.input.SAXBuilder;
 
 import gate.Factory;
+import gate.FeatureMap;
 import gate.Gate;
 import gate.Resource;
 import gate.corpora.TestDocument;
 import gate.creole.metadata.CreoleParameter;
 import gate.creole.metadata.CreoleResource;
+import gate.util.persistence.PersistenceManager;
 import junit.framework.TestCase;
 
 @SuppressWarnings("serial")
@@ -23,7 +28,7 @@
   private Plugin creolePlugin;
 
   @CreoleResource
-  public static class TestResource extends AbstractResource {
+  public static class TestResource extends AbstractProcessingResource {
 
     ResourceReference rr = null;
 
@@ -189,7 +194,47 @@
     }
   }
 
-  /*public void testPersistence() throws Exception {
+  public void testPersistence() throws Exception {
 
-  }*/
+    Resource resource = null;
+
+    File xgappFile = null;
+    File txtFile = null;
+    
+    try {
+      xgappFile = File.createTempFile("rr-test", ".xgapp");
+      xgappFile.createNewFile();
+      
+      txtFile = new File(xgappFile.getParentFile(),"test-file.txt");
+      
+      FeatureMap params = Factory.newFeatureMap();      
+      params.put("param", new ResourceReference(txtFile.toURI()));
+      resource = Factory.createResource(TestResource.class.getName(),params);  
    
+            
+      PersistenceManager.saveObjectToFile(resource, xgappFile);
+            
+      SAXBuilder builder = new SAXBuilder();
+      Document doc = builder.build(xgappFile);
+      
+      Element entry = 
doc.getRootElement().getChild("application").getChild("initParams").getChild("localMap").getChild("entry");
+      
+      assertEquals("couldn't find a param entry", 
"param",entry.getChildText("string"));
+      
+      Element value = 
entry.getChild("gate.util.persistence.PersistenceManager-RRPersistence");
+      
+      assertNotNull("We couldn't find the RRPersistence wrapper",value);
+      
+      assertEquals("The URI was not as expected","$relpath$test-file.txt", 
value.getChildText("uriString"));
+      
+    } finally {
+      if (xgappFile != null) xgappFile.deleteOnExit();
+      
+      if(resource != null) {
+        Factory.deleteResource(resource);
+      }
+      
+      
+    }
+
+  }
 }
\ No newline at end of file

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