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 */ 016 017package org.ametys.web; 018 019import java.util.regex.Pattern; 020 021import javax.jcr.NoSuchWorkspaceException; 022import javax.jcr.RepositoryException; 023import javax.jcr.Session; 024import javax.jcr.observation.Event; 025import javax.jcr.observation.ObservationManager; 026 027import org.apache.avalon.framework.service.ServiceException; 028import org.apache.avalon.framework.service.ServiceManager; 029import org.apache.commons.lang3.ArrayUtils; 030 031import org.ametys.plugins.repository.AmetysObjectResolver; 032import org.ametys.plugins.repository.ModifiableTraversableAmetysObject; 033import org.ametys.plugins.repository.activities.ActivityHolder; 034import org.ametys.plugins.repository.jcr.DefaultTraversableAmetysObject; 035import org.ametys.runtime.config.Config; 036import org.ametys.web.live.LiveWorkspaceListener; 037import org.ametys.web.repository.site.Site; 038import org.ametys.web.repository.site.SiteManager; 039import org.ametys.web.synchronization.SynchronizeComponent; 040 041/** 042 * Web plugin init class 043 */ 044public class Init extends org.ametys.cms.Init 045{ 046 private SiteManager _siteManager; 047 private SynchronizeComponent _synchronizeComponent; 048 049 @Override 050 public void service(ServiceManager manager) throws ServiceException 051 { 052 super.service(manager); 053 _siteManager = (SiteManager) manager.lookup(SiteManager.ROLE); 054 _synchronizeComponent = (SynchronizeComponent) manager.lookup(SynchronizeComponent.ROLE); 055 } 056 057 @Override 058 public void init() throws Exception 059 { 060 DefaultTraversableAmetysObject root = _resolver.resolveByPath("/"); 061 062 Session session = _repository.getAdminSession(); 063 ObservationManager manager = session.getWorkspace().getObservationManager(); 064 065 // Create Live workspace if needed 066 createLiveWorkspace(); 067 068 // Create archives workspace if needed 069 createArchiveWorkspace(); 070 071 // Register a non-recursive live workspace listener for root nodes 072 manager.addEventListener(new LiveWorkspaceListener(_repository, _synchronizeComponent, getLogger()), 073 Event.NODE_ADDED 074 | Event.NODE_REMOVED 075 | Event.NODE_MOVED 076 | Event.PROPERTY_ADDED 077 | Event.PROPERTY_CHANGED 078 | Event.PROPERTY_REMOVED, 079 root.getNode().getPath(), false, null, null, false); 080 081 // Create plugins root node if needed 082 createPluginsRootNode(root); 083 084 // Create sites root node if needed 085 createSitesRootNode(root); 086 087 // Register a live workspace listener for plugins, excluding root contents and ACL nodes 088 manager.addEventListener(new LiveWorkspaceListener(_repository, _synchronizeComponent, getLogger(), ArrayUtils.toArray(Pattern.compile("/ametys:root/ametys:plugins/[^/]+/ametys:contents.*"), Pattern.compile("/ametys:root/ametys:plugins/.+/ametys-internal:acl.*"))), 089 Event.NODE_ADDED 090 | Event.NODE_REMOVED 091 | Event.NODE_MOVED 092 | Event.PROPERTY_ADDED 093 | Event.PROPERTY_CHANGED 094 | Event.PROPERTY_REMOVED, 095 root.getNode().getPath() + "/ametys:plugins", true, null, null, false); 096 097 // Create contents root node if needed 098 createContentsRootNode(root); 099 100 // Create resources root node if needed 101 createResourcesRootNode(root); 102 103 // Create shared resources (for all sites) root node if needed 104 createSharedResourcesNode(root); 105 106 root.getNode().getSession().logout(); 107 108 for (Site site : _siteManager.getSites()) 109 { 110 // Register a live workspace listener for plugins on each site, excluding root contents 111 manager.addEventListener(new LiveWorkspaceListener(_repository, _synchronizeComponent, getLogger(), ArrayUtils.toArray(Pattern.compile("/ametys:root/ametys-internal:sites/[^:]+/ametys-internal:plugins/[^/]+/ametys:contents.*"), Pattern.compile("/ametys:root/ametys-internal:sites/[^:]+/ametys-internal:plugins/.+/ametys-internal:acl.*"))), 112 Event.NODE_ADDED 113 | Event.NODE_REMOVED 114 | Event.NODE_MOVED 115 | Event.PROPERTY_ADDED 116 | Event.PROPERTY_CHANGED 117 | Event.PROPERTY_REMOVED, 118 site.getNode().getPath() + "/ametys-internal:plugins", true, null, null, false); 119 120 // Creates local plugins space at "<site>/ametys-internal:plugins" if needed 121 if (!site.hasChild("ametys-internal:plugins")) 122 { 123 site.createChild("ametys-internal:plugins", "ametys:unstructured"); 124 } 125 126 // Register a live workspace listener for resources explorer on each site 127 manager.addEventListener(new LiveWorkspaceListener(_repository, _synchronizeComponent, getLogger()), 128 Event.NODE_ADDED 129 | Event.NODE_REMOVED 130 | Event.NODE_MOVED 131 | Event.PROPERTY_ADDED 132 | Event.PROPERTY_CHANGED 133 | Event.PROPERTY_REMOVED, 134 site.getNode().getPath() + "/ametys-internal:resources", true, null, null, false); 135 136 // Creates local resources space at "<site>/ametys-internal:resources" if needed 137 if (!site.hasChild("ametys-internal:resources")) 138 { 139 site.createChild("ametys-internal:resources", "ametys:resources-collection"); 140 } 141 142 // Register a live workspace listener for activities on each site 143 manager.addEventListener(new LiveWorkspaceListener(_repository, _synchronizeComponent, getLogger()), 144 Event.NODE_ADDED 145 | Event.NODE_REMOVED 146 | Event.NODE_MOVED 147 | Event.PROPERTY_ADDED 148 | Event.PROPERTY_CHANGED 149 | Event.PROPERTY_REMOVED, 150 site.getNode().getPath() + "/" + ActivityHolder.ACTIVITIES_ROOT_NODE_NAME, true, null, null, false); 151 152 if (site.needsSave()) 153 { 154 site.saveChanges(); 155 } 156 } 157 } 158 159 /** 160 * Create the live workspace. 161 * @throws RepositoryException if a repository error occurred. 162 */ 163 protected void createLiveWorkspace() throws RepositoryException 164 { 165 Session session = null; 166 Session liveSession = null; 167 168 try 169 { 170 // Try to login 171 liveSession = _repository.login(WebConstants.LIVE_WORKSPACE); 172 } 173 catch (NoSuchWorkspaceException e) 174 { 175 getLogger().info("Live workspace does not exist, creating it..."); 176 177 session = _repository.login(); 178 session.getWorkspace().createWorkspace(WebConstants.LIVE_WORKSPACE); 179 liveSession = _repository.login(WebConstants.LIVE_WORKSPACE); 180 181 liveSession.getRootNode().addNode(AmetysObjectResolver.ROOT_REPO, AmetysObjectResolver.ROOT_TYPE); 182 liveSession.save(); 183 } 184 finally 185 { 186 if (session != null) 187 { 188 session.logout(); 189 } 190 if (liveSession != null) 191 { 192 liveSession.logout(); 193 } 194 } 195 } 196 197 /** 198 * Create the JCR root node for sites storage if needed 199 * @param rootNode The JCR root node 200 * @throws RepositoryException Thrown if the node cannot be created 201 */ 202 protected void createSitesRootNode(ModifiableTraversableAmetysObject rootNode) throws RepositoryException 203 { 204 if (!rootNode.hasChild(SiteManager.ROOT_SITES)) 205 { 206 rootNode.createChild(SiteManager.ROOT_SITES, "ametys:collection"); 207 rootNode.saveChanges(); 208 } 209 } 210 211 /** 212 * Create the JCR root node for shared resources storage if needed 213 * @param rootNode The JCR root node 214 * @throws RepositoryException Thrown if the node cannot be created 215 */ 216 protected void createSharedResourcesNode(ModifiableTraversableAmetysObject rootNode) throws RepositoryException 217 { 218 // Creates web-explorer space at "/ametys:plugins/web-explorer" if needed 219 DefaultTraversableAmetysObject pluginsNode = (DefaultTraversableAmetysObject) rootNode.getChild("ametys:plugins"); 220 if (!pluginsNode.hasChild("web-explorer")) 221 { 222 pluginsNode.createChild("web-explorer", "ametys:unstructured"); 223 } 224 225 if (pluginsNode.needsSave()) 226 { 227 pluginsNode.saveChanges(); 228 } 229 230 // Creates shared resources space at "/ametys:plugins/web-explorer/shared-resources" if needed 231 boolean useSharedResources = Config.getInstance().getValue("resources.shared.folder"); 232 DefaultTraversableAmetysObject explorerNode = (DefaultTraversableAmetysObject) pluginsNode.getChild("web-explorer"); 233 234 if (useSharedResources) 235 { 236 DefaultTraversableAmetysObject sharedRoot; 237 238 if (!explorerNode.hasChild("shared-resources")) 239 { 240 sharedRoot = (DefaultTraversableAmetysObject) explorerNode.createChild("shared-resources", "ametys:unstructured"); 241 } 242 else 243 { 244 sharedRoot = (DefaultTraversableAmetysObject) explorerNode.getChild("shared-resources"); 245 } 246 247 // Also automatically create the "all" share, available to all sites 248 if (!sharedRoot.hasChild("all")) 249 { 250 sharedRoot.createChild("all", "ametys:resources-collection"); 251 } 252 253 if (explorerNode.needsSave()) 254 { 255 explorerNode.saveChanges(); 256 } 257 } 258 } 259}