I have some problem with granting permissions in Java. I would like to implement app (e.g. myapp), which runs normaly, with all permissions, but when it loads code (from .jar or .class)(e.g. foo.jar and bar.class) from specific location (e.g http://example.net/libs), this code should run with specific permissions.
I thought the only one which I have to do is grant all permissions to myapp (via policy file) and then just simply create ProtectionDomain (on location http://example.net/libs/* and with specified permissions) and run libs via AccessController.
But when I grant permissions (only)(via policy file, see bottom) to myapp, they are granted to all code (including libraries foo.jar and bar.class) - which musn't.
So I stopped exploring how to grant permissions to libs and I have to solve this problem first.
(see EDIT at bottom)
Structure
I have myapp which contains main class (myapp.Main) and it's located in /home/java/:
/home/java/src/myapp/Main.java
/home/java/bin/myapp/Main.class
and libraries
http://example.net/libs/foo.jar
http://example.net/libs/bar.class
Implementation
I wrote myapp.Main.java like this:
package myapp;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
public class Main {
public static void main(String[] args) throws IOException {
//myapp should access
System.out.println("myapp.Main: " + System.getProperty("user.home"));
//find Foo class
Class<?> fooClass = findFooClass();
//invoke some its method
// this should fail
try {
System.out.println(fooClass.newInstance().toString());
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
return;
}
}
private static Class<?> findFooClass() throws IOException {
URL fooClassURL;
try {
fooClassURL = new URL("http://example.net/libs/foo.jar");
} catch (MalformedURLException e) {
e.printStackTrace();
return null;
}
URLClassLoader ucl = new URLClassLoader(new URL[]{fooClassURL});
Class<?> fooClass;
try {
fooClass = ucl.loadClass("foopackage.Foo");
} catch (ClassNotFoundException e) {
e.printStackTrace();
return null;
} finally {
ucl.close();
}
return fooClass;
}
}
and class foopackage.Foo like
package foopackage;
public class Foo {
public Foo() {
}
private void tryProperty() {
System.out.println("foopackage.Foo: " + System.getProperty("user.home"));
}
#Override
public String toString() {
tryProperty();
return super.toString();
}
}
Running
When I run myapp via this command
java -Djava.security.manager -Djava.security.policy=/home/java/myapp.policy myapp.Main
where file myapp.policy looks like
grant codeBase "file:/home/java/*" {
permission java.security.AllPermission;
};
it outputs twice home directory and then original value of Foo.toString.
(see EDIT at bottom)
I am asking - what am I doing wrong? What did I disunderstand?
EDIT:
The reason why permissions were granted to whole code was simply - while I was exploring security, I've got litle bit tangled and I granted all permissions via file ~/java.policy.
So, now I can grant permissions via policy file as expected. But still not works granting permissions via AccessController. myapp.Main has permissions granted via policy file and works fine (so it prints once home directory), but when it (via AccessController.doPrivileged) calls FooClassToStringAction's action, the foopackage.Foo has no permission to access property (which I IMHO grant by ProtectionDomain). Updated myapp.Main class' code:
package myapp;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.AllPermission;
import java.security.CodeSource;
import java.security.PermissionCollection;
import java.security.Permissions;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
import java.security.cert.Certificate;
public class Main {
public static class FooClassToStringAction implements PrivilegedAction<Void> {
private Class<?> fooClass;
public FooClassToStringAction(Class<?> fooClass) {
this.fooClass = fooClass;
}
#Override
public Void run() {
try {
System.out.println(fooClass.newInstance().toString());
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
return null;
}
return null;
}
}
public static void main(String[] args) throws IOException {
//myapp should access
System.out.println("myapp.Main: " + System.getProperty("user.home"));
//find Foo class
Class<?> fooClass = findFooClass();
ProtectionDomain domain = createProtectionDomain();
PrivilegedAction<Void> action = new FooClassToStringAction(fooClass);
AccessControlContext context = new AccessControlContext(new ProtectionDomain[] {domain});
AccessController.doPrivileged(action, context);
}
private static Class<?> findFooClass() throws IOException {
URL fooClassURL;
try {
fooClassURL = new URL("http://example.net/libs/*");
} catch (MalformedURLException e) {
e.printStackTrace();
return null;
}
URLClassLoader ucl = URLClassLoader.newInstance(new URL[] {fooClassURL});//new URLClassLoader(new URL[]{fooClassURL});
Class<?> fooClass;
try {
fooClass = ucl.loadClass("foopackage.Foo");
} catch (ClassNotFoundException e) {
e.printStackTrace();
return null;
} finally {
ucl.close();
}
return fooClass;
}
private static ProtectionDomain createProtectionDomain() {
URL url;
try {
url = new URL("http://example.net/libs/*");
} catch (MalformedURLException e) {
e.printStackTrace();
return null;
}
//I tried url=null or url=file:/- but no change
CodeSource codesource = new CodeSource(url, (Certificate[]) null);
PermissionCollection permissions = new Permissions();
//add various permissions to libraries here
permissions.add(new AllPermission());
return new ProtectionDomain(codesource, permissions);
}
}
Related
I'm using tTorrent Java implementation of the BitTorrent protocol. I'm at the point where I have to deal with a Tracker. The example code from the official repository loads torrent files from a given directory and announce them to the tracker. Then, starts it. I was hoping that the tracker would look for new torrent files in the directory automatically but, it doesn't seem to do so.
I pulled in a DirectoryWatcher and listened to create event; filtering torrent files. Passing the reference of Tracker object, I can announce the new file but, it doesn't seem to do anything.
How can I make the tracker aware of possible new torrent files in the directory while it's running?
DirectoryAwareTracker.java
import com.turn.ttorrent.tracker.TrackedTorrent;
import com.turn.ttorrent.tracker.Tracker;
import io.methvin.watcher.DirectoryChangeEvent;
import io.methvin.watcher.DirectoryChangeListener;
import io.methvin.watcher.DirectoryWatcher;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.file.Path;
public class DirectoryAwareTracker extends Tracker {
private DirectoryWatcher watcher;
private static final FilenameFilter torrentFilenameFilter = new FilenameFilter() {
#Override
public boolean accept(File dir, String name) {
return name.endsWith(".torrent");
}
};
DirectoryAwareTracker(InetSocketAddress address, Path directoryToWatch) throws IOException {
super(address);
File parent = new File(".");
for (File f : parent.listFiles(torrentFilenameFilter)) {
System.out.println("Loading torrent from " + f.getName());
try {
announce(TrackedTorrent.load(f));
} catch (Exception e) {
}
}
System.out.println("Starting tracker with {} announced torrents..." + getTrackedTorrents().size());
start();
watcher = DirectoryWatcher.create(directoryToWatch, new DirectoryChangeListener() {
#Override
public void onEvent(DirectoryChangeEvent directoryChangeEvent) throws IOException {
switch (directoryChangeEvent.eventType()) {
case CREATE:
File newFile = new File(directoryChangeEvent.path().toString());
System.out.println(directoryChangeEvent.path().toString());
System.out.println(newFile.isFile());
System.out.println(newFile.getName().endsWith(".torrent"));
if (newFile.isFile() && newFile.getName().endsWith(".torrent")) {
try {
announce(TrackedTorrent.load(newFile));
} catch (Exception e) {
}
}
break;
}
}
});
}
public void stopWatching() {
try {
watcher.close();
}
catch(Exception e) { }
}
public void watch() {
watcher.watch();
}
}
EDIT: This does not seem to be possible, see https://bugs.openjdk.java.net/browse/JDK-8039910.
I have a helper class that provides a Stream<Path>. This code just wraps Files.walk and sorts the output:
public Stream<Path> getPaths(Path path) {
return Files.walk(path, FOLLOW_LINKS).sorted();
}
As symlinks are followed, in case of loops in the filesystem (e.g. a symlink x -> .) the code used in Files.walk throws an UncheckedIOException wrapping an instance of FileSystemLoopException.
In my code I would like to catch such exceptions and, for example, just log a helpful message. The resulting stream could/should just stop providing entries as soon as this happens.
I tried adding .map(this::catchException) and .peek(this::catchException) to my code, but the exception is not caught in this stage.
Path checkException(Path path) {
try {
logger.info("path.toString() {}", path.toString());
return path;
} catch (UncheckedIOException exception) {
logger.error("YEAH");
return null;
}
}
How, if at all, can I catch an UncheckedIOException in my code giving out a Stream<Path>, so that consumers of the path do not encounter this exception?
As an example, the following code should never encounter the exception:
List<Path> paths = getPaths().collect(toList());
Right now, the exception is triggered by code invoking collect (and I could catch the exception there):
java.io.UncheckedIOException: java.nio.file.FileSystemLoopException: /tmp/junit5844257414812733938/selfloop
at java.nio.file.FileTreeIterator.fetchNextIfNeeded(FileTreeIterator.java:88)
at java.nio.file.FileTreeIterator.hasNext(FileTreeIterator.java:104)
at java.util.Iterator.forEachRemaining(Iterator.java:115)
at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at ...
EDIT: I provided a simple JUnit test class. In this question I ask you to fix the test by just modifying the code in provideStream.
package somewhere;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static java.nio.file.FileVisitOption.FOLLOW_LINKS;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
import static org.hamcrest.core.IsNot.not;
import static org.junit.Assert.fail;
public class StreamTest {
#Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
#Test
public void test() throws Exception {
Path rootPath = Paths.get(temporaryFolder.getRoot().getPath());
createSelfloop();
Stream<Path> stream = provideStream(rootPath);
assertThat(stream.collect(Collectors.toList()), is(not(nullValue())));
}
private Stream<Path> provideStream(Path rootPath) throws IOException {
return Files.walk(rootPath, FOLLOW_LINKS).sorted();
}
private void createSelfloop() throws IOException {
String root = temporaryFolder.getRoot().getPath();
try {
Path symlink = Paths.get(root, "selfloop");
Path target = Paths.get(root);
Files.createSymbolicLink(symlink, target);
} catch (UnsupportedOperationException x) {
// Some file systems do not support symbolic links
fail();
}
}
}
You can make your own walking stream factory:
public class FileTree {
public static Stream<Path> walk(Path p) {
Stream<Path> s=Stream.of(p);
if(Files.isDirectory(p)) try {
DirectoryStream<Path> ds = Files.newDirectoryStream(p);
s=Stream.concat(s, StreamSupport.stream(ds.spliterator(), false)
.flatMap(FileTree::walk)
.onClose(()->{ try { ds.close(); } catch(IOException ex) {} }));
} catch(IOException ex) {}
return s;
}
// in case you don’t want to ignore exceprions silently
public static Stream<Path> walk(Path p, BiConsumer<Path,IOException> handler) {
Stream<Path> s=Stream.of(p);
if(Files.isDirectory(p)) try {
DirectoryStream<Path> ds = Files.newDirectoryStream(p);
s=Stream.concat(s, StreamSupport.stream(ds.spliterator(), false)
.flatMap(sub -> walk(sub, handler))
.onClose(()->{ try { ds.close(); }
catch(IOException ex) { handler.accept(p, ex); } }));
} catch(IOException ex) { handler.accept(p, ex); }
return s;
}
// and with depth limit
public static Stream<Path> walk(
Path p, int maxDepth, BiConsumer<Path,IOException> handler) {
Stream<Path> s=Stream.of(p);
if(maxDepth>0 && Files.isDirectory(p)) try {
DirectoryStream<Path> ds = Files.newDirectoryStream(p);
s=Stream.concat(s, StreamSupport.stream(ds.spliterator(), false)
.flatMap(sub -> walk(sub, maxDepth-1, handler))
.onClose(()->{ try { ds.close(); }
catch(IOException ex) { handler.accept(p, ex); } }));
} catch(IOException ex) { handler.accept(p, ex); }
return s;
}
}
I'm trying LiveAudioStreaming in java. For livestreming through JMF. I'm getting following error.
Access restriction: The type Player is not accessible due to restriction on required library C:\Program Files (x86)\Java\jre7\lib\ext\jmf.jar.
Please help. I used code from this link
Here is the code:
package com.simpleaudioplayer.simpleaudioplayer;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import javax.media.*; // import JMF classes
import javax.swing.JFileChooser;
public class Main {
private Player audioPlayer = null;
public SimpleAudioPlayer(URL url) {
try {
//MediaLocator ml=new MediaLocator(url);
audioPlayer = Manager.createPlayer(url);
} catch (Exception ex) {
System.out.println(ex);
}
}
public SimpleAudioPlayer(File file) throws MalformedURLException {
this(file.toURI().toURL());
}
public void play() {
audioPlayer.start(); // start playing
}
public void stop() {
audioPlayer.stop(); //stop playing
audioPlayer.close();
}
public static void main(String[] args) {
try {
// TODO code application logic here
JFileChooser fc = new JFileChooser();
fc.showOpenDialog(null);
File file = fc.getSelectedFile();
SimpleAduioPlayer sap = new SimpleAduioPlayer(file);
sap.play();
//sap.stop();
} catch (MalformedURLException ex) {
System.out.println(ex);
}
}
}
I was playing around with classLoaders in Java and noticed a strange thing. If a classLoader loads a class from a jar, this jar is locked indefinitely even if you unreference your classLoader.
In the below example, the jar contains a class called HelloWorld. What I do is try to load the class contained in the jar via a classLoader which adds the jar dynamically. If you set skip to true and do not call Class.forName, you can delete the jar but if you do not skip and even if you unreference the classLoader (classLoader = null), the jar cannot be deleted until the JVM exits.
Why is that?
PS: I am using java 6 and the code is very verbose for testing purposes
package loader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
public class TestClassLoader {
private URLClassLoader classLoader;
public TestClassLoader() throws MalformedURLException, IOException {
System.out.println("Copying jar");
if (copyJar()) {
System.out.println("Copying SUCCESS");
performFirstCheck();
} else {
System.out.println("Copying FAILED");
}
}
public static void main(String[] args) throws IOException {
System.out.println("Test started");
TestClassLoader testClassLoader = new TestClassLoader();
System.out.println("Bye!");
}
public void performFirstCheck() throws IOException {
System.out.println("Checking class HelloWorld does not exist");
if (!checkClassFound(TestClassLoader.class.getClassLoader(), false)) {
System.out.println("Deleting jar");
deleteJar();
System.out.println("First Check SUCCESS");
performSecondCheck();
} else {
System.out.println("First Check FAILED");
}
}
private void performSecondCheck() throws IOException {
System.out.println("Copying jar");
if (copyJar()) {
System.out.println("Copying SUCCESS");
createClassLoaderAndCheck();
} else {
System.out.println("Copying FAILED");
}
}
private void createClassLoaderAndCheck() throws MalformedURLException {
System.out.println("Creating classLoader");
createClassLoader();
System.out.println("Checking class HelloWorld exist");
if (checkClassFound(classLoader, true)) {
System.out.println("Second Check SUCCESS");
classLoader = null;
System.out.println("Deleting jar");
if (deleteJar()) {
System.out.println("Deleting SUCCESS");
} else {
System.out.println("Deleting FAILED");
}
} else {
System.out.println("Second Check FAILED");
}
}
public void createClassLoader() throws MalformedURLException {
URL[] urls = new URL[1];
File classFile = new File("C:\\Users\\Adel\\Desktop\\classes.jar");
urls[0] = classFile.toURI().toURL();
classLoader = new URLClassLoader(urls);
}
public boolean checkClassFound(ClassLoader classLoader, boolean skip) {
if (skip) {
System.out.println("Skiping class loading");
return true;
} else {
try {
Class.forName("HelloWorld", true, classLoader);
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
}
public URLClassLoader getClassLoader() {
return classLoader;
}
public boolean copyJar() throws IOException {
File sourceJar = new File("C:\\Users\\Adel\\Desktop\\Folder\\classes.jar");
File destJar = new File("C:\\Users\\Adel\\Desktop\\classes.jar");
if (destJar.exists()) {
return false;
} else {
FileInputStream finput = new FileInputStream(sourceJar);
FileOutputStream foutput = new FileOutputStream(destJar);
byte[] buf = new byte[1024];
int len;
while ((len = finput.read(buf)) > 0) {
foutput.write(buf, 0, len);
}
finput.close();
foutput.close();
return true;
}
}
public boolean deleteJar() {
File destJar = new File("C:\\Users\\Adel\\Desktop\\classes.jar");
return destJar.delete();
}
}
I have found an answer and a workaround.
Based on this article and this amazing related article, it is a bad habit to use Class.forName(className, true, classLoader) because it keeps the class cached in the memory indefinitely.
The solution was to use classLoader.loadClass(clasName) instead, then once finished, unreference the classLoader and call the garbage collector using:
classLoader = null;
System.gc();
Hope this helps others! :)
Background Info:
My project was a complexe one: we had a GWT server acting as a RMI client to another server. So to create instances, GWT needed to download the classes from the server and load them. Later, GWT would resend instance to the server to persist them in database using Hibernate. In order to support hot deployment, we opted for dynamically class loading where a user would upload a jar and notifies the server who would load the classes from it and present them as available to GWT server
In Java 7 URLClassLoader has a #close() method that fixes this.
I have implemented a simple plugin based application with Java. Main plugin class is derived from and abstract class called "Plugin". The application reads that class from JAR file and runs the plugin by creating an instance of the class. Standard procedure I guess :)
Everything forks fine until now. But the problem occurs when I include a library to my plugin, like MySQL Connector. The exception NoClassDefFoundError and ClassNotFoundException are thrown after execution. I am overcoming the problem by adding MySQL connector library to the main application but what is the point then? :)
I am not a Java expert so I am not sure of any alternative solutions like defining a classpath for libraries etc.
Here is my plugin loader:
http://pastebin.com/90rQ9NfJ
And here is my plugin base class:
http://pastebin.com/Juuicwkm
I am executing from a GUI:
private void jButtonAddActionPerformed(java.awt.event.ActionEvent evt) {
JFileChooser fileChooser = new JFileChooser();
fileChooser.setFileFilter(new FileNameExtensionFilter("JTask Plugin (*.JAR)", "JAR"));
if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION)
{
File pluginFile = fileChooser.getSelectedFile();
PluginLoader pluginLoader = new PluginLoader();
Plugin plugin = pluginLoader.loadPlugin(pluginFile);
if (plugin != null)
jPanelPlugins.add(new PluginControl(jPanelPlugins, plugin));
}
}
You should really include your source code as well.
How are you executing the class i.e. via command line or from a GUI? If from the command line, then the MySQLConnector libraries, along with any other dependent library must be included in the classpath (java -classpath). The top answer to this question should help you- Java: how to import a jar file from command line
if the case, your class is a Mysql Driver you have to exclude (at the time the class is calling) classes that are not available. In the Folder of your .jar file there is one with the name "integration" it contains "jboss" and "c3p0" which are not present at this time.
while (en.hasMoreElements()) {
JarEntry entry = new JarEntry(en.nextElement());
String name = entry.getName();
if (name.contains("/integration/")) {
continue;
} else {
if (!entry.isDirectory() && name.toLowerCase().endsWith(".class"))
{
classList.add(name.replace(".class", ""));
}
}
}
This should load a mysql.xxx.jar file.
Try This
dynamicload.java
package dynamicloading;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.DriverPropertyInfo;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Enumeration;
import java.util.Properties;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
/**
*
* #author Administrator
*/
class com_mysql_jdbc_Driver implements Driver {
private Driver driver;
com_mysql_jdbc_Driver(Driver cmjd) {
this.driver = cmjd;
}
#Override
public boolean acceptsURL(String aurlS) throws SQLException {
return this.driver.acceptsURL(aurlS);
}
#Override
public Connection connect(String aurlS, Properties pP) throws SQLException {
return this.driver.connect(aurlS, pP);
}
#Override
public int getMajorVersion() {
return this.driver.getMajorVersion();
}
#Override
public int getMinorVersion() {
return this.driver.getMinorVersion();
}
#Override
public DriverPropertyInfo[] getPropertyInfo(String aurlS, Properties pP) throws SQLException {
return this.driver.getPropertyInfo(aurlS, pP);
}
#Override
public boolean jdbcCompliant() {
return this.driver.jdbcCompliant();
}
}
public class DynMain {
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws Exception {
/* please set to your path*/
File file = new File("U:/mozsamples/mysql-connector-java-5.1.19-bin.jar");
Driver cmjdD;
String aktCS;
String urlS = "jdbc:mysql://localhost/db";
String userS = "must-be-set";
String passS = "must-be-set";
Connection con;
Statement stmt;
URLClassLoader clazzLoader = URLClassLoader.newInstance(new URL[]{file.toURI().toURL()});
JarFile jarFile = new JarFile(file);
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry element = entries.nextElement();
if (element.getName().endsWith(".class")) {
String name = element.getName();
if (name.contains("/integration/")) {
System.out.println( "ignored: " + name );
continue;
} else
{
try {
aktCS = element.getName().replaceAll(".class", "").replaceAll("/", ".");
clazzLoader.loadClass(aktCS);
if (name.contains("com/mysql/jdbc/Driver")) {
cmjdD = (Driver)Class.forName(aktCS, true, clazzLoader).newInstance();
try {
DriverManager.registerDriver(new com_mysql_jdbc_Driver(cmjdD));
System.out.println( "register Class: " + aktCS );
} catch (SQLException e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
try {
con = DriverManager.getConnection(urlS,userS,passS);
stmt = con.createStatement();
/*ResultSet rs = stmt.executeQuery("select * from idcart where ID=255"); */
stmt.close();
} catch (SQLException esql) {
esql.printStackTrace();
}
int j=0 ;
System.out.println("loaded Driver----------------------------------");
for( Enumeration en = DriverManager.getDrivers() ; en.hasMoreElements() ; j++)
System.out.println( en.nextElement().getClass().getName() );
if (j==0) { System.out.println("Driverlist empty"); }
System.out.println("-----------------------------------------------");
}
}
Output:
register Class: com.mysql.jdbc.Driver
ignored: com/mysql/jdbc/integration/c3p0/MysqlConnectionTester.class
ignored: com/mysql/jdbc/integration/jboss/ExtendedMysqlExceptionSorter.class
ignored: com/mysql/jdbc/integration/jboss/MysqlValidConnectionChecker.class
loaded Driver----------------------------------
sun.jdbc.odbc.JdbcOdbcDriver
dynamicloading.com_mysql_jdbc_Driver
-----------------------------------------------
OK ???