1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package com.xpn.xwiki.script.sheet

File SheetScriptService.java

 

Coverage histogram

../../../../../img/srcFileCovDistChart8.png
54% of files have more coverage

Code metrics

2
26
11
1
235
98
14
0.54
2.36
11
1.27

Classes

Class Line # Actions
SheetScriptService 50 26 0% 14 8
0.794871879.5%
 

Contributing tests

This file is covered by 2 tests. .

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package com.xpn.xwiki.script.sheet;
21   
22    import java.lang.reflect.Field;
23    import java.lang.reflect.Method;
24    import java.util.ArrayList;
25    import java.util.List;
26   
27    import javax.inject.Inject;
28    import javax.inject.Named;
29    import javax.inject.Singleton;
30   
31    import org.xwiki.bridge.DocumentAccessBridge;
32    import org.xwiki.bridge.DocumentModelBridge;
33    import org.xwiki.component.annotation.Component;
34    import org.xwiki.model.reference.DocumentReference;
35    import org.xwiki.script.service.ScriptService;
36    import org.xwiki.sheet.SheetBinder;
37    import org.xwiki.sheet.SheetManager;
38   
39    import com.xpn.xwiki.api.Document;
40   
41    /**
42    * Exposes {@link SheetManager} and {@link SheetBinder} to Velocity scripts.
43    *
44    * @version $Id: a711de29f6409093d32f9777ba18e08e40881e3e $
45    * @since 3.2M3
46    */
47    @Component
48    @Named("sheet")
49    @Singleton
 
