JavaFX app overwriting files while being open causes exception - java

I have a runnable jar file (with a lib folder housing all the dependency jars). This is located on a network share which anyone that has access can run from. This works great except one huge caveat. If I want to deploy a new version of the software, I have to ask everyone to exit the application first. This is because if I overwrite the jars with new versions (or if there is a network blip), the running program stays open but as soon as they do an action that requires code in of the dependencies (jar file in lib folder), it will cause an exception:
Exception in thread "JavaFX Application Thread" java.lang.NoClassDefFoundError
The program will not produce an error, but certain actions will break, like communicating with an API etc.
Is there a way that I can resolve this so that I can publish updates while the user's are working or at least produce a prompt that will force them to close/and reopen the app etc.

One approach:
Provide a script which launches the application from a local copy of the remote code.
Store a version number with your app.
The script checks if there is a local copy of the app on the machine.
If no local version exists, the script copies the jars from your network share to a local copy.
If there is already a local copy, it checks the version against the network version.
If the network version is updated, it overwrites the local copy with the new remote version before launching the app,
otherwise it just launches the local copy.
If you want the users to be alerted that they are currently running an outdated copy, you could create a JavaFX task which polls the remote version number and checks it against the currently running version number. If they differ, you can alert and (if you wish) shutdown the app and re-trigger the launcher script.

