[oXygen-user] Web Author and more then one git submodules
oXygen XML Editor Support (Gabriel Titerlea)
support at oxygenxml.com
Fri Dec 6 06:54:04 CST 2019
Hello,
Regarding Web Author, we'll retain the current behavior regarding git
sub-modules for now.
But for your use-case we think allowing users to switch the file-browser
to the parent repository and choosing a file from there is a good
compromise.
To make this work you will need to add custom code that transforms
absolute URLs into relative URLs and vice versa while taking into
account sub-modules.
To do that there are 3 hooks where you should intervene using a custom
Web Author plugin [1][2].
1. Add a URI resolver [3] which will be used to resolve relative paths
to absolute paths.
2. Add a Relative Reference Resolver which will be used to resolve
absolute paths to relative paths on the server side.
3. Add a Relative Reference Resolver which will be used to resolve
absolute paths to relative paths on the client side.
I'm attaching an example for points 1 & 2:
package example.plugin
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.transform.Source;
import javax.xml.transform.TransformerException;
import javax.xml.transform.URIResolver;
import ro.sync.basic.util.URLUtil;
import ro.sync.exml.plugin.workspace.WorkspaceAccessPluginExtension;
import ro.sync.exml.workspace.api.standalone.StandalonePluginWorkspace;
public class MyWorkspaceAccessPluginExtension implements
WorkspaceAccessPluginExtension {
/**
* Predicate to check if a URL is inside a configured parent
repository.
* You can hard-code this, save it in an option or determine it
dynamically depending on your use-case.
* */
private Predicate<String> urlIsInsideParentRepository =
Pattern.compile("^gitgle://([^@]+@)?https%3A%2F%2Fgitlab.example.com%2Fowner%2Fparent-project/master/").asPredicate();
/**
* This regExp extract first part of a Git URL, without the path
part.
* More details about Git URLs:
https://www.oxygenxml.com/doc/versions/21.1.1.0/ug-waCustom/topics/oxy-url.html#oxy-url__oxyurl_unique_scheme
*
* In this example I'm looking at `gitgle` URLs which are URLs
for GitLab on-premise.
*/
private Pattern gitUrlWithoutPathPattern =
Pattern.compile("^gitgle://([^@]+@)?([^:/]+)(:\\d+)?/[^/]+/");
/**
* The URL of the submodule inside a parent repository.
*/
private String submoduleUrlInsideParent =
"gitgle://https%3A%2F%2Fgitlab.example.com%2Fowner%2Fparent-project/master/submodule/";
URIResolver uriResolver = new URIResolver() {
@Override
public Source resolve(String href, String base) throws
TransformerException {
try {
Optional<String> pathRelativeToParentRepo =
getPathRelativeToSubmoduleInParentRepo(href, base);
if (pathRelativeToParentRepo.isPresent()) {
URI uriInParentRepo = new URI(submoduleUrlInsideParent +
pathRelativeToParentRepo.get());
URL normalizedUrlInParentRepo =
uriInParentRepo.normalize().toURL();
/*
* Attach session information to the URL.
* This is needed to authenticate the requests that will
retrieve the content of this URL.
* */
URL hrefWithUserInfo =
URLUtil.attachUserInfo(normalizedUrlInParentRepo, new
URL(base).getUserInfo(), null, false);
return new Source() {
@Override
public void setSystemId(String systemId) {/**/}
@Override
public String getSystemId() {
return hrefWithUserInfo.toExternalForm();
}
};
}
} catch (URISyntaxException | MalformedURLException e) {/**/}
return null;
}
/**
* Returns a href that is relative to the submodule from the
parent URL if the given href represents a navigation outside of the
submodule.
* @param href An href attribute, which may be relative or
absolute.
* @param base The base URI against which the first argument
will be made absolute if the absolute URI is required.
* @return A href that is relative to the parent URL (The
repository that contains submodules).
* @throws URISyntaxException
*/
private Optional<String>
getPathRelativeToSubmoduleInParentRepo(String href, String base)
throws URISyntaxException {
Optional<String> relativePathToParentRepo = Optional.empty();
// If the URL is not inside a submodule there's no need to
make any change to it.
if (base != null && href != null /*&&
urlIsInsideSubmodule.test(base)*/) {
// If the href is absolute we leave it as is.
if (!new URI(href).isAbsolute()) {
String baseUrlWithoutFileName = base.substring(0,
base.lastIndexOf('/') + 1);
/*
* ______________ ______ ____________
* A git URL looks like this:
gitgle://REPOSITORY_URI/BRANCH/PATH/TO/FILE
*
* We want to append our relative href to the base git
URL and normalize it.
* But we need to add an extra "../" to account for the
/BRANCH/ part of the git URL.
* */
URI normalized = new URI(baseUrlWithoutFileName + "../" +
href).normalize();
String absoluteUrlInsideSubmodule = normalized.toString();
int upOneLevelIndex =
absoluteUrlInsideSubmodule.indexOf("..");
// After normalization any "../" left represents a
navigation outside the current submodule.
if (upOneLevelIndex != -1) {
String hrefRelativeToParent =
absoluteUrlInsideSubmodule.substring(upOneLevelIndex);
relativePathToParentRepo =
Optional.of(hrefRelativeToParent);
}
}
}
return relativePathToParentRepo;
}
};
@Override
public void applicationStarted(StandalonePluginWorkspace
pluginWorkspaceAccess) {
// Add a URI resolver which will be used to resolve relative
paths to absolute paths.
pluginWorkspaceAccess.getXMLUtilAccess().addPriorityURIResolver(uriResolver);
// Add a Relative Reference Resolver which will be used to
resolve absolute paths to relative paths.
pluginWorkspaceAccess.addRelativeReferencesResolver("gitgle",
(baseUrl, childUrl) -> {
try {
boolean baseIsInsideAParent =
urlIsInsideParentRepository.test(baseUrl.toExternalForm());
boolean childIsInsideAParent =
urlIsInsideParentRepository.test(childUrl.toExternalForm());
if (!baseIsInsideAParent && childIsInsideAParent) {
// Make the childUrl relative to the baseUrl while taking
submodules into account.
String baseUrlString = baseUrl.toExternalForm();
Matcher matcher =
gitUrlWithoutPathPattern.matcher(baseUrlString);
if (matcher.find()) {
String submoduleUrl =
baseUrlString.substring(matcher.start(), matcher.end());
URL submoduleURL = URLUtil.attachUserInfo(new
URL(submoduleUrl), baseUrl.getUserInfo(), null, false);
// To make this work for all submodules you could have
a map from a submodule URL to its URL inside the parent.
URL submoduleInParentURL = URLUtil.attachUserInfo(new
URL(submoduleUrlInsideParent), baseUrl.getUserInfo(), null, false);
String relativePathToRootOfSubmodule =
URLUtil.makeRelative(baseUrl, submoduleURL, true, true);
if (relativePathToRootOfSubmodule.equals(".")) {
relativePathToRootOfSubmodule = "";
}
String relativePathToTargetInsideParent =
URLUtil.makeRelative(submoduleInParentURL, childUrl, true, true);
// Resolved relative URL
return relativePathToRootOfSubmodule +
relativePathToTargetInsideParent;
}
}
} catch (MalformedURLException e) { /**/ }
return null;
});
}
@Override
public boolean applicationClosing() {
return true;
}
}
The example.plugin.MyWorkspaceAccessPluginExtension class need to be
referenced in the plugin.xml file of your plugin [4].
For point 2, you need to add a relative references resolver [5] in
javascript. This resolver will be used on the client's browser to
resolve URLs.
(function () {
workspace.addRelativeReferencesResolver('gitgle', function
(baseUrl, childUrl) {
// Re-implement the java code which was used for
`pluginWorkspaceAccess.addRelativeReferencesResolver`.
return "resolvedUrl";
});
})();
Let us know if you need anything else.
Best,
Gabriel
[1]
https://www.oxygenxml.com/doc/versions/21.1.1.0/ug-waCustom/topics/customizing_plugins.html
[2]
https://www.oxygenxml.com/doc/versions/21.1.1.0/ug-waCustom/topics/webapp-plugin-prototyping.html
<https://www.oxygenxml.com/doc/versions/21.1.1.0/ug-waCustom/topics/webapp-plugin-prototyping.html?hl=Go%20to%20the%20following%20repository%20and%20follow%20the%20instructions>
[3]
https://www.oxygenxml.com/doc/versions/21.1.1.0/ug-waCustom/topics/oxy-url.html
[4]
https://www.oxygenxml.com/doc/versions/21.1/ug-editor/topics/workspace-access-plugin.html
[5]
https://www.oxygenxml.com/maven/com/oxygenxml/oxygen-webapp/21.1.1.0/jsdoc/sync.api.Workspace.html#addRelativeReferencesResolver
Gabriel Titerlea
https://www.oxygenxml.com
On 03-Dec-19 18:48, Jirka Kosek wrote:
> On 3.12.2019 12:40, oXygen XML Editor Support (Gabriel Titerlea) wrote:
>> We're trying to justify a change to the current behavior regarding Git
>> sub-modules in Web Author. Please describe your use-case in more detail.
> It's project where requirements changed over the time ;-)
>
> Originally separate textbooks have been edited -- each textbook in a
> separate git repository. Each textbook has been standalone. For each
> textbook different group of users has access rights.
>
> Now requirements changed and some books need to reuse content
> (chapters/section, images, ...) from other books. Merging all individual
> repositories into one large repository (for example using git subtree
> feature) where there will be separate folder for each book is not viable
> as this way we would loose ability to give different access rights for
> different textbooks. Git can set access rights only on whole repository
> not on individual folders inside it.
>
> So using submodules we can keep textbooks that don't require inclusion
> of assets from other textbooks as they were in a separate repositories.
> Then textbooks that need to reuse content can be edited from "grandrepo"
> that would include all textbooks as submodules.
>
> Well, yes perhaps this is far beyond what git has been designed for. Git
> was fine for original requirements. Knowing current requirements at the
> start of project would mean that expensive CCMS should be used instead
> of git. :-(
>
> Thanks and have a nice day,
>
> Jirka
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.oxygenxml.com/pipermail/oxygen-user/attachments/20191206/a4a83491/attachment.html>
More information about the oXygen-user
mailing list