001/*
002 *  Copyright 2010 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.plugins.repository.metadata.jcr;
017
018import java.util.ArrayList;
019import java.util.Collection;
020
021import javax.jcr.ItemExistsException;
022import javax.jcr.Node;
023import javax.jcr.NodeIterator;
024import javax.jcr.PathNotFoundException;
025import javax.jcr.RepositoryException;
026import javax.jcr.lock.Lock;
027
028import org.apache.jackrabbit.util.Text;
029
030import org.ametys.plugins.repository.AmetysRepositoryException;
031import org.ametys.plugins.repository.RepositoryConstants;
032import org.ametys.plugins.repository.RepositoryIntegrityViolationException;
033import org.ametys.plugins.repository.jcr.NodeTypeHelper;
034import org.ametys.plugins.repository.metadata.ModifiableFile;
035import org.ametys.plugins.repository.metadata.ModifiableFolder;
036import org.ametys.plugins.repository.metadata.UnknownMetadataException;
037
038/**
039 * Java binding of a nt:folder JCR Node.<p>
040 * {@link Text#escapeIllegalJcrChars(String)} is used for
041 * escaping invalid JCR characters or character sequences.
042 */
043public class JCRFolder implements ModifiableFolder
044{
045    private Node _node;
046    private boolean _lockAlreadyChecked;
047    
048    /**
049     * Constructor
050     * @param node the nt:folder Node
051     */
052    public JCRFolder(Node node)
053    {
054        _node = node;
055    }
056    
057    /**
058     * Retrieves the underlying node.
059     * @return the underlying node.
060     */
061    public Node getNode()
062    {
063        return _node;
064    }
065    
066    @Override
067    public String getName() throws AmetysRepositoryException
068    {
069        try
070        {
071            return Text.unescapeIllegalJcrChars(_node.getName());
072        }
073        catch (RepositoryException e)
074        {
075            throw new AmetysRepositoryException(e);
076        }
077    }
078
079    public Collection<ModifiableFolder> getFolders()
080    {
081        ArrayList<ModifiableFolder> folders = new ArrayList<>();
082        try
083        {
084            NodeIterator it = _node.getNodes();
085            while (it.hasNext())
086            {
087                Node node = it.nextNode();
088                
089                if (NodeTypeHelper.isNodeType(node, "nt:folder"))
090                {
091                    folders.add(new JCRFolder(node));
092                }
093            }
094            
095            return folders;
096        }
097        catch (RepositoryException e)
098        {
099            throw new AmetysRepositoryException(e);
100        }
101    }
102
103    public ModifiableFolder getFolder(String folderName)
104    {
105        try
106        {
107            Node node = _node.getNode(Text.escapeIllegalJcrChars(folderName));
108            return new JCRFolder(node);
109        }
110        catch (PathNotFoundException e)
111        {
112            throw new UnknownMetadataException(e);
113        }
114        catch (RepositoryException e)
115        {
116            throw new AmetysRepositoryException(e);
117        }
118    }
119    
120    public ModifiableFolder addFolder(String folderName)
121    {
122        try
123        {
124            _checkLock();
125            Node node = _node.addNode(Text.escapeIllegalJcrChars(folderName), "nt:folder");
126            return new JCRFolder(node);
127        }
128        catch (ItemExistsException e)
129        {
130            throw new RepositoryIntegrityViolationException(e);
131        }
132        catch (RepositoryException e)
133        {
134            throw new AmetysRepositoryException(e);
135        }
136    }
137    
138    public Collection<ModifiableFile> getFiles()
139    {
140        ArrayList<ModifiableFile> files = new ArrayList<>();
141        try
142        {
143            NodeIterator it = _node.getNodes();
144            while (it.hasNext())
145            {
146                Node node = it.nextNode();
147                
148                if (NodeTypeHelper.isNodeType(node, "nt:file"))
149                {
150                    files.add(new JCRFile(node));
151                }
152            }
153            
154            return files;
155        }
156        catch (RepositoryException e)
157        {
158            throw new AmetysRepositoryException(e);
159        }
160    }
161    
162    @Override
163    public boolean hasFile(String fileName) throws AmetysRepositoryException
164    {
165        try
166        {
167            return _node.hasNode(Text.escapeIllegalJcrChars(fileName));
168        }
169        catch (RepositoryException e)
170        {
171            throw new AmetysRepositoryException(e);
172        }
173    }
174
175    public ModifiableFile getFile(String fileName)
176    {
177        try
178        {
179            Node node = _node.getNode(Text.escapeIllegalJcrChars(fileName));
180            return new JCRFile(node);
181        }
182        catch (PathNotFoundException e)
183        {
184            throw new UnknownMetadataException(e);
185        }
186        catch (RepositoryException e)
187        {
188            throw new AmetysRepositoryException(e);
189        }
190    }
191    
192    public ModifiableFile addFile(String fileName)
193    {
194        try
195        {
196            _checkLock();
197            Node node = _node.addNode(Text.escapeIllegalJcrChars(fileName), "nt:file");
198            return new JCRFile(node);
199        }
200        catch (ItemExistsException e)
201        {
202            throw new RepositoryIntegrityViolationException(e);
203        }
204        catch (RepositoryException e)
205        {
206            throw new AmetysRepositoryException(e);
207        }
208    }
209
210    @Override
211    public void remove(String name) throws AmetysRepositoryException
212    {
213        try
214        {
215            _checkLock();
216            Node node = _node.getNode(Text.escapeIllegalJcrChars(name));
217            node.remove();
218        }
219        catch (PathNotFoundException e)
220        {
221            throw new UnknownMetadataException(e);
222        }
223        catch (RepositoryException e)
224        {
225            throw new AmetysRepositoryException(e);
226        }
227    }
228
229    @Override
230    public void removeAll() throws AmetysRepositoryException
231    {
232        try
233        {
234            _checkLock();
235            NodeIterator it = _node.getNodes();
236            while (it.hasNext())
237            {
238                Node node = it.nextNode();
239                node.remove();
240            }
241        }
242        catch (RepositoryException e)
243        {
244            throw new AmetysRepositoryException(e);
245        }
246    }
247    
248    private void _checkLock() throws RepositoryException
249    {
250        if (!_lockAlreadyChecked && _node.isLocked())
251        {
252            Lock lock = _node.getSession().getWorkspace().getLockManager().getLock(_node.getPath());
253            Node lockHolder = lock.getNode();
254            
255            lockHolder.getSession().getWorkspace().getLockManager().addLockToken(lockHolder.getProperty(RepositoryConstants.METADATA_LOCKTOKEN).getString());
256            _lockAlreadyChecked = true;
257        }
258    }
259}