jackrabbit-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Francisco Carriedo Scher <fcarrie...@gmail.com>
Subject Re: Creating a nt:linkedFile
Date Fri, 06 Apr 2012 11:37:56 GMT
Hi there,

i wrote a custom IOHandler to have the nt:linkedFile nodes retrieved as the
file they link through the browser. I would like to offer it to anyone who
faces the same problem so i post it here and i will put it as answer to the
helpful link i found (see below). There are three code snippets: declaring
the nt:linkedFile as noncollection on the config.xml file, the IOHandler
Java class itself (the change needs to recompile the jackrabbit-jcr-server
project) and the line to add in the config.xml file (within
jackrabbit-webapp project, recompile it too) in order to use the brandnew
IOHandler (order matters, put the declaration on the first position). Here
it goes:

*******************************************************************************************************************
Set the nt:linkedFile as noncollection (config.xml on jackrabbit-webapp):

    [...]
    <!--
     Define nodetypes, that should never by displayed as 'collection'
    -->
    <noncollection>
        <nodetypes>
            <nodetype>nt:file</nodetype>
            *<nodetype>nt:linkedFile</nodetype>*
            <nodetype>nt:resource</nodetype>
        </nodetypes>
    </noncollection>
    [...]

*******************************************************************************************************************
LinkHandler.java (put it on
*org.apache.jackrabbit.server.io.LinkHandler*package within the
jackrabbit-jcr-server project).

package org.apache.jackrabbit.server.io;

import java.io.IOException;

import javax.jcr.Item;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.Property;
import javax.jcr.RepositoryException;

import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.webdav.DavResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LinkHandler implements IOHandler {

    private static Logger log = LoggerFactory.getLogger(LinkHandler.class);

    private IOManager ioManager;

    public IOManager getIOManager() {
        return this.ioManager;
    }

    public void setIOManager(IOManager ioManager) {
        this.ioManager = ioManager;

    }

    public String getName() {
        return getClass().getName();
    }

    public boolean canImport(ImportContext context, boolean isCollection) {
        // As we do not want this handler to manage the links on their
income
        // because they are properly managed by the existing handlers
        return false;
    }

    public boolean canImport(ImportContext context, DavResource resource) {
        // As we do not want this handler to manage the links on their
income
        // because they are properly managed by the existing handlers
        return false;
    }

    public boolean importContent(ImportContext context, boolean
isCollection) throws IOException {
        // TODO Auto-generated method stub
        return false;
    }

    public boolean importContent(ImportContext context, DavResource
resource) throws IOException {
        // TODO Auto-generated method stub
        return false;
    }

    public boolean canExport(ExportContext context, boolean isCollection) {
        // Error controlling i supose...
        if (context == null)
            return false;

        Item item;
        Node node;
        boolean itemIsNotNull;
        boolean isNode;
        boolean isLink;
        boolean result = false;


        item = context.getExportRoot();
        node = (Node) item;

        itemIsNotNull = (item != null);
        isNode = (item.isNode());
        try {
            // There is no content but a reference to content
            isLink = (node.getProperty("jcr:content") != null);
            // Everything right? Then true
            result = itemIsNotNull && isNode && isLink && (!isCollection);
        } catch (PathNotFoundException e) {
            e.printStackTrace();
        } catch (RepositoryException e) {
            e.printStackTrace();
        }
        return result;
    }

    public boolean canExport(ExportContext context, DavResource resource) {
        if (resource == null) {
            return false;
        }
        return canExport(context, resource.isCollection());
    }

    public boolean exportContent(ExportContext context, boolean
isCollection) throws IOException {

        if (!canExport(context,isCollection))
            throw new IOException(getName() + ": Cannot export " +
context.getExportRoot());

        try {
            Node linkedFile = (Node) context.getExportRoot();
            Node contentNode =
linkedFile.getProperty("jcr:content").getNode();
            System.out.println("LinkedFile: " + linkedFile.getName());
            if (context.hasStream()) {
                exportData(context,isCollection, contentNode);
            }
            return true;
        } catch (RepositoryException e) {

        }
        return false;
    }

    public boolean exportContent(ExportContext context, DavResource
resource) throws IOException {
        if (!canExport(context, resource)) {
            throw new IOException(getName() + ": Cannot export " +
context.getExportRoot());
        }
        return exportContent(context, resource.isCollection());
    }


    /**
     * Checks if the given content node contains a jcr:data property
     * and spools its value to the output stream of the export context.<br>
     * Please note, that subclasses that define a different structure of the
     * content node should create their own
     * {@link  #exportData(ExportContext, boolean, Node) exportData} method.
     *
     * @param context export context
     * @param isCollection <code>true</code> if collection
     * @param contentNode the content node
     * @throws IOException if an I/O error occurs
     */
    protected void exportData(ExportContext context, boolean isCollection,
Node contentNode) throws IOException, RepositoryException {
        if (contentNode.hasProperty(JcrConstants.JCR_DATA)) {
            Property p = contentNode.getProperty(JcrConstants.JCR_DATA);
            IOUtil.spool(p.getStream(), context.getOutputStream());
        } // else: stream undefined -> content length was not set
    }

}


