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