Extending LinkTextResolver

Having trouble deploying Oxygen XML Web Author? Got a bug to report? Post it all here.
manojdcoder
Posts: 67
Joined: Thu Oct 29, 2020 12:01 am

Extending LinkTextResolver

Post by manojdcoder »

Is it possible to override or add parameters to the href attribute of an XREF?

An XREF in my document (DITA) looks like,

Code: Select all

<xref href="filename.xml#elmentId"/>
It renders

Code: Select all

404 Not Found for: https://localhost:25608/filename.xml
I understand its based on the CSS from framework

Code: Select all

*[class~="topic/xref"][href]:empty {
    content: oxy_label(text, oxy_getSomeText(oxy_link-text(), 150, true), background-color, rgb(240, 240, 240));
}
The oxy_link-text() by default uses DitaLinkTextResolver() and returns 404 not found text. I have to add an auth token to the original href at runtime.

1. Is it possible to add the auth token via CSS?

In case of images, I use the following in CSS

Code: Select all

image[href] {
    content: oxy_url(oxy_replace(oxy_url(oxy_concat('${currentFileURL}', '&href=', attr(href))), 'DocumentBasePath', 'ImageBasePath'));;
}
The currentFileURL has auth token in it. Anything similar could be done for XREF?

2. If I must configure a custom Extensions Bundle to achieve this, how do I retain existing DITA features? dita.framework already has below extension, I'm not sure how can put my custom extension while keeping all features DITAExtensionsBundle

Code: Select all

<field name="extensionsBundleClassName">
    <String>ro.sync.ecss.extensions.dita.DITAExtensionsBundle</String>
</field>
cristi_talau
Posts: 513
Joined: Thu Sep 04, 2014 4:22 pm

Re: Extending LinkTextResolver

Post by cristi_talau »

Hello,

First of all, the recommended way to authenticate users is described here in our integration guide [1].

Regarding your questions,
1. The link text source is not customizable using CSS.
2. DITALinkText resolver is an all-or-nothing approach. At most you can delegate to the original implementation, but it seems that you need to handle all the references anyway.

An alternative approach would be to register a priority URIResolver like below:

Code: Select all

PluginWorkspaceProvider.getPluginWorkspace().getXMLUtilAccess().addPriorityURIResolver();
This resolver will be called whenever a relative href value needs to be resolved against the URL of the currently opened document.

Best,
Cristian

[1] https://www.oxygenxml.com/doc/versions/ ... _auth.html
manojdcoder
Posts: 67
Joined: Thu Oct 29, 2020 12:01 am

Re: Extending LinkTextResolver

Post by manojdcoder »

Thank you for your response.

I tried URIResolver, Oxygen says no protocol found as the url is simply filename.xml I think.

Any idea how may I handle this situation?
manojdcoder
Posts: 67
Joined: Thu Oct 29, 2020 12:01 am

Re: Extending LinkTextResolver

Post by manojdcoder »

Just wanted to update that URIResolver works perfectly for images.

But only in case of XREFs, it threw no protocol exception while it tries to load elements dialog for given document.

Error Log

Code: Select all

