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 */ 016package org.ametys.web.synchronization; 017 018import java.util.Map; 019import java.util.concurrent.TimeUnit; 020import java.util.concurrent.locks.Lock; 021 022import javax.jcr.Repository; 023import javax.jcr.RepositoryException; 024import javax.jcr.Session; 025 026import org.apache.avalon.framework.service.ServiceException; 027import org.apache.avalon.framework.service.ServiceManager; 028import org.apache.avalon.framework.service.Serviceable; 029 030import org.ametys.core.observation.Event; 031import org.ametys.core.observation.Observer; 032import org.ametys.runtime.plugin.component.AbstractLogEnabled; 033import org.ametys.web.WebConstants; 034import org.ametys.web.live.LiveAccessManager; 035 036/** 037 * Abstract {@link Observer} for synchronizing the workspace live.<p> 038 * A lock is used for write access to the live session in order to 039 * prevent errors from a parallel full synchronization or observer. 040 */ 041public abstract class AbstractSynchronizeObserver extends AbstractLogEnabled implements Observer, Serviceable 042{ 043 /** JCR repository. */ 044 protected Repository _repository; 045 /** Preview access manager. */ 046 protected LiveAccessManager _liveAccessManager; 047 /** The {@link SynchronizeComponent} */ 048 protected SynchronizeComponent _synchronizeComponent; 049 050 @Override 051 public void service(ServiceManager manager) throws ServiceException 052 { 053 _repository = (Repository) manager.lookup(Repository.class.getName()); 054 _liveAccessManager = (LiveAccessManager) manager.lookup(LiveAccessManager.ROLE); 055 _synchronizeComponent = (SynchronizeComponent) manager.lookup(SynchronizeComponent.ROLE); 056 } 057 058 @Override 059 public int getPriority(Event event) 060 { 061 return MAX_PRIORITY + 1000; 062 } 063 064 @Override 065 public void observe(Event event, Map<String, Object> transientVars) throws Exception 066 { 067 Lock lock = _liveAccessManager.getLiveWriteLock(); 068 069 try 070 { 071 // Ensure write access to the live workspace is exclusive 072 // try acquiring the lock for 2 seconds 073 if (lock.tryLock(2, TimeUnit.SECONDS)) 074 { 075 try 076 { 077 if (getLogger().isDebugEnabled()) 078 { 079 getLogger().debug("Preview write lock has been acquired: " + lock); 080 } 081 082 Session liveSession = null; 083 084 try 085 { 086 // Open a session to the workspace live 087 liveSession = _repository.login(WebConstants.LIVE_WORKSPACE); 088 _internalObserve(event, liveSession); 089 } 090 catch (RepositoryException e) 091 { 092 getLogger().error("Unable to synchronize workspace with event: " + event, e); 093 } 094 finally 095 { 096 if (liveSession != null) 097 { 098 liveSession.logout(); 099 } 100 } 101 } 102 finally 103 { 104 lock.unlock(); 105 } 106 } 107 else 108 { 109 if (getLogger().isInfoEnabled()) 110 { 111 getLogger().info("Unable to acquire live write lock, skipping synchronization"); 112 } 113 } 114 } 115 catch (InterruptedException e) 116 { 117 getLogger().error("Unable to acquire live write lock", e); 118 } 119 } 120 121 /** 122 * Observes the event with access to the live workspace. 123 * @param event the event. 124 * @param liveSession the session to the live workspace. 125 * @throws RepositoryException if an error occurs. 126 */ 127 protected abstract void _internalObserve(Event event, Session liveSession) throws RepositoryException; 128}