I was able to create a scheme in which I have multiple server folder locations that house the jar distributable. And this jar basically checks these locations for the latest copy of the application and runs that latest copy. I was able to get it working for both Mac and Windows (didn't test Linux) by detecting the OS.
So now, I can publish an update over the oldest app, and the next time the user opens the app, it will be the latest copy.
process.properties
location.a=Application/A
location.b=Application/B
app=app.jar
You can add folders A-Z but just add them into the properties.
Main.java
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
public class Main
{
public static Properties properties;
private static final String DEFAULT_PROPERTY_FILE_LOCATION = Paths.get("").toAbsolutePath().toString() + File.separator + "process.properties";
private static final String JAVE_EXEC;
static
{
String os = System.getProperty("os.name");
if (StringUtils.containsIgnoreCase(os, "win"))
{
JAVA_EXEC = "java";
} else if (StringUtils.containsIgnoreCase(os, "mac"))
{
JAVA_EXEC = "/usr/bin/java";
} else if (StringUtils.containsIgnoreCase(os, "nux") || StringUtils.containsIgnoreCase(os, "nix"))
{
JAVA_EXEC = "/usr/bin/java";
} else
{
JAVA_EXEC = "java";
}
}
/**
* #param args the command line arguments
*/
public static void main(String[] args)
{
Main.properties = new Properties();
try
{
InputStream in = new FileInputStream(DEFAULT_PROPERTY_FILE_LOCATION);
Main.properties.load(in);
System.out.println("Loaded property file: " + DEFAULT_PROPERTY_FILE_LOCATION);
TreeMap<Long, String> locations = new TreeMap<>();
String appName = Main.properties.getProperty("app");
if (validateProperties(properties))
{
for (int letter = 'a'; letter <= 'z'; ++letter)
{
String location = "location." + (char) letter;
if (Main.properties.getProperty(location) != null)
{
String networkLocation = Paths.get("").toAbsolutePath() + File.separator + Main.properties.getProperty(location);
File file = new File(networkLocation + File.separator + appName);
if (file.exists())
{
locations.put(FileUtils.lastModified(file), networkLocation);
}
}
}
if (!locations.isEmpty())
{
Runtime.getRuntime().exec(new String[]
{
JAVA_EXEC, "-jar", locations.lastEntry().getValue() + File.separator + appName
}, null, new File(locations.lastEntry().getValue()));
}
}
} catch (IOException ex)
{
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
private static boolean validateProperties(Properties properties)
{
List<String> mandatoryProperties = new ArrayList<>();
mandatoryProperties.add("app");
for (String mandatoryProperty : mandatoryProperties)
{
if (properties.get(mandatoryProperty) == null)
{
System.out.println("Failed - Property: " + mandatoryProperty + " doesn't exist.");
return false;
}
}
return true;
}
}

Related

Maven OSGi project compiles, but won't run

I have been trying to port Paul Bakker's (#paul-bakker) Making JavaFX better with OSGi : javafx-osgi-example to a maven OSGi project that uses the Apache Felix Maven Bundle Plugin (BND). So far it compiles without any errors, but I can't get it to run:
Starting OSGi Framework
Found declarative services implementation: file:/C:/Users/Rev/.m2/repository/org/apache/felix/org.apache.felix.scr/1.6.2/org.apache.felix.scr-1.6.2.jar
INFO : org.apache.felix.scr (1): Version = 1.6.2
Bundle: org.apache.felix.framework
Registered service: [org.osgi.service.resolver.Resolver]
Registered service: [org.osgi.service.packageadmin.PackageAdmin]
Registered service: [org.osgi.service.startlevel.StartLevel]
Bundle: org.apache.felix.scr
Registered service: [org.apache.felix.scr.ScrService]
Registered service: [org.osgi.service.cm.ManagedService]
Registered service: [org.apache.felix.scr.impl.ScrGogoCommand]
DEBUG: Starting ComponentActorThread
Bundle: null
Bundle: null
Bundle: null
As you can see, the bundles never get started. No errors are thrown. It just simply doesn't start.
Why won't the bundles start?
THE PROJECT SOURCES
Paul Bakker's (The original non-maven project) : javafx-osgi-example
My maven implementation of Paul Bakker's javafx-osgi-example : JavaFX-Maven-Multi-Module-OSGi
From the terminal (Windows), mvn clean install works perfectly.
UPDATE
I've been trying to run it from Eclipse, but to no success:
Run -> Run as -> Java Application
Eclipse Java EE IDE for Web Developers.
Version: Mars.2 Release (4.5.2)
Build id: 20160218-0600
UPDATE
I have a class App under dist in the package rev.dist that does the launching. It goes loops throug all the directories under the rev and starts any jars whose names match the names under resources/plugins.txt.
APP.java
package rev.dist;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.stream.Collectors;
import org.apache.commons.io.FilenameUtils;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.launch.Framework;
import org.osgi.framework.launch.FrameworkFactory;
public class App {
FrameworkFactory frameworkFactory;
private Framework framework;
private List<String> pluginsList = new ArrayList<>();
private int addedPlugins;
public static void main(String[] args) throws BundleException, URISyntaxException {
App app = new App();
app.initialize();
}
private void initialize() throws BundleException, URISyntaxException {
this.plugins();
Map<String, String> map = new HashMap<String, String>();
// make sure the cache is cleaned
map.put(Constants.FRAMEWORK_STORAGE_CLEAN, Constants.FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT);
map.put("ds.showtrace", "true");
map.put("ds.showerrors", "true");
frameworkFactory = ServiceLoader.load(FrameworkFactory.class).iterator().next();
framework = frameworkFactory.newFramework(map);
System.out.println("Starting OSGi Framework");
framework.init();
loadScrBundle(framework);
File baseDir = new File("../");
String baseDirPath = baseDir.getAbsolutePath();
File[] files = new File(baseDirPath).listFiles();
this.showFiles(files);
for (Bundle bundle : framework.getBundleContext().getBundles()) {
bundle.start();
System.out.println("Bundle: " + bundle.getSymbolicName());
if (bundle.getRegisteredServices() != null) {
for (ServiceReference<?> serviceReference : bundle.getRegisteredServices())
System.out.println("\tRegistered service: " + serviceReference);
}
}
}
public void showFiles(File[] files) throws BundleException {
if (addedPlugins != pluginsList.size()) {
System.out.println(":: " + pluginsList.size());
addedPlugins--;
}
for (File file : files) {
if (file.isDirectory()) {
// System.out.println("Directory: " + file.getName());
showFiles(file.listFiles()); // Calls same method again.
} else {
String[] bits = file.getName().split(".");
if (bits.length > 0 && bits[bits.length - 1].equalsIgnoreCase("jar")) {
// framework.getBundleContext().installBundle(file.toURI().toString());
}
// String ext = FilenameUtils.getExtension(file.getAbsolutePath());
String basename = FilenameUtils.getBaseName(file.getName());
if (pluginsList.contains(basename)) {
framework.getBundleContext().installBundle(file.toURI().toString());
System.out.println("File: " + file.getName());
System.out.println("Base >>>>>>>>>>>>> : " + basename);
pluginsList.remove(basename);
}
}
}
}
public void plugins() {
File plugins = new File("src/main/resources/plugins.txt");
String fileName = plugins.getAbsolutePath();
try (BufferedReader br = Files.newBufferedReader(Paths.get(fileName))) {
// br returns as stream and convert it into a List
pluginsList = br.lines().collect(Collectors.toList());
} catch (IOException e) {
e.printStackTrace();
}
pluginsList.forEach(System.out::println);
addedPlugins = pluginsList.size();
}
private void loadScrBundle(Framework framework) throws URISyntaxException, BundleException {
URL url = getClass().getClassLoader().getResource("org/apache/felix/scr/ScrService.class");
if (url == null)
throw new RuntimeException("Could not find the class org.apache.felix.scr.ScrService");
String jarPath = url.toURI().getSchemeSpecificPart().replaceAll("!.*", "");
System.out.println("Found declarative services implementation: " + jarPath);
framework.getBundleContext().installBundle(jarPath).start();
}
}
I have released a couple of first Early Access versions of Drombler FX - the modular application framework for JavaFX.
It's not based on Paul Bakker's work, but it's based on OSGi and Maven (POM-first), as well. Maybe you find it useful. The application framework is Open Source.
There is also a tutorial with a Getting Started page.

External library not available when deploy with fat-jar

I'm using in my program the bluecove library.
While running the program via eclipse, all works smooth. I'm now trying to deploy my program, and following this post i'm using fat-jar.
When i run the jar file (created by fat-jar), the library can't be located, and i'm getting the exception BlueCove libraries not available as result of this line local = LocalDevice.getLocalDevice();.
In the fat-jar window i tried also to add bluecove-2.1.0.jar to the Class-Path place, and also with the path \src\JoJoServer\bluecove-2.1.0.jar.
I tried also to place the bluecove's jar file in different folders, such as the src, or an external folder.
Although i know it's not recommended, i tried the option of One-Jar, nevertheless it didn't help.
To run the jar (the one created by fat jar) i simply double click the file.
What i'm missing?
This is the entire code:
import java.io.IOException;
import javax.bluetooth.BluetoothStateException;
import javax.bluetooth.DiscoveryAgent;
import javax.bluetooth.LocalDevice;
import javax.bluetooth.UUID;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
import javax.microedition.io.StreamConnectionNotifier;
#Override
public void run() {
// retrieve the local Bluetooth device object
LocalDevice local = null;
StreamConnectionNotifier notifier;
StreamConnection connection = null;
// setup the server to listen for connection
try {
local = LocalDevice.getLocalDevice();
local.setDiscoverable(DiscoveryAgent.GIAC);
UUID uuid = new UUID("0000110100001000800000805F9B34FB", false);
System.out.println(uuid.toString());
String url = "btspp://localhost:" + uuid.toString() + ";name=RemoteBluetooth";
notifier = (StreamConnectionNotifier)Connector.open(url);
} catch (BluetoothStateException e) {
System.out.println("Bluetooth is not turned on.");
e.printStackTrace();
return;
}
// ...
}
I have no clue what could be your problem, but I've tried the process and everything works, so just a summary of what I've did. Maybe you will figure it out by following it...
I don't understand how the posted code could be the entire, I see no class definition. :)
So I've modified it to the main method and it works both from the Eclipse and also by running the JAR generated by the FatJar.
The modified code of the BTTest class:
package test;
import java.io.IOException;
import javax.bluetooth.BluetoothStateException;
import javax.bluetooth.DiscoveryAgent;
import javax.bluetooth.LocalDevice;
import javax.bluetooth.UUID;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
import javax.microedition.io.StreamConnectionNotifier;
public class BTTest {
public static void main(String[] args) throws Exception{
// retrieve the local Bluetooth device object
LocalDevice local = null;
StreamConnectionNotifier notifier;
StreamConnection connection = null;
// setup the server to listen for connection
try {
local = LocalDevice.getLocalDevice();
local.setDiscoverable(DiscoveryAgent.GIAC);
UUID uuid = new UUID("0000110100001000800000805F9B34FB", false);
System.out.println(uuid.toString());
String url = "btspp://localhost:" + uuid.toString()
+ ";name=RemoteBluetooth";
notifier = (StreamConnectionNotifier) Connector.open(url);
} catch (BluetoothStateException e) {
System.out.println("Bluetooth is not turned on.");
e.printStackTrace();
return;
}
// ...
}
}
To run or produce it, I have just put the bluecove library in the build path and created the fat jar with a simple way:
http://oi60.tinypic.com/vg1jpt.jpg
Starting the generated jar from command line:
D:\testProjects\bttest>java -jar bttest_fat.jar
BlueCove version 2.1.0 on winsock
0000110100001000800000805f9b34fb
BlueCove stack shutdown completed
Can you post a difference to your process?

java flickr and flickrj download user pictures

Hi I am new to flickrj library.
Have foundational java knowledge though.
The project that I am working on requires me to authenticate into flickr and then download geo-tagged images into a folder in local hard drive. The program will be Desktop application program.
I am approaching the program by breaking down into 3 steps.
1.Proper authentication to be completed.(which i have succeeded)
2.Try to download all the photos that user has when authenticated.
3.Try to alter the code a little so that it will only download geo-tagged images.
My problems is on step 2. I cant download logged-in user images let alone geo-tagged ones.
I am trying the code provided by Daniel Cukier here
But I am running into problem.
My netbeans simply strike off at the line 77 on .getOriginalAsStream() part, with the error "java.lang.RuntimeException: Uncompilable source code - Erroneous sym type: java.io.ByteArrayOutputStream.write"
From my understanding netbeans striking off a line means , it is depreciated but shouldnt it still work? What is holding this whole problem back?
I have tried researching and basically I have to admit , it is beyond my capability to trouble shoot. If anyone has any idea on what i am doing wrong , I would be so grateful.
Ps: I am not looking to be spoon fed but please answer me in idiot-friendly way as I am still a student and my java isn't the greatest.
This code is what I have so far.
import com.aetrion.flickr.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Properties;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.SAXException;
import com.aetrion.flickr.auth.Auth;
import com.aetrion.flickr.auth.AuthInterface;
import com.aetrion.flickr.auth.Permission;
import com.aetrion.flickr.photos.Photo;
import com.aetrion.flickr.photos.PhotoList;
import com.aetrion.flickr.photos.PhotosInterface;
import com.aetrion.flickr.util.IOUtilities;
import java.io.*;
import java.util.Iterator;
import org.apache.commons.io.FileUtils;
public class authenticate {
Flickr f;
RequestContext requestContext;
String frob = "";
String token = "";
Properties properties = null;
public authenticate() throws ParserConfigurationException, IOException, SAXException {
InputStream in = null;
try {
in = getClass().getResourceAsStream("/setup.properties");
properties = new Properties();
properties.load(in);
} finally {
IOUtilities.close(in);
}
f = new Flickr(
properties.getProperty("apiKey"),
properties.getProperty("secret"),
new REST()
);
Flickr.debugStream = false;
requestContext = RequestContext.getRequestContext();
AuthInterface authInterface = f.getAuthInterface();
try {
frob = authInterface.getFrob();
} catch (FlickrException e) {
e.printStackTrace();
}
System.out.println("frob: " + frob);
URL url = authInterface.buildAuthenticationUrl(Permission.DELETE, frob);
System.out.println("Press return after you granted access at this URL:");
System.out.println(url.toExternalForm());
BufferedReader infile =
new BufferedReader ( new InputStreamReader (System.in) );
String line = infile.readLine();
try {
Auth auth = authInterface.getToken(frob);
System.out.println("Authentication success");
// This token can be used until the user revokes it.
System.out.println("Token: " + auth.getToken());
System.out.println("nsid: " + auth.getUser().getId());
System.out.println("Realname: " + auth.getUser().getRealName());
System.out.println("Username: " + auth.getUser().getUsername());
System.out.println("Permission: " + auth.getPermission().getType());
PhotoList list = f.getPhotosetsInterface().getPhotos("72157629794698308", 100, 1);
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
Photo photo = (Photo) iterator.next();
File file = new File("/tmp/" + photo.getId() + ".jpg");
ByteArrayOutputStream b = new ByteArrayOutputStream();
b.write(photo.getOriginalAsStream());
FileUtils.writeByteArrayToFile(file, b.toByteArray());
}
} catch (FlickrException e) {
System.out.println("Authentication failed");
e.printStackTrace();
}
}
public static void main(String[] args) {
try {
authenticate t = new authenticate();
} catch(Exception e) {
e.printStackTrace();
}
System.exit(0);
}
}
You are correct in your interpretation of the strikeout that getOriginalAsStream() is deprecated. It looks like you might want to rework your code to use PhotosInterface.getImageAsStream(), passing the ORIGINAL size as one of the arguments.
To adjust NetBeans' behavior with respect to deprecated methods, you can follow the link recommended by #AljoshaBre as well as this one.
If you want download all your photos from Flickr, this is possible if you have a mac computer.
Download Aperture program on Apple Store and install it.
After to install, open the Aperture.
Go on preferences.
Click on 'Accounts' tab.
Click on plus sign (+) on bottom left to add a photo service.
Add the Flicker option.
Follow the login and authorization instructions.
Done! All your photos will be synchronized in you aperture library locate on ~/images/
I hope I have helped.

How to run the Linux "cd" command from Java?

I want to write a Java program to delete ~12 directories or files which are under my home directory. I am able to do this by using
Process proc = Runtime.getRuntime().exec("rm -rf *path*")
But I have to run this command 12 times or I can keep it in loop. What I really want is to have a file in my home directory that contains the names of all the directories and files to delete in it. My Java program should go to the home directory, read the file, and delete all the specified files.
I am stuck at the very first step – I am not able to cd to the home directory. Please let me know how can I achieve this.
Thanks for all of your replies.
But, here I don't really want to use the Java util classes rather I want to learn a way using which I can run Linux commands in my Java class. Being a deployment Intern, I have to reset the environment every time before deploying a new environment for the customer. For this, I repeatedly use some basic Linux commands. I can write a shell script to do this but for this time, I want to write a Java class in which I can put all these Linux commands and run from one class.
The commands which I use are:
kill all java processes which are started by the admin ONLY – for this I need to use multiple Linux commands with “pipe”
Remove all 12-directories/files from home directory
stop some services (like siebel, etc.) – for this I need to go under the particular directories and run ./shutdown.sh or ./stop_ns, etc.
run some database scripts – to reset the database schemas
again start the services – same as step 2 except this time I need to run ./start_ns, etc.
I really appreciate if you can let me know
a. How can I navigate into a directory using Java code
b. How can I run multiple Linux commands using pipe using Java code
Why do you need to "go" to the home directory? Just read the file wherever you are:
String homeDirectory = System.getProperty("user.home");
File file = new File(homeDirectory, "filenames.txt"); // Or whatever
// Now load the file using "file" in the constructor call to FileInputStream etc
It's very rarely a good idea to require that a process changes working directory just to do the right thing.
You dont need to change directory. You can just read file using absolute path using FileReader(String fileName).
For deleting entire directories, try Apache Commons IO's class FileUtils:
FileUtils.deleteDirectory(new File(System.getProperty("user.home")));
Or use cleanDirectory to delete everything in home but not home itself:
FileUtils.cleanDirectory(new File(System.getProperty("user.home")));
If you want to delete specific files only (e.g. those matching a name pattern), list the files first, then delete them:
File startDir = new File(System.getProperty("user.home"));
//this should return the leaf files first, then the inner nodes of the directory tree
Collection<File> files = FileUtils.listFiles(startDir , someFileFiler, someDirFilter);
for(File f : files) {
f.delete();
}
"cd" is a shell internal command, not a executable program.
Even you can change dir in java program by whatever means like JNA, when it exit, the current dir in shell is not changed, because the java program runs in another process than the shell.
But we still can do something about it.
eg. I want to make a new shell command called xcd, it popup a GUI shows a list let you select directories existed in bash history, and change current dir to it for you.
in ~/.bashrc add a line:
xcd(){
XCDRES=`xcd.sh`
if [ "$XCDRES" ]; then
cd "$XCDRES"
fi
}
2.xcd.sh is
#!/bin/bash
java -cp $PATH1/xcd.jar neoe.xcd.Main
and add xcd.sh to PATH
the java program is
package neoe.xcd;
import java.awt.Toolkit;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
public class Main {
public static String getUserHomeDir() {
return System.getProperty("user.home");
}
public static void main(String[] args) throws Exception {
new Main().run();
}
public static String readString(InputStream ins, String enc) throws IOException {
if (enc == null)
enc = "UTF-8";
BufferedReader in = new BufferedReader(new InputStreamReader(ins, enc));
char[] buf = new char[1000];
int len;
StringBuffer sb = new StringBuffer();
while ((len = in.read(buf)) > 0) {
sb.append(buf, 0, len);
}
in.close();
return sb.toString();
}
private String[] selection = new String[1];
private void run() throws Exception {
File hisfile = new File(getUserHomeDir(), ".bash_history");
if (!hisfile.exists()) {
System.err.println(".bash_history not exists, quit");
return;
}
String[] ss = readString(new FileInputStream(hisfile), null).split("\n");
List<String> res = new ArrayList<String>();
Set uniq = new HashSet();
for (String s : ss) {
s = s.trim();
if (!s.startsWith("cd /")) {
continue;
}
s = s.substring(3);
File f = new File(s);
if (f.isDirectory()) {
s = f.getAbsolutePath();
if (uniq.contains(s)) {
continue;
}
uniq.add(s);
res.add(s);
}
}
if (res.isEmpty()) {
System.err.println("no cd entry, quit");
return;
}
Collections.sort(res);
String cd1 = selectFromList(res);
if (cd1 == null) {
System.err.println("not selected, quit");
return;
}
doCd(cd1);
}
private void doCd(String cd1) throws Exception {
System.out.println(cd1);
}
private String selectFromList(List<String> res) {
final JList list = new JList(res.toArray());
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
final JDialog frame = wrapFrame(new JScrollPane(list), "select dir to cd");
list.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() > 1) {
String s = (String) list.getSelectedValue();
selection[0] = s;
frame.dispose();
}
}
});
list.addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
int kc = e.getKeyCode();
if (kc == KeyEvent.VK_ESCAPE) {
frame.dispose();
} else if (kc == KeyEvent.VK_ENTER) {
String s = (String) list.getSelectedValue();
selection[0] = s;
frame.dispose();
}
}
});
frame.setVisible(true);
frame.requestFocus();
return selection[0];
}
private JDialog wrapFrame(JComponent comp, String title) {
JDialog frame = new JDialog();
frame.setTitle("select dir to cd");
frame.setModal(true);
frame.add(comp);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setSize(400, 600);
frame.setLocationRelativeTo(null);
return frame;
}
}
use xcd in shell.
You can't really do that. Java programs don't really allow you to change the "current working directory" as most people understand it (not without using native code, anyway). The normal Java approach is to open a File instance on the directory you want to manipulate, and then use operations on that instance to manipulate the files/directories in question.
For details on how to delete directories programatically in Java, see: Delete directories recursively in Java

How to browse the file system of a server machine when connecting with a client (java)

I'm in the process of making a proof of concept to dissociate the business code from the gui for the ps3 media server (http://www.ps3mediaserver.org/). For this I've got a project hosted at source forge (http://sourceforge.net/projects/pms-remote/). The client should be a simple front end to configure the server from any location within a network having the rights to connect to the server.
On the server side, all service have been exposed using javax.jws and the client proxy has been generated using wsimport.
One of the features of the current features (actually, the only blocking one), is to define the folders that will be shared by the server. As the client and server are now running as a single application on the same machine, it's trivial to browse its file system.
Problem: I'd like to expose the file system of the server machine through web services. This will allow any client (the one I'm currently working on is the same as the original using java swing) to show available folders and to select the ones that will be shown by the media server. In the end the only thing I'm interested in is an absolute folder path (string).
I thought I'd find a library giving me this functionality but couldn't find any.
Browsing the files using a UNC path and accessing a distant machine doesn't seem feasible, as it wouldn't be transparent for the user.
For now I don't want to worry about security issues, I'll figure these out once the rest seems feasible.
I'd be grateful for any input.
Thanks, Philippe
I've ended up creating a pretty simple web service letting either list all root folders or all child folders for a given path.
It's now up to the client to have a (GUI) browser to access this service.
package net.pms.plugin.webservice.filesystem;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import net.pms.plugin.webservice.ServiceBase;
#WebService(serviceName = "FileSystem", targetNamespace = "http://ps3mediaserver.org/filesystem")
public class FileSystemWebService extends ServiceBase {
#WebMethod()
public List<String> getRoots() {
List<String> roots = new ArrayList<String>();
for(File child : File.listRoots()) {
roots.add(child.getAbsolutePath());
}
return roots;
}
#WebMethod()
public List<String> getChildFolders(#WebParam(name="folderPath") String folderPath) throws FileNotFoundException {
List<String> children = new ArrayList<String>();
File d = new File(folderPath);
if(d.isDirectory()) {
for(File child : d.listFiles()) {
if(child.isDirectory() && !child.isHidden()) {
children.add(child.getAbsolutePath());
}
}
} else {
throw new FileNotFoundException();
}
return children;
}
}
For people wanting to use this, here's the ServiceBase class as well
package net.pms.plugin.webservice;
import javax.xml.ws.Endpoint;
import org.apache.log4j.Logger;
public abstract class ServiceBase {
private static final Logger log = Logger.getLogger(ServiceBase.class);
protected boolean isInitialized;
/**
* the published endpoint
*/
private Endpoint endpoint = null;
/**
*
* Start to listen for remote requests
*
* #param host ip or host name
* #param port port to use
* #param path name of the web service
*/
public void bind(String host, int port, String path) {
String endpointURL = "http://" + host + ":" + port + "/" + path;
try {
endpoint = Endpoint.publish(endpointURL, this);
isInitialized = true;
log.info("Sucessfully bound enpoint: " + endpointURL);
} catch (Exception e) {
log.error("Failed to bind enpoint: " + endpointURL, e);
}
}
/**
* Stop the webservice
*/
public void shutdown() {
log.info("Shut down " + getClass().getName());
if (endpoint != null)
endpoint.stop();
endpoint = null;
}
}
From the client, you might be able to leverage the output of smbclient -L. On the server, a suitable servlet might do.

Categories

Resources