View Javadoc
1   /***************************************************************************
2    * Copyright (C) 2003-2009 eXo Platform SAS.
3    *
4    * This program is free software; you can redistribute it and/or
5    * modify it under the terms of the GNU Affero General Public License
6    * as published by the Free Software Foundation; either version 3
7    * of the License, or (at your option) any later version.
8    *
9    * This program is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   * GNU General Public License for more details.
13   *
14   * You should have received a copy of the GNU General Public License
15   * along with this program; if not, see<http://www.gnu.org/licenses/>.
16   *
17   **************************************************************************/
18  package org.exoplatform.ecm.webui.component.admin.taxonomy;
19  
20  import java.security.AccessControlException;
21  import java.util.ArrayList;
22  import java.util.List;
23  
24  import javax.jcr.Node;
25  import javax.jcr.RepositoryException;
26  import javax.jcr.Session;
27  import javax.jcr.Workspace;
28  
29  import org.exoplatform.ecm.webui.component.admin.taxonomy.action.UIActionForm;
30  import org.exoplatform.ecm.webui.component.admin.taxonomy.action.UIActionTaxonomyManager;
31  import org.exoplatform.ecm.webui.component.admin.taxonomy.action.UIActionTypeForm;
32  import org.exoplatform.ecm.webui.component.admin.taxonomy.tree.info.UIPermissionTreeForm;
33  import org.exoplatform.ecm.webui.component.admin.taxonomy.tree.info.UIPermissionTreeInfo;
34  import org.exoplatform.ecm.webui.component.admin.taxonomy.tree.info.UIPermissionTreeManager;
35  import org.exoplatform.ecm.webui.core.bean.PermissionBean;
36  import org.exoplatform.ecm.webui.selector.UISelectable;
37  import org.exoplatform.ecm.webui.utils.PermissionUtil;
38  import org.exoplatform.ecm.webui.utils.Utils;
39  import org.exoplatform.portal.webui.util.Util;
40  import org.exoplatform.services.cms.actions.ActionServiceContainer;
41  import org.exoplatform.services.cms.taxonomy.TaxonomyService;
42  import org.exoplatform.services.cms.taxonomy.TaxonomyTreeData;
43  import org.exoplatform.services.cms.taxonomy.impl.TaxonomyAlreadyExistsException;
44  import org.exoplatform.services.cms.taxonomy.impl.TaxonomyNodeAlreadyExistsException;
45  import org.exoplatform.services.jcr.RepositoryService;
46  import org.exoplatform.services.jcr.access.AccessControlEntry;
47  import org.exoplatform.services.jcr.access.AccessControlList;
48  import org.exoplatform.services.jcr.access.PermissionType;
49  import org.exoplatform.services.jcr.core.ExtendedNode;
50  import org.exoplatform.services.security.IdentityConstants;
51  import org.exoplatform.services.wcm.utils.WCMCoreUtils;
52  import org.exoplatform.webui.config.annotation.ComponentConfig;
53  import org.exoplatform.webui.config.annotation.EventConfig;
54  import org.exoplatform.webui.core.UIComponent;
55  import org.exoplatform.webui.core.UIContainer;
56  import org.exoplatform.webui.core.UIPopupWindow;
57  import org.exoplatform.webui.event.Event;
58  import org.exoplatform.webui.event.EventListener;
59  import org.exoplatform.webui.form.UIFormStringInput;
60  
61  /**
62   * Created by The eXo Platform SARL
63   * Author : Hoang Van Hung
64   *          hunghvit@gmail.com
65   * Apr 3, 2009
66   */
67  
68  @ComponentConfig(
69      template =  "app:/groovy/webui/component/admin/taxonomy/UITaxonomyTreeWizard.gtmpl",
70      events = {
71        @EventConfig(listeners = UITaxonomyTreeContainer.RefreshActionListener.class),
72        @EventConfig(listeners = UITaxonomyTreeContainer.CancelActionListener.class)
73      }
74  )
75  
76  public class UITaxonomyTreeContainer extends UIContainer implements UISelectable {
77  
78    private int                selectedStep_          = 1;
79  
80    private int                currentStep_           = 0;
81  
82    private TaxonomyTreeData   taxonomyTreeData;
83  
84    public static final String POPUP_PERMISSION       = "PopupTaxonomyTreePermission";
85  
86    public static final String POPUP_TAXONOMYHOMEPATH = "PopupTaxonomyJCRBrowser";
87  
88    private String[]           actions_               = { "Cancel" };
89  
90    public UITaxonomyTreeContainer() throws Exception {
91      addChild(UITaxonomyTreeMainForm.class, null, "TaxonomyTreeMainForm");
92      addChild(UIPermissionTreeManager.class, null, "TaxonomyPermissionTree").setRendered(false);
93      addChild(UIActionTaxonomyManager.class, null, null).setRendered(false);
94    }
95  
96    public String[] getActions() {return actions_;}
97  
98    public void setCurrentSep(int step) {
99      currentStep_ = step;
100   }
101 
102   public int getCurrentStep() {
103     return currentStep_;
104   }
105 
106   public void setSelectedStep(int step) {
107     selectedStep_ = step;
108   }
109 
110   public int getSelectedStep() {
111     return selectedStep_;
112   }
113 
114   public TaxonomyTreeData getTaxonomyTreeData() {
115     return taxonomyTreeData;
116   }
117 
118   public void setTaxonomyTreeData(TaxonomyTreeData taxonomyTreeData) {
119     this.taxonomyTreeData = taxonomyTreeData;
120   }
121 
122   public void viewStep(int step) {
123     selectedStep_ = step;
124     currentStep_ = step - 1;
125     List<UIComponent> children = getChildren();
126     for(int i=0; i<children.size(); i++){
127       if(i == getCurrentStep()) {
128         children.get(i).setRendered(true);
129       } else {
130         children.get(i).setRendered(false);
131       }
132     }
133   }
134 
135   public void refresh() throws Exception {
136     if (taxonomyTreeData == null) {
137       taxonomyTreeData = new TaxonomyTreeData();
138     }
139     taxonomyTreeData.setRepository(getApplicationComponent(RepositoryService.class).getCurrentRepository()
140                                                                                    .getConfiguration()
141                                                                                    .getName());
142     String taxoTreeName = taxonomyTreeData.getTaxoTreeName();
143     UIActionTaxonomyManager uiActionTaxonomyManager = getChild(UIActionTaxonomyManager.class);
144     UIActionTypeForm uiActionTypeForm = uiActionTaxonomyManager.getChild(UIActionTypeForm.class);
145     if (taxonomyTreeData.isEdit()) {
146       removeChild(UITaxonomyTreeCreateChild.class);
147       UITaxonomyTreeCreateChild uiTaxonomyCreateChild = addChild(UITaxonomyTreeCreateChild.class, null, null);
148       TaxonomyService taxonomyService = getApplicationComponent(TaxonomyService.class);
149       ActionServiceContainer actionService = getApplicationComponent(ActionServiceContainer.class);
150       Node taxoTreeNode = taxonomyService.getTaxonomyTree(taxoTreeName,
151           true);
152       if (taxoTreeNode != null) {
153         loadData(taxoTreeNode);
154         Node actionNode = actionService.getAction(taxoTreeNode, taxonomyTreeData
155             .getTaxoTreeActionName());
156         uiActionTaxonomyManager.removeChild(UIActionForm.class);
157         UIActionForm uiActionForm = uiActionTaxonomyManager.addChild(UIActionForm.class, null, null);
158         uiActionTypeForm.setDefaultActionType(taxonomyTreeData.getTaxoTreeActionTypeName());
159         uiActionForm.createNewAction(taxoTreeNode, taxonomyTreeData.getTaxoTreeActionTypeName(), true);
160         uiActionForm.setWorkspace(taxonomyTreeData.getTaxoTreeWorkspace());
161         uiActionForm.setNodePath(actionNode.getPath());
162         if (uiTaxonomyCreateChild == null)
163           uiTaxonomyCreateChild = addChild(UITaxonomyTreeCreateChild.class, null, null);
164         uiTaxonomyCreateChild.setWorkspace(getTaxonomyTreeData().getTaxoTreeWorkspace());
165         uiTaxonomyCreateChild.setTaxonomyTreeNode(taxoTreeNode);
166         UIPermissionTreeInfo uiPermInfo = findFirstComponentOfType(UIPermissionTreeInfo.class);
167         UIPermissionTreeForm uiPermForm = findFirstComponentOfType(UIPermissionTreeForm.class);
168         uiPermInfo.setCurrentNode(taxoTreeNode);
169         uiPermForm.setCurrentNode(taxoTreeNode);
170         uiPermInfo.updateGrid();
171       }
172     }
173     uiActionTypeForm.setDefaultActionType(null);
174     findFirstComponentOfType(UITaxonomyTreeMainForm.class).update(taxonomyTreeData);
175   }
176 
177   private void loadData(Node taxoTreeTargetNode) throws RepositoryException, Exception{
178     String taxoTreeName = taxonomyTreeData.getTaxoTreeName();
179     if (taxoTreeName == null || taxoTreeName.length() == 0) return;
180     if (taxoTreeTargetNode != null) {
181       Session session = taxoTreeTargetNode.getSession();
182       taxonomyTreeData.setTaxoTreeWorkspace(session.getWorkspace().getName());
183       taxonomyTreeData.setTaxoTreeHomePath(taxoTreeTargetNode.getParent().getPath());
184       taxonomyTreeData.setTaxoTreePermissions("");
185       ActionServiceContainer actionService = getApplicationComponent(ActionServiceContainer.class);
186       List<Node> lstActionNodes = actionService.getActions(taxoTreeTargetNode);
187       if (lstActionNodes != null && lstActionNodes.size() > 0) {
188         Node node = lstActionNodes.get(0);
189         if (node != null) {
190           taxonomyTreeData.setTaxoTreeActionName(node.getName());
191           taxonomyTreeData.setTaxoTreeActionTypeName(node.getPrimaryNodeType().getName());
192         }
193       }
194     }
195   }
196 
197   private UIFormStringInput getFormInputById(String id) {
198     return (UIFormStringInput)findComponentById(id);
199   }
200 
201   public Session getSession(String workspace) throws RepositoryException {
202     return WCMCoreUtils.getSystemSessionProvider().getSession(workspace, 
203                                                               WCMCoreUtils.getRepository());
204   }
205 
206   public void doSelect(String selectField, Object value) throws Exception {
207     getFormInputById(selectField).setValue(value.toString());
208     UITaxonomyManagerTrees uiContainer = getAncestorOfType(UITaxonomyManagerTrees.class);
209     for (UIComponent uiChild : uiContainer.getChildren()) {
210       if (uiChild.getId().equals(UITaxonomyTreeContainer.POPUP_PERMISSION)
211           || uiChild.getId().equals(UITaxonomyTreeContainer.POPUP_TAXONOMYHOMEPATH)) {
212         UIPopupWindow uiPopup = uiContainer.getChildById(uiChild.getId());
213         uiPopup.setRendered(false);
214         uiPopup.setShow(false);
215       }
216     }
217   }
218 
219   /**
220    * Add taxonomy tree with given name, workspace, home path. Add permission for tree node
221    * @param name
222    * @param workspace
223    * @param homePath
224    * @param permBeans
225    * @throws TaxonomyAlreadyExistsException
226    * @throws TaxonomyNodeAlreadyExistsException
227    * @throws AccessControlException
228    * @throws Exception
229    */
230   public void addTaxonomyTree(String name, String workspace, String homePath, List<PermissionBean> permBeans)
231       throws TaxonomyAlreadyExistsException, TaxonomyNodeAlreadyExistsException, AccessControlException, Exception {
232     TaxonomyService taxonomyService = getApplicationComponent(TaxonomyService.class);
233     taxonomyService.addTaxonomyNode(workspace, homePath, name, Util.getPortalRequestContext().getRemoteUser());
234     Session session = getSession(workspace);
235     Node homeNode = (Node)session.getItem(homePath);
236     Node taxonomyTreeNode = homeNode.getNode(name);
237     ExtendedNode node = (ExtendedNode) taxonomyTreeNode;
238     if (permBeans != null && permBeans.size() > 0) {
239       if (PermissionUtil.canChangePermission(node)) {
240         if (node.canAddMixin("exo:privilegeable")){
241           node.addMixin("exo:privilegeable");
242         }
243         if (node.isNodeType("exo:privilegeable")) {
244           AccessControlList acl = node.getACL();
245           List<AccessControlEntry> permissionEntries = acl.getPermissionEntries();
246           String nodeOwner = Utils.getNodeOwner(node);
247           for (AccessControlEntry accessControlEntry : permissionEntries) {
248             String identity = accessControlEntry.getIdentity();
249             if (IdentityConstants.SYSTEM.equals(identity) || identity.equals(nodeOwner)) {
250               continue;
251             }
252             node.removePermission(identity);
253           }
254           if(nodeOwner != null) {
255             node.setPermission(nodeOwner, PermissionType.ALL);
256           }
257           if(PermissionUtil.canChangePermission(node)) {
258             for(PermissionBean permBean : permBeans) {
259               List<String> permsList = new ArrayList<String>();
260               if (permBean.isRead()) permsList.add(PermissionType.READ);
261               if (permBean.isAddNode()) permsList.add(PermissionType.ADD_NODE);
262               if (permBean.isRemove()) permsList.add(PermissionType.REMOVE);
263               if (permsList.size() > 0) {
264                 node.setPermission(permBean.getUsersOrGroups(), permsList.toArray(new String[permsList.size()]));
265               }
266             }
267           }
268           node.save();
269         }
270       }
271     }
272     homeNode.save();
273     session.save();
274     taxonomyService.addTaxonomyTree(taxonomyTreeNode);
275   }
276 
277   /**
278    * Update taxonomy tree: If home path or workspace is changed, move taxonomy tree to new target
279    * @param name
280    * @param workspace
281    * @param homePath
282    * @return true: if taxonomy tree already has moved successfully
283    *         false: if taxonomy has not changed
284    * @throws RepositoryException
285    * @throws AccessControlException
286    * @throws Exception
287    */
288   public boolean updateTaxonomyTree(String name, String workspace, String homePath, String actionName)
289       throws RepositoryException, AccessControlException, Exception {
290     String repository = getApplicationComponent(RepositoryService.class).getCurrentRepository()
291                                                                         .getConfiguration()
292                                                                         .getName();
293     TaxonomyService taxonomyService = getApplicationComponent(TaxonomyService.class);
294     Node taxonomyTreeNode = taxonomyService.getTaxonomyTree(name, true);
295     Node homeNode = taxonomyTreeNode.getParent();
296     String srcWorkspace = taxonomyTreeNode.getSession().getWorkspace().getName();
297     Session session = getSession(workspace);
298     Workspace objWorkspace = session.getWorkspace();
299     //No change
300     if (homeNode.getPath().equals(homePath) && srcWorkspace.equals(workspace)) return false;
301     ActionServiceContainer actionService = getApplicationComponent(ActionServiceContainer.class);
302     if (actionService.hasActions(taxonomyTreeNode)) {
303       actionService.removeAction(taxonomyTreeNode, actionName, repository);
304     }
305 
306     String destPath = homePath + "/" + name;
307     destPath = destPath.replaceAll("/+", "/");
308     if (srcWorkspace.equals(workspace)) {
309       objWorkspace.move(taxonomyTreeNode.getPath(), destPath);
310     } else {
311       objWorkspace.copy(srcWorkspace, taxonomyTreeNode.getPath(), destPath);
312       taxonomyTreeNode.remove();
313       homeNode.save();
314     }
315     session.save();
316     //Update taxonomy tree
317     taxonomyTreeNode = (Node)session.getItem(destPath);
318     taxonomyService.updateTaxonomyTree(name, taxonomyTreeNode);
319     return true;
320   }
321 
322   public static class RefreshActionListener extends EventListener<UITaxonomyTreeContainer> {
323     public void execute(Event<UITaxonomyTreeContainer> event) throws Exception {
324       event.getSource().refresh();
325       event.getRequestContext().addUIComponentToUpdateByAjax(event.getSource());
326     }
327   }
328 
329   public static class CancelActionListener extends EventListener<UITaxonomyTreeContainer> {
330     public void execute(Event<UITaxonomyTreeContainer> event) throws Exception {
331       UITaxonomyTreeContainer uiTaxonomyTreeContainer = event.getSource();
332       UIPopupWindow uiPopup = uiTaxonomyTreeContainer.getParent();
333       UITaxonomyManagerTrees uiTaxonomyManagerTrees = uiTaxonomyTreeContainer.getAncestorOfType(UITaxonomyManagerTrees.class);
334       uiTaxonomyManagerTrees.removeChildById(UITaxonomyTreeList.ST_ADD);
335       uiTaxonomyManagerTrees.removeChildById(UITaxonomyTreeList.ST_EDIT);
336       uiTaxonomyManagerTrees.update();
337       uiPopup.setRendered(false);
338       uiPopup.setShow(false);
339       event.getRequestContext().addUIComponentToUpdateByAjax(uiTaxonomyManagerTrees);
340     }
341   }
342 }