I have been writing a program for a group of Minecrafters and their Modpack, the program is a custom launcher. The problem is when Mac-OSX users try using the program it has problems with making its folder in /Users/<username>/Library/Application Support/.melbvicminecraft/, I know it is a permissions problem, but I want to find a way to let them use the application without the need for them to have root permissions.
Main.java:
public static File getMinecraftDir()
{
String os = getOS();
String userHome = System.getProperty("user.home", ".");
if(os == "win")
{
String appdata = System.getenv("APPDATA");
String location = appdata != null ? appdata : userHome;
return new File(location);
}
else if(os == "mac")
{
return new File(userHome, "Library/Application Support/");
}
else
return new File(userHome);
}
MinecraftLoginThread.java:
/**
* Make a new Minecraft login handler with the selected dir
*
* #param settings Settings file located on the <strong>server</strong>
* #param server The content server
* #param minecraftDir minecraftDir The selected Minecraft dir
*/
public MinecraftLoginThread(SettingsFile settings, String server, File minecraftDir)
{
try
{
UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
}
catch (Exception e)
{
try
{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch(Exception e1)
{
e1.printStackTrace();
}
}
try
{
Main.logger.debug("Minecraft dir: " + minecraftDir.getAbsolutePath());
Main.logger.debug("Minecraft exists: " + minecraftDir.exists());
if(!minecraftDir.exists())
{
try
{
minecraftDir.setWritable(true);
minecraftDir.setReadable(true);
if(minecraftDir.mkdirs())
Main.logger.debug("Made new Minecraft dir: " + minecraftDir.getAbsolutePath());
else
Main.killError("Failed to make new Minecraft dir!");
}
catch (Exception e) { Main.killError(e.toString()); }
}
if(!(new File(minecraftDir, "lastLogin").exists()))
(new File(minecraftDir, "lastLogin")).createNewFile();
this.lastLogin = new SettingsFile((new File(minecraftDir, "lastLogin")));
this.lastLogin.load();
}
catch(Exception e)
{
e.printStackTrace();
}
this.settings = settings;
this.server = server;
this.backgroundManager = new BackgroundManager(server + settings.getSetting("net.melbvicmc.launcher.mlbl"));
this.mcDir = minecraftDir;
this.optionsDialog = new MinecraftOptionsDialog(this);
loadJFrameLayout();
}
Here is the log from a mac: The log
The application can be found here: Launcher Download
Related
Problem in creating a new workspace in an Eclipse RCP application.
When the RCP application is launched, a dialog is prompted to ask the workspace location.
When the location is given, then there is error saying "Could not launch the product because the specified workspace cannot be created.
The specified workspace directory is either invalid or read-only".
I have followed the code from IDEApplication.java from eclipse, but still I am facing same issue.
Application code:
#SuppressWarnings("restriction")
public class MyRcpApplication implements IApplication
{
private static final String METADATA_PROJECTS_PATH = "/.plugins/org.eclipse.core.resources/.projects";
private static final String METADATA_ROOT = ".metadata";
private static final String COMMAND_ARG = "--container";
private static final String SYSTEM_PROPERTY_EXIT_CODE = "eclipse.exitcode";
private static final String WORKSPACE_VERSION_KEY = "org.eclipse.core.runtime";
private static final String VERSION_FILENAME = "version.ini";
private static final String WORKSPACE_VERSION_VALUE = "1"; //$NON-NLS-1$
public static final String METADATA_FOLDER = ".metadata"; //$NON-NLS-1$
private Shell shell;
/*
* (non-Javadoc)
*
* #see org.eclipse.equinox.app.IApplication#start(org.eclipse.equinox.app.IApplicationContext)
*/
#Override
public Object start(final IApplicationContext context)
{
Display display = PlatformUI.createDisplay();
Shell shell = display.getActiveShell();
try
{
// for backward compatibility we need to clear the workspace before start also
cleanUpTheWorkSpace();
boolean instanceLocationCheck = checkInstanceLocation(shell, context.getArguments());
if (!instanceLocationCheck)
{
MessageDialog.openError(shell, IDEWorkbenchMessages.IDEApplication_workspaceInUseTitle,
"Could not launch the product because the associated workspace is currently in use by another My Application.");
return IApplication.EXIT_OK;
}
int returnCode = PlatformUI.createAndRunWorkbench(display, new MyApplicationWorkbenchAdvisor());
if (returnCode == PlatformUI.RETURN_RESTART)
{
// eclipse.exitcode system property may be set to re-launch
if (IApplication.EXIT_RELAUNCH.equals(Integer.getInteger(SYSTEM_PROPERTY_EXIT_CODE)))
{
return IApplication.EXIT_RELAUNCH;
}
return IApplication.EXIT_RESTART;
}
// if application return code is exit clean up the workspace
// cleanUpTheWorkSpace();
return IApplication.EXIT_OK;
}
finally
{
if (display != null)
{
display.dispose();
}
Location instanceLoc = Platform.getInstanceLocation();
if (instanceLoc != null)
{
instanceLoc.release();
}
}
}
#SuppressWarnings("rawtypes")
private boolean checkInstanceLocation(final Shell shell, final Map arguments)
{
Location instanceLoc = Platform.getInstanceLocation();
if (instanceLoc == null)
{
MessageDialog.openError(shell, "Workspace is Mandatory", "IDEs need a valid workspace.");
return false;
}
// -data "/valid/path", workspace already set
if (instanceLoc.isSet())
{
// make sure the meta data version is compatible (or the user has
// chosen to overwrite it).
try
{
// Used to check whether are we launching My application from development environment or not
if (isDevLaunchMode(arguments))
{
return true;
}
// Used to check instance location is locked or not
if (instanceLoc.isLocked())
{
return false;
}
// we failed to create the directory.
// Two possibilities:
// 1. directory is already in use
// 2. directory could not be created
File workspaceDirectory = new File(instanceLoc.getURL().getFile());
if (workspaceDirectory.exists())
{
if (isDevLaunchMode(arguments))
{
return true;
}
MessageDialog.openError(
shell,
"Workspace Cannot Be Locked",
"Could not launch the product because the associated workspace at '" + workspaceDirectory.getAbsolutePath()
+ "' is currently in use by another Eclipse application");
}
else
{
MessageDialog
.openError(
shell,
"Workspace Cannot Be Created",
"Could not launch the product because the specified workspace cannot be created. The specified workspace directory is either invalid or read-only.");
}
}
catch (IOException e)
{
MessageDialog.openError(shell, "Internal Error", e.getMessage());
}
}
else
{
try
{
// -data #noDefault or -data not specified, prompt and set
ChooseWorkspaceData launchData = new ChooseWorkspaceData(instanceLoc.getDefault());
boolean force = false;
while (true)
{
URL workspaceUrl = promptForWorkspace(shell, launchData, force);
if (workspaceUrl == null)
{
return false;
}
// if there is an error with the first selection, then force the
// dialog to open to give the user a chance to correct
force = true;
try
{
// the operation will fail if the url is not a valid
// instance data area, so other checking is unneeded
if (instanceLoc.set(workspaceUrl, false))
{
launchData.writePersistedData();
writeWorkspaceVersion(workspaceUrl);
return true;
}
}
catch (IllegalStateException e)
{
MessageDialog
.openError(
shell,
IDEWorkbenchMessages
.IDEApplication_workspaceCannotBeSetTitle,
IDEWorkbenchMessages
.IDEApplication_workspaceCannotBeSetMessage);
return false;
}
// by this point it has been determined that the workspace is
// already in use -- force the user to choose again
MessageDialog.openError(shell, IDEWorkbenchMessages
.IDEApplication_workspaceInUseTitle,
IDEWorkbenchMessages.
IDEApplication_workspaceInUseMessage);
}
}
catch (IllegalStateException | IOException e)
{
}
}
return true;
}
private static void writeWorkspaceVersion(final URL defaultValue)
{
Location instanceLoc = Platform.getInstanceLocation();
if (instanceLoc.isReadOnly())
{
// MessageDialog.openError(shell,"Read-Only Dialog", "Location was read-only");
System.out.println("Instance Got Locked......");
}
if ((instanceLoc == null) || instanceLoc.isReadOnly())
{
return;
}
File versionFile = getVersionFile(instanceLoc.getURL(), true);
if (versionFile == null)
{
return;
}
OutputStream output = null;
try
{
String versionLine = WORKSPACE_VERSION_KEY + '=' + WORKSPACE_VERSION_VALUE;
output = new FileOutputStream(versionFile);
output.write(versionLine.getBytes("UTF-8")); //$NON-NLS-1$
}
catch (IOException e)
{
IDEWorkbenchPlugin.log("Could not write version file", //$NON-NLS-1$
StatusUtil.newStatus(IStatus.ERROR, e.getMessage(), e));
}
finally
{
try
{
if (output != null)
{
output.close();
}
}
catch (IOException e)
{
// do nothing
}
}
}
/*
* (non-Javadoc)
*
* #see org.eclipse.equinox.app.IApplication#stop()
*/
#Override
public void stop()
{
if (!PlatformUI.isWorkbenchRunning())
{
return;
}
final IWorkbench workbench = PlatformUI.getWorkbench();
final Display display = workbench.getDisplay();
display.syncExec(new Runnable()
{
#Override
public void run()
{
if (!display.isDisposed())
{
workbench.close();
}
}
});
}
private URL promptForWorkspace(final Shell shell, final ChooseWorkspaceData launchData, boolean force)
{
URL url = null;
do
{
new ChooseWorkspaceDialog(shell, launchData, false, force).prompt(force);
String instancePath = launchData.getSelection();
if (instancePath == null)
{
return null;
}
// the dialog is not forced on the first iteration, but is on every
// subsequent one -- if there was an error then the user needs to be
// allowed to
force = true;
// create the workspace if it does not already exist
File workspace = new File(instancePath);
if (!workspace.exists())
{
workspace.mkdir();
}
try
{
// Don't use File.toURL() since it adds a leading slash that Platform does not
// handle properly. See bug 54081 for more details.
String path = workspace.getAbsolutePath().replace(File.separatorChar, '/');
url = new URL("file", null, path); //$NON-NLS-1$
}
catch (MalformedURLException e)
{
MessageDialog
.openError(
shell,
IDEWorkbenchMessages
.IDEApplication_workspaceInvalidTitle,
IDEWorkbenchMessages
.IDEApplication_workspaceInvalidMessage);
continue;
}
}
while (!checkValidWorkspace(shell, url));
return url;
}
private boolean checkValidWorkspace(final Shell shell, final URL url)
{
String version = readWorkspaceVersion(url);
// if the version could not be read, then there is not any existing
// workspace data to trample, e.g., perhaps its a new directory that
// is just starting to be used as a workspace
if (version == null)
{
return true;
}
final int ide_version = Integer.parseInt(WORKSPACE_VERSION_VALUE);
int workspace_version = Integer.parseInt(version);
// equality test is required since any version difference (newer
// or older) may result in data being trampled
if (workspace_version == ide_version)
{
return true;
}
// At this point workspace has been detected to be from a version
// other than the current ide version -- find out if the user wants
// to use it anyhow.
String title = "My App Titile"; //$NON-NLS-1$
String message = "My App Message";
MessageBox mbox = new MessageBox(shell, SWT.OK | SWT.CANCEL
| SWT.ICON_WARNING | SWT.APPLICATION_MODAL);
mbox.setText(title);
mbox.setMessage(message);
return mbox.open() == SWT.OK;
}
private static String readWorkspaceVersion(final URL workspace)
{
File versionFile = getVersionFile(workspace, false);
if ((versionFile == null) || !versionFile.exists())
{
return null;
}
try
{
// Although the version file is not spec'ed to be a Java properties
// file, it happens to follow the same format currently, so using
// Properties to read it is convenient.
Properties props = new Properties();
FileInputStream is = new FileInputStream(versionFile);
try
{
props.load(is);
}
finally
{
is.close();
}
return props.getProperty(WORKSPACE_VERSION_KEY);
}
catch (IOException e)
{
IDEWorkbenchPlugin.log("Could not read version file", new Status( //$NON-NLS-1$
IStatus.ERROR, IDEWorkbenchPlugin.IDE_WORKBENCH,
IStatus.ERROR,
e.getMessage() == null ? "" : e.getMessage(), //$NON-NLS-1$,
e));
return null;
}
}
private static File getVersionFile(final URL workspaceUrl, final boolean create)
{
if (workspaceUrl == null)
{
return null;
}
try
{
// make sure the directory exists
File metaDir = new File(workspaceUrl.getPath(), METADATA_FOLDER);
if (!metaDir.exists() && (!create || !metaDir.mkdir()))
{
return null;
}
// make sure the file exists
File versionFile = new File(metaDir, VERSION_FILENAME);
if (!versionFile.exists()
&& (!create || !versionFile.createNewFile()))
{
return null;
}
return versionFile;
}
catch (IOException e)
{
// cannot log because instance area has not been set
return null;
}
}
#SuppressWarnings("rawtypes")
private static boolean isDevLaunchMode(final Map args)
{
// see org.eclipse.pde.internal.core.PluginPathFinder.isDevLaunchMode()
if (Boolean.getBoolean("eclipse.pde.launch"))
{
return true;
}
return args.containsKey("-pdelaunch"); //$NON-NLS-1$
}
/**
* Deletes all the available projects in the workspace
*/
private void cleanUpTheWorkSpace()
{
// this will be the
String[] commands = Platform.getCommandLineArgs();
if (commands != null)
{
List<String> args = Arrays.asList(commands);
if (args.contains(COMMAND_ARG))
{
// if project is in the root delete it.. it will delete associated metadata
IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
if (projects != null)
{
for (IProject project : projects)
{
try
{
project.delete(true, new NullProgressMonitor());
}
catch (CoreException e)
{
// msgHandler.post(MsgSeverity.ERROR, "Unable to clear the workspace");
}
}
}
// if project is not in the root but if its in the workspace delete the metadata too
File[] workSpaceFiles = Platform.getLocation().toFile().listFiles();
for (File file : workSpaceFiles)
{
if (METADATA_ROOT.equals(file.getName()))
{
File projectMeta = new File(file.getPath() + METADATA_PROJECTS_PATH);
if ((projectMeta != null) && projectMeta.exists())
{
File[] children = projectMeta.listFiles();
for (File child : children)
{
FileUtils.deleteQuietly(child);
}
}
}
/*
* else { FileUtils.deleteQuietly(file); }
*/
}
}
}
}
}
Try run Eclipse as administrator.
Your code is just calling
if (instanceLoc.isLocked())
{
return false;
}
to check if the workspace is locked, but is doing nothing to make the workspace locked so this will always fall through to the error code.
IDEApplication does this:
if (instanceLoc.lock()) {
writeWorkspaceVersion();
return null;
}
you need to do something similar.
This code works fine in Linux but not in Windows 7: to get file contents update I have to click on the output file. Where is the trick?
I am using Windows 7 prof, NetBeans IDE 8.0 RC1 (Build 201402242200) updated to version NetBeans 8.0 Patch 1.1, JDK 1.8
package watchfilethreadmod;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.file.Files;
import static java.nio.file.LinkOption.NOFOLLOW_LINKS;
import java.nio.file.Path;
import java.nio.file.Paths;
import static java.nio.file.StandardWatchEventKinds.*;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
public class WatchFileThreadMod {
static class WatchFile {
String fileName;
long lastFilePos;
RandomAccessFile file;
public WatchFile(String _fileName, RandomAccessFile _file) {
fileName = _fileName;
lastFilePos = 0;
file = _file;
}
}
public static void shutDownListener(Thread thread) {
Thread thr = thread;
if (thr != null) {
thr.interrupt();
}
}
private static class MyWatchQueueReader implements Runnable {
/**
* the watchService that is passed in from above
*/
private WatchService myWatcher;
public ArrayList<WatchFile> threadFileToWatch;
public String dirPath;
public MyWatchQueueReader(String _dirPath, WatchService myWatcher, ArrayList<WatchFile> _threadFileToWatch) {
this.myWatcher = myWatcher;
this.threadFileToWatch = _threadFileToWatch;
this.dirPath = _dirPath;
}
private void openFile(WatchFile obj) {
try {
System.out.println("Open file "+obj.fileName);
obj.file = new RandomAccessFile(dirPath + "/" + obj.fileName, "r");
} catch (FileNotFoundException e) {
obj.file = null;
System.out.println("filename " + obj.fileName + " non trovato");
}
obj.lastFilePos = 0;
}
private void process(WatchEvent evt) {
String thisLine;
ArrayList<WatchFile> auxList = threadFileToWatch;
for (WatchFile obj : auxList) {
if (obj.fileName.equals(evt.context().toString())) {
if (obj.file == null) {
openFile(obj);
}
try {
obj.file.seek(obj.lastFilePos);
} catch (IOException e) {
System.err.println("Seek error: " + e);
}
try {
thisLine = obj.file.readLine();
if ((thisLine == null)&&(evt.kind() == ENTRY_MODIFY)) {
System.out.printf("---> thisLine == null received %s event for file: %s\n",
evt.kind(), evt.context());
obj.file.close();
System.out.println("Close file "+obj.fileName);
openFile(obj);
thisLine = obj.file.readLine();
}
while (thisLine != null) { // while loop begins here
if (thisLine.length() > 0) {
if (thisLine.substring(thisLine.length() - 1).equals("*")) {
obj.lastFilePos = obj.file.getFilePointer();
System.out.println(obj.fileName + ": " + thisLine);
}
}
thisLine = obj.file.readLine();
} // end while
} // end try
catch (IOException e) {
System.err.println("Error: " + e);
}
}
}
}
/**
* In order to implement a file watcher, we loop forever ensuring
* requesting to take the next item from the file watchers queue.
*/
#Override
public void run() {
try {
// get the first event before looping
WatchKey key = myWatcher.take();
while (key != null) {
// we have a polled event, now we traverse it and
// receive all the states from it
for (WatchEvent event : key.pollEvents()) {
WatchEvent.Kind eventType = event.kind();
if (eventType == OVERFLOW) {
continue;
}
process(event);
}
key.reset();
key = myWatcher.take();
}
} catch (InterruptedException e) {
ArrayList<WatchFile> auxList = threadFileToWatch;
for (WatchFile obj : auxList) {
if (obj.file != null) {
try {
obj.file.close();
System.out.println("chiusura file " + obj.fileName);
} catch (IOException ex) {
System.out.println("errore in chiusura file");
Logger.getLogger(WatchFileThreadMod.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
//e.printStackTrace();
}
System.out.println("Stopping thread");
}
}
public static void main(String[] args) throws Exception {
// get the directory we want to watch, using the Paths singleton class
//Path toWatch = Paths.get(DIRECTORY_TO_WATCH);
ArrayList<WatchFile> fileToWatch = new ArrayList<>();
String filename;
RandomAccessFile file;
fileToWatch.add(new WatchFile("EURUSD.rlt", new RandomAccessFile(args[0] + "/EURUSD.rlt", "r")));
filename = "EURCHF2.rlt";
try {
file = new RandomAccessFile(args[0] + "/" + filename, "r");
} catch (FileNotFoundException e) {
file = null;
System.out.println("filename " + filename + " non trovato");
}
fileToWatch.add(new WatchFile(filename, file));
fileToWatch = fileToWatch;
Path toWatch = Paths.get(args[0]);
if (toWatch == null) {
throw new UnsupportedOperationException("Directory not found");
}
// Sanity check - Check if path is a folder
try {
Boolean isFolder = (Boolean) Files.getAttribute(toWatch,
"basic:isDirectory", NOFOLLOW_LINKS);
if (!isFolder) {
throw new IllegalArgumentException("Path: " + toWatch + " is not a folder");
}
} catch (IOException ioe) {
// Folder does not exists
ioe.printStackTrace();
}
// make a new watch service that we can register interest in
// directories and files with.
WatchService myWatcher = toWatch.getFileSystem().newWatchService();
// start the file watcher thread below
MyWatchQueueReader fileWatcher = new MyWatchQueueReader(args[0], myWatcher, fileToWatch);
Thread processingThread = new Thread(fileWatcher, "FileWatcher");
processingThread.start();
toWatch.register(myWatcher, ENTRY_CREATE, ENTRY_MODIFY);
}
}
Edit: reduced code as requested.
Edit 2: file path
Edit 3: Metatrader code I am using to write data
#property strict
int file_handle;
string InpFileName = _Symbol + ".rlt"; // File name
input string InpDirectoryName = "Data"; // Folder name
int OnInit()
{
ResetLastError();
file_handle = FileOpen(InpDirectoryName + "//" + InpFileName, FILE_SHARE_READ|FILE_WRITE|FILE_TXT|FILE_ANSI);
if(file_handle == INVALID_HANDLE) {
PrintFormat("Failed to open %s file, Error code = %d", InpFileName, GetLastError());
ExpertRemove();
}
return INIT_SUCCEEDED;
}
void OnTick()
{
// file_handle = FileOpen(InpDirectoryName + "//" + InpFileName, FILE_SHARE_READ|FILE_WRITE|FILE_TXT|FILE_ANSI);
// Datetime), Bid, Volume
// string s = FileRead()
string s = TimeToStr(TimeGMT()) + "|" + Bid + "|" + Volume[0];
FileWriteString(file_handle, s + "|*\r\n");
FileFlush(file_handle);
//FileClose(file_handle);
}
void OnDeinit(const int reason)
{
FileClose(file_handle);
}
Edit 4: Screencast to better show my issue: data updates only when I click on the output file
Watch Service does not update
First of all, a premise : I'm answering this question primarily for future users of WatchService, which (like me) could experience this problem (i.e. on some systems events are signaled way after they occur).
The problem is that the implementation of this feature in Java is native, so it is platform-dependant (take a look at https://docs.oracle.com/javase/7/docs/api/java/nio/file/WatchService.html, under the section 'platform dependencies').
In particular, on Windows 7 (and MacOSX afaict) the implementation uses polling to retrieve the changes from the filesystem, so you can't rely on the 'liveliness' of notifications from a WatchService. The notifications will eventually be signaled, but there are no guarantees on when it will happen.
I don't have a rigorous solution to this problem, but after a lot of trial and error I can describe what works for me :
First, when writing to a file that is registered (i.e. 'watched'), I try to flush the content every time I can and update the 'last modified' attribute on the file, e.g. :
try (FileWriter writer = new FileWriter(outputFile)) {
writer.write("The string to write");
outputFile.setLastModified(System.currentTimeMillis());
writer.flush();
}
Second, I try to 'trigger' the refresh from code (I know it's not good code, but in this case, I'm just happy it works 99% of the time)
Thread.sleep(2000);
// in case I've just created a file and I'm watching the ENTRY_CREATE event on outputDir
outputDir.list();
or (if watching ENTRY_MODIFY on a particular file in outputDir)
Thread.sleep(2000);
outputFile.length();
In both cases, a sleep call simply 'gives the time' to the mechanism underlying the WatchService to trigger, even though 2 seconds are probably a lot more than it is needed.
Probably missing quotes on file path.
This code works fine in Linux but not in Windows 7: to get file contents update I have to click on the output file. Where is the trick?
I am using Windows 7 prof, NetBeans IDE 8.0 RC1 (Build 201402242200) updated to version NetBeans 8.0 Patch 1.1, JDK 1.8
package watchfilethreadmod;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.file.Files;
import static java.nio.file.LinkOption.NOFOLLOW_LINKS;
import java.nio.file.Path;
import java.nio.file.Paths;
import static java.nio.file.StandardWatchEventKinds.*;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
public class WatchFileThreadMod {
static class WatchFile {
String fileName;
long lastFilePos;
RandomAccessFile file;
public WatchFile(String _fileName, RandomAccessFile _file) {
fileName = _fileName;
lastFilePos = 0;
file = _file;
}
}
public static void shutDownListener(Thread thread) {
Thread thr = thread;
if (thr != null) {
thr.interrupt();
}
}
private static class MyWatchQueueReader implements Runnable {
/**
* the watchService that is passed in from above
*/
private WatchService myWatcher;
public ArrayList<WatchFile> threadFileToWatch;
public String dirPath;
public MyWatchQueueReader(String _dirPath, WatchService myWatcher, ArrayList<WatchFile> _threadFileToWatch) {
this.myWatcher = myWatcher;
this.threadFileToWatch = _threadFileToWatch;
this.dirPath = _dirPath;
}
private void openFile(WatchFile obj) {
try {
System.out.println("Open file "+obj.fileName);
obj.file = new RandomAccessFile(dirPath + "/" + obj.fileName, "r");
} catch (FileNotFoundException e) {
obj.file = null;
System.out.println("filename " + obj.fileName + " non trovato");
}
obj.lastFilePos = 0;
}
private void process(WatchEvent evt) {
String thisLine;
ArrayList<WatchFile> auxList = threadFileToWatch;
for (WatchFile obj : auxList) {
if (obj.fileName.equals(evt.context().toString())) {
if (obj.file == null) {
openFile(obj);
}
try {
obj.file.seek(obj.lastFilePos);
} catch (IOException e) {
System.err.println("Seek error: " + e);
}
try {
thisLine = obj.file.readLine();
if ((thisLine == null)&&(evt.kind() == ENTRY_MODIFY)) {
System.out.printf("---> thisLine == null received %s event for file: %s\n",
evt.kind(), evt.context());
obj.file.close();
System.out.println("Close file "+obj.fileName);
openFile(obj);
thisLine = obj.file.readLine();
}
while (thisLine != null) { // while loop begins here
if (thisLine.length() > 0) {
if (thisLine.substring(thisLine.length() - 1).equals("*")) {
obj.lastFilePos = obj.file.getFilePointer();
System.out.println(obj.fileName + ": " + thisLine);
}
}
thisLine = obj.file.readLine();
} // end while
} // end try
catch (IOException e) {
System.err.println("Error: " + e);
}
}
}
}
/**
* In order to implement a file watcher, we loop forever ensuring
* requesting to take the next item from the file watchers queue.
*/
#Override
public void run() {
try {
// get the first event before looping
WatchKey key = myWatcher.take();
while (key != null) {
// we have a polled event, now we traverse it and
// receive all the states from it
for (WatchEvent event : key.pollEvents()) {
WatchEvent.Kind eventType = event.kind();
if (eventType == OVERFLOW) {
continue;
}
process(event);
}
key.reset();
key = myWatcher.take();
}
} catch (InterruptedException e) {
ArrayList<WatchFile> auxList = threadFileToWatch;
for (WatchFile obj : auxList) {
if (obj.file != null) {
try {
obj.file.close();
System.out.println("chiusura file " + obj.fileName);
} catch (IOException ex) {
System.out.println("errore in chiusura file");
Logger.getLogger(WatchFileThreadMod.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
//e.printStackTrace();
}
System.out.println("Stopping thread");
}
}
public static void main(String[] args) throws Exception {
// get the directory we want to watch, using the Paths singleton class
//Path toWatch = Paths.get(DIRECTORY_TO_WATCH);
ArrayList<WatchFile> fileToWatch = new ArrayList<>();
String filename;
RandomAccessFile file;
fileToWatch.add(new WatchFile("EURUSD.rlt", new RandomAccessFile(args[0] + "/EURUSD.rlt", "r")));
filename = "EURCHF2.rlt";
try {
file = new RandomAccessFile(args[0] + "/" + filename, "r");
} catch (FileNotFoundException e) {
file = null;
System.out.println("filename " + filename + " non trovato");
}
fileToWatch.add(new WatchFile(filename, file));
fileToWatch = fileToWatch;
Path toWatch = Paths.get(args[0]);
if (toWatch == null) {
throw new UnsupportedOperationException("Directory not found");
}
// Sanity check - Check if path is a folder
try {
Boolean isFolder = (Boolean) Files.getAttribute(toWatch,
"basic:isDirectory", NOFOLLOW_LINKS);
if (!isFolder) {
throw new IllegalArgumentException("Path: " + toWatch + " is not a folder");
}
} catch (IOException ioe) {
// Folder does not exists
ioe.printStackTrace();
}
// make a new watch service that we can register interest in
// directories and files with.
WatchService myWatcher = toWatch.getFileSystem().newWatchService();
// start the file watcher thread below
MyWatchQueueReader fileWatcher = new MyWatchQueueReader(args[0], myWatcher, fileToWatch);
Thread processingThread = new Thread(fileWatcher, "FileWatcher");
processingThread.start();
toWatch.register(myWatcher, ENTRY_CREATE, ENTRY_MODIFY);
}
}
Edit: reduced code as requested.
Edit 2: file path
Edit 3: Metatrader code I am using to write data
#property strict
int file_handle;
string InpFileName = _Symbol + ".rlt"; // File name
input string InpDirectoryName = "Data"; // Folder name
int OnInit()
{
ResetLastError();
file_handle = FileOpen(InpDirectoryName + "//" + InpFileName, FILE_SHARE_READ|FILE_WRITE|FILE_TXT|FILE_ANSI);
if(file_handle == INVALID_HANDLE) {
PrintFormat("Failed to open %s file, Error code = %d", InpFileName, GetLastError());
ExpertRemove();
}
return INIT_SUCCEEDED;
}
void OnTick()
{
// file_handle = FileOpen(InpDirectoryName + "//" + InpFileName, FILE_SHARE_READ|FILE_WRITE|FILE_TXT|FILE_ANSI);
// Datetime), Bid, Volume
// string s = FileRead()
string s = TimeToStr(TimeGMT()) + "|" + Bid + "|" + Volume[0];
FileWriteString(file_handle, s + "|*\r\n");
FileFlush(file_handle);
//FileClose(file_handle);
}
void OnDeinit(const int reason)
{
FileClose(file_handle);
}
Edit 4: Screencast to better show my issue: data updates only when I click on the output file
Watch Service does not update
First of all, a premise : I'm answering this question primarily for future users of WatchService, which (like me) could experience this problem (i.e. on some systems events are signaled way after they occur).
The problem is that the implementation of this feature in Java is native, so it is platform-dependant (take a look at https://docs.oracle.com/javase/7/docs/api/java/nio/file/WatchService.html, under the section 'platform dependencies').
In particular, on Windows 7 (and MacOSX afaict) the implementation uses polling to retrieve the changes from the filesystem, so you can't rely on the 'liveliness' of notifications from a WatchService. The notifications will eventually be signaled, but there are no guarantees on when it will happen.
I don't have a rigorous solution to this problem, but after a lot of trial and error I can describe what works for me :
First, when writing to a file that is registered (i.e. 'watched'), I try to flush the content every time I can and update the 'last modified' attribute on the file, e.g. :
try (FileWriter writer = new FileWriter(outputFile)) {
writer.write("The string to write");
outputFile.setLastModified(System.currentTimeMillis());
writer.flush();
}
Second, I try to 'trigger' the refresh from code (I know it's not good code, but in this case, I'm just happy it works 99% of the time)
Thread.sleep(2000);
// in case I've just created a file and I'm watching the ENTRY_CREATE event on outputDir
outputDir.list();
or (if watching ENTRY_MODIFY on a particular file in outputDir)
Thread.sleep(2000);
outputFile.length();
In both cases, a sleep call simply 'gives the time' to the mechanism underlying the WatchService to trigger, even though 2 seconds are probably a lot more than it is needed.
Probably missing quotes on file path.
I am currently working on a project about calculations.I have done the main part of my project,Also integrated SVN Commit function to my code (using .ini file to read the specific address etc. )
I can easily Commit the files, what I am trying is I want to implement the real-time log to my console. Is there any way to implement the log to the console ? Not the general log but the commit log which should be real time.
I am using eclipse for mac, I've heard about SVNKit but I am really poor about SVN.
Thanks in advance for any information
--- EDIT ---
This is the code for reading the svn commands from .ini file
public static String iniSVNOkut(String deger, String getObje, String fetchObje){
Ini uzantilariAlIni = null;
try
{
String uzantiAyarlari = "Uzantilar.ini";
try
{
uzantilariAlIni = new Ini(new FileReader(uzantiAyarlari));
}
catch (InvalidFileFormatException e)
{
System.err.print("Hata InvalidFileFormat : " + e.getMessage() + "\n" );
e.printStackTrace();
}
catch(FileNotFoundException e)
{
System.err.print("Hata FileNotFoundException : " + e.getMessage() + "\n" );
e.printStackTrace();
}
catch (IOException e)
{
System.err.print("Hata IOException : " + e.getMessage() + "\n" );
e.printStackTrace();
}
return deger = uzantilariAlIni.get(getObje).fetch(fetchObje);
}
finally
{
}
}
This is what .ini includes
[svnAdresi]
svnAdresiniAl = svn co http://svn.svnkit.com/repos/svnkit/trunk/ /Users/sample/Documents/workspace/SatirHesaplaGUI/svnTestMAC
This is how I call it
String svnAdresi;
svnAdresi = IniFonksiyon.iniSVNOkut(svnAdresi, "svnAdresi", "svnAdresiniAl");
Runtime cmdCalistir = Runtime.getRuntime();
try
{
Process islem = cmdCalistir.exec(svnAdresi);
}
catch (Exception e)
{
e.printStackTrace();
}
If I understand your question correctly, you want to read the Subversion commit log into your console application.
The easiest way is to use SVNKit.
Here's how I did it.
private static List<SVNLogEntry> logEntryList;
/*
* Gets the Subversion log records for the directory
*/
LogHandler handler = new LogHandler();
String[] paths = { directory };
try {
repository.log(paths, latestRevision, 1L, false, true, handler);
} catch (SVNException svne) {
if (svne.getMessage().contains("not found")) {
logEntryList = new ArrayList<SVNLogEntry>();
} else {
CobolSupportLog.logError(
"Error while fetching the repository history: "
+ svne.getMessage(), svne);
return false;
}
}
logEntryList = handler.getLogEntries();
directory - string pointing to a particular directory or module
latestRevision - largest revision number from Subversion. Placing the latestRevision second in the log method invocation returns the log records in most recent order.
If you want the log records in sequential order, from 1 to latestRevision, then the 1L would be placed second, and the latestRevision would be placed third.
repository - Subversion repository that you've already authenticated.
Here's LogHandler.
public class LogHandler implements ISVNLogEntryHandler {
protected static final int REVISION_LIMIT = 5;
protected List<SVNLogEntry> logEntryList;
public LogHandler() {
logEntryList = new ArrayList<SVNLogEntry>();
}
public void handleLogEntry(SVNLogEntry logEntry) throws SVNException {
logEntryList.add(logEntry);
}
public List<SVNLogEntry> getLogEntries() {
if (logEntryList.size() <= REVISION_LIMIT) {
return logEntryList;
} else {
return logEntryList.subList(0, REVISION_LIMIT);
}
}
}
Okay, I'm trying to create a custom client for Minecraft (don't worry, my question has nothing to do with Minecraft in particular), and I added an abstract class to manage a configuration file using Java's built-in Properties system. I have a method that loads a properties file or creates it if it doesn't already exist. This method is called at the beginning of all my other methods (although it only does anything the first time its called).
The properties file gets created just fine when I run Minecraft the first time, but somehow when I run it the second time, the file gets blanked out. I'm not sure where or why or how I'm wiping the file clean, can someone please help me? Here's my code; the offending method is loadConfig():
package net.minecraft.src;
import java.util.*;
import java.util.regex.*;
import java.io.*;
/**
* Class for managing my custom client's properties
*
* #author oxguy3
*/
public abstract class OxProps
{
public static boolean configloaded = false;
private static Properties props = new Properties();
private static String[] usernames;
public static void loadConfig() {
System.out.println("loadConfig() called");
if (!configloaded) {
System.out.println("loading config for the first time");
File cfile = new File("oxconfig.properties");
boolean configisnew;
if (!cfile.exists()) {
System.out.println("cfile failed exists(), creating blank file");
try {
configisnew = cfile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
configisnew=true;
}
} else {
System.out.println("cfile passed exists(), proceding");
configisnew=false;
}
FileInputStream cin = null;
FileOutputStream cout = null;
try {
cin = new FileInputStream(cfile);
cout = new FileOutputStream(cfile);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
if (!configisnew) { //if the config already existed
System.out.println("config already existed");
try {
props.load(cin);
} catch (IOException e) {
e.printStackTrace();
}
} else { //if it doesn't exist, and therefore needs to be created
System.out.println("creating new config");
props.setProperty("names", "oxguy3, Player");
props.setProperty("cloak_url", "http://s3.amazonaws.com/MinecraftCloaks/akronman1.png");
try {
props.store(cout, "OXGUY3'S CUSTOM CLIENT\n\ncloak_url is the URL to get custom cloaks from\nnames are the usernames to give cloaks to\n");
cout.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
String names = props.getProperty("names");
System.out.println("names: "+names);
try {
usernames = Pattern.compile(", ").split(names);
} catch (NullPointerException npe) {
npe.printStackTrace();
}
System.out.println("usernames: "+Arrays.toString(usernames));
configloaded=true;
}
}
public static boolean checkUsername(String username) {
loadConfig();
System.out.println("Checking username...");
for (int i=0; i<usernames.length; i++) {
System.out.println("comparing "+username+" with config value "+usernames[i]);
if (username.startsWith(usernames[i])){
System.out.println("we got a match!");
return true;
}
}
System.out.println("no match found");
return false;
}
public static String getCloakUrl() {
loadConfig();
return props.getProperty("cloak_url", "http://s3.amazonaws.com/MinecraftCloaks/akronman1.png");
}
}
If it's too hard to read here, it's also on Pastebin: http://pastebin.com/9UscXWap
Thanks!
You are unconditionally creating new FileOutputStream(cfile). This will overwrite the existing file with an empty one. You should only invoke the FileOutputStream constructor when writing a new config file.
if (configloaded)
return;
File cfile = new File("oxconfig.properties");
try {
if (cfile.createNewFile()) {
try {
FileOutputStream cout = new FileOutputStream(cfile);
props.setProperty("names", "oxguy3, Player");
props.setProperty("cloak_url", "http://...");
...
cout.flush();
} finally {
cout.close();
}
} else {
FileInputStream cin = new FileInputStream(cfile);
try {
props.load(cin);
} finally {
cin.close();
}
}
configloaded=true;
} catch(IOException ex) {
e.printStackTrace();
}