Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that implements system utility methods 
4
 *  Copyright: 2008 Regents of the University of California and the
5
 *             National Center for Ecological Analysis and Synthesis
6
 *    Authors: Michael Daigle
7
 * 
8
 *   '$Author: daigle $'
9
 *     '$Date: 2009-02-17 09:28:11 -0800 (Tue, 17 Feb 2009) $'
10
 * '$Revision: 4805 $'
11
 *
12
 * This program is free software; you can redistribute it and/or modify
13
 * it under the terms of the GNU General Public License as published by
14
 * the Free Software Foundation; either version 2 of the License, or
15
 * (at your option) any later version.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 * GNU General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU General Public License
23
 * along with this program; if not, write to the Free Software
24
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25
 */
26

    
27
package edu.ucsb.nceas.metacat.util;
28

    
29
import java.io.IOException;
30
import java.util.regex.Matcher;
31
import java.util.regex.Pattern;
32
import javax.servlet.ServletContext;
33
import javax.servlet.http.HttpServletRequest;
34

    
35
import org.apache.log4j.Logger;
36

    
37
import edu.ucsb.nceas.metacat.MetaCatVersion;
38
import edu.ucsb.nceas.metacat.service.PropertyService;
39
import edu.ucsb.nceas.metacat.service.ServiceException;
40
import edu.ucsb.nceas.metacat.service.ServiceService;
41
import edu.ucsb.nceas.utilities.FileUtil;
42
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
43

    
44
public class SystemUtil {
45

    
46
	private static Logger logMetacat = Logger.getLogger(SystemUtil.class);
47
	private static String METACAT_SERVLET = "metacat";
48
	private static int OS_CLASS = 0;
49
	
50
	// Class of OS.  If we need more granularity, we should create a version
51
	// list and access it separately.
52
	public static int WIN_OS = 1;
53
	public static int LINUX_OS = 2;
54
	public static int MAC_OS = 3;
55
	public static int OTHER_OS = 4;
56
	
57
	/**
58
	 * private constructor - all methods are static so there is no no need to
59
	 * instantiate.
60
	 */
61
	private SystemUtil() {}
62

    
63
	/**
64
	 * Get the OS for this system.
65
	 * @return an integer representing the class of OS.  Possibilities are:
66
	 *     WIN_OS = 1;
67
	 *     LINUX_OS = 2;
68
	 *     MAC_OS = 3;
69
	 *     OTHER_OS = 4;
70
	 */
71
	public static int getOsClass() {
72
		if (OS_CLASS > 0) {
73
			return OS_CLASS;
74
		}
75
		
76
		String osName = System.getProperty("os.name");
77
		if (osName.startsWith("Windows")) {
78
			OS_CLASS =  WIN_OS;
79
		} else if (osName.startsWith("Linux")) {
80
			OS_CLASS =  LINUX_OS;
81
		} else if (osName.startsWith("Mac")) {
82
			OS_CLASS =  MAC_OS;
83
		} else if (osName.startsWith("Mac")) {
84
			OS_CLASS =  OTHER_OS;
85
		}
86
		
87
		return OS_CLASS;
88
	}
89
	
90
	/**
91
	 * Attempt to discover the server name. The name is retrieved from the http
92
	 * servlet request. This is used by configuration routines before the port
93
	 * has been populated in metacat.properties. it is possible the port that
94
	 * the user configures might be different than the name we get here. You
95
	 * should use getServerPort() instead of this method whenever possible.
96
	 * 
97
	 * @param request
98
	 *            the http servlet request we will use to find the server name
99
	 * 
100
	 * @return a string holding the server name
101
	 */
102
	public static String discoverServerName(HttpServletRequest request) {
103
		String serverName = request.getServerName();
104

    
105
		return serverName;
106
	}
107

    
108
	/**
109
	 * Attempt to discover the server port. The port is retrieved from the http
110
	 * servlet request. This is used by configuration routines before the port
111
	 * has been populated in metacat.properties. it is possible the port that
112
	 * the user configures might be different than the port we get here. You
113
	 * should use getServerPort() instead of this method whenever possible.
114
	 * 
115
	 * @param request
116
	 *            the http servlet request we will use to find the server port
117
	 * 
118
	 * @return a string holding the server port
119
	 */
120
	public static String discoverServerPort(HttpServletRequest request) {
121
		return Integer.toString(request.getServerPort());
122
	}
123
	
124
	/**
125
	 * Attempt to discover the server ssl port. The ssl port is assumed using
126
	 * the standard port. This is used by configuration routines before the port
127
	 * has been populated in metacat.properties. it is possible the prot that
128
	 * the user configures might be different than the port we get here. You
129
	 * should use getServerSSLPort() instead of this method whenever possible.
130
	 * 
131
	 * @param request
132
	 *            the http servlet request we will use to find the server port
133
	 * 
134
	 * @return a string holding the server ssl port
135
	 */
136
	public static String discoverServerSSLPort(HttpServletRequest request) {
137
		String serverPort = discoverServerPort(request);
138

    
139
		if (serverPort.length() == 4 && serverPort.charAt(0) == '8') {
140
			return "8443";
141
		}
142

    
143
		return "443";
144
	}
145

    
146
	/**
147
	 * Get the server URL which is made up of the server name + : + the http
148
	 * port number. Note that if the port is 80, it is left off.
149
	 * 
150
	 * @return string holding the server URL
151
	 */
152
	public static String getServerURL() throws PropertyNotFoundException {
153
		String ServerURL = "http://" + PropertyService.getProperty("server.name");
154
		String httpPort = PropertyService.getProperty("server.httpPort");
155
		if (!httpPort.equals("80")) {
156
			ServerURL += ":" + httpPort;
157
		}
158

    
159
		return ServerURL;
160
	}
161

    
162
	/**
163
	 * Get the secure server URL which is made up of the server name + : + the
164
	 * https port number. Note that if the port is 443, it is left off.
165
	 * 
166
	 * @return string holding the server URL
167
	 */
168
	public static String getSecureServerURL() throws PropertyNotFoundException {
169
		String ServerURL = "https://" + getSecureServer();
170
		return ServerURL;
171
	}
172
	
173
	/**
174
	 * Get the secure server  which is made up of the server name + : + the
175
	 * https port number. Note that if the port is 443, it is left off.
176
	 * NOTE: does NOT include "https://"
177
	 * @see getSecureServerURL()
178
	 * 
179
	 * @return string holding the secure server
180
	 */
181
	public static String getSecureServer() throws PropertyNotFoundException {
182
		String server = PropertyService.getProperty("server.name");
183
		String httpPort = PropertyService.getProperty("server.httpSSLPort");
184
		if (!httpPort.equals("443")) {
185
			server = server + ":" + httpPort;
186
		}
187

    
188
		return server;
189
	}
190

    
191
	/**
192
	 * Get the CGI URL which is made up of the server URL + file separator + the
193
	 * CGI directory
194
	 * 
195
	 * @return string holding the server URL
196
	 */
197
	public static String getCGI_URL() throws PropertyNotFoundException{
198
		return getContextURL() 
199
				+ PropertyService.getProperty("application.cgiDir");
200
	}
201

    
202
	/**
203
	 * Get the server URL with the context. This is made up of the server URL +
204
	 * file separator + the context
205
	 * 
206
	 * @return string holding the server URL with context
207
	 */
208
	public static String getContextURL() throws PropertyNotFoundException {
209
		return getServerURL() + "/"
210
				+ PropertyService.getProperty("application.context");
211
	}
212

    
213
	/**
214
	 * Get the servlet URL. This is made up of the server URL with context +
215
	 * file separator + the metacat servlet name
216
	 * 
217
	 * @return string holding the servlet URL
218
	 */
219
	public static String getServletURL() throws PropertyNotFoundException {
220
		return getContextURL() + "/" + METACAT_SERVLET;
221
	}
222

    
223
	/**
224
	 * Get the style skins URL. This is made up of the server URL with context +
225
	 * file separator + "style" + file separator + "skins"
226
	 * 
227
	 * @return string holding the style skins URL
228
	 */
229
	public static String getStyleSkinsURL() throws PropertyNotFoundException {
230
		return getContextURL() + "/" + "style" + "/" + "skins";
231
	}
232

    
233
	/**
234
	 * Get the style common URL. This is made up of the server URL with context +
235
	 * file separator + "style" + file separator + "common"
236
	 * 
237
	 * @return string holding the style common URL
238
	 */
239
	public static String getStyleCommonURL() throws PropertyNotFoundException {
240
		return getContextURL() + "/" + "style" + "/" + "common";
241
	}
242
	
243
	/**
244
	 * Get the metacat version by getting the string representation from
245
	 * metacat.properties and instantiating a MetaCatVersion object.
246
	 * The info is set in build.properties and then populated into metacat.properties
247
	 * at build time using Ant token replacement.
248
	 * 
249
	 * @return a MetaCatVersion object holding metacat version information
250
	 */
251
	public static MetaCatVersion getMetacatVersion() throws PropertyNotFoundException {
252
		String metacatVersionString = 
253
			PropertyService.getProperty("application.metacatVersion");
254
		return new MetaCatVersion(metacatVersionString);
255
	}
256
	
257
	/**
258
	 * Gets a string that holds some description about the release. Typically this is 
259
	 * used during release candidates for display purposes and might hold something
260
	 * like "Release Candidate 1".  Normally it is empty for final production release.
261
	 * The info is set in build.properties and then populated into metacat.properties
262
	 * at build time using Ant token replacement.
263
	 * 
264
	 * @return a MetaCatVersion object holding metacat version information
265
	 */
266
	public static String getMetacatReleaseInfo() throws PropertyNotFoundException {
267
		return PropertyService.getProperty("application.metacatReleaseInfo");
268
	}
269

    
270
	/**
271
	 * Get the context directory. This is made up of the deployment directory + file
272
	 * separator + context
273
	 * 
274
	 * @return string holding the context directory
275
	 */
276
	public static String getContextDir() throws PropertyNotFoundException {
277
		return PropertyService.getProperty("application.deployDir") + FileUtil.getFS()
278
				+ PropertyService.getProperty("application.context");
279
	}
280

    
281
	/**
282
	 * Attempt to discover the context for this application. This is a best
283
	 * guess scenario. It is used by configuration routines before the context
284
	 * has been populated in metacat.properties. You should always use
285
	 * getApplicationContext() instead of this method if possible.
286
	 * 
287
	 * @param servletContext
288
	 *            the servlet context we will use to find the application context
289
	 * 
290
	 * @return a string holding the context
291
	 */
292
	public static String discoverApplicationContext(ServletContext servletContext) {
293
		String applicationContext = "";
294
		String realPath = servletContext.getRealPath("/");
295

    
296
		if (realPath.charAt(realPath.length() - 1) == '/') {
297
			realPath = realPath.substring(0, realPath.length() - 1);
298
		}
299
		
300
		int lastSlashIndex = realPath.lastIndexOf('/');
301
		if (lastSlashIndex != -1) {
302
			applicationContext = realPath.substring(lastSlashIndex + 1);
303
		}
304
				
305
		logMetacat.debug("application context: " + applicationContext);
306

    
307
		return applicationContext;
308
	}
309
	
310
	/**
311
	 * Gets the stored backup location.  This location is held in a file at
312
	 * <user_home>/.<application_context>/backup-location
313
	 * 
314
	 * @return a string holding the backup location.  Null if none could be found.
315
	 */
316
	public static String getStoredBackupDir() throws UtilException {
317
		String applicationContext = null;
318
		try {
319
			applicationContext = ServiceService.getRealApplicationContext();
320
			// Check if there is a file at
321
			// <user_home>/<application_context>/backup-location. If so, it
322
			// should contain one line that is a file that points to a writable
323
			// directory. If that is true, use that value as the backup dir.
324
			String storedBackupFileLoc = getUserHomeDir() + FileUtil.getFS() + "."
325
					+ applicationContext + FileUtil.getFS() + "backup-location";
326
			if (FileUtil.getFileStatus(storedBackupFileLoc) >= FileUtil.EXISTS_READABLE) {
327
				String storedBackupDirLoc = FileUtil
328
						.readFileToString(storedBackupFileLoc);
329
				if (FileUtil.isDirectory(storedBackupDirLoc)
330
						&& FileUtil.getFileStatus(storedBackupDirLoc) > FileUtil.EXISTS_READABLE) {
331
					return storedBackupDirLoc;
332
				}
333
			}
334
		} catch (IOException ioe) {
335
			logMetacat.warn("I/O problem finding backup location: " + ioe.getMessage());
336
		} catch (ServiceException se) {
337
			logMetacat.warn("Could not get real application context: " + se.getMessage());
338
		}
339
		return null;
340
	}
341
	
342
	public static void writeStoredBackupFile(String backupPath) throws UtilException {
343
		String applicationContext = null;
344
		try {
345
			applicationContext = ServiceService.getRealApplicationContext();
346
			// Write the backup path to
347
			// <user_home>/.<application_context>/backup-location. 
348
			String storedBackupFileDir = getUserHomeDir() + FileUtil.getFS() + "." + applicationContext;
349
			String storedBackupFileLoc = storedBackupFileDir + FileUtil.getFS() + "backup-location";
350
			if (!FileUtil.isDirectory(storedBackupFileDir)) {
351
				FileUtil.createDirectory(storedBackupFileDir);
352
			}
353
			if (FileUtil.getFileStatus(storedBackupFileLoc) == FileUtil.DOES_NOT_EXIST) {
354
				FileUtil.createFile(storedBackupFileLoc);
355
			}		
356
			if (FileUtil.getFileStatus(storedBackupFileLoc) < FileUtil.EXISTS_READ_WRITABLE) {
357
				throw new UtilException("Stored backup location file is not writable: " + storedBackupFileLoc);
358
			}
359
			
360
			FileUtil.writeFile(storedBackupFileLoc, backupPath);
361
			
362
		} catch (IOException ioe) {
363
			logMetacat.warn("I/O proplem finding backup location: " + ioe.getMessage());
364
		} catch (ServiceException se) {
365
			logMetacat.warn("Could not get real application context: " + se.getMessage());
366
		}
367
	}
368
	
369
	/**
370
	 * Attempt to discover the external (to the metacat installation)
371
	 * directory where metacat will hold backup files.   This functionality 
372
	 * is used to populate the configuration utility initially.  The user 
373
	 * can change the directory manually, so you can't rely on this method 
374
	 * to give you the actual directory.  Here are the steps taken to discover
375
	 * the directory:
376
	 * 
377
     * -- 1) Look for an existing hidden (.<application_context>) directory in a default system directory.  Get 
378
	 *       the default base directory for the OS.  (See application.windowsBackupBaseDir and 
379
	 *       application.linuxBackupBaseDir in metacat.properties.)  If a directory called 
380
	 *       <base_dir>/metacat/.<application_context> exists, return <base_dir>/metacat.
381
	 * -- 2) Otherwise, look for an existing hidden (.metacat) directory in the user directory. If a directory 
382
	 *       called <user_dir>/metacat/.<application_context> exists for the user that started tomcat, 
383
	 *       return <user_dir>/metacat.
384
	 * -- 3) Otherwise, look for an existing metacat directory in a default system directory.  Get 
385
	 *       the default base directory for the OS.  (See application.windowsBackupBaseDir and 
386
	 *       application.linuxBackupBaseDir in metacat.properties.)  If a directory called 
387
	 *       <base_dir>/metacat exists, return <base_dir>/metacat.
388
	 * -- 4) Otherwise, look for an existing metacat directory in the user directory. If a directory 
389
	 *       called <user_dir>/metacat/ exists for the user that started tomcat, return <user_dir>/metacat.
390
	 * -- 5) Otherwise, is the <base_dir> writable by the user that started tomcat?  If so, return 
391
	 *       <base_dir>/metacat
392
	 * -- 6) Does the <user_home> exist?  If so, return <user_home>/metacat
393
	 * -- 7) Otherwise, return null
394
	 *    
395
	 * @return a string holding the backup directory path
396
	 */
397
	public static String discoverExternalDir() throws UtilException {
398
		String applicationContext = null; 
399
		
400
		try {
401
			applicationContext = ServiceService.getRealApplicationContext();
402
			
403
			// Set the default location using the os
404
			String systemDir = "";
405
			if (getOsClass() == WIN_OS) {
406
				systemDir = PropertyService.getProperty("application.windowsBackupBaseDir");
407
			} else {
408
				systemDir = PropertyService.getProperty("application.linuxBackupBaseDir");
409
			}	
410
			String systemMetacatDir = systemDir + FileUtil.getFS() + "metacat";
411
			String systemBackupDir = systemMetacatDir + FileUtil.getFS() + "."
412
					+ applicationContext;
413

    
414
			String userHomeDir = getUserHomeDir();
415
			String userHomeMetacatDir = userHomeDir + FileUtil.getFS() + "metacat";
416
			String userHomeBackupDir = userHomeMetacatDir + FileUtil.getFS() + "." + applicationContext;
417

    
418
			// If <system_dir>/metacat/.<application_context> exists writable, 
419
			// return <system_dir>/metacat
420
			if ((FileUtil.getFileStatus(systemBackupDir) >= FileUtil.EXISTS_READ_WRITABLE)) {
421
				return systemMetacatDir;
422
			}
423

    
424
			// Otherwise if <user_dir>/metacat/.<application_context> exists writable, return
425
			// <user_dir>/metacat
426
			if ((FileUtil.getFileStatus(userHomeBackupDir) >= FileUtil.EXISTS_READ_WRITABLE)) {
427
				return userHomeMetacatDir;
428
			}
429

    
430
			// Otherwise if <system_dir>/metacat exists writable, create 
431
			// <system_dir>/metacat/.<application_context> and return <system_dir>/metacat
432
			if ((FileUtil.getFileStatus(systemMetacatDir) >= FileUtil.EXISTS_READ_WRITABLE)) {
433
				// go ahead and create the backup hidden dir
434
				FileUtil.createDirectory(systemBackupDir);
435
				return systemMetacatDir;
436
			}
437

    
438
			// Otherwise if <user_dir>/metacat exists writable, create 
439
			// <user_dir>/metacat/.<application_context> and return <user_dir>/metacat
440
			if ((FileUtil.getFileStatus(userHomeMetacatDir) >= FileUtil.EXISTS_READ_WRITABLE)) {
441
				// go ahead and create the backup hidden dir
442
				FileUtil.createDirectory(userHomeBackupDir);
443
				return userHomeMetacatDir;
444
			}
445
			
446
			// Otherwise if <system_dir> exists, create 
447
			// <system_dir>/metacat/.<application_context> and return <system_dir>/metacat
448
			if ((FileUtil.getFileStatus(systemDir) >= FileUtil.EXISTS_READ_WRITABLE)) {
449
				// go ahead and create the backup hidden dir
450
				FileUtil.createDirectory(systemBackupDir);
451
				return systemMetacatDir;
452
			}
453

    
454
			// Otherwise if <user_dir> exists, return <user_dir> create 
455
			// <user_dir>/metacat/.<application_context> and return <user_dir>/metacat
456
			if ((FileUtil.getFileStatus(userHomeDir) >= FileUtil.EXISTS_READ_WRITABLE)) {
457
				// go ahead and create the backup hidden dir
458
				FileUtil.createDirectory(userHomeBackupDir);
459
				return userHomeMetacatDir;
460
			}
461

    
462
		} catch (IOException ioe) {
463
			logMetacat.warn("I/O proplem finding backup location: " + ioe.getMessage());
464
		} catch (ServiceException se) {
465
			logMetacat.warn("Could not get real application context: " + se.getMessage());
466
		} catch (PropertyNotFoundException pnfe) {
467
			logMetacat.warn("Could not get default backup base dir property: "
468
					+ pnfe.getMessage());
469
		}
470
	
471
		// Otherwise, return userHomeDir
472
		return null;
473
	}
474
	
475
	/**
476
	 * Store the location of the backup file location into a file at 
477
	 * <user_home>/<application_dir>/backup-location
478
	 * 
479
	 * @param externalDir the backup file location.
480
	 */
481
	public static void storeExternalDirLocation(String externalDir) {
482
		if (getUserHomeDir() != null) {
483
			String applicationContext = null;
484
			String storedBackupLocDir = null;
485
			String storedBackupLocFile = null;
486
			try {
487
				applicationContext = ServiceService.getRealApplicationContext();
488
				storedBackupLocDir = getUserHomeDir() + FileUtil.getFS() + "."
489
						+ applicationContext;
490
				storedBackupLocFile = storedBackupLocDir + FileUtil.getFS()
491
						+ "backup-location";
492
			
493
				FileUtil.createDirectory(storedBackupLocDir);
494
				FileUtil.writeFile(storedBackupLocFile, externalDir);
495
			} catch (IOException ioe) {
496
				logMetacat.error("I/O error while trying to write stored backup directory: "
497
							+ storedBackupLocFile + " : " + ioe.getMessage());
498
			} catch (ServiceException se) {
499
				logMetacat.error("Could not get real application directory while trying to write "
500
							+ "stored backup directory: "+ storedBackupLocFile + " : " + se.getMessage());
501
			}
502
		} else {
503
			logMetacat.warn("Could not write out stored backup directory." 
504
					+ " User directory does not exist");
505
		}
506
	}
507

    
508
	/**
509
	 * Get the style skins directory. This is made up of the tomcat directory
510
	 * with context + file separator + "style" + file separator + "skins"
511
	 * 
512
	 * @return string holding the style skins directory
513
	 */
514
	public static String getStyleSkinsDir() throws PropertyNotFoundException {
515
		return getContextDir() + FileUtil.getFS() + "style" + FileUtil.getFS()
516
				+ "skins";
517
	}
518

    
519
	/**
520
	 * Get the SQL directory. This is made up of the context directory + file
521
	 * separator + sql
522
	 * 
523
	 * @return string holding the sql directory
524
	 */
525
	public static String getSQLDir() throws PropertyNotFoundException {
526
		return getContextDir() + FileUtil.getFS() + "WEB-INF" + FileUtil.getFS() + "sql";
527
	}
528

    
529
	/**
530
	 * Get the default style URL from metacat.properties.
531
	 * 
532
	 * @return string holding the default style URL
533
	 */
534
	public static String getDefaultStyleURL() throws PropertyNotFoundException {
535
		return getStyleCommonURL() + "/"
536
				+ PropertyService.getProperty("application.default-style");
537
	}
538

    
539
	/**
540
	 * Attempt to discover the deployment directory for this application. This is a
541
	 * best guess scenario. It is used by configuration routines before the
542
	 * deployment directory has been populated in metacat.properties. 
543
	 * 
544
	 * @param request
545
	 *            the http servlet request we will use to find the tomcat directory
546
	 * 
547
	 * @return a string holding the web application directory
548
	 */
549
	public static String discoverDeployDir(HttpServletRequest request) {
550
		ServletContext servletContext = request.getSession()
551
				.getServletContext();
552
		String realPath = servletContext.getRealPath(".");
553
		String contextPath = request.getContextPath();
554
		
555
		logMetacat.debug("realPath: " + realPath);
556
		logMetacat.debug("contextPath: " + contextPath);
557

    
558
		Pattern pattern = Pattern.compile(contextPath + "/\\.$");
559
		Matcher matcher = pattern.matcher(realPath);
560
		
561
		if (matcher.find()) {
562
			realPath = matcher.replaceFirst("");
563
		}
564
		
565
		return realPath;
566
	}
567
	
568
	/**
569
	 * Get the current user's home directory
570
	 * 
571
	 * @return a string holding the home directory
572
	 */
573
	public static String getUserHomeDir() {
574
		return System.getProperty("user.home");
575
	}
576

    
577
}
(11-11/12)