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  package org.exoplatform.services.wcm.category;
18  
19  import java.util.ArrayList;
20  import java.util.HashMap;
21  import java.util.Iterator;
22  import java.util.List;
23  import java.util.Map;
24  import java.util.Set;
25  
26  import javax.jcr.Node;
27  import javax.jcr.Session;
28  import javax.jcr.Workspace;
29  import javax.jcr.nodetype.NodeType;
30  import javax.jcr.nodetype.PropertyDefinition;
31  
32  import org.apache.commons.lang.StringUtils;
33  import org.exoplatform.container.configuration.ConfigurationManager;
34  import org.exoplatform.container.xml.InitParams;
35  import org.exoplatform.container.xml.ObjectParameter;
36  import org.exoplatform.container.xml.ValueParam;
37  import org.exoplatform.services.cms.BasePath;
38  import org.exoplatform.services.cms.JcrInputProperty;
39  import org.exoplatform.services.cms.actions.ActionServiceContainer;
40  import org.exoplatform.services.cms.actions.impl.ActionConfig;
41  import org.exoplatform.services.cms.actions.impl.ActionConfig.TaxonomyAction;
42  import org.exoplatform.services.cms.impl.DMSConfiguration;
43  import org.exoplatform.services.cms.impl.DMSRepositoryConfiguration;
44  import org.exoplatform.services.cms.impl.Utils;
45  import org.exoplatform.services.cms.link.LinkManager;
46  import org.exoplatform.services.cms.taxonomy.TaxonomyService;
47  import org.exoplatform.services.cms.taxonomy.impl.TaxonomyAlreadyExistsException;
48  import org.exoplatform.services.cms.taxonomy.impl.TaxonomyConfig;
49  import org.exoplatform.services.cms.taxonomy.impl.TaxonomyConfig.Permission;
50  import org.exoplatform.services.cms.taxonomy.impl.TaxonomyConfig.Taxonomy;
51  import org.exoplatform.services.jcr.RepositoryService;
52  import org.exoplatform.services.jcr.access.PermissionType;
53  import org.exoplatform.services.jcr.core.ExtendedNode;
54  import org.exoplatform.services.jcr.core.ManageableRepository;
55  import org.exoplatform.services.jcr.ext.common.SessionProvider;
56  import org.exoplatform.services.jcr.ext.hierarchy.NodeHierarchyCreator;
57  import org.exoplatform.services.log.ExoLogger;
58  import org.exoplatform.services.log.Log;
59  import org.exoplatform.services.wcm.portal.artifacts.CreatePortalPlugin;
60  import org.exoplatform.services.wcm.utils.WCMCoreUtils;
61  
62  /**
63   * Created by The eXo Platform SAS
64   * Author : eXoPlatform
65   * chuong_phan@exoplatform.com, phan.le.thanh.chuong@gmail.com
66   * Aug 11, 2009
67   */
68  public class CreateTaxonomyPlugin extends CreatePortalPlugin {
69  
70    private static final Log LOG = ExoLogger.getLogger(CreateTaxonomyPlugin.class.getName());
71  
72    public static final String MIX_AFFECTED_NODETYPE  = "mix:affectedNodeTypes";
73  
74    public static final String AFFECTED_NODETYPE      = "exo:affectedNodeTypeNames";
75  
76    public static final String ALL_DOCUMENT_TYPES     = "ALL_DOCUMENT_TYPES";
77  
78    /** The workspace. */
79    private String                  workspace                  = "";
80  
81    /** The path. */
82    private String                  path                       = "";
83  
84    /** The tree name. */
85    private String                  treeName                   = "";
86  
87    /** The permissions. */
88    private List<Permission>        permissions                = new ArrayList<Permission>(4);
89  
90    /** The auto create in new repository_. */
91    private boolean                 autoCreateWithNewSite_ = false;
92  
93    /** The repository service_. */
94    private RepositoryService       repositoryService;
95  
96    /** The taxonomy service_. */
97    private TaxonomyService         taxonomyService;
98  
99    /** The link manager service_. */
100   private LinkManager             linkManager;
101 
102   /** The base taxonomies storage_. */
103   private String                  baseTaxonomiesStorage;
104 
105   /** The base taxonomies definition_. */
106   private String                  baseTaxonomiesDefinition;
107 
108   /** The action service container_. */
109   private ActionServiceContainer  actionServiceContainer;
110 
111   /** The params_. */
112   private InitParams              params;
113 
114   /** The dms configuration_. */
115   private DMSConfiguration        dmsConfiguration;
116 
117   /** The name. */
118   private String                  name;
119 
120   private String                   portalName;
121 
122   /**
123    * Instantiates a new initial taxonomy plugin.
124    *
125    * @param params the params
126    * @param configurationManager the configuration manager
127    * @param repositoryService the repository service
128    * @param nodeHierarchyCreator the node hierarchy creator
129    * @param taxonomyService the taxonomy service
130    * @param actionServiceContainer the action service container
131    * @param dmsConfiguration the dms configuration
132    *
133    * @throws Exception the exception
134    */
135   public CreateTaxonomyPlugin(InitParams params,
136                                ConfigurationManager configurationManager,
137                                RepositoryService repositoryService,
138                                NodeHierarchyCreator nodeHierarchyCreator,
139                                TaxonomyService taxonomyService,
140                                ActionServiceContainer actionServiceContainer,
141                                DMSConfiguration dmsConfiguration,
142                                LinkManager linkManager) throws Exception {
143     super(params, configurationManager, repositoryService);
144 
145     this.repositoryService = repositoryService;
146     this.baseTaxonomiesStorage = nodeHierarchyCreator.getJcrPath(BasePath.TAXONOMIES_TREE_STORAGE_PATH);
147     this.baseTaxonomiesDefinition = nodeHierarchyCreator.getJcrPath(BasePath.TAXONOMIES_TREE_DEFINITION_PATH);
148     this.taxonomyService = taxonomyService;
149     this.actionServiceContainer = actionServiceContainer;
150     this.params = params;
151     this.dmsConfiguration = dmsConfiguration;
152     this.linkManager = linkManager;
153   }
154 
155   /*
156    * (non-Javadoc)
157    * @see
158    * org.exoplatform.services.wcm.portal.artifacts.BasePortalArtifactsPlugin
159    * #deployToPortal(java.lang.String,
160    * org.exoplatform.services.jcr.ext.common.SessionProvider)
161    */
162   public void deployToPortal(SessionProvider sessionProvider, String portalName) throws Exception {
163     this.portalName = portalName;
164     ValueParam autoCreated = params.getValueParam("autoCreateWithNewSite");
165     ValueParam workspaceParam = params.getValueParam("workspace");
166     ValueParam pathParam = params.getValueParam("path");
167     ValueParam nameParam = params.getValueParam("treeName");
168     if (autoCreated != null)
169       autoCreateWithNewSite_ = Boolean.parseBoolean(autoCreated.getValue());
170     if(!autoCreateWithNewSite_) return;
171     if (pathParam == null || workspaceParam == null || workspaceParam.getValue().trim().length() == 0) {
172       path = baseTaxonomiesStorage;
173     } else {
174       path = pathParam.getValue();
175       workspace = workspaceParam.getValue();
176     }
177     if (nameParam != null) {
178       treeName = nameParam.getValue();
179     }
180 
181     if (treeName.contains("{treeName}")) {
182       treeName = StringUtils.replace(treeName, "{treeName}", portalName);
183     }
184 
185     path = StringUtils.replace(path, "{portalName}", portalName);
186 
187     Session session = null;
188     try {
189       // Get source information
190       Node srcTaxonomy = taxonomyService.getTaxonomyTree(treeName);
191       String srcWorkspace = srcTaxonomy.getSession().getWorkspace().getName();
192 
193       // Get destination information
194       ManageableRepository repository = repositoryService.getCurrentRepository();
195       session = sessionProvider.getSession(this.workspace, repository);
196       Workspace destWorkspace = session.getWorkspace();
197       String destPath = path + "/" + srcTaxonomy.getName();
198 
199       // If same workspace
200       if (srcWorkspace.equals(destWorkspace.getName())) {
201         destWorkspace.move(srcTaxonomy.getPath(), destPath);
202       } else {
203         // Clone taxonomy tree across workspace
204         destWorkspace.clone(srcWorkspace, srcTaxonomy.getPath(), destPath, true);
205 
206         // Remove old link taxonomy tree in definition
207         String dmsSystemWorkspaceName = dmsConfiguration.getConfig().getSystemWorkspace();
208         Node taxonomyDefinition = (Node) sessionProvider.getSession(dmsSystemWorkspaceName,
209                                                                     repository)
210                                                         .getItem(baseTaxonomiesDefinition);
211         Node srcLinkTaxonomy = taxonomyDefinition.getNode(srcTaxonomy.getName());
212         srcLinkTaxonomy.remove();
213 
214         // Remove old taxonomy tree
215         srcTaxonomy.remove();
216 
217         // Register new taxonomy tree in definition
218         Node destTaxonomy = (Node) session.getItem(destPath);
219         linkManager.createLink(taxonomyDefinition, destTaxonomy);
220       }
221       session.save();
222       return;
223     } catch (Exception e) {
224       init();
225     }
226   }
227 
228   /**
229    * Inits the.
230    *
231    * @throws Exception the exception
232    */
233   public void init() throws Exception {
234     importPredefineTaxonomies();
235   }
236 
237   /* (non-Javadoc)
238    * @see org.exoplatform.services.deployment.DeploymentPlugin#getName()
239    */
240   public String getName() {
241     return name;
242   }
243 
244   /* (non-Javadoc)
245    * @see org.exoplatform.services.deployment.DeploymentPlugin#setName(java.lang.String)
246    */
247   public void setName(String name) {
248     this.name = name;
249   }
250 
251   /**
252    * Gets the path.
253    *
254    * @return the path
255    */
256   public String getPath() {
257     return path;
258   }
259 
260   /**
261    * Sets the path.
262    *
263    * @param path the new path
264    */
265   public void setPath(String path) {
266     this.path = path;
267   }
268 
269   /**
270    * Gets the permissions.
271    *
272    * @return the permissions
273    */
274   public List<Permission> getPermissions() {
275     return permissions;
276   }
277 
278   /**
279    * Sets the permissions.
280    *
281    * @param permissions the new permissions
282    */
283   public void setPermissions(List<Permission> permissions) {
284     this.permissions = permissions;
285   }
286 
287   /**
288    * Gets the workspace.
289    *
290    * @return the workspace
291    */
292   public String getWorkspace() {
293     return workspace;
294   }
295 
296   /**
297    * Sets the workspace.
298    *
299    * @param workspace the new workspace
300    */
301   public void setWorkspace(String workspace) {
302     this.workspace = workspace;
303   }
304 
305   /**
306    * Import predefine taxonomies.
307    *
308    * @param repository the repository
309    *
310    * @throws Exception the exception
311    */
312   @SuppressWarnings("unchecked")
313   private void importPredefineTaxonomies() throws Exception {
314     ManageableRepository manageableRepository = this.repositoryService.getCurrentRepository();
315     DMSRepositoryConfiguration dmsRepoConfig = this.dmsConfiguration.getConfig();
316     if (getWorkspace() == null) {
317       setWorkspace(dmsRepoConfig.getSystemWorkspace());
318     }
319     Session session = manageableRepository.getSystemSession(getWorkspace());
320     Node taxonomyStorageNode = (Node) session.getItem(getPath());
321     if (taxonomyStorageNode.hasProperty("exo:isImportedChildren")) {
322       session.logout();
323       return;
324     }
325     taxonomyStorageNode.setProperty("exo:isImportedChildren", true);
326     Iterator<ObjectParameter> it = params.getObjectParamIterator();
327     Node taxonomyStorageNodeSystem = Utils.makePath(taxonomyStorageNode, treeName, "exo:taxonomy",
328             null);
329     taxonomyStorageNode.save();
330     while (it.hasNext()) {
331       ObjectParameter objectParam = it.next();
332       if (objectParam.getName().equals("permission.configuration")) {
333         TaxonomyConfig config = (TaxonomyConfig) objectParam.getObject();
334         for (Taxonomy taxonomy : config.getTaxonomies()) {
335           Map mapPermissions = getPermissions(taxonomy.getPermissions());
336           if (mapPermissions != null) {
337             ((ExtendedNode) taxonomyStorageNodeSystem).setPermissions(mapPermissions);
338           }
339           if (taxonomyStorageNodeSystem.canAddMixin("mix:referenceable")) {
340             taxonomyStorageNodeSystem.addMixin("mix:referenceable");
341           }
342         }
343       } else if (objectParam.getName().equals("taxonomy.configuration")) {
344         TaxonomyConfig config = (TaxonomyConfig) objectParam.getObject();
345         for (Taxonomy taxonomy : config.getTaxonomies()) {
346           Node taxonomyNode = Utils.makePath(taxonomyStorageNodeSystem, taxonomy.getPath(),
347               "exo:taxonomy", getPermissions(taxonomy.getPermissions()));
348           if (taxonomyNode.canAddMixin("mix:referenceable")) {
349             taxonomyNode.addMixin("mix:referenceable");
350           }
351 
352           if (taxonomyNode.canAddMixin("exo:rss-enable")) {
353             taxonomyNode.addMixin("exo:rss-enable");
354           }
355           if(StringUtils.isNotEmpty(taxonomy.getTitle())) {
356             taxonomyNode.setProperty("exo:title", taxonomy.getTitle());
357           } else {
358             taxonomyNode.setProperty("exo:title", taxonomy.getName());
359           }
360 
361           taxonomyNode.save();
362         }
363       } else if (objectParam.getName().equals("predefined.actions")) {
364         ActionConfig config = (ActionConfig) objectParam.getObject();
365         List actions = config.getActions();
366         for (Iterator iter = actions.iterator(); iter.hasNext();) {
367           TaxonomyAction action = (TaxonomyAction) iter.next();
368           addAction(action, taxonomyStorageNodeSystem);
369         }
370       }
371 
372     }
373     taxonomyStorageNode.save();
374     try {
375       taxonomyService.addTaxonomyTree(taxonomyStorageNodeSystem);
376     } catch (TaxonomyAlreadyExistsException e) {
377       if (LOG.isErrorEnabled()) LOG.error("Cannot add taxonomy tree", e);
378     }
379     session.logout();
380   }
381 
382   /**
383    * Adds the action.
384    *
385    * @param action the action
386    * @param srcNode the src node
387    * @param repository the repository
388    *
389    * @throws Exception the exception
390    */
391   private void addAction(ActionConfig.TaxonomyAction action, Node srcNode)
392       throws Exception {
393     Map<String, JcrInputProperty> sortedInputs = new HashMap<String, JcrInputProperty>();
394     JcrInputProperty jcrInputName = new JcrInputProperty();
395     jcrInputName.setJcrPath("/node/exo:name");
396     jcrInputName.setValue(action.getName());
397     sortedInputs.put("/node/exo:name", jcrInputName);
398     JcrInputProperty jcrInputDes = new JcrInputProperty();
399     jcrInputDes.setJcrPath("/node/exo:description");
400     jcrInputDes.setValue(action.getDescription());
401     sortedInputs.put("/node/exo:description", jcrInputDes);
402 
403     JcrInputProperty jcrInputLife = new JcrInputProperty();
404     jcrInputLife.setJcrPath("/node/exo:lifecyclePhase");
405     jcrInputLife.setValue(action.getLifecyclePhase().toArray(new String[0]));
406     sortedInputs.put("/node/exo:lifecyclePhase", jcrInputLife);
407 
408     JcrInputProperty jcrInputHomePath = new JcrInputProperty();
409     jcrInputHomePath.setJcrPath("/node/exo:storeHomePath");
410     String homepath = action.getHomePath();
411     homepath = StringUtils.replace(homepath, "{portalName}", portalName);
412     homepath = StringUtils.replace(homepath, "{treeName}", treeName);
413     jcrInputHomePath.setValue(homepath);
414     sortedInputs.put("/node/exo:storeHomePath", jcrInputHomePath);
415 
416     JcrInputProperty jcrInputTargetWspace = new JcrInputProperty();
417     jcrInputTargetWspace.setJcrPath("/node/exo:targetWorkspace");
418     jcrInputTargetWspace.setValue(action.getTargetWspace());
419     sortedInputs.put("/node/exo:targetWorkspace", jcrInputTargetWspace);
420 
421     JcrInputProperty jcrInputTargetPath = new JcrInputProperty();
422     jcrInputTargetPath.setJcrPath("/node/exo:targetPath");
423     String targetPath = action.getTargetPath();
424     targetPath = StringUtils.replace(targetPath, "{portalName}", portalName);
425     jcrInputTargetPath.setValue(targetPath);
426     sortedInputs.put("/node/exo:targetPath", jcrInputTargetPath);
427 
428     JcrInputProperty rootProp = sortedInputs.get("/node");
429     if (rootProp == null) {
430       rootProp = new JcrInputProperty();
431       rootProp.setJcrPath("/node");
432       rootProp.setValue((sortedInputs.get("/node/exo:name")).getValue());
433       sortedInputs.put("/node", rootProp);
434     } else {
435       rootProp.setValue((sortedInputs.get("/node/exo:name")).getValue());
436     }
437     actionServiceContainer.addAction(srcNode, action.getType(), sortedInputs);
438     Node actionNode = actionServiceContainer.getAction(srcNode, action.getName());
439     if (action.getRoles() != null) {
440       String[] roles = StringUtils.split(action.getRoles(), ";");
441       actionNode.setProperty("exo:roles", roles);
442     }
443 
444     Iterator mixins = action.getMixins().iterator();
445     NodeType nodeType;
446     String value;
447     ManageableRepository manageableRepository = WCMCoreUtils.getRepository();
448     while (mixins.hasNext()) {
449       ActionConfig.Mixin mixin = (ActionConfig.Mixin) mixins.next();
450       actionNode.addMixin(mixin.getName());
451       Map<String, String> props = mixin.getParsedProperties();
452       Set keys = props.keySet();
453       nodeType = manageableRepository.getNodeTypeManager().getNodeType(mixin.getName());
454       for (Iterator iterator = keys.iterator(); iterator.hasNext();) {
455         String key = (String) iterator.next();
456         for(PropertyDefinition pro : nodeType.getPropertyDefinitions()) {
457           if (pro.getName().equals(key)) {
458             if (pro.isMultiple()) {
459               value = props.get(key);
460               if (value != null) {
461                 actionNode.setProperty(key, value.split(","));
462               }
463             } else {
464               actionNode.setProperty(key, props.get(key));
465             }
466             break;
467           }
468         }
469       }
470     }
471     actionNode.save();
472   }
473 
474   /**
475    * Gets the permissions.
476    *
477    * @param listPermissions the list permissions
478    *
479    * @return the permissions
480    */
481   private Map<String, String[]> getPermissions(List<Permission> listPermissions) {
482     Map<String, String[]> permissionsMap = new HashMap<String, String[]>();
483     for (Permission permission : listPermissions) {
484       StringBuilder strPer = new StringBuilder();
485       if ("true".equals(permission.getRead()))
486         strPer.append(PermissionType.READ);
487       if ("true".equals(permission.getAddNode()))
488         strPer.append(",").append(PermissionType.ADD_NODE);
489       if ("true".equals(permission.getSetProperty()))
490         strPer.append(",").append(PermissionType.SET_PROPERTY);
491       if ("true".equals(permission.getRemove()))
492         strPer.append(",").append(PermissionType.REMOVE);
493       permissionsMap.put(permission.getIdentity(), strPer.toString().split(","));
494     }
495     return permissionsMap;
496   }
497 
498 }