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