*******************************************************************************************************************
Declare the IOHandler:

    [...]
     <class name="org.apache.jackrabbit.server.io.IOManagerImpl" />
        *<iohandler>**
            <class name="org.apache.jackrabbit.server.io.LinkHandler" />
        </iohandler>*
        <iohandler>
            <class name="org.apache.jackrabbit.server.io.VersionHandler" />
        </iohandler>
        <iohandler>
            <class
name="org.apache.jackrabbit.server.io.VersionHistoryHandler" />
        </iohandler>
     [...]


******************************************************************************************************
END
******************************************************************************************************

Just to recall it, tips about the behaviour of the garbage collector and
links? (asked on previous posts).


Thanks for your attention!



2012/4/6 Francisco Carriedo Scher <fcarriedos@gmail.com>

> Hi there,
>
> right after posting the last question i found a helpful one:
>
>
> http://jackrabbit.510166.n4.nabble.com/Using-nt-linkedFile-s-in-WebDav-td513737.html
>
> Anyway, i am pretty interested in the behaviour of the garbage collector
> respecting the links (will i obtain the same behaviour than the links in
> Unix?).
>
> Thank you very much for your attention!
>
>
>
>
>
>
>
>
>
> 2012/4/5 Francisco Carriedo Scher <fcarriedos@gmail.com>
>
>> Hi there,
>>
>> i am creating now nt:linkedfile nodes to nt:file nodes correctly but as
>> i tried to access the contents through the browser i am not getting the
>> content actually and getting an empty directory listing instead (the same
>> of accessing an empty nt:folder node. By the way i noticed that nt:file
>> nodes are exposed in the browser like this:
>>
>> http://localhost:8080/name/repository/default/file.jpg
>>
>> and linked files like this (note the ending backslash):
>>
>> http://localhost:8080/name/repository/default/linkedfile.jpg*/*
>>
>>
>> The code i am using is the following and i access the repository through
>> Webdav:
>>
>>                         *// Node to place the nt:linkedfile node*
>>             folderNode = session.getNode(directoryForLink);
>>             *// The nt:file node the new link will point to*
>>             fileToLink = session.getNode(pathToLink);
>>             *// Creating the link node...*
>>             newLink = folderNode.addNode(linkname,
>> JcrConstants.NT_LINKEDFILE);
>>             *// Adding the content as a reference to the "real" content*
>>             newLink.setProperty("jcr:content",
>> fileToLink.getNode("jcr:content"));
>>             session.save();
>>
>> Is this the expected behaviour? What else should i do to get the linked
>> files exposing the content through the browser as if they were files?
>>
>>
>> Additionally, will the scenario described above (files, linked files,
>> exposing everything through Webdav) work correctly with the garbage
>> collection running? By working i mean than the following would go fine:
>>
>> 1) User A stores a photo file myPhoto.jpg
>> 2) User B stores a link to myPhoto.jpg named BsphotoFile.jpg
>> 3) User A decides to delete myPhoto.jpg file
>> 4) Is B still able to access the BsphotoFile.jpg?
>>
>> I expect the garbage collection to work similar to Unix links (deleting
>> link only deletes the file when it is the last link) but i prefer to
>> ensure, any info about this?
>>
>>
>> Thanks for your attention in advance!
>>
>> Regards.
>>
>>
>>
>>
>> 2012/3/22 Francisco Carriedo Scher <fcarriedos@gmail.com>
>>
>>> Thank you very much David, i was trying to clone the procedure of
>>> creating a nt:file node, setting the REFERENCE as a property worked
>>> perfectly and the link is created.
>>>
>>> Thank you very much for your time!
>>>
>>>
>>> 2012/3/21 David Buchmann <david.buchmann@liip.ch>
>>>
>>>> -----BEGIN PGP SIGNED MESSAGE-----
>>>> Hash: SHA1
>>>>
>>>> answer is inline
>>>>
>>>> Am 20.03.2012 23:40, schrieb Francisco Carriedo Scher:
>>>> > Thanks Lukas for your quick response, anyway i'm affraid i am still
>>>> missing
>>>> > something...
>>>> >
>>>> > First i add the "mix:referenceable" not only to the nt:file node but
>>>> to
>>>> > it's jcr:content node too for the nt:file to be linked later:
>>>> >
>>>> >
>>>> >         Node fileNode = folderNode.addNode(file.getName(), "nt:file");
>>>> >         fileNode.addMixin("mix:referenceable");
>>>> >         Node resNode = fileNode.addNode("jcr:content", "nt:resource");
>>>> >         resNode.addMixin("mix:referenceable");
>>>> >         resNode.setProperty("jcr:mimeType", mimeType);
>>>> >         resNode.setProperty("jcr:encoding", encoding);
>>>> >         resNode.setProperty("jcr:data", binary);
>>>> >         session.save();
>>>> >
>>>> >
>>>> > and then tried this code:
>>>> >
>>>> >             folderNode = session.getNode(directoryForLink);
>>>> >             fileToLink = session.getNode(pathToLink);
>>>> >
>>>> >             for (NodeType aux : fileToLink.getMixinNodeTypes())
>>>> >                 System.out.println(aux.getName());
>>>> >             *// PRINTS: mix:referenceable*
>>>> >
>>>> >             resNode = fileToLink.getNode("jcr:content");
>>>> >
>>>> >             for (NodeType aux : resNode.getMixinNodeTypes())
>>>> >                 System.out.println(aux.getName());
>>>> >             *// PRINTS: NOTHING*
>>>> >
>>>> >             newLink = folderNode.addNode(linkname,
>>>> > JcrConstants.NT_LINKEDFILE);
>>>> >             newLink.addNode(JcrConstants.JCR_CONTENT,
>>>> > resNode.getIdentifier());
>>>>
>>>> you try to add a node with the name that is in JCR_CONTENT and the type
>>>> of the identifier. that makes no sense for jcr. the reference is a
>>>> property. a child node can never be a reference.
>>>> you want to do something like:
>>>> newLink.setProperty("jcr:content", resNode);
>>>>
>>>> then you can do link.getProperty("jcr:content").getNode() to get the
>>>> referenced node.
>>>>
>>>> >             *// EXCEPTION RAISES (during the line above)        *
>>>> >             session.save();
>>>> >
>>>> > and got this exception:
>>>> >
>>>> > javax.jcr.nodetype.NoSuchNodeTypeException:
>>>> > {}c01df2eb-7af0-49c7-a7fd-1a4fbc3b9822
>>>> >
>>>> >
>>>> > Any idea? Thanks for your attention!
>>>> >
>>>> >
>>>> >
>>>> >
>>>> > 2012/3/20 Lukas Kahwe Smith <mls@pooteeweet.org>
>>>> >
>>>> >>
>>>> >> On Mar 20, 2012, at 17:31 , Francisco Carriedo Scher wrote:
>>>> >>
>>>> >>> Hello,
>>>> >>>
>>>> >>> i have been trying to create a nt:linkedFile node but i don't
know
>>>> what
>>>> >> is
>>>> >>> "REFERENCE" in
>>>> >>>
>>>> >>> [nt:linkedFile] > nt:hierarchyNode
>>>> >>>  primaryitem jcr:content
>>>> >>>  - jcr:content (REFERENCE) mandatory
>>>> >>>
>>>> >>> I have tried with the path of the node i want to link, a reference
>>>> >> obtained
>>>> >>> through JcrUtils.getReferences(nodeToLink)... But different
>>>> exceptions
>>>> >>> arised.
>>>> >>
>>>> >>
>>>> >> references work on UUID's
>>>> >> the target node needs to have the mixing type "mix:referenceable"
>>>> which
>>>> >> would give it a UUID automatically on save.
>>>> >>
>>>> >> regards,
>>>> >> Lukas Kahwe Smith
>>>> >> mls@pooteeweet.org
>>>> >>
>>>> >>
>>>> >>
>>>> >>
>>>> >
>>>>
>>>> - --
>>>> Liip AG // Agile Web Development // T +41 26 422 25 11
>>>> CH-1700 Fribourg // PGP 0xA581808B // www.liip.ch
>>>> -----BEGIN PGP SIGNATURE-----
>>>> Version: GnuPG v1.4.10 (GNU/Linux)
>>>> Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
>>>>
>>>> iEYEARECAAYFAk9pnVwACgkQqBnXnqWBgIv48ACfUIgy5KBnVkr3NK7iRB30LIiv
>>>> jT4AoLNruVeXXYM1hOCuZ06Ojoy2DOYu
>>>> =msAN
>>>> -----END PGP SIGNATURE-----
>>>>
>>>
>>>
>>
>

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message