In a wizard I am creating a package and trying to check if a resource already exists with a different case to avoid ResourceException thrown by org.eclipse.core.internal.resources.Resource#checkDoesNotExist. For example I get this exception when I try to create a package com.Example.test while com.example.test already exist. So I would like to make a check for the every segment of the package name. The case for existing com.Example.test is already handled in my code.
Since the method checkDoesNotExist is in the internal class and not declared by IResource it's not in the public API and I cannot use it to make the check before calling IFolder#create. The method IResource#exists is useless in this case because it's case sensitive.
Currently I have the following solution:
/**
* This method checks if a package or its part exists in the given source folder with a different case.
*
* #param pfr A source folder where to look package in.
* #param packageName Name of the package, e.g. "com.example.test"
* #return A String containing path of the existing resource relative to the project, null if the package name has no conflicts.
* #throws CoreException
* #throws IOException
*/
public static String checkPackageDoesExistWithDifferentCase(IPackageFragmentRoot pfr, String packageName)
throws CoreException, IOException
{
IPath p = pfr.getResource().getLocation();
String[] packagePathSegments = packageName.split("\\.");
for (int i = 0; i < packagePathSegments.length; i++)
{
p = p.append(packagePathSegments[i]);
File f = new File(p.toString());
String canonicalPath = f.getCanonicalPath();
if (f.exists() && !canonicalPath.equals(p.toOSString()))
return canonicalPath.substring(pfr.getJavaProject().getResource().getLocation().toOSString().length() + 1);
}
return null;
}
The issue about this solution is that it would work only on Windows, since f.exists() would return false on case-sensitive filesystems.
As you pointed out, there is not API, but you can check the parent resource if it has a member with the same (case-insensitive) name like this:
IContainer parent = newFolder.getParent();
IResource[] members = parent.members();
for( IResource resource : members ) {
if( resource.getName().equalsIgnoreCase( newFolder.getName() ) ) {
...
}
}
Related
I have a code that saves a textfile, but the path of that textfile and the name are hardcoded.
How can i make that the user select his/her own path and the name of the file?
int[][] sudokuNumbers = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
try (
PrintStream output = new PrintStream(new File("C:\\Users\\David\\Desktop\\Proyecto4.3\\output.txt"));) {
for (int i = 0; i < sudokuNumbers.length; i++) {
String s= "";
for (int j = 0; j < sudokuNumbers[i].length; j++) {
s+= "|" + sudokuNumbers[i][j] + "|";
}
output.println(s);
}
output.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
The task is relatively easy to carry out however you will need a couple methods to assist you. If a User is to supply a custom path (specific for them-self) then you will need to ensure that the path will be created so that it exists before the file is created and written to. Another thing to consider is that there may also be a requirement of Permissions to be granted to the application so as to carry out the task within the local file system (if this is where the file is to be created) or wherever else.
Obviously you will need to provide a means for the User to supply a path and file name. The best way to do this in my opinion is with a Folder Chooser dialog. The reason I say this is because it's not nearly as prone to mistakes (spelling, system format, etc.) as it would be if the User completely typed in the desired path and file name. Basically, the less control you give the User to the local file system the better off your application will be. Creating a folder (directory) based on the User Name within a preset file system location and utilizing a User name and date/time for file names is relatively common and can be all auto-generated, this eliminates the possibility of any file system errors. If possible, your application should maintain full control of such a task but understandably this can not always be the case for specific applications where User interaction with the file system is a requirement due to the fact that it's sole functionality is based on such interaction. For example, a File System Explorer where creating, cutting, copying, pasting, deleting, and editing of files and folders is its allowable purpose.
To demonstrate what I'm talking about I have quickly created a small Java runnable you can play with to see how the provided custom methods work. The code is well commented so that you can understand what is going on. Unfortunately all the commenting makes the code file look large when in fact it isn't if you were to remove them.
For simplicity, when we run the provided little console application it first asks for a User's Name. This Users Name will serve two specific purposes.
1) It will be used to create a specific Folder for that particular User only.
2) When a file is saved the file name will start with the User's name and then be followed with date/time data and finally contain the
".txt" file name extension.
Again, just for example purposes, as soon as a User enters his/her name into the console a Folders Selection dialog window will be displayed so that a main folder location can be selected where Users sub-folders will be created in and ultimately the Users data files will be saved under his/her folder name.
The file data is automatically saved once the home folder is selected and the console indicates of success once completed. Our little console application then simply ends.
Here is the Java runnable:
package choosefolder;
import java.awt.Component;
import java.awt.Container;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintStream;
import java.time.LocalDateTime;
import java.util.Scanner;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
public class ChooseFolder {
// Declare & initialize required String variables.
// These are global to the entire Class.
private static String userName = "";
private static String savePath = "";
public static void main(String[] args) {
//Setup a Scanner to get User input from console.
Scanner input = new Scanner(System.in);
// Ask for and get the Users Name and convert it to lowercase
// so as to maintain nameing consistency. No sense having "John Doe"
// one day and "john Doe" the next. This would consider 2 different
// Users since the second name has a lowercase "j" in "John" and
// therefore create two separate folder. Converting all supplied names
// to lowercase eliminates this problem.
while (userName.equals("")) {
System.out.println("\nPlease Enter User Name:");
userName = input.nextLine().toLowerCase();
}
// Open a Folders selection dialog window and allow for
// selection of a home folder where all Users saved files
// will be saved. Once we get the selected folder we then
// add the Users name to the path and create it.
savePath = openFoldersDialog("", "Select Home Folder To Save User Folders & File In...") + "\\" + userName;
// Create a special path just for the Users Name (ie: C:\My Files\John Doe\).
if (!createPath(savePath)) {
// If false was returnd from the createPath() method
// then there was an error while creating the path.
// Read console output to get the Error.
System.out.println("\n\u001B[31mError creating Users Save Path! Exiting...\u001B[39;49m");
System.exit(0);
}
// Get the local date & time so we can add it to
// our file namewhen its created.
LocalDateTime dateTime = LocalDateTime.now();
// Create the new file path & file name. This will be the path
// and file name where our Users data will be saved. We take the
// Users path e created and then add the file name to the end. The
// file name consists of the supplied User's name, the date/time and
// the .txt file name extension. Unwanted characters are also removed
// from the Date/Time. So, our path may look something like:
// C:\My Files\John Doe-20160419T155758107.txt
String filePathAndName = savePath + "\\" + userName + "-" +
dateTime.toString().replace("-", "").
replace(":", "").replace(".", "") + ".txt";
// Here is your code. This is the data saved to file....
int[][] sudokuNumbers = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
try (
// Notice the filePathAndName variable which we declared and initialized above.
PrintStream output = new PrintStream(new File(filePathAndName));) {
for (int i = 0; i < sudokuNumbers.length; i++) {
String s= "";
for (int j = 0; j < sudokuNumbers[i].length; j++) {
s+= "|" + sudokuNumbers[i][j] + "|";
}
output.println(s);
}
output.close();
}
catch (FileNotFoundException e) {
System.out.println(e.getMessage());
}
finally {
// Notify in console of success.
System.out.println("\n\u001B[34mFile Saved SUCCESSFULLY in:\n\u001B[39;49m" + filePathAndName);
}
}
/**
* Opens a Folder (directory) selection dialog window. All parameters for this method are optional but if you supply
* something to the last parameter then you must supply something to the parameters preceding it even if it's a null
* string ("") (see usage examples below)
*
* Example Usage:
*
* openFolderDialog(); //Allowed
* openFolderDialog("C:\\"); //Allowed
* openFolderDialog("", "Select The Folder You Need"); //Allowed
* openFolderDialog("", "", "Select Folder"); //Allowed
* openFolderDialog("", "", ""); //Allowed
* openFolderDialog( , "Your Folders, "Select Folder"); //Not Allowed
* openFolderDialog( , , "Select Folder"); //Not Allowed
* openFolderDialog("C:\\", "Your Folders, ); //Not Allowed
*
* I think you get the idea here.
*
* #param dialogOptions OPTIONAL - 3 String Type Parameters
* startPath - String - Default is the running applications' home folder. The path
* supplied here tells the dialog where to start displaying folders from.
* If you just want to use default but would like to supply something to
* the other optional parameters then just supply a null string ("") here.
*
* dialogTitle - String - Dialog Window Title - Default is "Select Folder...". You can
* supply whatever title you like for the dialog window.
*
* openButtonCaption - String - The Select Button Caption - Default is "Select". You can supply
* whatever you like for a button caption and it can be more than one word
* but do keep in mind that the button increases in length to accommodate the
* the supplied string.
*
* #return The selected Folder (directory) full path as string. Returns Null is nothing was selected.
*/
public static String openFoldersDialog(String... dialogOptions) {
String startPath = "";
try {
startPath = new File(".").getCanonicalPath();
} catch (IOException ex) {}
String dialogTitle = "Select Folder...";
String openButtonCaption = "Select";
if (dialogOptions.length != 0) {
if (dialogOptions.length >= 1) {
if (!dialogOptions[0].isEmpty()) { startPath = dialogOptions[0]; }
}
if (dialogOptions.length >= 2) {
if (!dialogOptions[1].isEmpty()) { dialogTitle = dialogOptions[1]; }
}
if (dialogOptions.length == 3) {
if (!dialogOptions[2].isEmpty()) { openButtonCaption = dialogOptions[2]; }
}
}
File sp = new File(startPath);
JFileChooser fc = new JFileChooser(sp);
//Remove the "Files Type:" combo box and label from dialog.
removeJFCFilesTypeComponent(fc);
fc.setDialogTitle(dialogTitle);
fc.setAcceptAllFileFilterUsed(false);
fc.setRequestFocusEnabled(true);
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int userSelection = fc.showDialog(null, openButtonCaption); //.showSaveDialog(null);
if (userSelection == JFileChooser.APPROVE_OPTION) {
String f = fc.getSelectedFile().getPath();
return f;
}
return null;
}
/**
* Removes the Filter ComboBox from the supplied JFileChooser object.
* This helps make the JFileChooser dialog window look more like a
* folder selection dialog.
* #param filechooser The object name of the JFileChooser object.
*/
public static void removeJFCFilesTypeComponent(Container filechooser) {
Component[] components = filechooser.getComponents();
for (Component component : components) {
if (component instanceof JComboBox) {
Object sel = ((JComboBox) component).getSelectedItem();
if (sel.toString().contains("AcceptAllFileFilter")) {
component.setVisible(false);
// OR
//con.remove(component);
}
}
if (component instanceof JLabel) {
String text = ((JLabel) component).getText();
if (text.equals("Files of Type:")) {
component.setVisible(false);
// OR
//con.remove(component);
}
}
if (component instanceof Container) {
removeJFCFilesTypeComponent((Container) component);
}
}
}
/**
* Creates the supplied path into the local file system if it doesn't already exist. You must
* make sure permissions are properly in place before using this method otherwise the path may
* not be created within the file system.
* #param pathString The path to create (must not include a file name). Will not create path if it already exists.
* #return Boolean True if successful and Boolean False if not.
*/
public static boolean createPath(String pathString) {
if (pathString.isEmpty()) { return false; }
if (doesFolderExist(pathString)) { return true; }
try {
File foldersToMake = new File(pathString);
foldersToMake.mkdirs();
return true;
}
catch (Exception ex) {
System.out.println("*** CreatePath() - Exception Encountered:\n*** " + ex.getMessage());
return false;
}
}
/**
* This method simply return boolean true or false if the supplied path exists.
* #param folderPathString (String) The full path to check. No File Name is allowed
* to be in this path.
* #return
*/
public static boolean doesFolderExist(String folderPathString) {
boolean tf = false;
try {
if (folderPathString.isEmpty() || "".equals(folderPathString)) { return tf; }
File f = new File(folderPathString);
if(f.exists() && f.isDirectory()) { tf = true; }
}
catch (Exception e) {
System.out.println("*** DoesFolderExist() - Exception Encountered:\n*** " + e.getMessage());
tf = false;
}
return tf;
}
}
I hope this helps you (and others).
I'm sorry if this title is badly named, I can't think of a better way to phrase it and so edits would be welcomed.
Most applications I've seen that require hard drive file storage create a folder in a suitable place depending on the operating system. On Windows these folders lie in \Users\[current user]\AppData\[etc], on Mac these folders lie in /Users/[current user]/Library/Application Support/[etc], Ubuntu has a similar thing that I can't think of right now.
I would like to know, how are these file paths consistently found in differing operating systems with different users, and is there, at least in java, a simple way to achieve this?
Thank you.
There should be, but there isn't. I even submitted a bug/RFE about it, but as far as I know, it was never accepted. Here's what I use:
public class ApplicationDirectories {
private static final Logger logger =
Logger.getLogger(ApplicationDirectories.class.getName());
private static final Path config;
private static final Path data;
private static final Path cache;
static {
String os = System.getProperty("os.name");
String home = System.getProperty("user.home");
if (os.contains("Mac")) {
config = Paths.get(home, "Library", "Application Support");
data = config;
cache = config;
} else if (os.contains("Windows")) {
String version = System.getProperty("os.version");
if (version.startsWith("5.")) {
config = getFromEnv("APPDATA", false,
Paths.get(home, "Application Data"));
data = config;
cache = Paths.get(home, "Local Settings", "Application Data");
} else {
config = getFromEnv("APPDATA", false,
Paths.get(home, "AppData", "Roaming"));
data = config;
cache = getFromEnv("LOCALAPPDATA", false,
Paths.get(home, "AppData", "Local"));
}
} else {
config = getFromEnv("XDG_CONFIG_HOME", true,
Paths.get(home, ".config"));
data = getFromEnv("XDG_DATA_HOME", true,
Paths.get(home, ".local", "share"));
cache = getFromEnv("XDG_CACHE_HOME", true,
Paths.get(home, ".cache"));
}
}
/** Prevents instantiation. */
private ApplicationDirectories() {
}
/**
* Retrieves a path from an environment variable, substituting a default
* if the value is absent or invalid.
*
* #param envVar name of environment variable to read
* #param mustBeAbsolute whether enviroment variable's value should be
* considered invalid if it's not an absolute path
* #param defaultPath default to use if environment variable is absent
* or invalid
*
* #return environment variable's value as a {#code Path},
* or {#code defaultPath}
*/
private static Path getFromEnv(String envVar,
boolean mustBeAbsolute,
Path defaultPath) {
Path dir;
String envDir = System.getenv(envVar);
if (envDir == null || envDir.isEmpty()) {
dir = defaultPath;
logger.log(Level.CONFIG,
envVar + " not defined in environment"
+ ", falling back on \"{0}\"", dir);
} else {
dir = Paths.get(envDir);
if (mustBeAbsolute && !dir.isAbsolute()) {
dir = defaultPath;
logger.log(Level.CONFIG,
envVar + " is not an absolute path"
+ ", falling back on \"{0}\"", dir);
}
}
return dir;
}
/**
* Returns directory where the native system expects an application
* to store configuration files for the current user. No attempt is made
* to create the directory, and no checks are done to see if it exists.
*
* #param appName name of application
*/
public static Path configDir(String appName)
{
return config.resolve(appName);
}
/**
* Returns directory where the native system expects an application
* to store implicit data files for the current user. No attempt is made
* to create the directory, and no checks are done to see if it exists.
*
* #param appName name of application
*/
public static Path dataDir(String appName)
{
return data.resolve(appName);
}
/**
* Returns directory where the native system expects an application
* to store cached data for the current user. No attempt is made
* to create the directory, and no checks are done to see if it exists.
*
* #param appName name of application
*/
public static Path cacheDir(String appName)
{
return cache.resolve(appName);
}
}
Some notes:
I'm not sure the code for older Windows versions is even necessary, as Java 8 doesn't run on Windows XP.
The XDG Directory Specification says “All paths set in these environment variables must be absolute. If an implementation encounters a relative path in any of these variables it should consider the path invalid and ignore it.”
The directory can be found with the method
static String defaultDirectory() {
String os = System.getProperty("os.name").toLowerCase();
if (OS.contains("win"))
return System.getenv("APPDATA");
else if (OS.contains("mac"))
return System.getProperty("user.home") + "/Library/Application Support";
else if (OS.contains("nux"))
return System.getProperty("user.home");
else
return System.getProperty("user.dir");
}
It is worth noting that on Linux any such folders should be hidden by beginning their name with .
(Answer found from users CodeBunny and Denis Tulskiy on this post)
I'm building an application which stores its data in H2 database files, so my save files have the extension .h2.db.
When opening the application, the user has to select which save file should be loaded. To make it easier to recognize these files, is it possible to tell H2 to use custom file extensions?
Looking at the Database URL overview of H2, I can only specify the name of the database. I would prefer a extension like .save over the default .h2.db. Is there a reasonable way to achieve this?
A workaround would be to link the *.save-file to a temporary folder, renaming it to the correct suffix. If this is the only solution, I guess I would go with the default extension.
H2 database supports pluggable file system so with a bit of extra code you can use any extension you want. You just need to create a wrapper, register it and use your own database URL. The wrapper could look like this:
package my.test;
import org.h2.store.fs.FilePath;
import org.h2.store.fs.FilePathWrapper;
public class FilePathTestWrapper extends FilePathWrapper {
private static final String[][] MAPPING = {
{".h2.db", ".save"},
{".lock.db", ".save.lock"}
};
#Override
public String getScheme() {
return "save";
}
#Override
public FilePathWrapper wrap(FilePath base) {
// base.toString() returns base.name
FilePathTestWrapper wrapper = (FilePathTestWrapper) super.wrap(base);
wrapper.name = getPrefix() + wrapExtension(base.toString());
return wrapper;
}
#Override
protected FilePath unwrap(String path) {
String newName = path.substring(getScheme().length() + 1);
newName = unwrapExtension(newName);
return FilePath.get(newName);
}
protected static String wrapExtension(String fileName) {
for (String[] pair : MAPPING) {
if (fileName.endsWith(pair[1])) {
fileName = fileName.substring(0, fileName.length() - pair[1].length()) + pair[0];
break;
}
}
return fileName;
}
protected static String unwrapExtension(String fileName) {
for (String[] pair : MAPPING) {
if (fileName.endsWith(pair[0])) {
fileName = fileName.substring(0, fileName.length() - pair[0].length()) + pair[1];
break;
}
}
return fileName;
}
}
Then you'll need to register it:
FilePathTestWrapper wrapper = new FilePathTestWrapper();
FilePath.register(wrapper);
And use database URL like this:
"jdbc:h2:save:./mydatabase"
Note the "save:" prefix, it should match string returned by getScheme() method. I put a bit more details here: http://shuvikov.net/blog/renaming-h2-database-files
You cannot define a new extension (suffix) for the H2 database name (page file)
In my code i have a similar need (user may select the database) and this is what i do:
File file=new FileImport(shell, "*"+org.h2.engine.Constants.SUFFIX_PAGE_FILE).filePicker();
if (file!=null){
String database=file.getAbsolutePath().
replace(org.h2.engine.Constants.SUFFIX_PAGE_FILE, "");
...
}
NOTE: FileImport is a class writen by me that extends SWT FileDialog: https://code.google.com/p/marcolopes/source/browse/org.dma.eclipse/src/org/dma/eclipse/swt/dialogs/file/FileImport.java
The filename extensions (notice there are many, not just .h2.db) are set in Constants.java:
/**
* The file name suffix of page files.
*/
public static final String SUFFIX_PAGE_FILE = ".h2.db";
And used directly throughout the codebase, e.g. in Database.java:
/**
* Check if a database with the given name exists.
*
* #param name the name of the database (including path)
* #return true if one exists
*/
static boolean exists(String name) {
if (FileUtils.exists(name + Constants.SUFFIX_PAGE_FILE)) {
return true;
}
return FileUtils.exists(name + Constants.SUFFIX_MV_FILE);
}
So no, you cannot specify a custom file extension for the database. You'll be much better off either not worrying about this, or using a FileNameExtensionFilter to limit your user's choices, like JoopEggen suggested.
You could zip up your database files and rename the .zip to some other extension like .save. Then you unzip your .save file in order to get to the .h2.db file. Note this is how Jars work - they're just zip files under the covers.
You might also look at the Game Developer Stack Exchange, and consider posting a question there like "How do I create user-friendly save files" and describe your problem if you really can't expect your users to tolerate .h2.db files.
I have a file in the res/raw folder called "book1tabs.txt", but in general I will not know what it is called. Then I have to do something like follows:
InputStream in = this.mCtx.getResources().openRawResource(R.raw.book1tabs);
But I want to use a string variable, like
String param = "book1tabs";
And be able to open up that same input stream.
Is there any way to do this?
Thanks
You can do something like this
String param = "book1tabs";
InputStream in = this.mCtx.getResources().openRawResource(mCtx.getResources().getIdentifier(param,"raw", mCtx.getPackageName()));
getIdentifier() will return the id from R.java of particular parameter you passed.
Exactly what it will do is as follow
Maps the Package Name
Navigate to typeDef you provided
Finds the resource name you provided in the typeDef
For more information http://developer.android.com/reference/android/content/res/Resources.html
I find this method to be very useful to pull all sorts of resources by their string names...
#SuppressWarnings("rawtypes")
public static int getResourceId(String name, Class resType){
try {
Class res = null;
if(resType == R.drawable.class)
res = R.drawable.class;
if(resType == R.id.class)
res = R.id.class;
if(resType == R.string.class)
res = R.string.class;
if(resType == R.raw.class)
res = R.raw.class;
Field field = res.getField(name);
int retId = field.getInt(null);
return retId;
}
catch (Exception e) {
// Log.d(TAG, "Failure to get drawable id.", e);
}
return 0;
}
This will return the numeric id (assuming such a resource exists). For the Class pass in R.drawable and for the string whatever it's xml based ID name is.
I always have this method hanging around all my projects for easy access.
I would like to (and I don't know if it's possible) do something if jarA is in my classpath and do something else if jarB is in my classpath. I am NOT going to be specifying these jars in the Netbeans project library references because I don't know which of the jars will be used.
Now including the jar in my Netbeans project library references works when I try to use the jar's classes through reflection. But when I remove the netbeans project library reference but add the jar to my classpath the reflection does not work.
My question is really 1) can this be done? 2) Am I thinking about it correctly 3) How come when I specify -cp or -classpath to include the directory containing the jar it doesn't work? 4) How come when I specify the directory in my manifest.mf in the jar file it doesn't work?
Please let me know. This is really bothering me.
Thanks,
Julian
on point 3 - you should include the fully qualified jar name in your classpath, not just the directory.
I believe so!
ClassLoader.getSystemClassLoader()getURLs();
This will tell you which Jar files are in your classpath. Then do X or Y as you please.
A classpath can reference a directory that contains .class files, or it can reference a .jar file directly. If it references a directory that contains .jar files, they will not be included.
java -help says this about -classpath: "list of directories, JAR archives,
and ZIP archives to search for class files." This is very clear that a directory on the classpath is searched for class files, not JAR archives.
This is how I'm doing it. The inner class encapsulates the singleton instance of the logger and its trace method (heh - I know - a singleton inside a singleton). The outer class only uses it if the special class can be loaded, otherwise we go on without it. Hopefully you can modify this to suit your needs. And any suggestions as to better code are always appreciated! :-) HTH
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Provides centralized access to standardized output formatting. Output is sent to System.out and,
* if the classpath allows it, to the Cisco CTIOS LogManager. (This is NOT a dependency, however.)
*
*/
public class LogWriter
{
protected static LogWriter me = null;
private SimpleDateFormat dateFormat = null;
private StringBuffer line = null;
CLogger ciscoLogger = null;
/*
* The following 2 methods constitute the thread-safe singleton pattern.
*/
private static class LogWriterHolder
{
public static LogWriter me = new LogWriter();
}
/**
* Returns singleton instance of the class. Thread-safe. The only way to get one is to use this.
*
* #return an instance of LogWriter
*/
public static LogWriter sharedInstance()
{
return LogWriterHolder.me;
}
#SuppressWarnings("unchecked")
LogWriter()
{
dateFormat = new SimpleDateFormat("yyyyMMddHHmmss ");
line = new StringBuffer();
try {
Class x = Class.forName("com.cisco.cti.ctios.util.LogManager");
if( x != null ) {
java.lang.reflect.Method m = x.getMethod("Instance", new Class[0]);
java.lang.reflect.Method n = x.getMethod("Trace", int.class, String.class );
if( m != null ) {
Object y = m.invoke( x , new Object[0] );
if( n != null ) {
ciscoLogger = new CLogger();
ciscoLogger.target = y;
ciscoLogger.traceImpl = n ;
}
}
}
} catch(Throwable e )
{
System.err.println( e.getMessage() ) ;
e.printStackTrace();
}
}
/**
* Formats a line and sends to System.out. The collection and formatting of the text is
* thread safe.
*
* #param message The human message you want to display in the log (required).
* #param hostAddress Host address of server (optional)
* #param hostPort Port on hostAddresss (optional) - also used for className in object-specific logs.
*/
public void log( String message, String hostAddress, String hostPort )
{
if ( message == null || message.length() < 3 ) return;
synchronized( this )
{
try {
line.delete(0, line.length());
line.append(dateFormat.format(new Date()));
line.append(hostAddress);
line.append(":");
line.append(hostPort);
line.append(" ");
while (line.length() < 28)
line.append(" ");
line.append(message);
this.write( line.toString() );
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void write(String line )
{
System.out.println( line ) ;
}
/**
* Write a simple log message to output delegates (default is System.out).
* <p>
* Will prepend each line with date in yyyyMMddHHmmss format. there will be a big space
* after the date, in the spot where host and port are normally written, when {#link LogWriter#log(String, String, String) log(String,String,String)}
* is used.
*
* #param message What you want to record in the log.
*/
public void log( String message )
{
if( ciscoLogger != null ) ciscoLogger.trace(0x01, message );
this.log( message, "", "");
}
class CLogger
{
Object target;
Method traceImpl;
#SuppressWarnings("boxing")
public void trace( int x, String y )
{
try {
traceImpl.invoke( target, x, y) ;
} catch( Throwable e ) {
// nothing to say about this
}
}
}
}