This is an automated email from the ASF dual-hosted git repository.
skygo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git
The following commit(s) were added to refs/heads/master by this push:
new 314bcd9 [NETBEANS-3745] Clean up abandoned user dirs
new 7106cd4 Merge pull request #1897 from lkishalmi/janitor
314bcd9 is described below
commit 314bcd9d0ef67d457526dfcd5b97e868be928551
Author: Laszlo Kishalmi <[email protected]>
AuthorDate: Thu Jan 23 18:20:16 2020 -0800
[NETBEANS-3745] Clean up abandoned user dirs
---
nbbuild/cluster.properties | 1 +
platform/core.kit/nbproject/project.xml | 6 +
platform/janitor/build.xml | 24 +++
platform/janitor/licenseinfo.xml | 28 +++
platform/janitor/manifest.mf | 5 +
platform/janitor/nbproject/project.properties | 19 ++
platform/janitor/nbproject/project.xml | 106 +++++++++
.../org/netbeans/modules/janitor/Bundle.properties | 19 ++
.../src/org/netbeans/modules/janitor/Janitor.java | 236 +++++++++++++++++++++
.../netbeans/modules/janitor/resources/clean.gif | Bin 0 -> 852 bytes
10 files changed, 444 insertions(+)
diff --git a/nbbuild/cluster.properties b/nbbuild/cluster.properties
index b19b2cf..48b940b 100644
--- a/nbbuild/cluster.properties
+++ b/nbbuild/cluster.properties
@@ -218,6 +218,7 @@ nb.cluster.platform=\
editor.mimelookup,\
editor.mimelookup.impl,\
favorites,\
+ janitor,\
javahelp,\
junitlib,\
keyring,\
diff --git a/platform/core.kit/nbproject/project.xml
b/platform/core.kit/nbproject/project.xml
index 367a975..8893caa 100644
--- a/platform/core.kit/nbproject/project.xml
+++ b/platform/core.kit/nbproject/project.xml
@@ -78,6 +78,12 @@
</run-dependency>
</dependency>
<dependency>
+
<code-name-base>org.netbeans.modules.janitor</code-name-base>
+ <run-dependency>
+ <specification-version>1.0</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
<code-name-base>org.netbeans.modules.masterfs</code-name-base>
<run-dependency>
<release-version>2</release-version>
diff --git a/platform/janitor/build.xml b/platform/janitor/build.xml
new file mode 100644
index 0000000..e084b7e
--- /dev/null
+++ b/platform/janitor/build.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+<project basedir="." default="build" name="platform/janitor">
+ <import file="../../nbbuild/templates/projectized.xml"/>
+</project>
diff --git a/platform/janitor/licenseinfo.xml b/platform/janitor/licenseinfo.xml
new file mode 100644
index 0000000..7d97822
--- /dev/null
+++ b/platform/janitor/licenseinfo.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+<licenseinfo>
+ <fileset>
+ <file>src/org/netbeans/modules/janitor/resources/clean.gif</file>
+ <license ref="Apache-2.0-ASF" />
+ <comment type="COMMENT_UNSUPPORTED" />
+ </fileset>
+</licenseinfo>
diff --git a/platform/janitor/manifest.mf b/platform/janitor/manifest.mf
new file mode 100644
index 0000000..2124b90
--- /dev/null
+++ b/platform/janitor/manifest.mf
@@ -0,0 +1,5 @@
+Manifest-Version: 1.0
+OpenIDE-Module: org.netbeans.modules.janitor
+OpenIDE-Module-Localizing-Bundle:
org/netbeans/modules/janitor/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
diff --git a/platform/janitor/nbproject/project.properties
b/platform/janitor/nbproject/project.properties
new file mode 100644
index 0000000..0f73a11
--- /dev/null
+++ b/platform/janitor/nbproject/project.properties
@@ -0,0 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+is.autoload=true
+javac.source=1.8
+javac.compilerargs=-Xlint -Xlint:-serial
diff --git a/platform/janitor/nbproject/project.xml
b/platform/janitor/nbproject/project.xml
new file mode 100644
index 0000000..d48778a
--- /dev/null
+++ b/platform/janitor/nbproject/project.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+<project xmlns="http://www.netbeans.org/ns/project/1">
+ <type>org.netbeans.modules.apisupport.project</type>
+ <configuration>
+ <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
+ <code-name-base>org.netbeans.modules.janitor</code-name-base>
+ <module-dependencies>
+ <dependency>
+
<code-name-base>org.netbeans.api.annotations.common</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <release-version>1</release-version>
+ <specification-version>1.34</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
+ <code-name-base>org.netbeans.api.progress</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <release-version>1</release-version>
+ <specification-version>1.54</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
+ <code-name-base>org.openide.awt</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <specification-version>7.75</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
+ <code-name-base>org.openide.dialogs</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <specification-version>7.49</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
+ <code-name-base>org.openide.filesystems</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <specification-version>9.17</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
+ <code-name-base>org.openide.modules</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <specification-version>7.55</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
+ <code-name-base>org.openide.util</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <specification-version>9.14</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
+ <code-name-base>org.openide.util.ui</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <specification-version>9.15</specification-version>
+ </run-dependency>
+ </dependency>
+ <dependency>
+ <code-name-base>org.openide.windows</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <specification-version>6.84</specification-version>
+ </run-dependency>
+ </dependency>
+ </module-dependencies>
+ <public-packages/>
+ </data>
+ </configuration>
+</project>
diff --git
a/platform/janitor/src/org/netbeans/modules/janitor/Bundle.properties
b/platform/janitor/src/org/netbeans/modules/janitor/Bundle.properties
new file mode 100644
index 0000000..ae1c450
--- /dev/null
+++ b/platform/janitor/src/org/netbeans/modules/janitor/Bundle.properties
@@ -0,0 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+OpenIDE-Module-Name=Janitor
+
+OpenIDE-Module-Short-Description=Removes unused cache/data
diff --git a/platform/janitor/src/org/netbeans/modules/janitor/Janitor.java
b/platform/janitor/src/org/netbeans/modules/janitor/Janitor.java
new file mode 100644
index 0000000..203acaa
--- /dev/null
+++ b/platform/janitor/src/org/netbeans/modules/janitor/Janitor.java
@@ -0,0 +1,236 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.janitor;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.time.Duration;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.WeakHashMap;
+import java.util.concurrent.atomic.AtomicLong;
+import javax.swing.Icon;
+import org.netbeans.api.annotations.common.StaticResource;
+import org.netbeans.api.progress.ProgressHandle;
+import org.openide.*;
+import org.openide.awt.Notification;
+import org.openide.awt.NotificationDisplayer;
+import org.openide.modules.Places;
+import org.openide.util.*;
+import org.openide.util.NbBundle.Messages;
+import org.openide.windows.OnShowing;
+
+/**
+ *
+ * @author Laszlo Kishalmi
+ */
+@Messages({
+ "# {0} - is the user directory name",
+ "# {1} - the days of abandonement",
+ "# {2} - the disk space can be reclaimed (in megabytes)",
+ "TIT_ABANDONED_USERDIR=NetBeans {0} was abandoned {1} days ago.",
+ "# {0} - is the user directory name",
+ "# {1} - the days of abandonement",
+ "# {2} - the disk space can be reclaimed (in megabytes)",
+ "DESC_ABANDONED_USERDIR=Remove unused data and cache directories of
NetBeans {0}. "
+ + "Free up {2}Mb of disk space.",
+})
+public class Janitor {
+
+ private static final long UNUSED_DAYS = 30;
+
+ private static final String LOGFILE_NAME = "var/log/messages.log"; //NOI18N
+ @StaticResource
+ private static final String CLEAN_ICON =
"org/netbeans/modules/janitor/resources/clean.gif"; //NOI18N
+
+ static final RequestProcessor JANITOR_RP = new RequestProcessor("janitor",
1); //NOI18N
+ static final Map<ActionListener, Notification> CLEANUP_TASKS = new
WeakHashMap<>();
+ static final Runnable SCAN_FOR_JUNK = () -> {
+ Icon clean = ImageUtilities.loadImageIcon(CLEAN_ICON, false);
+ List<Pair<String, Integer>> otherVersions = getOtherVersions();
+
+ for (Pair<String, Integer> ver : otherVersions) {
+ long toFree = size(getUserDir(ver.first())) +
size(getCacheDir(ver.first()));
+ toFree = toFree / (1024 * 1024) + 1;
+ ActionListener cleanupListener = cleanupAction(ver.first());
+ Notification nf = NotificationDisplayer.getDefault().notify(
+ Bundle.TIT_ABANDONED_USERDIR(ver.first(), ver.second(),
toFree),
+ clean,
+ Bundle.DESC_ABANDONED_USERDIR(ver.first(), ver.second(),
toFree),
+ cleanupListener);
+ CLEANUP_TASKS.put(cleanupListener, nf);
+ }
+ };
+
+ @Messages({
+ "TIT_CONFIRM_CLEANUP=Confirm Cleanup",
+ "# {0} - the dirname to be cleaned up",
+ "TXT_CONFIRM_CLEANUP=Are you sure to remove user and cache data for
NetBeans {0}?",
+ "# {0} - the dirname to be cleaned up",
+ "LBL_CLEANUP=Removing user and cache dirs of {0}"
+ })
+ static ActionListener cleanupAction(String name) {
+ return new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent evt) {
+ DialogDescriptor descriptor = new DialogDescriptor(
+ Bundle.TXT_CONFIRM_CLEANUP(name),
+ Bundle.TIT_CONFIRM_CLEANUP(),
+ true,
+ DialogDescriptor.YES_NO_OPTION,
+ DialogDescriptor.YES_OPTION,
+ null
+ ); if (DialogDescriptor.YES_OPTION ==
DialogDisplayer.getDefault().notify(descriptor)) {
+ JANITOR_RP.post(() -> {
+ try (ProgressHandle handle =
ProgressHandle.createHandle(Bundle.LBL_CLEANUP(name))){
+ handle.start();
+ deleteDir(getUserDir(name));
+ deleteDir(getCacheDir(name));
+ }
+ });
+ }
+ Notification nf = CLEANUP_TASKS.get(this);
+ if (nf != null) {
+ nf.clear();
+ }
+ }
+ };
+ }
+
+ @OnShowing
+ public static final class PlatformOpenHook implements Runnable {
+
+ @Override
+ public void run() {
+ // Starting delayed, not to interfere with other startup IO
operations
+ JANITOR_RP.post(SCAN_FOR_JUNK, 60_000);
+ }
+
+ }
+
+ static File getUserDir(String version) {
+ File ret = null;
+ File userDir = Places.getUserDirectory();
+ if (userDir != null) {
+ ret = new File(userDir.getParentFile(), version);
+ ret = ret.isDirectory() ? ret : null;
+ }
+
+ return ret;
+ }
+
+ static File getCacheDir(String version) {
+ File ret = null;
+ File cacheDir = Places.getCacheDirectory();
+ if (cacheDir != null) {
+ ret = new File(cacheDir.getParentFile(), version);
+ ret = ret.isDirectory() ? ret : null;
+ }
+ return ret;
+ }
+
+ static void deleteDir(File dir) {
+ if (dir == null) return;
+ Path path = dir.toPath();
+ try {
+ Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
+ @Override
+ public FileVisitResult visitFile(Path file,
BasicFileAttributes attrs) throws IOException {
+ Files.delete(file);
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult postVisitDirectory(Path dir,
IOException exc) throws IOException {
+ Files.delete(dir);
+ return FileVisitResult.CONTINUE;
+ }
+ });
+ } catch(IOException ex) {
+ // Well we've tried
+ }
+ }
+
+ public static long size(File f) {
+
+ if (f == null) {
+ return 0;
+ }
+ final Path path = f.toPath();
+ final AtomicLong size = new AtomicLong(0);
+
+ try {
+ Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
+ @Override
+ public FileVisitResult visitFile(Path file,
BasicFileAttributes attrs) {
+ size.addAndGet(attrs.size());
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult visitFileFailed(Path file, IOException
exc) {
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult postVisitDirectory(Path dir,
IOException exc) {
+ return FileVisitResult.CONTINUE;
+ }
+ });
+ } catch (IOException e) {
+ }
+
+ return size.get();
+ }
+
+ static List<Pair<String, Integer>> getOtherVersions() {
+ File userDir = Places.getUserDirectory();
+ List<Pair<String, Integer>> ret = new LinkedList<>();
+ Instant now = Instant.now();
+ if (userDir != null) {
+ File userParent = userDir.getParentFile();
+ for (File f : userParent.listFiles()) {
+ Path logFile = new File(f, LOGFILE_NAME).toPath();
+ if (!f.equals(userDir) && Files.isRegularFile(logFile)) {
+ try {
+ Instant lastModified =
Files.getLastModifiedTime(logFile).toInstant();
+ Integer age = (int) Duration.between(lastModified,
now).toDays();
+ if (lastModified.plus(UNUSED_DAYS,
ChronoUnit.DAYS).isBefore(now)) {
+ ret.add(Pair.of(f.getName(), age));
+ }
+ } catch (IOException ex) {
+ //Just ignore what we can't process
+ }
+ }
+ }
+ }
+ return ret;
+ }
+
+}
diff --git
a/platform/janitor/src/org/netbeans/modules/janitor/resources/clean.gif
b/platform/janitor/src/org/netbeans/modules/janitor/resources/clean.gif
new file mode 100644
index 0000000..570a323
Binary files /dev/null and
b/platform/janitor/src/org/netbeans/modules/janitor/resources/clean.gif differ
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists