/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright (c) 1997-2011 Oracle and/or its affiliates. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development * and Distribution License("CDDL") (collectively, the "License"). You * may not use this file except in compliance with the License. You can * obtain a copy of the License at * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html * or packager/legal/LICENSE.txt. See the License for the specific * language governing permissions and limitations under the License. * * When distributing the software, include this License Header Notice in each * file and include the License file at packager/legal/LICENSE.txt. * * GPL Classpath Exception: * Oracle designates this particular file as subject to the "Classpath" * exception as provided by Oracle in the GPL Version 2 section of the License * file that accompanied this code. * * Modifications: * If applicable, add the following below the License Header, with the fields * enclosed by brackets [] replaced by your own identifying information: * "Portions Copyright [year] [name of copyright owner]" * * Contributor(s): * If you wish your version of this file to be governed by only the CDDL or * only the GPL Version 2, indicate your decision by adding "[Contributor] * elects to include this software in this distribution under the [CDDL or GPL * Version 2] license." If you don't indicate a single choice of license, a * recipient has the option to distribute your version of this file under * either the CDDL, the GPL Version 2 or to extend the choice of license to * its licensees as provided above. However, if you add GPL Version 2 code * and therefore, elected the GPL Version 2 license, then the option applies * only if the new code is made subject to such option by the copyright * holder. */ package com.sun.tools.xjc.servlet.reaper; import java.io.File; import java.io.FileFilter; import java.io.IOException; /** * This thread is used by the DiskManagerServlet to periodically * clean up temporary files created by XJCServlet and JavaDocServlet. */ class Reaper extends Thread { // the root directory to reap private final File rootTmpDir; // disk space usage private long diskUsage; // amount of disk space reaped on the current sweep private long reapedSpace; // how often the reaper thread should wake up and run (in milliseconds) private static final long reapInterval = 1000 * 60 * 5; // 5 min. /* * initialize the reaper */ Reaper() throws IOException { super("JAXB servlet disk reaper"); rootTmpDir = DiskManagerServlet.getRootTmpDir(); } /* (non-Javadoc) * @see java.lang.Runnable#run() */ public void run() { while (true) { try { // reap stale sessions long currentReap = reapStaleSessions(); if( currentReap != 0 ) reapedSpace = currentReap; // calculate the disk usage diskUsage = calculateTotalDiskUsage(); // sleep Thread.sleep( reapInterval ); } catch (InterruptedException ignored) { } } } /** * Traverse tmpDir looking for directories that are older than the * timout value and reap them. * * @return the amount of disk space freeded by the operation */ private long reapStaleSessions() { File[] sessions = getJAXBSessions(); long reapedSpace = 0; for( int i = 0; i < sessions.length; i++ ) { if( isStale( sessions[i] ) ) { // add up the disk usage reapedSpace += calculateDirSize( sessions[i] ); // and reap it deleteDir( sessions[i] ); } } return reapedSpace; } /* * find all directories whose name begins with the session prefix */ private File[] getJAXBSessions() { File[] sessions = rootTmpDir.listFiles( new FileFilter() { public boolean accept(File pathname) { if( pathname.isDirectory() && pathname.getName().startsWith( DiskManagerServlet.SESSION_DIR_PREFIX )) { return true; } return false; } }); return sessions; } /** * determine if the specified directory has been modified within * a specified timeout * * @param dir the directory * @return true if the file is older than the timeout */ private boolean isStale(File dir) { return (System.currentTimeMillis() - dir.lastModified()) > DiskManagerServlet.TIMEOUT; } /** * recursively delete the directory * * @param dir the directory to delete */ protected void deleteDir(File dir) { File[] files = dir.listFiles(); for( int i = 0; i < files.length; i++ ) { if( files[i].isDirectory() ) { deleteDir( files[i] ); } else { files[i].delete(); } } dir.delete(); } /** * Find and delete all jaxb directories in the root tmp dir */ protected void deleteAll() { File[] sessions = getJAXBSessions(); for( int i = 0; i < sessions.length; i++ ) { deleteDir( sessions[i] ); } } /** * Calculate the number of bytes of disk space being used under * the specified directory. * * @return the disk usage in bytes */ private long calculateDirSize(File directory) { File[] files = directory.listFiles(); long usage = 0; for (int i = 0; i < files.length; i++) { if (files[i].isDirectory()) { usage += calculateDirSize(files[i]); } else { usage += files[i].length(); } } return usage; } private long calculateTotalDiskUsage() { File[] sessions = getJAXBSessions(); long bytes = 0; for( int i = 0; i < sessions.length; i++ ) { bytes += calculateDirSize( sessions[i] ); } return bytes; } /** * @return */ public long getDiskUsage() { return diskUsage; } /** * @return */ public long getReapedSpace() { return reapedSpace; } /** * @return */ public File getTmpDir() { return rootTmpDir; } /* * testing purposes only */ public static void main( String[] args ) throws Exception { Reaper r = new Reaper(); System.out.println( r.calculateDirSize( new File( args[0] ) ) ); } /** * re-calculate disk usage - this method is called everytime the * DiskManagerServlet is run */ protected void update() { // calculate the disk usage diskUsage = calculateTotalDiskUsage(); } }