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