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
[email protected]
https://lists.sourceforge.net/lists/listinfo/gate-cvs