View Javadoc
1   /*
2    * Copyright (C) 2003-2007 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  package org.exoplatform.services.cms.taxonomy.impl;
18  
19  import org.apache.commons.lang.StringUtils;
20  import org.exoplatform.container.component.BaseComponentPlugin;
21  import org.exoplatform.container.xml.InitParams;
22  import org.exoplatform.container.xml.ObjectParameter;
23  import org.exoplatform.container.xml.ValueParam;
24  import org.exoplatform.services.cms.BasePath;
25  import org.exoplatform.services.cms.JcrInputProperty;
26  import org.exoplatform.services.cms.actions.ActionServiceContainer;
27  import org.exoplatform.services.cms.actions.impl.ActionConfig;
28  import org.exoplatform.services.cms.actions.impl.ActionConfig.TaxonomyAction;
29  import org.exoplatform.services.cms.impl.DMSConfiguration;
30  import org.exoplatform.services.cms.impl.DMSRepositoryConfiguration;
31  import org.exoplatform.services.cms.impl.Utils;
32  import org.exoplatform.services.cms.taxonomy.TaxonomyService;
33  import org.exoplatform.services.cms.taxonomy.impl.TaxonomyConfig.Permission;
34  import org.exoplatform.services.cms.taxonomy.impl.TaxonomyConfig.Taxonomy;
35  import org.exoplatform.services.jcr.RepositoryService;
36  import org.exoplatform.services.jcr.access.AccessControlEntry;
37  import org.exoplatform.services.jcr.access.PermissionType;
38  import org.exoplatform.services.jcr.core.ExtendedNode;
39  import org.exoplatform.services.jcr.core.ManageableRepository;
40  import org.exoplatform.services.jcr.ext.hierarchy.NodeHierarchyCreator;
41  import org.exoplatform.services.log.ExoLogger;
42  import org.exoplatform.services.log.Log;
43  import org.exoplatform.services.security.IdentityConstants;
44  
45  import javax.jcr.Node;
46  import javax.jcr.Session;
47  import javax.jcr.nodetype.NodeType;
48  import javax.jcr.nodetype.PropertyDefinition;
49  import java.util.ArrayList;
50  import java.util.HashMap;
51  import java.util.Iterator;
52  import java.util.List;
53  import java.util.Map;
54  import java.util.Set;
55  
56  /**
57   * Created by The eXo Platform SARL Author : Ly Dinh Quang
58   * quang.ly@exoplatform.com xxx5669@gmail.com Mar 31, 2009
59   */
60  public class TaxonomyPlugin extends BaseComponentPlugin {
61    private String                 workspace                  = null;
62  
63    private String                 path                       = "";
64  
65    private String                 treeName                   = "";
66  
67    private List<Permission>       permissions                = new ArrayList<Permission>(4);
68  
69    private boolean                autoCreateInNewRepository_ = true;
70  
71    private RepositoryService      repositoryService_;
72  
73    private TaxonomyService        taxonomyService_;
74  
75    private String                 baseTaxonomiesStorage_;
76  
77    private ActionServiceContainer actionServiceContainer_;
78  
79    private InitParams             params_;
80  
81    final static String MIX_AFFECTED_NODETYPE  = "mix:affectedNodeTypes";
82    final static String AFFECTED_NODETYPE      = "exo:affectedNodeTypeNames";
83    final static String ALL_DOCUMENT_TYPES     = "ALL_DOCUMENT_TYPES";
84  
85    private DMSConfiguration dmsConfiguration_;
86    private static final Log LOG  = ExoLogger.getLogger(TaxonomyPlugin.class.getName());
87  
88    public TaxonomyPlugin(InitParams params, RepositoryService repositoryService,
89        NodeHierarchyCreator nodeHierarchyCreator, TaxonomyService taxonomyService,
90        ActionServiceContainer actionServiceContainer,
91        DMSConfiguration dmsConfiguration) throws Exception {
92      repositoryService_ = repositoryService;
93      baseTaxonomiesStorage_ = nodeHierarchyCreator.getJcrPath(BasePath.TAXONOMIES_TREE_STORAGE_PATH);
94      taxonomyService_ = taxonomyService;
95      actionServiceContainer_ = actionServiceContainer;
96      params_ = params;
97      ValueParam autoCreated = params_.getValueParam("autoCreateInNewRepository");
98      ValueParam workspaceParam = params_.getValueParam("workspace");
99      ValueParam pathParam = params_.getValueParam("path");
100     ValueParam nameParam = params_.getValueParam("treeName");
101     if (autoCreated != null) autoCreateInNewRepository_ = Boolean.parseBoolean(autoCreated.getValue());
102     if (workspaceParam != null) {
103       workspace = workspaceParam.getValue();
104     }
105     if (pathParam == null) {
106       path = baseTaxonomiesStorage_;
107     } else {
108       path = pathParam.getValue();
109     }
110     if (nameParam != null) {
111       treeName = nameParam.getValue();
112     }
113     dmsConfiguration_ = dmsConfiguration;
114   }
115   
116   public void init() throws Exception {
117     importPredefineTaxonomies();
118   }  
119 
120   public String getName() {
121     return name;
122   }
123 
124   public void setName(String name) {
125     this.name = name;
126   }
127 
128   public String getPath() {
129     return path;
130   }
131 
132   public void setPath(String path) {
133     this.path = path;
134   }
135 
136   public List<Permission> getPermissions() {
137     return permissions;
138   }
139 
140   public void setPermissions(List<Permission> permissions) {
141     this.permissions = permissions;
142   }
143 
144   public String getWorkspace() {
145     return workspace;
146   }
147 
148   public void setWorkspace(String workspace) {
149     this.workspace = workspace;
150   }
151 
152   @SuppressWarnings("unchecked")
153   private void importPredefineTaxonomies() throws Exception {
154     ManageableRepository manageableRepository = repositoryService_.getCurrentRepository();
155     DMSRepositoryConfiguration dmsRepoConfig = dmsConfiguration_.getConfig();
156     if (workspace == null) {
157       setWorkspace(dmsRepoConfig.getSystemWorkspace());
158     } else {
159       // in case workspace is not initialized, we choose dms system workspace default
160       if (!manageableRepository.isWorkspaceInitialized(workspace))
161         setWorkspace(dmsRepoConfig.getSystemWorkspace());
162     }
163     Session session = manageableRepository.getSystemSession(getWorkspace());
164     if(Utils.getAllEditedConfiguredData(
165       "TaxonomyTree", "EditedConfiguredTaxonomyTree", true).contains(treeName)) return;
166     Node taxonomyStorageNode = (Node) session.getItem(path);
167     if (taxonomyStorageNode.hasNode(treeName)) {
168       session.logout();
169       return;
170     }
171     taxonomyStorageNode.setProperty("exo:isImportedChildren", true);
172     Iterator<ObjectParameter> it = params_.getObjectParamIterator();
173     Node taxonomyStorageNodeSystem = Utils.makePath(taxonomyStorageNode, treeName, "exo:taxonomy",
174             null);
175     String systemUser = IdentityConstants.SYSTEM;
176 
177     while (it.hasNext()) {
178       ObjectParameter objectParam = it.next();
179       if (objectParam.getName().equals("permission.configuration")) {
180         TaxonomyConfig config = (TaxonomyConfig) objectParam.getObject();
181         for (Taxonomy taxonomy : config.getTaxonomies()) {
182           Map mapPermissions = getPermissions(taxonomy.getPermissions());
183           if (mapPermissions != null) {
184             ((ExtendedNode) taxonomyStorageNodeSystem).setPermissions(mapPermissions);
185           }
186           if (taxonomyStorageNodeSystem.canAddMixin("mix:referenceable")) {
187             taxonomyStorageNodeSystem.addMixin("mix:referenceable");
188           }
189           if (!containsUserInACL(((ExtendedNode)taxonomyStorageNodeSystem).getACL().getPermissionEntries(), systemUser)) {
190             if (taxonomyStorageNodeSystem.canAddMixin("exo:privilegeable"))
191               taxonomyStorageNodeSystem.addMixin("exo:privilegeable");
192             ((ExtendedNode)taxonomyStorageNodeSystem).setPermission(systemUser, PermissionType.ALL);
193           }
194         }
195         session.save();
196       } else if (objectParam.getName().equals("taxonomy.configuration")) {
197         TaxonomyConfig config = (TaxonomyConfig) objectParam.getObject();
198         for (Taxonomy taxonomy : config.getTaxonomies()) {
199           Node taxonomyNode = Utils.makePath(taxonomyStorageNodeSystem, taxonomy.getPath(),
200               "exo:taxonomy", getPermissions(taxonomy.getPermissions()));
201 
202           if (!containsUser(taxonomy.getPermissions(), systemUser)) {
203             if (taxonomyNode.canAddMixin("exo:privilegeable"))
204               taxonomyNode.addMixin("exo:privilegeable");
205             ((ExtendedNode)taxonomyNode).setPermission(systemUser, PermissionType.ALL);
206           }
207           if (taxonomyNode.canAddMixin("mix:referenceable")) {
208             taxonomyNode.addMixin("mix:referenceable");
209           }
210           if (taxonomyNode.canAddMixin("exo:rss-enable")) {
211             taxonomyNode.addMixin("exo:rss-enable");
212           }
213           if(taxonomy.getTitle() != null && !taxonomy.getTitle().isEmpty()) {
214             taxonomyNode.setProperty("exo:title", taxonomy.getTitle());
215           } else {
216             taxonomyNode.setProperty("exo:title", taxonomy.getName());
217           }
218 
219           taxonomyNode.getSession().save();
220         }
221       } else if (objectParam.getName().equals("predefined.actions")) {
222         ActionConfig config = (ActionConfig) objectParam.getObject();
223         List actions = config.getActions();
224         for (Iterator iter = actions.iterator(); iter.hasNext();) {
225           TaxonomyAction action = (TaxonomyAction) iter.next();
226           taxonomyStorageNodeSystem = (Node)session.getItem(taxonomyStorageNodeSystem.getPath());
227           addAction(action, taxonomyStorageNodeSystem);
228         }
229       }
230 
231     }
232     session.save();
233     try {
234       taxonomyService_.addTaxonomyTree(taxonomyStorageNodeSystem);
235     } catch (TaxonomyAlreadyExistsException e) {
236       if (LOG.isErrorEnabled()) {
237         LOG.error("Unexpected error", e);
238       }
239     }
240     session.save();
241     session.logout();
242   }
243 
244   private boolean containsUserInACL(List<AccessControlEntry> entries, String userName) {
245     if (userName == null) return false;
246     for (AccessControlEntry entry : entries)
247       if (userName.equals(entry.getIdentity()))
248           return true;
249     return false;
250   }
251 
252   private boolean containsUser(List<Permission> permissions, String userName) {
253     if (userName == null) return false;
254     for (Permission permission : permissions)
255       if (userName.equals(permission.getIdentity()))
256           return true;
257     return false;
258   }
259 
260   private void addAction(ActionConfig.TaxonomyAction action, Node srcNode)
261       throws Exception {
262     ManageableRepository manageRepo = repositoryService_.getCurrentRepository();
263     Map<String, JcrInputProperty> sortedInputs = new HashMap<String, JcrInputProperty>();
264     JcrInputProperty jcrInputName = new JcrInputProperty();
265     jcrInputName.setJcrPath("/node/exo:name");
266     jcrInputName.setValue(action.getName());
267     sortedInputs.put("/node/exo:name", jcrInputName);
268     JcrInputProperty jcrInputDes = new JcrInputProperty();
269     jcrInputDes.setJcrPath("/node/exo:description");
270     jcrInputDes.setValue(action.getDescription());
271     sortedInputs.put("/node/exo:description", jcrInputDes);
272 
273     JcrInputProperty jcrInputLife = new JcrInputProperty();
274     jcrInputLife.setJcrPath("/node/exo:lifecyclePhase");
275     jcrInputLife.setValue(action.getLifecyclePhase().toArray(new String[0]));
276     sortedInputs.put("/node/exo:lifecyclePhase", jcrInputLife);
277 
278     JcrInputProperty jcrInputHomePath = new JcrInputProperty();
279     jcrInputHomePath.setJcrPath("/node/exo:storeHomePath");
280     jcrInputHomePath.setValue(action.getHomePath());
281     sortedInputs.put("/node/exo:storeHomePath", jcrInputHomePath);
282 
283     JcrInputProperty jcrInputTargetWspace = new JcrInputProperty();
284     jcrInputTargetWspace.setJcrPath("/node/exo:targetWorkspace");
285     jcrInputTargetWspace.setValue(action.getTargetWspace());
286     sortedInputs.put("/node/exo:targetWorkspace", jcrInputTargetWspace);
287 
288     JcrInputProperty jcrInputTargetPath = new JcrInputProperty();
289     jcrInputTargetPath.setJcrPath("/node/exo:targetPath");
290     jcrInputTargetPath.setValue(action.getTargetPath());
291     sortedInputs.put("/node/exo:targetPath", jcrInputTargetPath);
292 
293     JcrInputProperty rootProp = sortedInputs.get("/node");
294     if (rootProp == null) {
295       rootProp = new JcrInputProperty();
296       rootProp.setJcrPath("/node");
297       rootProp.setValue((sortedInputs.get("/node/exo:name")).getValue());
298       sortedInputs.put("/node", rootProp);
299     } else {
300       rootProp.setValue((sortedInputs.get("/node/exo:name")).getValue());
301     }
302     actionServiceContainer_.addAction(srcNode, action.getType(), sortedInputs);
303     Node actionNode = actionServiceContainer_.getAction(srcNode, action.getName());
304     if (action.getRoles() != null) {
305       String[] roles = StringUtils.split(action.getRoles(), ";");
306       actionNode.setProperty("exo:roles", roles);
307     }
308 
309     Iterator mixins = action.getMixins().iterator();
310     NodeType nodeType;
311     String value;
312     while (mixins.hasNext()) {
313       ActionConfig.Mixin mixin = (ActionConfig.Mixin) mixins.next();
314       actionNode.addMixin(mixin.getName());
315       Map<String, String> props = mixin.getParsedProperties();
316       Set keys = props.keySet();
317       nodeType = manageRepo.getNodeTypeManager().getNodeType(mixin.getName());
318       for (Iterator iterator = keys.iterator(); iterator.hasNext();) {
319         String key = (String) iterator.next();
320         for(PropertyDefinition pro : nodeType.getPropertyDefinitions()) {
321           if (pro.getName().equals(key)) {
322             if (pro.isMultiple()) {
323               value = props.get(key);
324                   if (value != null) {
325                     actionNode.setProperty(key, value.split(","));
326                   }
327                 } else {
328                 actionNode.setProperty(key, props.get(key));
329               }
330             break;
331           }
332         }
333       }
334     }
335     actionNode.getSession().save();
336   }
337 
338   public Map getPermissions(List<Permission> listPermissions) {
339     Map<String, String[]> permissionsMap = new HashMap<String, String[]>();
340     for (Permission permission : listPermissions) {
341       StringBuilder strPer = new StringBuilder();
342       if ("true".equals(permission.getRead()))
343         strPer.append(PermissionType.READ);
344       if ("true".equals(permission.getAddNode()))
345         strPer.append(",").append(PermissionType.ADD_NODE);
346       if ("true".equals(permission.getSetProperty()))
347         strPer.append(",").append(PermissionType.SET_PROPERTY);
348       if ("true".equals(permission.getRemove()))
349         strPer.append(",").append(PermissionType.REMOVE);
350       permissionsMap.put(permission.getIdentity(), strPer.toString().split(","));
351     }
352     return permissionsMap;
353   }
354 }