ro.sync.servlet.RESTDitaSupport - Error parsing document for possible reference targets: no protocol: my_dita_file_name.xml
java.net.MalformedURLException: no protocol: my_dita_file_name.xml
        at java.net.URL.<init>(URL.java:672) ~[?:?]
        at java.net.URL.<init>(URL.java:568) ~[?:?]
        at java.net.URL.<init>(URL.java:515) ~[?:?]
        at ro.sync.servlet.RESTDitaSupport.getDitaReferenceTargets(RESTDitaSupport.java:60) ~[classes/:?]
        at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
        at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:?]
        at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
        at java.lang.reflect.Method.invoke(Method.java:564) ~[?:?]
        at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:139) ~[resteasy-jaxrs.jar:3.6.3.Final]
        at org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:510) ~[resteasy-jaxrs.jar:3.6.3.Final]
        at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:400) ~[resteasy-jaxrs.jar:3.6.3.Final]
        at org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$0(ResourceMethodInvoker.java:364) ~[resteasy-jaxrs.jar:3.6.3.Final]
        at org.jboss.resteasy.core.interception.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:355) ~[resteasy-jaxrs.jar:3.6.3.Final]
        at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:366) ~[resteasy-jaxrs.jar:3.6.3.Final]
        at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:338) ~[resteasy-jaxrs.jar:3.6.3.Final]
        at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:311) ~[resteasy-jaxrs.jar:3.6.3.Final]
        at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:439) ~[resteasy-jaxrs.jar:3.6.3.Final]
        at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:229) ~[resteasy-jaxrs.jar:3.6.3.Final]
        at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:135) ~[resteasy-jaxrs.jar:3.6.3.Final]
        at org.jboss.resteasy.core.interception.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:355) [resteasy-jaxrs.jar:3.6.3.Final]
        at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:138) [resteasy-jaxrs.jar:3.6.3.Final]
        at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:215) [resteasy-jaxrs.jar:3.6.3.Final]
        at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:227) [resteasy-jaxrs.jar:3.6.3.Final]
        at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56) [resteasy-jaxrs.jar:3.6.3.Final]
        at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:51) [resteasy-jaxrs.jar:3.6.3.Final]
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) [servlet-api.jar:4.0.FR]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) [catalina.jar:9.0.37]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [catalina.jar:9.0.37]
        at ro.sync.ecss.webapp.d.h.doFilter(Unknown Source) [oxygen.jar:?]
        at ro.sync.ecss.extensions.api.webapp.license.LicenseEnforcerFilter.doFilter(Unknown Source) [oxygen.jar:?]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [catalina.jar:9.0.37]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [catalina.jar:9.0.37]
        at ro.sync.servlet.config.OxygenLanguageFilter.doFilter(OxygenLanguageFilter.java:44) [classes/:?]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [catalina.jar:9.0.37]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [catalina.jar:9.0.37]
        at ro.sync.servlet.config.OxygenContextFilter.doFilter(OxygenContextFilter.java:61) [classes/:?]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [catalina.jar:9.0.37]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [catalina.jar:9.0.37]
        at ro.sync.servlet.config.UTF8CharsetEnforcer.doFilter(UTF8CharsetEnforcer.java:28) [classes/:?]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [catalina.jar:9.0.37]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [catalina.jar:9.0.37]
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) [tomcat-websocket.jar:9.0.37]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [catalina.jar:9.0.37]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [catalina.jar:9.0.37]
        at ro.sync.auth.CsrfFilter.doFilter(CsrfFilter.java:75) [classes/:?]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [catalina.jar:9.0.37]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [catalina.jar:9.0.37]
        at ro.sync.auth.ClientSessionFilter.doFilter(ClientSessionFilter.java:72) [classes/:?]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [catalina.jar:9.0.37]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [catalina.jar:9.0.37]
        at ro.sync.servlet.ssl.SSLRedirectFilter.doFilter(SSLRedirectFilter.java:69) [classes/:?]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [catalina.jar:9.0.37]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [catalina.jar:9.0.37]
        at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449) [shiro-web.jar:1.5.2]
        at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365) [shiro-web.jar:1.5.2]
        at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90) [shiro-core.jar:1.5.2]
        at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83) [shiro-core.jar:1.5.2]
        at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:387) [shiro-core.jar:1.5.2]
        at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362) [shiro-web.jar:1.5.2]
        at ro.sync.auth.WebappShiroFilter.doFilterInternal(WebappShiroFilter.java:68) [classes/:?]
        at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125) [shiro-web.jar:1.5.2]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [catalina.jar:9.0.37]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [catalina.jar:9.0.37]
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) [catalina.jar:9.0.37]
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [catalina.jar:9.0.37]
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) [catalina.jar:9.0.37]
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) [catalina.jar:9.0.37]
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [catalina.jar:9.0.37]
        at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:690) [catalina.jar:9.0.37]
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) [catalina.jar:9.0.37]
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) [catalina.jar:9.0.37]
        at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:373) [tomcat-coyote.jar:9.0.37]
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) [tomcat-coyote.jar:9.0.37]
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) [tomcat-coyote.jar:9.0.37]
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1589) [tomcat-coyote.jar:9.0.37]
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-coyote.jar:9.0.37]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) [?:?]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) [?:?]
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-util.jar:9.0.37]
        at java.lang.Thread.run(Thread.java:832) [?:?]
 
