001 package com.softnetConsult.utils.sys;
002
003 import java.io.File;
004 import java.io.FileInputStream;
005 import java.io.IOException;
006
007 import com.softnetConsult.utils.reflect.ClassTools;
008 import com.softnetConsult.utils.reflect.ClassVersionInfo;
009
010 /**
011 * Static system, memory and time management utility functions.
012 *
013 * <p style="font-size:smaller;">This product includes software developed by the
014 * <strong>SoftNet-Consult Java Utility Library</strong> project and its contributors.<br />
015 * (<a href="http://java-tools.sourceforge.net" target="_blank">http://java-tools.sourceforge.net</a>)<br />
016 * Copyright (c) 2007-2008 SoftNet-Consult.<br />
017 * Copyright (c) 2007-2008 G. Paperin.<br />
018 * All rights reserved.
019 * </p>
020 * <p style="font-size:smaller;">File: SystemTools.java<br />
021 * Library API version: {@value com.softnetConsult.utils.APIProperties#apiVersion}<br />
022 * Java compliance version: {@value com.softnetConsult.utils.APIProperties#javaComplianceVersion}
023 * </p>
024 * <p style="font-size:smaller;">Redistribution and use in source and binary forms, with or
025 * without modification, are permitted provided that the following terms and conditions are met:
026 * </p>
027 * <p style="font-size:smaller;">1. Redistributions of source code must retain the above
028 * acknowledgement of the SoftNet-Consult Java Utility Library project, the above copyright
029 * notice, this list of conditions and the following disclaimer.<br />
030 * 2. Redistributions in binary form must reproduce the above acknowledgement of the
031 * SoftNet-Consult Java Utility Library project, the above copyright notice, this list of
032 * conditions and the following disclaimer in the documentation and/or other materials
033 * provided with the distribution.<br />
034 * 3. All advertising materials mentioning features or use of this software or any derived
035 * software must display the following acknowledgement:<br />
036 * <em>This product includes software developed by the SoftNet-Consult Java Utility Library
037 * project and its contributors.</em>
038 * </p>
039 * <p style="font-size:smaller;">THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY
040 * OF ANY KIND, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
041 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
042 * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
043 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
044 * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
045 * </p>
046 * @author Greg Paperin (<a href="http://www.paperin.org" target="_blank">http://www.paperin.org</a>)
047 * @version {@value com.softnetConsult.utils.APIProperties#apiVersion}
048 *
049 */
050 public final class SystemTools {
051
052 /**
053 * Prevents instances of this class from being created
054 * as this class contains only static utility methods.
055 */
056 private SystemTools() {}
057
058
059 /**
060 * Fetches the current memory information and formats the data in a human readable string.
061 *
062 * @return A human readable string containing information on available free memory, memory
063 * used by the current application, the total memory size of the current JVM and the maximum
064 * amount of memory that the current JVM will attempt to use.
065 */
066 public static String getMemInfoString() {
067 Runtime rt = Runtime.getRuntime();
068 long free = rt.freeMemory();
069 long total = rt.totalMemory();
070 long max = rt.maxMemory();
071 String s = String.format("Memory info: Free: %,d KB; Used: %,d; Total: %,d KB; Max: %,d KB.",
072 free >>> 10, (total - free) >>> 10, total >>> 10, max >>> 10);
073 return s;
074 }
075
076
077 /**
078 * Prints a human readable line with the current memory information to std-out,
079 * equivalent to {@code System.out.println(getMemInfoString())}.
080 *
081 */
082 public static void printMemInfoLine() {
083 System.out.println(getMemInfoString());
084 }
085
086
087 /**
088 * Allows calling {@code Thread.sleep} without the nuisance of surrounding the call with
089 * a {@code try-catch} block. A possible {@code InterruptedException} is caught and ignored.
090 *
091 * @param millis The length of time to sleep in milliseconds.
092 */
093 public static void sleep(long millis) {
094 try {
095 Thread.sleep(millis);
096 } catch(InterruptedException e) { }
097 }
098
099
100 /**
101 * Allows calling {@code Thread.sleep} without the nuisance of surrounding the call with
102 * a {@code try-catch} block. A possible {@code InterruptedException} is caught and ignored.
103 *
104 * @param millis The length of time to sleep in milliseconds.
105 * @param nanos 0-999999 additional nanoseconds to sleep.
106 */
107 public static void sleep(long millis, int nanos) {
108 try {
109 Thread.sleep(millis, nanos);
110 } catch(InterruptedException e) { }
111 }
112
113
114 /**
115 * Allows calling {@code Object.wait} without the nuisance of surrounding the call with
116 * a {@code try-catch} block. A possible {@code InterruptedException} is caught and ignored.
117 *
118 * @param millis The length of time to sleep in milliseconds.
119 * @param object The object for which to wait.
120 */
121 public static void wait(long millis, Object object) {
122 try {
123 object.wait(millis);
124 } catch(InterruptedException e) { }
125 }
126
127
128 /**
129 * Allows calling {@code Object.wait} without the nuisance of surrounding the call with
130 * a {@code try-catch} block. A possible {@code InterruptedException} is caught and ignored.
131 *
132 * @param millis The length of time to sleep in milliseconds.
133 * @param nanos 0-999999 additional nanoseconds to sleep.
134 * @param object The object for which to wait.
135 */
136 public static void wait(long millis, int nanos, Object object) {
137 try {
138 object.wait(millis, nanos);
139 } catch(InterruptedException e) { }
140 }
141
142
143 /**
144 * Determines how many days, hours, minutes, seconds and milliseconds the specified time
145 * period contains.
146 * Note that the specified time period, i.e. the absolude difference between {@code startMillis}
147 * and {@code endMillis} may not be larger than {@code 185542587187199999L} milliseconds, as an internal
148 * overflow would occur otherwise. The limit of {@code 185542587187199999L milliseconds} corrsponds to
149 * {@code ( (Integer.MAX_VALUE + 1L) * 86400000L - 1L ) milliseconds} or
150 * {@code Integer.MAX_VALUE days, 23 hours, 59 minures and 59.999 seconds} or
151 * {@code 2147483647 days, 23:59:59.999}.
152 *
153 * @param startMillis The milliseconds marking the beginning of a time period.
154 * @param endMillis The milliseconds marking the end of a time period.
155 *
156 * @return An {@code int}-array containg exactly 5 following elements:<br />
157 * index {@code [4]}: number of whole days in the specified time period;<br />
158 * index {@code [3]}: number of whole hours not covered by the whole days in the specified time period;<br />
159 * index {@code [2]}: number of whole minutes not covered by the whole hours in the specified time period;<br />
160 * index {@code [1]}: number of whole seconds not covered by the whole mins in the specified time period;<br />
161 * index {@code [0]}: number of whole millisecs not covered by the whole secs in the specified time period;<br />
162 *
163 * @throws IllegalArgumentException If the absolute value of the difference between {@code startMillis}
164 * and {@code endMillis} is larger than {@code 185542587187199999L}.
165 */
166 public static int[] timePeriod(long startMillis, long endMillis) {
167
168 long period = endMillis - startMillis;
169 if (0L > period)
170 period = -period;
171
172 if (period > 185542587187199999L) // 185542587187199999L = (Integer.MAX_VALUE + 1L) * 86400000L - 1L
173 throw new IllegalArgumentException("Cannot split a time period of longer "
174 + "than 185542587187199999L milliseconds");
175
176 int[] dets = new int[5];
177 dets[4] = (int) (period / 86400000L); // days
178 period = period % 86400000L;
179 dets[3] = (int) (period / 3600000L); // hours
180 period = period % 3600000L;
181 dets[2] = (int) (period / 60000L); // mins
182 period = period % 60000L;
183 dets[1] = (int) (period / 1000L); // secs
184 dets[0] = (int) (period % 1000L); // millis
185 return dets;
186 }
187
188
189 /**
190 * Formats a time interval to a nicely readable format without the need
191 * to involve a formatter. No validity checks are performed.
192 *
193 * @param millis Milliseconds
194 * @param secs Seconds.
195 * @param mins Minutes.
196 * @param hours Hours.
197 * @param days Days.
198 * @return Time formated as in for example {@code 3 days, 17:08:53.006}.
199 */
200 public static String formatTime(int millis, int secs, int mins, int hours, int days) {
201
202 millis = (millis < 0 ? -millis : millis);
203 secs = (secs < 0 ? -secs : secs);
204 mins = (mins < 0 ? -mins : mins);
205 hours = (hours < 0 ? -hours : hours);
206 days = (days < 0 ? -days : days);
207
208 if (days > 1) {
209 return String.format("%d days, %02d:%02d:%02d.%03d",
210 days, hours, mins, secs, millis);
211 } else if (days == 1) {
212 return String.format("1 day, %02d:%02d:%02d.%03d",
213 hours, mins, secs, millis);
214 } else {
215 return String.format("%02d:%02d:%02d.%03d",
216 hours, mins, secs, millis);
217 }
218 }
219
220
221 /**
222 * Formats the specified time period as specified in {@link #formatTime(int, int, int, int, int)};
223 * note that {@link #timePeriod(long, long)} is used to process the time period and therefore the
224 * same restrictions as in that method apply to this method.
225 *
226 * @param startMillis The milliseconds marking the beginning of a time period.
227 * @param endMillis The milliseconds marking the end of a time period.
228 * @return Time period formated as in for example {@code 3 days, 17:08:53.006}.
229 * @see #timePeriod(long, long)
230 * @see #formatTime(int, int, int, int, int)
231 */
232 public static String formatTimePeriod(long startMillis, long endMillis) {
233 int[] timeDets = timePeriod(startMillis, endMillis);
234 return formatTime(timeDets[0], timeDets[1], timeDets[2], timeDets[3], timeDets[4]);
235 }
236
237
238 /**
239 * Gets the class version info of the specified Java class file.
240 *
241 * @param classfile A {@code File} representing a physical Java class file.
242 * @return A {@code ClassVersionInfo}-object containing information about the
243 * major and the minor versions of the specified class file as well as the minimum
244 * JVM version required to run that class file. If the specified file is not a valid
245 * Java class file (according to the magic numer check) this method returns {@code null}.
246 * @throws IOException If there was an error when reading the specified file.
247 */
248 public static ClassVersionInfo getClassVersionInfo(File classfile) throws IOException {
249 FileInputStream in = new FileInputStream(classfile);
250 try { return ClassTools.getClassVersionInfo(in); }
251 finally { in.close(); }
252 }
253
254 /**
255 * Gets the class version info of the specified Java class file.
256 *
257 * @param classfile The full path of a physical Java class file.
258 * @return A {@code ClassVersionInfo}-object containing information about the
259 * major and the minor versions of the specified class file as well as the minimum
260 * JVM version required to run that class file. If the specified file is not a valid
261 * Java class file (according to the magic numer check) this method returns {@code null}.
262 * @throws IOException If there was an error when reading the specified file.
263 */
264 public static ClassVersionInfo getClassVersionInfo(String classfile) throws IOException {
265 FileInputStream in = new FileInputStream(classfile);
266 try { return ClassTools.getClassVersionInfo(in); }
267 finally { in.close(); }
268 }
269
270 } // public class SystemTools