<rootspace
name="System Accessors"
public="true"
uri="urn:org:elbeesee:ext:system:accessors">
<accessor>
<id>system.SpaceStaticResourceList.accessor</id>
<class>org.elbeesee.ext.system.SpaceStaticResourceListAccessor</class>
<grammar>
<active>
<identifier>active:ssrls</identifier>
<argument name="space" desc="space identifier (urn)"/>
<argument name="version" min="0" max="1" desc="space version"/>
</active>
</grammar>
</accessor>
<fileset>
<regex>res:/resources/stylesheets/.*</regex>
</fileset>
<import>
<uri>urn:org:netkernel:xml:core</uri>
<private/>
</import>
<import>
<uri>urn:org:netkernel:ext:layer1</uri>
<private/>
</import>
</rootspace>
Nothing special there, same definition as the original active:sls. It's in the code that things are different, so lets have a look at that :
What happens here ?
1) Determine the module of the rootspace that is passed as an argument.
2) Extract the rootspace from the module.xml of that module.
3) Determine all possible file resources of the module.
4) Loop through the filesets defined in the rootspace and use those to filter the file resources so only the valid ones remain.
This is the stylesheet that is used to extract the rootspace from module.xml :
Nothing special there, same definition as the original active:sls. It's in the code that things are different, so lets have a look at that :
package org.elbeesee.ext.system;
// Author: Tom Geudens
// Date : 2012/04/08
// The usual suspects for an accessor.
import org.netkernel.layer0.nkf.*;
import org.netkernel.layer0.meta.impl.SourcedArgumentMetaImpl;
import org.netkernel.module.standard.endpoint.StandardAccessorImpl;
// Processing.
import java.io.File;
import java.net.URI;
import java.util.Iterator;
import org.netkernel.container.IKernel;
import org.netkernel.module.standard.StandardSpace;
import org.netkernel.layer0.boot.BootUtils;
import org.netkernel.layer0.representation.IHDSNode;
import org.netkernel.layer0.representation.impl.HDSBuilder;
import org.netkernel.layer0.urii.SimpleIdentifierImpl;
import org.netkernel.urii.ISpaceWithIdentity;
import org.netkernel.urii.impl.Version;
public class SpaceStaticResourceListAccessor extends StandardAccessorImpl {
public SpaceStaticResourceListAccessor() {
this.declareThreadSafe();
this.declareArgument(new SourcedArgumentMetaImpl("space",null,null,new Class[] {String.class}));
this.declareArgument(new SourcedArgumentMetaImpl("version",null,null,new Class[] {String.class}));
}
private IHDSNode listDirectory(INKFRequestContext aContext, File aDirectoryFile) {
return listDirectory(aContext, aDirectoryFile, "res:/");
}
private IHDSNode listDirectory(INKFRequestContext aContext, File aDirectoryFile, String aResourcePath) {
HDSBuilder lDirectoryBuilder = new HDSBuilder();
File[] lDirectoryFiles = aDirectoryFile.listFiles();
lDirectoryBuilder.pushNode("resources");
for (int i=0; i < lDirectoryFiles.length; i++) {
if (lDirectoryFiles[i].isDirectory()) {
String lResourcePath = aResourcePath + lDirectoryFiles[i].getName() + "/";
lDirectoryBuilder.importChildren(listDirectory(aContext,lDirectoryFiles[i],lResourcePath).getFirstNode("/resources"));
}
else {
lDirectoryBuilder.addNode("resource", aResourcePath + lDirectoryFiles[i].getName());
}
}
lDirectoryBuilder.popNode();
return lDirectoryBuilder.getRoot();
}
public void onSource(INKFRequestContext aContext) throws Exception {
// One mandatory argument
String aSpaceIdentifier = aContext.getThisRequest().getArgumentValue("space");
// One optional argument
Version aVersion = null;
if (aContext.getThisRequest().argumentExists("version")) {
aVersion = new Version(aContext.getThisRequest().getArgumentValue("version"));
}
// Processing
IKernel lKernel = null;
ISpaceWithIdentity lSpace = null;
StandardSpace lSS = null;
String lSource;
lKernel = aContext.getKernelContext().getKernel();
lSpace = lKernel.getSpace(new SimpleIdentifierImpl(aSpaceIdentifier), aVersion, aVersion);
if (lSpace == null) {
throw new NKFException("Space is not found");
}
if (!(lSpace instanceof StandardSpace)) {
throw new NKFException ("Space is not a standard module space");
}
lSS = (StandardSpace)lSpace;
lSource = lSS.getOwningModule().getSource().toString();
lSource = BootUtils.fixURIString(lSource);
IHDSNode lModuleXML = null;
IHDSNode lRootSpace = null;
if (lSource.startsWith("file:")) {
lModuleXML = aContext.source(lSource + "module.xml",IHDSNode.class);
}
INKFRequest subrequest = aContext.createRequest("active:xslt");
subrequest.addArgumentByValue("operand", lModuleXML);
subrequest.addArgument("operator", "res:/resources/stylesheets/module.xsl");
subrequest.addArgumentByValue("spaceid", aSpaceIdentifier);
subrequest.setRepresentationClass(IHDSNode.class);
lRootSpace = (IHDSNode)aContext.issueRequest(subrequest);
File lSourceFile = new File(URI.create(lSource));
IHDSNode lSourceContent = listDirectory(aContext,lSourceFile);
HDSBuilder lValidResources = new HDSBuilder();
lValidResources.pushNode("resources");
Iterator<IHDSNode> lIterator = lRootSpace.getNodes("/rootspace/fileset").iterator();
while(lIterator.hasNext()) {
IHDSNode lFileset = lIterator.next();
String lGlob = null;
String lRegex = null;
lGlob = (String)lFileset.getFirstValue("glob");
lRegex = (String)lFileset.getFirstValue("regex");
if (lGlob != null) {
System.out.println("fileset glob = " + lGlob);
}
if (lRegex != null) {
Iterator<IHDSNode> lIterResource = lSourceContent.getNodes("/resources/resource").iterator();
while (lIterResource.hasNext()) {
IHDSNode lResource = lIterResource.next();
String lResourceString = (String)lResource.getValue();
if (lResourceString.matches(lRegex)) {
lValidResources.addNode("resource", lResourceString);
}
}
}
}
lValidResources.popNode();
// One response
INKFResponse response = null;
// response = aContext.createResponseFrom(lRootSpace.getRoot());
// response = aContext.createResponseFrom(lSourceContent.getRoot());
response = aContext.createResponseFrom(lValidResources.getRoot());
}
}
What happens here ?
1) Determine the module of the rootspace that is passed as an argument.
2) Extract the rootspace from the module.xml of that module.
3) Determine all possible file resources of the module.
4) Loop through the filesets defined in the rootspace and use those to filter the file resources so only the valid ones remain.
This is the stylesheet that is used to extract the rootspace from module.xml :
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:nk="http://netkernel.org"
version="1.0">
<xsl:output method="xml"
indent="yes"
encoding="UTF-8"
omit-xml-declaration="yes"/>
<xsl:param name="spaceid" nk:class="java.lang.String" />
<xsl:template match="/module">
<xsl:copy-of select="rootspace[@uri=$spaceid]"/>
</xsl:template>
</xsl:stylesheet>
And ... done.
Or so it seems, you might have noticed I labeled this entry "part 1". There's some work to be done yet :
* Next to regex, a fileset can also be glob or grammar defined. All three should be handled (at the moment only regex is).
* A fileset definition can contain a rewrite. I want to get the real valid resources, so we need to provide a rewrite too.
* A module can be expanded or jarred. At the moment the accessor only works for expanded modules. I want jars too.
As you can see there's room for a "part 2" (and beyond ?). Watch this space ! There might be other requirements you are interested in. Let me know and I'll add them.
Since this was a lot of code real fast, my next blog entry will once again be a philosophical one. You've been warned !
And ... done.
Or so it seems, you might have noticed I labeled this entry "part 1". There's some work to be done yet :
* Next to regex, a fileset can also be glob or grammar defined. All three should be handled (at the moment only regex is).
* A fileset definition can contain a rewrite. I want to get the real valid resources, so we need to provide a rewrite too.
* A module can be expanded or jarred. At the moment the accessor only works for expanded modules. I want jars too.
As you can see there's room for a "part 2" (and beyond ?). Watch this space ! There might be other requirements you are interested in. Let me know and I'll add them.
Since this was a lot of code real fast, my next blog entry will once again be a philosophical one. You've been warned !