001/* 002 * Copyright 2013 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.plugins.skincommons; 017 018import java.io.File; 019import java.io.FileReader; 020import java.io.FileWriter; 021import java.io.IOException; 022import java.io.Writer; 023import java.util.Date; 024import java.util.List; 025 026import org.apache.avalon.framework.component.Component; 027import org.apache.avalon.framework.logger.AbstractLogEnabled; 028import org.apache.avalon.framework.service.ServiceException; 029import org.apache.avalon.framework.service.ServiceManager; 030import org.apache.avalon.framework.service.Serviceable; 031import org.apache.avalon.framework.thread.ThreadSafe; 032import org.apache.commons.io.IOUtils; 033import org.joda.time.format.ISODateTimeFormat; 034 035import org.ametys.core.user.CurrentUserProvider; 036import org.ametys.core.user.UserIdentity; 037 038/** 039 * Component to manage lock on skin directories. 040 * 041 */ 042public class SkinLockManager extends AbstractLogEnabled implements Component, ThreadSafe, Serviceable 043{ 044 /** The Avalon role name */ 045 public static final String ROLE = SkinLockManager.class.getName(); 046 047 private CurrentUserProvider _userProvider; 048 049 @Override 050 public void service(ServiceManager smanager) throws ServiceException 051 { 052 _userProvider = (CurrentUserProvider) smanager.lookup(CurrentUserProvider.ROLE); 053 } 054 055 /** 056 * Determines if the current user can write in skin directory 057 * @param file The skin directory 058 * @return <code>true</code> if the skin directory is not locked by another user 059 * @throws IOException If an error occurred 060 */ 061 public boolean canWrite (File file) throws IOException 062 { 063 return getLockOwner(file).equals(_userProvider.getUser()); 064 } 065 066 /** 067 * Create or update .lock file 068 * @param file The skin directory 069 * @param toolId The id of tool responsible for lock. 070 * @throws IOException If an error occurred 071 */ 072 public void updateLockFile (File file, String toolId) throws IOException 073 { 074 File lockFile = new File(file, ".lock"); 075 if (lockFile.exists()) 076 { 077 lockFile.delete(); 078 } 079 lockFile.createNewFile(); 080 081 try (Writer writer = new FileWriter(lockFile);) 082 { 083 IOUtils.write(UserIdentity.userIdentityToString(_userProvider.getUser()) + "\n", writer); 084 IOUtils.write(ISODateTimeFormat.dateTime().print(new Date().getTime()) + "\n", writer); 085 IOUtils.write(toolId, writer); 086 } 087 } 088 089 /** 090 * Remove lock file 091 * @param file The skin directory 092 */ 093 public void unlock (File file) 094 { 095 File lockFile = new File(file, ".lock"); 096 if (lockFile.exists()) 097 { 098 lockFile.delete(); 099 } 100 } 101 102 /** 103 * Determines if the skin directory is locked 104 * @param file The skin directory 105 * @return <code>true</code> if the skin directory is locked 106 */ 107 public boolean isLocked (File file) 108 { 109 File lockFile = new File(file, ".lock"); 110 return lockFile.exists(); 111 } 112 113 /** 114 * Get lock owner 115 * @param file The skin directory 116 * @return The lock owner or null. 117 * @throws IOException if an error occurs while manipulating files 118 */ 119 public UserIdentity getLockOwner (File file) throws IOException 120 { 121 File lockFile = new File(file, ".lock"); 122 if (!lockFile.exists()) 123 { 124 return null; 125 } 126 127 try (FileReader reader = new FileReader(lockFile);) 128 { 129 List<String> lines = IOUtils.readLines(reader); 130 131 if (!lines.isEmpty()) 132 { 133 return UserIdentity.stringToUserIdentity(lines.get(0)); 134 } 135 136 return null; 137 } 138 } 139 140 /** 141 * Get tool responsible for lock 142 * @param file The skin directory 143 * @return The tool responsible for lock or <code>null</code> 144 * @throws IOException if an error occurs while manipulating files 145 */ 146 public String getLockTool (File file) throws IOException 147 { 148 File lockFile = new File(file, ".lock"); 149 if (!lockFile.exists()) 150 { 151 return null; 152 } 153 154 try (FileReader reader = new FileReader(lockFile);) 155 { 156 List<String> lines = IOUtils.readLines(reader); 157 158 if (!lines.isEmpty() && lines.size() > 2) 159 { 160 return lines.get(2); 161 } 162 163 return null; 164 } 165 } 166 167 /** 168 * Get the last modified date 169 * @param file The skin directory 170 * @return the last modified date 171 * @throws IOException if an error occurs while manipulating files 172 */ 173 public Date lastModified (File file) throws IOException 174 { 175 File lockFile = new File(file, ".lock"); 176 if (!lockFile.exists()) 177 { 178 return null; 179 } 180 181 try (FileReader reader = new FileReader(lockFile);) 182 { 183 List<String> lines = IOUtils.readLines(reader); 184 185 if (!lines.isEmpty() && lines.size() > 1) 186 { 187 return ISODateTimeFormat.dateTime().parseDateTime(lines.get(1)).toDate(); 188 } 189 190 return null; 191 } 192 catch (IndexOutOfBoundsException e) 193 { 194 return null; 195 } 196 } 197}