50    public class SheetScriptService implements ScriptService
51    {
52    /**
53    * The component used to manage the sheets.
54    */
55    @Inject
56    private SheetManager sheetManager;
57   
58    /**
59    * The component used to manage the class sheet bindings.
60    */
61    @Inject
62    @Named("class")
63    private SheetBinder classSheetBinder;
64   
65    /**
66    * The component used to manage the document sheet bindings.
67    */
68    @Inject
69    @Named("document")
70    private SheetBinder documentSheetBinder;
71   
72    /**
73    * The component used to check access rights on sheets.
74    */
75    @Inject
76    private DocumentAccessBridge documentAccessBridge;
77   
78    /**
79    * Returns the list of sheets associated with a XWiki document.
80    *
81    * @param document the document for which to retrieve the sheets
82    * @param action the action for which to retrieve the sheets ('view', 'edit' etc.)
83    * @return the list of sheets available for the specified document on the specified action; these are sheets
84    * designed to be displayed when the specified action is performed on the given document; only the sheets
85    * that the current user has the right to view are returned
86    */
 
87  50 toggle public List<DocumentReference> getSheets(Document document, String action)
88    {
89  50 return filterViewable(this.sheetManager.getSheets(getReadOnlyDocument(document), action));
90    }
91   
92    /**
93    * Retrieves the list of sheets explicitly bound to a XWiki class.
94    *
95    * @param classDocument a document holding a class definition
96    * @return the list of sheets explicitly bound to the given class; these are sheets designed to be applied to
97    * documents that have objects of the given class; only the sheets that the current user has the right to
98    * view are returned
99    */
 
100  12 toggle public List<DocumentReference> getClassSheets(Document classDocument)
101    {
102  12 return filterViewable(this.classSheetBinder.getSheets(getReadOnlyDocument(classDocument)));
103    }
104   
105    /**
106    * Binds a sheet to a XWiki class. Changes are not persisted until the class document is saved.
107    *
108    * @param classDocument a document holding a class definition
109    * @param sheetReference a reference to a sheet
110    * @return {@code true} if the sheet was successfully bound, {@code false} otherwise
111    */
 
112  2 toggle public boolean bindClassSheet(Document classDocument, DocumentReference sheetReference)
113    {
114  2 return this.classSheetBinder.bind(getModifiableDocument(classDocument), sheetReference);
115    }
116   
117    /**
118    * Removes the binding between a XWiki class and a sheet. Changes are not persisted until the class document is
119    * saved.
120    *
121    * @param classDocument a document holding a class definition
122    * @param sheetReference a reference to a sheet
123    * @return {@code true} if the sheet was successfully unbound, {@code false} otherwise
124    */
 
125  0 toggle public boolean unbindClassSheet(Document classDocument, DocumentReference sheetReference)
126    {
127  0 return this.classSheetBinder.unbind(getModifiableDocument(classDocument), sheetReference);
128    }
129   
130    /**
131    * Retrieves the list of sheets explicitly bound to a XWiki document.
132    *
133    * @param document a XWiki document
134    * @return the list of sheets explicitly bound to the given document; only the sheets that the current user has the
135    * right to view are returned
136    */
 
137  12 toggle public List<DocumentReference> getDocumentSheets(Document document)
138    {
139  12 return filterViewable(this.documentSheetBinder.getSheets(getReadOnlyDocument(document)));
140    }
141   
142    /**
143    * Binds a sheet to a XWiki document. Changes are not persisted until the document is saved.
144    *
145    * @param document a XWiki document
146    * @param sheetReference a reference to a sheet
147    * @return {@code true} if the sheet was successfully bound, {@code false} otherwise
148    */
 
149  0 toggle public boolean bindDocumentSheet(Document document, DocumentReference sheetReference)
150    {
151  0 return this.documentSheetBinder.bind(getModifiableDocument(document), sheetReference);
152    }
153   
154    /**
155    * Removes the binding between a XWiki document and a sheet. Changes are not persisted until the document is saved.
156    *
157    * @param document a XWiki document
158    * @param sheetReference a reference to a sheet
159    * @return {@code true} if the sheet was successfully unbound, {@code false} otherwise
160    */
 
161  0 toggle public boolean unbindDocumentSheet(Document document, DocumentReference sheetReference)
162    {
163  0 return this.documentSheetBinder.unbind(getModifiableDocument(document), sheetReference);
164    }
165   
166    /**
167    * Retrieves the list of documents that have explicitly bound the specified sheet.
168    *
169    * @param sheetReference a reference to a sheet
170    * @return the list of documents that have the specified sheet explicitly bound
171    */
 
172  1 toggle public List<DocumentReference> getDocuments(DocumentReference sheetReference)
173    {
174  1 List<DocumentReference> documents = new ArrayList<DocumentReference>();
175  1 documents.addAll(this.documentSheetBinder.getDocuments(sheetReference));
176  1 documents.addAll(this.classSheetBinder.getDocuments(sheetReference));
177  1 return filterViewable(documents);
178    }
179   
180    /**
181    * @param documentReferences a list of document references
182    * @return only the references that point to documents that can be viewed by the current user
183    */
 
184  75 toggle private List<DocumentReference> filterViewable(List<DocumentReference> documentReferences)
185    {
186  75 List<DocumentReference> viewable = new ArrayList<DocumentReference>();
187  75 for (DocumentReference documentReference : documentReferences) {
188  46 if (this.documentAccessBridge.isDocumentViewable(documentReference)) {
189  44 viewable.add(documentReference);
190    }
191    }
192  75 return viewable;
193    }
194   
195    /**
196    * Note: This method accesses the low level XWiki document through reflection in order to bypass programming rights.
197    *
198    * @param document an instance of {@link Document} received from a script
199    * @return an instance of {@link DocumentModelBridge} that wraps the low level document object exposed by the given
200    * document API and that <em>must</em> not be modified
201    */
 
202  74 toggle private DocumentModelBridge getReadOnlyDocument(Document document)
203    {
204  74 try {
205    // HACK: We try to access the XWikiDocument instance wrapped by the document API using reflection because we
206    // want to bypass the programming rights requirements.
207  74 Field docField = Document.class.getDeclaredField("doc");
208  74 docField.setAccessible(true);
209  74 return (DocumentModelBridge) docField.get(document);
210    } catch (Exception e) {
211  0 throw new RuntimeException("Failed to access the XWikiDocument instance wrapped by the document API.", e);
212    }
213    }
214   
215    /**
216    * Note: This method gets the low level XWiki document through reflection by calling a protected method.
217    *
218    * @param document an instance of {@link Document} received from a script
219    * @return an instance of {@link DocumentModelBridge} that wraps the low level document object exposed by the given
220    * document API and that can be <em>safely</em> modified
221    */
 
222  2 toggle private DocumentModelBridge getModifiableDocument(Document document)
223    {
224  2 try {
225    // HACK: We try to get the modifiable XWikiDocument instance wrapped by the document API using reflection
226    // because the corresponding method that clones the wrapped XWikiDocument instance is protected.
227  2 Method getDocMethod = Document.class.getDeclaredMethod("getDoc", new Class[] {});
228  2 getDocMethod.setAccessible(true);
229  2 return (DocumentModelBridge) getDocMethod.invoke(document);
230    } catch (Exception e) {
231  0 throw new RuntimeException(
232    "Failed to get the modifiable XWikiDocument instance wrapped by the document API.", e);
233    }
234    }
235    }