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