I am trying to create a fat-jar programmatically. So far, I managed to create a Jar file with my code inside. The problem is that, if I run this, I receive an exception saying Cannot load user class: org.company.bla.bla.
Here is my code
private static void createJar() throws IOException {
Manifest manifest = new Manifest();
manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
JarOutputStream target = new JarOutputStream(new FileOutputStream("events.jar"), manifest);
Path root = Paths.get(".").normalize().toAbsolutePath();
System.out.println(root.toString());
Files.walk(root).forEach(f -> add(f.toFile(), target));
target.close();
}
private static void add(File source, JarOutputStream target)
{
BufferedInputStream in = null;
try {
if (source.isDirectory()) {
String name = source.getPath().replace("\\", "/");
if (!name.isEmpty()) {
if (!name.endsWith("/"))
name += "/";
JarEntry entry = new JarEntry(name);
entry.setTime(source.lastModified());
target.putNextEntry(entry);
target.closeEntry();
}
for (File nestedFile: source.listFiles())
add(nestedFile, target);
return;
}
JarEntry entry = new JarEntry(source.getPath().replace("\\", "/"));
entry.setTime(source.lastModified());
target.putNextEntry(entry);
in = new BufferedInputStream(new FileInputStream(source));
byte[] buffer = new byte[1024];
while (true) {
int count = in.read(buffer);
if (count == -1)
break;
target.write(buffer, 0, count);
}
target.closeEntry();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
How can I also add the dependencies to this Jar? Or where is the path where the dependencies are so I can include them?
Related
How can I add a executable into assets and run it in Android and show the output?
I've a executable that will work. I assume there will need to be some chmod in the code.
Thank you.
here is my answer
put copyAssets() to your mainactivity.
someone's code:
private void copyAssets() {
AssetManager assetManager = getAssets();
String[] files = null;
try {
files = assetManager.list("");
} catch (IOException e) {
Log.e("tag", "Failed to get asset file list.", e);
}
for(String filename : files) {
InputStream in = null;
OutputStream out = null;
try {
in = assetManager.open(filename);
File outFile = new File(getFilesDir(), filename);
out = new FileOutputStream(outFile);
copyFile(in, out);
} catch(IOException e) {
Log.e("tag", "Failed to copy asset file: " + filename, e);
}
finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
// NOOP
}
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
// NOOP
}
}
}
}
}
private void copyFile(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
}
also here is code to run command
public String runcmd(String cmd){
try {
Process p = Runtime.getRuntime().exec(cmd);
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
int read;
char[] buffer = new char[4096];
StringBuffer out = new StringBuffer();
while ((read = in.read(buffer)) > 0) {
out.append(buffer, 0, read);
}
in.close();
p.waitFor();
return out.substring(0);
} catch (IOException e) {
throw new RuntimeException(e);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
you may need to change it to
String prog= "programname";
String[] env= { "parameter 1","p2"};
File dir= new File(getFilesDir().getAbsolutePath());
Process p = Runtime.getRuntime().exec(prog,env,dir);
to ensure proper parameter handling
also add this to your main code
to check proper copying of files
String s;
File file4 = new File(getFilesDir().getAbsolutePath()+"/executable");
file4.setExecutable(true);
s+=file4.getName();
s+=file4.exists();
s+=file4.canExecute();
s+=file4.length();
//output s however you want it
should write: filename, true, true, correct filelength.
Place your executable in raw folder, then run it by using ProcessBuilder or Runtime.exec like they do here http://gimite.net/en/index.php?Run%20native%20executable%20in%20Android%20App
I am trying to programmatically create a runnable jar file. I am using the following code:
The add method:
private static void add(File source, JarOutputStream target) throws IOException
{
BufferedInputStream in = null;
try
{
if (source.isDirectory())
{
String name = source.getPath().replace("\\", File.separator);
if (!name.isEmpty())
{
if (!name.endsWith(File.separator))
name += File.separator;
JarEntry entry = new JarEntry(name);
entry.setTime(source.lastModified());
target.putNextEntry(entry);
//target.closeEntry();
}
for (File nestedFile: source.listFiles())
add(nestedFile, target);
return;
}
JarEntry entry = new JarEntry(source.getPath().replace("\\", "/"));
entry.setTime(source.lastModified());
target.putNextEntry(entry);
in = new BufferedInputStream(new FileInputStream(source));
byte[] buffer = new byte[1024];
while (true)
{
int count = in.read(buffer);
if (count == -1)
break;
target.write(buffer, 0, count);
}
target.closeEntry();
}
finally
{
if (in != null)
in.close();
}
}
Its implementation:
try {
File[] files = new File("tmp").listFiles();
for (File file : files) {
System.out.println("Archiving: "+file.getName());
add(file, target);
}
} catch (IOException e) {
e.printStackTrace();
}
try {
target.close();
} catch (IOException e) {
e.printStackTrace();
}
I am trying to add all of the contents of the tmp directory to my jar, but I do not want to prefix all of the namespaces with tmp.. I tried using this code to iterate through the the files in tmp and add them but I keep getting errors saying "no such file or directory". I am pretty sure that's because it is looking outside the tmp directory. However, when I change it to add(new File("tmp"+File.separator+file.getName()), target); I end up with "tmp" in my namespaces (because I started with the tmp/ directory). Is there a way around this?
Here is an example:
I have a jar file with the Main-Class attribute com.name.proj.ProjDriver
When I decompress it into the tmp folder I end up with the file in tmp/com/name/proj/ProjDriver.class. I then recompress my jar using the manifest object from the old jar still specifying the main class as com.name.proj.ProjDriver but now it is actually tmp.com.name.proj.ProjDriver. How can I avoid having tmp. as a prefix for all the namespaces?
Replace your code with this:
private static void add(File source, JarOutputStream target) throws IOException
{
BufferedInputStream in = null;
try
{
if (source.isDirectory())
{
String name = source.getPath().replace("\\", File.separator);
if (!name.isEmpty())
{
if (!name.endsWith(File.separator))
name += File.separator;
JarEntry entry = new JarEntry(name);
entry.setTime(source.lastModified());
target.putNextEntry(entry);
//target.closeEntry();
}
for (File nestedFile: source.listFiles())
try{add(nestedFile, target);}catch(IOException e){System.out.println(e);}
return;
}
JarEntry entry = new JarEntry(source.getPath().replace("tmp\\","").replace("\\", "/"));
entry.setTime(source.lastModified());
target.putNextEntry(entry);
in = new BufferedInputStream(new FileInputStream(source));
byte[] buffer = new byte[1024];
while (true)
{
int count = in.read(buffer);
if (count == -1)
break;
target.write(buffer, 0, count);
}
target.closeEntry();
}
finally
{
if (in != null)
in.close();
}
}
I have varied this row:
JarEntry entry = new JarEntry(source.getPath().replace("tmp\\","").replace("\\", "/"));
I'm using the code below to try and move my database file to my sdcard. I have no problems except that I get a redline under sd. Any ideas?
File data = Environment.getDataDirectory();
if (sd.canWrite()) {
String currentDBPath = "\\data\\application.package\\databases\\name";
String backupDBPath = "name";
File currentDB = new File(data, currentDBPath);
File backupDB = new File(sd, backupDBPath);
if (currentDB.exists()) {
FileChannel src;
try {
src = new FileInputStream(currentDB).getChannel();
FileChannel dst = new FileOutputStream(backupDB).getChannel();
try {
dst.transferFrom(src, 0, src.size());
src.close();
dst.close();
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
You can only use a variable if you create an instance of it:
Put this before your code:
File sd = Environment.getExternalStorageDirectory();
if you are using SQLite database try this:
public class _DBHelper extends SQLiteOpenHelper {
public boolean backUp() throws Exception
{
InputStream input = null;
OutputStream output = null;
try {
SQLiteDatabase db = this.getReadableDatabase();
String strSource = db.getPath();
String strDest = Utilities.getAppDocumentsFolder(_context) + "/"
+ DATABASE_NAME;
File fileDest = new File(strDest);
if (fileDest.exists())
{
fileDest.delete();
}
input = new FileInputStream(strSource);
output = new FileOutputStream(strDest);
byte[] buffer = new byte[1024];
int length;
while ((length = input.read(buffer)) > 0) {
output.write(buffer, 0, length);
}
} catch (Exception e) {
throw e;
} finally
{
if (output != null)
{
output.flush();
output.close();
}
if (input != null)
{
input.close();
}
}
return true;
}
}
I'm using the code below to try and move my database file to my sdcard. I have no problems except that I get a redline under sd. Any ideas?
File data = Environment.getDataDirectory();
if (sd.canWrite()) {
String currentDBPath = "\\data\\application.package\\databases\\name";
String backupDBPath = "name";
File currentDB = new File(data, currentDBPath);
File backupDB = new File(sd, backupDBPath);
if (currentDB.exists()) {
FileChannel src;
try {
src = new FileInputStream(currentDB).getChannel();
FileChannel dst = new FileOutputStream(backupDB).getChannel();
try {
dst.transferFrom(src, 0, src.size());
src.close();
dst.close();
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
You can only use a variable if you create an instance of it:
Put this before your code:
File sd = Environment.getExternalStorageDirectory();
if you are using SQLite database try this:
public class _DBHelper extends SQLiteOpenHelper {
public boolean backUp() throws Exception
{
InputStream input = null;
OutputStream output = null;
try {
SQLiteDatabase db = this.getReadableDatabase();
String strSource = db.getPath();
String strDest = Utilities.getAppDocumentsFolder(_context) + "/"
+ DATABASE_NAME;
File fileDest = new File(strDest);
if (fileDest.exists())
{
fileDest.delete();
}
input = new FileInputStream(strSource);
output = new FileOutputStream(strDest);
byte[] buffer = new byte[1024];
int length;
while ((length = input.read(buffer)) > 0) {
output.write(buffer, 0, length);
}
} catch (Exception e) {
throw e;
} finally
{
if (output != null)
{
output.flush();
output.close();
}
if (input != null)
{
input.close();
}
}
return true;
}
}
I have a set of files in my Maven resource folder:
+ src
+ main
+ resources
+ mydir
+ myfile1.txt
+ myfile2.txt
How can I iterate mydir? Not only in Eclipse, but when running JUnit tests from the command line, and from a dependent jar.
File mydir = new File("mydir");
for (File f : dir.listFiles()) {
dosomething...
}
Thanks for a hint!
Nutshell, roughly:
URL pathUrl = clazz.getClassLoader().getResource("mydir/");
if ((pathURL != null) && pathUrl.getProtocol().equals("file")) {
return new File(pathUrl.toURI()).list();
}
Tested; Groovy:
def resourcesInDir(String dir) {
def ret = []
pathUrl = this.class.getClassLoader().getResource(dir)
if ((pathUrl != null) && pathUrl.getProtocol().equals("file")) {
new File(pathUrl.toURI()).list().each {
ret << "${dir}/${it}"
}
}
ret
}
files = resourcesInDir("tmp/")
files.each {
s = this.class.getResourceAsStream(it)
println s.text
}
In the end, this is what I came up with to handle accessing files within referenced jars:
public class ResourceHelper {
public static File getFile(String resourceOrFile)
throws FileNotFoundException {
try {
// jar:file:/home/.../blue.jar!/path/to/file.xml
URI uri = getURL(resourceOrFile).toURI();
String uriStr = uri.toString();
if (uriStr.startsWith("jar")) {
if (uriStr.endsWith("/")) {
throw new UnsupportedOperationException(
"cannot unjar directories, only files");
}
String jarPath = uriStr.substring(4, uriStr.indexOf("!"))
.replace("file:", "");
String filePath = uriStr.substring(uriStr.indexOf("!") + 2);
JarFile jarFile = new JarFile(jarPath);
assert (jarFile.size() > 0) : "no jarFile at " + jarPath;
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry jarEntry = entries.nextElement();
if (jarEntry.toString().equals(filePath)) {
InputStream input = jarFile.getInputStream(jarEntry);
assert (input != null) : "empty is for " + jarEntry;
return tmpFileFromStream(input, filePath);
}
}
assert (false) : "file" + filePath + " not found in " + jarPath;
return null;
} else {
return new File(uri);
}
} catch (URISyntaxException e) {
throw new FileNotFoundException(resourceOrFile);
} catch (IOException e) {
throw new FileNotFoundException(resourceOrFile);
}
}
private static File tmpFileFromStream(InputStream is, String filePath)
throws IOException {
String fileName = filePath.substring(filePath.lastIndexOf("/") + 1,
filePath.lastIndexOf("."));
assert (fileName != null) : "filename cannot be null for " + filePath;
String extension = filePath.substring(filePath.lastIndexOf("."));
assert (extension != null) : "extension cannot be null for " + filePath;
File tmpFile = File.createTempFile(fileName, extension);
// tempFile.deleteOnExit();
assert (tmpFile.exists()) : "could not create tempfile";
OutputStream out = new FileOutputStream(tmpFile);
int read = 0;
byte[] bytes = new byte[1024];
while ((read = is.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
is.close();
out.flush();
out.close();
assert (tmpFile.length() > 0) : "file empty "
+ tmpFile.getAbsolutePath();
return tmpFile;
}
public static File getTempFile(String resourceOrFile) throws IOException {
InputStream input = getInputStream(resourceOrFile);
File tempFile = IOUtils.createTempDir();
tempFile.deleteOnExit();
FileOutputStream output = new FileOutputStream(tempFile);
byte[] buffer = new byte[4096];
int bytesRead = input.read(buffer);
while (bytesRead != -1) {
output.write(buffer, 0, bytesRead);
bytesRead = input.read(buffer);
}
output.close();
input.close();
return tempFile;
}
public static InputStream getInputStream(String resourceOrFile)
throws FileNotFoundException {
try {
return getURL(resourceOrFile).openStream();
} catch (Exception e) {
throw new FileNotFoundException(resourceOrFile);
}
}
public static URL getURL(String resourceOrFile)
throws FileNotFoundException {
File file = new File(resourceOrFile);
// System.out.println("checking file ");
// is file
if (file.exists()) {
// System.out.println("file exists");
try {
return file.toURI().toURL();
} catch (MalformedURLException e) {
throw new FileNotFoundException(resourceOrFile);
}
}
// is resource
if (!file.exists()) {
// System.out.println("file resource");
URL url = Thread.class.getResource(resourceOrFile);
if (url != null) {
return url;
}
url = Thread.class.getResource("/" + resourceOrFile);
if (url != null) {
return url;
}
}
throw new FileNotFoundException(resourceOrFile);
}
}