manojdcoder
Posts: 67
Joined: Thu Oct 29, 2020 12:01 am

Re: Extending LinkTextResolver

Post by manojdcoder »

Finally I managed to get references fully working using both RelativeReferenceResolver and URIResolver

Code: Select all

PluginWorkspaceProvider.getPluginWorkspace().addRelativeReferencesResolver();
PluginWorkspaceProvider.getPluginWorkspace().getXMLUtilAccess().addPriorityURIResolver();
I pass fully qualified document / reference urls to Oxygen, which is converted to relative url (just filename in my case) by RelativeReferenceResolver while inserting it into document. The same is converted back to fully qualified url using URIResolver when it tries to fetch the document / reference content.

Now I have one last issue, when I insert a Cross Reference to a DITA document / topic [Example 1], it renders the title of the document / topic automatically.

Example 1:

Code: Select all

<xref href="filename.xml"/><
But when I insert a Cross Reference to a DITA Element [Example 2], it simply shows empty space instead the element's content

Example 2:

Code: Select all

<xref href="filename.xml#topic/elementId"/>
Any thoughts how to render the content of the element there? Is that something supported by Oxygen?
mihaela
Posts: 504
Joined: Wed May 20, 2009 2:40 pm

Re: Extending LinkTextResolver

Post by mihaela »

Hi,

The fact that the cross reference to an element shows empty space is intended. We do this to be consistent with the output. If you will generate a PDF from your file that contains a cross reference to an element you will see that there is no link in the document if you do not insert some text in the xref element. So, if you choose to render some text from the referenced element you will leave the impression that this is the way the output will look like and the user will not enter some text there.

Anyway, if you still really want to change this beaviour you will have to overwrite the default implementation from ro.sync.ecss.extensions.dita.link.DitaLinkTextResolver.resolveReference(AuthorNode).
Please let us know if you need more details.

Best Regards,
Mihaela
Mihaela Calotescu
http://www.oxygenxml.com
manojdcoder
Posts: 67
Joined: Thu Oct 29, 2020 12:01 am

Re: Extending LinkTextResolver

Post by manojdcoder »

Thank you Mihaela for the prompt response.

Yes, please. I would like more details on customising the default behaviour, render the content of the element thats referenced.
mihaela
Posts: 504
Joined: Wed May 20, 2009 2:40 pm

Re: Extending LinkTextResolver

Post by mihaela »

Hello,

First you have to download the default framework operations source code [1].
You will see that the DitaLinkTextResolver is created in the following method from DITAExtensionsBundle:

Code: Select all

ro.sync.ecss.extensions.dita.DITAExtensionsBundle.createLinkTextResolver()
So, what you can do is to create and use your own extensions bundle [2] that extends the default DITAExtensionsBundle and ovverwrite the createLinkTextResolver method. You may provide an extension of the default DitaLinkTextResolver and provide the result you want for element references in resolveReference(AuthorNode).

[1] https://www.oxygenxml.com/oxygen_sdk/do ... ource-code
[2] https://www.oxygenxml.com/doc/versions/ ... undle.html

Best regards,
Mihaela
Mihaela Calotescu
http://www.oxygenxml.com
manojdcoder
Posts: 67
Joined: Thu Oct 29, 2020 12:01 am

Re: Extending LinkTextResolver

Post by manojdcoder »

Great, Thank you. Exactly what I was looking for.
Post Reply