extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/projectarchive/ProjectArchiveService.java

Code
Comments
Other
Rev Date Author Line
3802 21 Mar 16 nicklas 1 package net.sf.basedb.reggie.projectarchive;
3802 21 Mar 16 nicklas 2
3802 21 Mar 16 nicklas 3
3802 21 Mar 16 nicklas 4 import java.util.HashSet;
3802 21 Mar 16 nicklas 5 import java.util.Iterator;
3802 21 Mar 16 nicklas 6 import java.util.Set;
3802 21 Mar 16 nicklas 7 import java.util.TimerTask;
3802 21 Mar 16 nicklas 8
3802 21 Mar 16 nicklas 9 import net.sf.basedb.clients.web.extensions.service.ServiceControllerAction;
3802 21 Mar 16 nicklas 10 import net.sf.basedb.clients.web.extensions.service.Services;
3802 21 Mar 16 nicklas 11 import net.sf.basedb.core.Application;
3802 21 Mar 16 nicklas 12 import net.sf.basedb.core.DbControl;
3802 21 Mar 16 nicklas 13 import net.sf.basedb.core.FileServer;
3802 21 Mar 16 nicklas 14 import net.sf.basedb.core.Include;
3802 21 Mar 16 nicklas 15 import net.sf.basedb.core.ItemQuery;
3802 21 Mar 16 nicklas 16 import net.sf.basedb.core.Sample;
3802 21 Mar 16 nicklas 17 import net.sf.basedb.core.SessionControl;
3802 21 Mar 16 nicklas 18 import net.sf.basedb.core.query.Annotations;
3802 21 Mar 16 nicklas 19 import net.sf.basedb.core.query.Expressions;
3802 21 Mar 16 nicklas 20 import net.sf.basedb.core.query.Hql;
3802 21 Mar 16 nicklas 21 import net.sf.basedb.core.query.Restrictions;
4306 17 Jan 17 nicklas 22 import net.sf.basedb.opengrid.CmdResult;
4306 17 Jan 17 nicklas 23 import net.sf.basedb.opengrid.OpenGrid;
4306 17 Jan 17 nicklas 24 import net.sf.basedb.opengrid.RemoteHost;
4306 17 Jan 17 nicklas 25 import net.sf.basedb.opengrid.RemoteSession;
4306 17 Jan 17 nicklas 26 import net.sf.basedb.opengrid.ScriptBuilder;
4306 17 Jan 17 nicklas 27 import net.sf.basedb.opengrid.config.ConnectionInfo;
3802 21 Mar 16 nicklas 28 import net.sf.basedb.reggie.Reggie;
3802 21 Mar 16 nicklas 29 import net.sf.basedb.reggie.dao.Annotationtype;
3802 21 Mar 16 nicklas 30 import net.sf.basedb.reggie.dao.Fileserver;
3802 21 Mar 16 nicklas 31 import net.sf.basedb.reggie.dao.Subtype;
4306 17 Jan 17 nicklas 32 import net.sf.basedb.reggie.grid.ScriptUtil;
3802 21 Mar 16 nicklas 33 import net.sf.basedb.util.Values;
3802 21 Mar 16 nicklas 34 import net.sf.basedb.util.extensions.Extension;
7076 27 Mar 23 nicklas 35 import net.sf.basedb.util.extensions.logging.ExtensionsLog;
7076 27 Mar 23 nicklas 36 import net.sf.basedb.util.extensions.logging.ExtensionsLogger;
3802 21 Mar 16 nicklas 37
3802 21 Mar 16 nicklas 38 import org.slf4j.LoggerFactory;
3802 21 Mar 16 nicklas 39
3802 21 Mar 16 nicklas 40 /**
3802 21 Mar 16 nicklas 41   Service for managing file permission in the project archive.
3802 21 Mar 16 nicklas 42   It will check the database at regular intervals for cases and
3802 21 Mar 16 nicklas 43   load their {@link Annotationtype#CONSENT} annotation. Files
3802 21 Mar 16 nicklas 44   that correspond to a case with consent = "Yes" will get read 
3802 21 Mar 16 nicklas 45   permissin for the group, all other files will be private.
3802 21 Mar 16 nicklas 46   
3802 21 Mar 16 nicklas 47   Note that checks are usually made in 2-hour intervals, but a job handler may
3802 21 Mar 16 nicklas 48   call {@link #setForceCheck()} when a job has ended to force a check at the next
3802 21 Mar 16 nicklas 49   timer event (typically within the next 5 seconds).
3802 21 Mar 16 nicklas 50   
3802 21 Mar 16 nicklas 51   @author nicklas
3802 21 Mar 16 nicklas 52   @since 4.3
3802 21 Mar 16 nicklas 53 */
3802 21 Mar 16 nicklas 54 public class ProjectArchiveService 
3802 21 Mar 16 nicklas 55 {
3802 21 Mar 16 nicklas 56
7076 27 Mar 23 nicklas 57   private static final ExtensionsLogger logger = 
7076 27 Mar 23 nicklas 58     ExtensionsLog.getLogger("net.sf.basedb.reggie.project-archive-service", true).wrap(LoggerFactory.getLogger(ProjectArchiveService.class));
3802 21 Mar 16 nicklas 59
3802 21 Mar 16 nicklas 60   // The singleton
3802 21 Mar 16 nicklas 61   private static ProjectArchiveService instance = null;
3802 21 Mar 16 nicklas 62
3802 21 Mar 16 nicklas 63   // At most 120 minutes between permission checks (1 when debugging)
7076 27 Mar 23 nicklas 64   private static final long MAX_WAIT_INTERVAL_NORMAL = 120 * 60000;
7076 27 Mar 23 nicklas 65   private static final long MAX_WAIT_INTERVAL_DEBUG = 1 * 60000;
3802 21 Mar 16 nicklas 66
3802 21 Mar 16 nicklas 67   /**
3802 21 Mar 16 nicklas 68     Get the singleton instance of the service. If the service has
3802 21 Mar 16 nicklas 69     not been created yet it is created at this time.
3802 21 Mar 16 nicklas 70   */
3802 21 Mar 16 nicklas 71   public static final ProjectArchiveService getInstance()
3802 21 Mar 16 nicklas 72   {
3802 21 Mar 16 nicklas 73     if (instance == null)
3802 21 Mar 16 nicklas 74     {
3802 21 Mar 16 nicklas 75       synchronized (ProjectArchiveService.class)
3802 21 Mar 16 nicklas 76       {
3802 21 Mar 16 nicklas 77         if (instance == null)
3802 21 Mar 16 nicklas 78         {
3802 21 Mar 16 nicklas 79           ProjectArchiveService tmp = new ProjectArchiveService();
3802 21 Mar 16 nicklas 80           instance = tmp;
3802 21 Mar 16 nicklas 81         }
3802 21 Mar 16 nicklas 82       }
3802 21 Mar 16 nicklas 83     }
3802 21 Mar 16 nicklas 84     return instance;
3802 21 Mar 16 nicklas 85   }
3802 21 Mar 16 nicklas 86
3802 21 Mar 16 nicklas 87   private volatile boolean isRunning;
3802 21 Mar 16 nicklas 88   private SessionControl systemSc;
3802 21 Mar 16 nicklas 89   private Extension<ServiceControllerAction> ext;
3802 21 Mar 16 nicklas 90   private TimerTask timer;
3802 21 Mar 16 nicklas 91   
3802 21 Mar 16 nicklas 92   // Time when last check for permissions was made
3802 21 Mar 16 nicklas 93   private volatile long lastPermissionCheck;
3802 21 Mar 16 nicklas 94   // If flag is set, we force check for permissions
3802 21 Mar 16 nicklas 95   private volatile boolean forcePermissionCheck;
3802 21 Mar 16 nicklas 96   
3802 21 Mar 16 nicklas 97   private ProjectArchiveService()
3802 21 Mar 16 nicklas 98   {}
3802 21 Mar 16 nicklas 99   
3802 21 Mar 16 nicklas 100   /**
3802 21 Mar 16 nicklas 101     Is the service running or not?
3802 21 Mar 16 nicklas 102   */
3802 21 Mar 16 nicklas 103   public boolean isRunning()
3802 21 Mar 16 nicklas 104   {
3802 21 Mar 16 nicklas 105     return isRunning;
3802 21 Mar 16 nicklas 106   }
3802 21 Mar 16 nicklas 107
3802 21 Mar 16 nicklas 108   /**
3802 21 Mar 16 nicklas 109     Start the service if it is not running.
3802 21 Mar 16 nicklas 110   */
3802 21 Mar 16 nicklas 111   public synchronized void start(SessionControl systemSc, Extension<ServiceControllerAction> ext)
3802 21 Mar 16 nicklas 112   {
3802 21 Mar 16 nicklas 113     if (!isRunning)
3802 21 Mar 16 nicklas 114     {
3802 21 Mar 16 nicklas 115       logger.debug("Starting project-archive file permissions service");
3802 21 Mar 16 nicklas 116       this.systemSc = systemSc;
3802 21 Mar 16 nicklas 117       this.ext = ext;
3802 21 Mar 16 nicklas 118       
3802 21 Mar 16 nicklas 119       Reggie.getRootSessionControl(systemSc);
3802 21 Mar 16 nicklas 120       
3802 21 Mar 16 nicklas 121       timer = Application.getScheduler().scheduleAtFixedRate(
3802 21 Mar 16 nicklas 122         new PermissionCheckTask(), 30000, 30000, false);
3802 21 Mar 16 nicklas 123       
3802 21 Mar 16 nicklas 124       isRunning = true;
3802 21 Mar 16 nicklas 125       logger.debug("Project-archive file permissions service is now running");
3802 21 Mar 16 nicklas 126     }
3802 21 Mar 16 nicklas 127   }
3802 21 Mar 16 nicklas 128
3802 21 Mar 16 nicklas 129   /**
3802 21 Mar 16 nicklas 130     Stop the service if it is running.
3802 21 Mar 16 nicklas 131   */
3802 21 Mar 16 nicklas 132   public synchronized void stop()
3802 21 Mar 16 nicklas 133   {
3802 21 Mar 16 nicklas 134     if (isRunning)
3802 21 Mar 16 nicklas 135     {
3802 21 Mar 16 nicklas 136       logger.debug("Stopping project-archive file permissions service");
3802 21 Mar 16 nicklas 137       isRunning = false;
3802 21 Mar 16 nicklas 138
3802 21 Mar 16 nicklas 139       if (timer != null)
3802 21 Mar 16 nicklas 140       {
3802 21 Mar 16 nicklas 141         timer.cancel();
3802 21 Mar 16 nicklas 142         timer = null;
3802 21 Mar 16 nicklas 143       }
3802 21 Mar 16 nicklas 144       systemSc = null;
3802 21 Mar 16 nicklas 145       ext = null;
3802 21 Mar 16 nicklas 146       lastPermissionCheck = 0;
3802 21 Mar 16 nicklas 147       forcePermissionCheck = false;
3802 21 Mar 16 nicklas 148       Reggie.closeRootSessionControl();
3802 21 Mar 16 nicklas 149       
3802 21 Mar 16 nicklas 150       logger.debug("Project-archive file permissions service has stopped");
3802 21 Mar 16 nicklas 151     }
3802 21 Mar 16 nicklas 152   }
3802 21 Mar 16 nicklas 153   
3802 21 Mar 16 nicklas 154   /**
3802 21 Mar 16 nicklas 155     Restart the service.
3802 21 Mar 16 nicklas 156   */
3802 21 Mar 16 nicklas 157   public synchronized void restart()
3802 21 Mar 16 nicklas 158   {
3802 21 Mar 16 nicklas 159     if (ext != null) Services.restart(ext);
3802 21 Mar 16 nicklas 160   }
3802 21 Mar 16 nicklas 161
3802 21 Mar 16 nicklas 162   /**
3802 21 Mar 16 nicklas 163     Set a flag forcing the service to perform a check at the next
3802 21 Mar 16 nicklas 164     timer event. This method is intended to be called when a
3802 21 Mar 16 nicklas 165     there is a known change in permissions.
3802 21 Mar 16 nicklas 166   */
3802 21 Mar 16 nicklas 167   public void setForceCheck()
3802 21 Mar 16 nicklas 168   {
3802 21 Mar 16 nicklas 169     this.forcePermissionCheck = true;
3802 21 Mar 16 nicklas 170   }
3802 21 Mar 16 nicklas 171   
3802 21 Mar 16 nicklas 172   /**
3802 21 Mar 16 nicklas 173     Perform a file permission check. Note that this method may return without doing
3802 21 Mar 16 nicklas 174     anything depending on how long time it was since the last check and if
3802 21 Mar 16 nicklas 175     the {@link #setForceCheck()} has been called or not.
3802 21 Mar 16 nicklas 176   */
3802 21 Mar 16 nicklas 177   void permissionCheck()
3802 21 Mar 16 nicklas 178   {
3802 21 Mar 16 nicklas 179     long now = System.currentTimeMillis();
3802 21 Mar 16 nicklas 180     long timeSinceLastCheck = now - lastPermissionCheck;
3802 21 Mar 16 nicklas 181
3802 21 Mar 16 nicklas 182     // If we have not waited long enough and there there is no recent request we don't have to check
7076 27 Mar 23 nicklas 183     long maxWaitInterval = logger.isDebugEnabled() ? MAX_WAIT_INTERVAL_DEBUG : MAX_WAIT_INTERVAL_NORMAL;
7076 27 Mar 23 nicklas 184     if (timeSinceLastCheck < maxWaitInterval && !forcePermissionCheck)
3802 21 Mar 16 nicklas 185     {
7076 27 Mar 23 nicklas 186       logger.debug("No project-archive permission check since no recent request and not long enough wait time [" + (timeSinceLastCheck / 1000) + " seconds]");
3802 21 Mar 16 nicklas 187       return;
3802 21 Mar 16 nicklas 188     }
3802 21 Mar 16 nicklas 189
3802 21 Mar 16 nicklas 190     forcePermissionCheck = false;
3802 21 Mar 16 nicklas 191     lastPermissionCheck = now;
7076 27 Mar 23 nicklas 192     logger.debug("Time for project-archive permission check [" + (timeSinceLastCheck / 1000) + " seconds]");
3802 21 Mar 16 nicklas 193     
3802 21 Mar 16 nicklas 194     SessionControl sc = Reggie.getRootSessionControl(systemSc);
3802 21 Mar 16 nicklas 195     DbControl dc = null;
3802 21 Mar 16 nicklas 196     try
3802 21 Mar 16 nicklas 197     {
6599 22 Feb 22 nicklas 198       dc = sc.newDbControl("Reggie: Project archive service");
3802 21 Mar 16 nicklas 199       
3802 21 Mar 16 nicklas 200       // Load all specimen with parent case that has with Consent=Yes
3802 21 Mar 16 nicklas 201       ItemQuery<Sample> query = Sample.getQuery();
3802 21 Mar 16 nicklas 202       Subtype.SPECIMEN.addFilter(dc, query);
3802 21 Mar 16 nicklas 203       query.setIncludes(sc.getActiveProjectId() != 0 ? Reggie.INCLUDE_IN_CURRENT_PROJECT : Include.ALL);
3802 21 Mar 16 nicklas 204       // Join Case
3802 21 Mar 16 nicklas 205       query.join(Hql.innerJoin("parent", "cse"));
3802 21 Mar 16 nicklas 206       // Consent==Yes
3802 21 Mar 16 nicklas 207       query.join(Annotations.innerJoin("cse", Annotationtype.CONSENT.load(dc), "cs"));
3802 21 Mar 16 nicklas 208       query.restrict(Restrictions.eq(Hql.alias("cs"), Expressions.string("Yes")));
3802 21 Mar 16 nicklas 209       
7076 27 Mar 23 nicklas 210       if (logger.isDebugEnabled()) logger.debug(query.toQl(dc));
3802 21 Mar 16 nicklas 211       
6565 01 Feb 22 nicklas 212       Set<String> itemNamesWithConsent = new HashSet<String>();
3802 21 Mar 16 nicklas 213       Iterator<Sample> it = query.iterate(dc);
3802 21 Mar 16 nicklas 214       while (it.hasNext())
3802 21 Mar 16 nicklas 215       {
6565 01 Feb 22 nicklas 216         itemNamesWithConsent.add(it.next().getName());
3802 21 Mar 16 nicklas 217       }
6565 01 Feb 22 nicklas 218
6565 01 Feb 22 nicklas 219       // Load blood items with Consent=Yes
6565 01 Feb 22 nicklas 220       query = Sample.getQuery();
6565 01 Feb 22 nicklas 221       Subtype.BLOOD.addFilter(dc, query);
6565 01 Feb 22 nicklas 222       query.setIncludes(sc.getActiveProjectId() != 0 ? Reggie.INCLUDE_IN_CURRENT_PROJECT : Include.ALL);
6565 01 Feb 22 nicklas 223       // Consent==Yes
6565 01 Feb 22 nicklas 224       query.join(Annotations.innerJoin(Annotationtype.CONSENT.load(dc), "cs"));
6565 01 Feb 22 nicklas 225       query.restrict(Restrictions.eq(Hql.alias("cs"), Expressions.string("Yes")));
3802 21 Mar 16 nicklas 226       
7076 27 Mar 23 nicklas 227       if (logger.isDebugEnabled()) logger.debug(query.toQl(dc));
6565 01 Feb 22 nicklas 228       
6565 01 Feb 22 nicklas 229       it = query.iterate(dc);
6565 01 Feb 22 nicklas 230       while (it.hasNext())
6565 01 Feb 22 nicklas 231       {
6565 01 Feb 22 nicklas 232         itemNamesWithConsent.add(it.next().getName());
6565 01 Feb 22 nicklas 233       }
6565 01 Feb 22 nicklas 234
3802 21 Mar 16 nicklas 235       if (logger.isDebugEnabled()) 
3802 21 Mar 16 nicklas 236       {
6565 01 Feb 22 nicklas 237         logger.debug("Found " + itemNamesWithConsent.size() + " specimen/blood items with Consent=Yes");
3802 21 Mar 16 nicklas 238       }
3802 21 Mar 16 nicklas 239       
3802 21 Mar 16 nicklas 240       FileServer projectArchive = Fileserver.PROJECT_ARCHIVE.load(dc);
7052 21 Feb 23 nicklas 241       FileServer projectArchiveDNA = Fileserver.PROJECT_ARCHIVE_DNA.load(dc);
3802 21 Mar 16 nicklas 242       dc.close();
7052 21 Feb 23 nicklas 243       
7052 21 Feb 23 nicklas 244       permissionCheck(projectArchive, itemNamesWithConsent);
7052 21 Feb 23 nicklas 245       permissionCheck(projectArchiveDNA, itemNamesWithConsent);
7052 21 Feb 23 nicklas 246       
7052 21 Feb 23 nicklas 247     }
7052 21 Feb 23 nicklas 248     finally
7052 21 Feb 23 nicklas 249     {
7052 21 Feb 23 nicklas 250       lastPermissionCheck = System.currentTimeMillis();
7052 21 Feb 23 nicklas 251       if (dc != null) dc.close();
7052 21 Feb 23 nicklas 252     }
7052 21 Feb 23 nicklas 253   }
7052 21 Feb 23 nicklas 254   
7052 21 Feb 23 nicklas 255   
7052 21 Feb 23 nicklas 256   private void permissionCheck(FileServer fileServer, Set<String> itemNamesWithConsent)
7052 21 Feb 23 nicklas 257   {
7052 21 Feb 23 nicklas 258     if (logger.isDebugEnabled())
7052 21 Feb 23 nicklas 259     {
7076 27 Mar 23 nicklas 260       logger.debug(fileServer.getName() + ": " + fileServer.getHost()+":"+fileServer.getRootPath());
7052 21 Feb 23 nicklas 261     }
7052 21 Feb 23 nicklas 262     
7052 21 Feb 23 nicklas 263     RemoteSession session = null;
7052 21 Feb 23 nicklas 264     int numItems = 0;
7052 21 Feb 23 nicklas 265     try
7052 21 Feb 23 nicklas 266     {
7052 21 Feb 23 nicklas 267       // Get the project archive and connect to it via SSH
7052 21 Feb 23 nicklas 268       RemoteHost host = new RemoteHost(new ConnectionInfo(fileServer));
7052 21 Feb 23 nicklas 269       String rootPath = ScriptUtil.checkValidPath(fileServer.getRootPath(), true, true);
7052 21 Feb 23 nicklas 270       session = host.connect(5);
3802 21 Mar 16 nicklas 271
3802 21 Mar 16 nicklas 272       // List all files in root folder. Returns one entry per line white-space-separated columns:
3802 21 Mar 16 nicklas 273       // <permissions> <'d' or 'f'> <path>
3802 21 Mar 16 nicklas 274       // Example: 750 d 1234567.1/l.r.m.c.lib.g
4573 15 Sep 17 nicklas 275       // -L option is important since the top-level (aka. "site") directory may be a symbolic link
7076 27 Mar 23 nicklas 276       String cmd = "find -L " + rootPath + " -printf '%m %y %P\\n'";
7076 27 Mar 23 nicklas 277       if (logger.isDebugEnabled()) logger.debug(cmd);
7052 21 Feb 23 nicklas 278       CmdResult<String> find = session.executeCmd(cmd, 120);
3802 21 Mar 16 nicklas 279       if (logger.isTraceEnabled()) logger.trace(find.toString());
3802 21 Mar 16 nicklas 280       
3802 21 Mar 16 nicklas 281       if (find.getExitStatus() != 0)
3802 21 Mar 16 nicklas 282       {
3802 21 Mar 16 nicklas 283         logger.error("find failed: " + find);
3802 21 Mar 16 nicklas 284         return;
3802 21 Mar 16 nicklas 285       }
3802 21 Mar 16 nicklas 286             
3802 21 Mar 16 nicklas 287       String[] lines = find.getStdout().split("\\n");
3918 03 May 16 nicklas 288       if (logger.isDebugEnabled())
3918 03 May 16 nicklas 289       {
7076 27 Mar 23 nicklas 290         logger.debug("Found " + lines.length + " files/directories in " + rootPath);
3918 03 May 16 nicklas 291       }
3918 03 May 16 nicklas 292
3802 21 Mar 16 nicklas 293       int numNoChange = 0;
3802 21 Mar 16 nicklas 294       int numToChange = 0;
3918 03 May 16 nicklas 295       int numChanged = 0;
3918 03 May 16 nicklas 296       int numFailed = 0;
3918 03 May 16 nicklas 297       int lastLine = lines.length - 1;
3802 21 Mar 16 nicklas 298       ScriptBuilder script = new ScriptBuilder();
3918 03 May 16 nicklas 299       for (int lineNo = 0; lineNo < lines.length; lineNo++)
3802 21 Mar 16 nicklas 300       {
3918 03 May 16 nicklas 301         String line = lines[lineNo];
3802 21 Mar 16 nicklas 302         if (logger.isTraceEnabled()) logger.trace(line);
3802 21 Mar 16 nicklas 303         String[] entry = line.split("\\s+", 3);
3802 21 Mar 16 nicklas 304         if (entry.length < 3) continue;
3802 21 Mar 16 nicklas 305         
3802 21 Mar 16 nicklas 306         String path = entry[2];
3802 21 Mar 16 nicklas 307         // Get rid of path that we do not care about
3802 21 Mar 16 nicklas 308         if (path.startsWith("debug")) path = path.substring(5);
3802 21 Mar 16 nicklas 309         if (path.startsWith("/")) path = path.substring(1);
4573 15 Sep 17 nicklas 310         // If the path starts with a two-digit directory (eg. 11/) we remove the first 3 characters
4573 15 Sep 17 nicklas 311          if (path.matches("\\d\\d/.*")) path = path.substring(3);
4573 15 Sep 17 nicklas 312         if (path.length() > 2) // '2' since we do not want to touch the site-directories
3802 21 Mar 16 nicklas 313         {
3918 03 May 16 nicklas 314           numItems++;
3918 03 May 16 nicklas 315           // Get the part before the first '/'
3918 03 May 16 nicklas 316           // This should be the specimen name
3918 03 May 16 nicklas 317           int dirIndex = path.indexOf("/");
3918 03 May 16 nicklas 318           String spName = dirIndex < 0 ? path : path.substring(0, dirIndex);
3918 03 May 16 nicklas 319           
3918 03 May 16 nicklas 320           int permissions = Values.getInt(entry[0]);
3918 03 May 16 nicklas 321           boolean isDirectory = "d".equals(entry[1]);
6565 01 Feb 22 nicklas 322           int expectedPermissions = (itemNamesWithConsent.contains(spName) ?
3918 03 May 16 nicklas 323               FilePermission.CONSENT : FilePermission.NO_CONSENT).getPermission(isDirectory);
3918 03 May 16 nicklas 324           if (expectedPermissions != permissions)
3802 21 Mar 16 nicklas 325           {
3918 03 May 16 nicklas 326             numToChange++;
3918 03 May 16 nicklas 327             // A permission change is needed
3918 03 May 16 nicklas 328             if (logger.isDebugEnabled())
3918 03 May 16 nicklas 329             {
3918 03 May 16 nicklas 330               logger.debug(entry[2] + " need permissions change: " + permissions + " -> "+expectedPermissions);
3918 03 May 16 nicklas 331             }
3918 03 May 16 nicklas 332             script.cmd("chmod " + expectedPermissions + " " + rootPath + "/" + entry[2]);
3802 21 Mar 16 nicklas 333           }
3918 03 May 16 nicklas 334           else
3918 03 May 16 nicklas 335           {
3918 03 May 16 nicklas 336             numNoChange++;
3918 03 May 16 nicklas 337             if (logger.isTraceEnabled())
3918 03 May 16 nicklas 338             {
3918 03 May 16 nicklas 339               logger.trace(entry[2] + " has expected permissions: " + permissions);
3918 03 May 16 nicklas 340             }
3918 03 May 16 nicklas 341           }
3802 21 Mar 16 nicklas 342         }
3918 03 May 16 nicklas 343         
3918 03 May 16 nicklas 344         if (numToChange == 100 || (lineNo == lastLine && numToChange > 0))
3802 21 Mar 16 nicklas 345         {
3918 03 May 16 nicklas 346           // Update the file permissions
3918 03 May 16 nicklas 347           if (logger.isTraceEnabled()) logger.trace(script.toString());
7052 21 Feb 23 nicklas 348           CmdResult<String> chmod = session.executeCmd(script.toString(), 30);
3918 03 May 16 nicklas 349           if (logger.isTraceEnabled()) logger.trace(chmod.toString());
3918 03 May 16 nicklas 350           
3918 03 May 16 nicklas 351           if (chmod.getExitStatus() == 0)
3802 21 Mar 16 nicklas 352           {
3918 03 May 16 nicklas 353             if (logger.isDebugEnabled())
3918 03 May 16 nicklas 354             {
3918 03 May 16 nicklas 355               logger.debug("File permissions modified on " + numToChange + " files");
3918 03 May 16 nicklas 356             }
3918 03 May 16 nicklas 357             numChanged += numToChange;
3802 21 Mar 16 nicklas 358           }
3918 03 May 16 nicklas 359           else
3918 03 May 16 nicklas 360           {
3918 03 May 16 nicklas 361             numFailed += numToChange;
3918 03 May 16 nicklas 362             logger.error("chmod failed: " + chmod);
3918 03 May 16 nicklas 363           }
3918 03 May 16 nicklas 364           
3918 03 May 16 nicklas 365           script = new ScriptBuilder();
3918 03 May 16 nicklas 366           numToChange = 0;
3802 21 Mar 16 nicklas 367         }
3802 21 Mar 16 nicklas 368       }
7076 27 Mar 23 nicklas 369       logger.info(fileServer.getName()+": Checked " + numItems + " file permissions; " + 
3918 03 May 16 nicklas 370           numChanged + " was modified, " + 
3918 03 May 16 nicklas 371           numFailed + " failed and " + 
3918 03 May 16 nicklas 372           numNoChange + " had expected permissions.");
3802 21 Mar 16 nicklas 373       
3802 21 Mar 16 nicklas 374     }
7076 27 Mar 23 nicklas 375     catch (RuntimeException ex)
7076 27 Mar 23 nicklas 376     {
7076 27 Mar 23 nicklas 377       logger.error(fileServer.getName()+": "+ex.getMessage(), ex);
7076 27 Mar 23 nicklas 378     }
3802 21 Mar 16 nicklas 379     finally
3802 21 Mar 16 nicklas 380     {
7052 21 Feb 23 nicklas 381       OpenGrid.close(session);
7076 27 Mar 23 nicklas 382       logger.debug(fileServer.getName()+": Processed project-archive permission checks for " + numItems + " items");
3802 21 Mar 16 nicklas 383     }
3802 21 Mar 16 nicklas 384   }
3802 21 Mar 16 nicklas 385   
3802 21 Mar 16 nicklas 386
3802 21 Mar 16 nicklas 387   /**
3802 21 Mar 16 nicklas 388     Timer for permission checks
3802 21 Mar 16 nicklas 389   */
3802 21 Mar 16 nicklas 390   static class PermissionCheckTask
3802 21 Mar 16 nicklas 391     extends TimerTask
3802 21 Mar 16 nicklas 392   {
3802 21 Mar 16 nicklas 393     public PermissionCheckTask() 
3802 21 Mar 16 nicklas 394     {}
3802 21 Mar 16 nicklas 395     
3802 21 Mar 16 nicklas 396     @Override
3802 21 Mar 16 nicklas 397     public void run()
3802 21 Mar 16 nicklas 398     {
3802 21 Mar 16 nicklas 399       try
3802 21 Mar 16 nicklas 400       {
3802 21 Mar 16 nicklas 401         getInstance().permissionCheck();
3802 21 Mar 16 nicklas 402       }
3802 21 Mar 16 nicklas 403       catch (Exception ex)
3802 21 Mar 16 nicklas 404       {
3802 21 Mar 16 nicklas 405         logger.error("Exception when performing project-archive permission check", ex);
3802 21 Mar 16 nicklas 406       }
3802 21 Mar 16 nicklas 407     }
3802 21 Mar 16 nicklas 408
3802 21 Mar 16 nicklas 409   }
3802 21 Mar 16 nicklas 410   
3802 21 Mar 16 nicklas 411 }