Permalink
Browse files

Add support for installation of various module types by intent

  • Loading branch information...
1 parent f060741 commit a4e33fcecb4a10fe5eaad9e239ce1e055a55d92a @paddybyers committed Nov 25, 2011
View
1 app/.classpath
@@ -3,6 +3,7 @@
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+ <classpathentry kind="lib" path="contrib/jtar-1.0.4.jar"/>
<classpathentry kind="src" path="libnode_src"/>
<classpathentry kind="output" path="bin"/>
</classpath>
View
9 app/.project
@@ -2,6 +2,8 @@
<projectDescription>
<name>app</name>
<comment></comment>
+ <projects>
+ </projects>
<buildSpec>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
@@ -28,4 +30,11 @@
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
+ <linkedResources>
+ <link>
+ <name>libnode_src</name>
+ <type>2</type>
+ <locationURI>_android_libnode_9e68607/src</locationURI>
+ </link>
+ </linkedResources>
</projectDescription>
View
6 app/AndroidManifest.xml
@@ -30,6 +30,12 @@
<intent-filter>
<action android:name="org.meshpoint.anode.STOPALL" />
</intent-filter>
+ <intent-filter>
+ <action android:name="org.meshpoint.anode.INSTALL" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="org.meshpoint.anode.UNINSTALL" />
+ </intent-filter>
</receiver>
<service android:exported="true" android:enabled="true" android:name=".AnodeService" android:description="@string/anode_service_description" android:label="@string/anode_service">
<!-- disabled until we work out how to get a valid context for a Service triggered by these
View
BIN app/contrib/jtar-1.0.4.jar
Binary file not shown.
View
64 app/src/org/meshpoint/anode/AnodeReceiver.java
@@ -1,7 +1,6 @@
package org.meshpoint.anode;
import org.meshpoint.anode.Runtime.IllegalStateException;
-import org.meshpoint.anode.Runtime.InitialisationException;
import org.meshpoint.anode.Runtime.NodeException;
import android.content.BroadcastReceiver;
@@ -15,9 +14,13 @@
public static final String ACTION_START = "org.meshpoint.anode.START";
public static final String ACTION_STOP = "org.meshpoint.anode.STOP";
public static final String ACTION_STOPALL = "org.meshpoint.anode.STOPALL";
+ public static final String ACTION_INSTALL = "org.meshpoint.anode.INSTALL";
+ public static final String ACTION_UNINSTALL = "org.meshpoint.anode.UNINSTALL";
public static final String CMD = "cmdline";
public static final String INST = "instance";
public static final String OPTS = "options";
+ public static final String MODULE = "module";
+ public static final String PATH = "path";
public AnodeReceiver() {
super();
@@ -26,50 +29,45 @@ public AnodeReceiver() {
@Override
public void onReceive(Context ctx, Intent intent) {
/* get the system options */
- String options = intent.getStringExtra(OPTS);
- String[] opts = options == null ? null : options.split("\\s");
-
- try {
- Runtime.initRuntime(ctx, opts);
- } catch (InitialisationException e) {
- Log.v(TAG, "AnodeReceiver.onReceive::getRuntime: exception: " + e + "; cause: " + e.getCause());
- return;
- }
-
- /* unconditionally do any stop action */
String action = intent.getAction();
if(ACTION_STOPALL.equals(action)) {
- for(Isolate isolate : AnodeService.getAll())
- stopInstance(isolate);
+ if(Runtime.isInitialised()) {
+ for(Isolate isolate : AnodeService.getAll())
+ stopInstance(isolate);
+ }
return;
}
if(ACTION_STOP.equals(action)) {
- String instance = intent.getStringExtra(INST);
- if(instance == null) {
- instance = AnodeService.soleInstance();
+ if(Runtime.isInitialised()) {
+ String instance = intent.getStringExtra(INST);
if(instance == null) {
- Log.v(TAG, "AnodeReceiver.onReceive::stop: no instance specified");
+ instance = AnodeService.soleInstance();
+ if(instance == null) {
+ Log.v(TAG, "AnodeReceiver.onReceive::stop: no instance specified");
+ return;
+ }
+ }
+ Isolate isolate = AnodeService.getInstance(instance);
+ if(isolate == null) {
+ Log.v(TAG, "AnodeReceiver.onReceive::stop: instance " + instance + " not found");
return;
}
+ stopInstance(isolate);
}
- Isolate isolate = AnodeService.getInstance(instance);
- if(isolate == null) {
- Log.v(TAG, "AnodeReceiver.onReceive::stop: instance " + instance + " not found");
- return;
- }
- stopInstance(isolate);
return;
}
-
- /* get the launch commandline */
- String args = intent.getStringExtra(CMD);
- /* if no cmdline was sent, then launch the activity for interactive behaviour */
- if(args == null || args.isEmpty()) {
- intent.setClassName(ctx, AnodeActivity.class.getName());
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- ctx.startActivity(intent);
- return;
+ if(ACTION_START.equals(action)) {
+ /* get the launch commandline */
+ String args = intent.getStringExtra(CMD);
+
+ /* if no cmdline was sent, then launch the activity for interactive behaviour */
+ if(args == null || args.isEmpty()) {
+ intent.setClassName(ctx, AnodeActivity.class.getName());
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ ctx.startActivity(intent);
+ return;
+ }
}
/* otherwise, start service */
View
118 app/src/org/meshpoint/anode/AnodeService.java
@@ -1,5 +1,9 @@
package org.meshpoint.anode;
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
import java.util.Collection;
import java.util.HashMap;
@@ -8,6 +12,7 @@
import org.meshpoint.anode.Runtime.NodeException;
import org.meshpoint.anode.Runtime.StateListener;
import org.meshpoint.anode.util.ArgProcessor;
+import org.meshpoint.anode.util.ModuleUtils;
import android.app.IntentService;
import android.content.Intent;
@@ -53,6 +58,9 @@ static synchronized String soleInstance() {
**********************/
public AnodeService() {
super(":anode.AnodeService");
+ (new File(Constants.APP_DIR)).mkdirs();
+ (new File(Constants.MODULE_DIR)).mkdirs();
+ (new File(Constants.RESOURCE_DIR)).mkdirs();
}
private void initRuntime(String[] opts) {
@@ -65,17 +73,27 @@ private void initRuntime(String[] opts) {
@Override
protected void onHandleIntent(Intent intent) {
- /* get system options */
- String options = intent.getStringExtra(AnodeReceiver.OPTS);
- String[] opts = options == null ? null : options.split("\\s");
- initRuntime(opts);
-
/* we should not get a stop action; should have been intercepted by the receiver */
String action = intent.getAction();
if(AnodeReceiver.ACTION_STOP.equals(action)) {
Log.v(TAG, "AnodeService.onHandleIntent::stop: internal error");
return;
}
+
+ if(AnodeReceiver.ACTION_START.equals(action)) {
+ /* get system options before handling this invocation */
+ String options = intent.getStringExtra(AnodeReceiver.OPTS);
+ String[] opts = options == null ? null : options.split("\\s");
+ initRuntime(opts);
+ handleStart(intent);
+ } else if(AnodeReceiver.ACTION_INSTALL.equals(action)) {
+ handleInstall(intent);
+ } else if(AnodeReceiver.ACTION_UNINSTALL.equals(action)) {
+ handleUninstall(intent);
+ }
+ }
+
+ private void handleStart(Intent intent) {
/* get the launch commandline */
String args = intent.getStringExtra(AnodeReceiver.CMD);
@@ -89,7 +107,7 @@ protected void onHandleIntent(Intent intent) {
/* create a new instance based on the supplied args */
ArgProcessor argProcessor = new ArgProcessor(intent.getExtras(), args);
- String[] processedArgs = argProcessor.process();
+ String[] processedArgs = argProcessor.processArray();
/* launch directly */
try {
@@ -120,4 +138,92 @@ public void stateChanged(final int state) {
}
}
+ private void handleInstall(Intent intent) {
+
+ /* get the specified arguments */
+ String module = intent.getStringExtra(AnodeReceiver.MODULE);
+ String path = intent.getStringExtra(AnodeReceiver.PATH);
+ File moduleResource;
+ boolean remove_tmp_resource = false;
+
+ /* if no path was specified, it is an error */
+ if(path == null || path.isEmpty()) {
+ Log.v(TAG, "AnodeService.onHandleInstall: no path specified");
+ return;
+ }
+
+ /* resolve expected module type from path */
+ int type = ModuleUtils.guessModuleType(path);
+ String extn = ModuleUtils.getExtensionForType(type);
+
+ /* guess the module name, if not already specified */
+ if(module == null || module.isEmpty()) {
+ int pathEnd = path.lastIndexOf('/') + 1;
+ module = path.substring(pathEnd, path.length()-extn.length());
+ }
+
+ /* download module if http or https */
+ if(path.startsWith("http://") || path.startsWith("https://")) {
+ String filename = ModuleUtils.getResourceUriHash(path);
+ try {
+ moduleResource = ModuleUtils.getResource(new URI(path), filename);
+ remove_tmp_resource = true;
+ } catch(IOException e) {
+ Log.v(TAG, "handleInstall: aborting (unable to download resource); exception: " + e + "; resource = " + path);
+ return;
+ } catch(URISyntaxException e) {
+ Log.v(TAG, "handleInstall: aborting (invalid URI specified for resource); exception: " + e + "; resource = " + path);
+ return;
+ }
+ } else {
+ moduleResource = new File(path);
+ }
+
+ /* unpack if necessary */
+ if(type >= ModuleUtils.TYPE_UNPACK) {
+ try {
+ moduleResource = ModuleUtils.unpack(moduleResource, module, type);
+ remove_tmp_resource = true;
+ } catch(IOException e) {
+ Log.v(TAG, "handleInstall: aborting (unable to unpack resource); exception: " + e + "; resource = " + path);
+ return;
+ }
+ }
+
+ /* copy processed package to modules dir */
+ File installLocation = ModuleUtils.getModuleFile(module, type);
+ if(installLocation.exists()) {
+ if(!ModuleUtils.deleteFile(installLocation)) {
+ Log.v(TAG, "handleInstall: aborting (unable to delete old module version); resource = " + path + ", destination = " + installLocation.toString());
+ return;
+ }
+ }
+ if(ModuleUtils.copyFile(moduleResource, installLocation)) {
+ if(remove_tmp_resource)
+ ModuleUtils.deleteFile(moduleResource);
+ Log.v(TAG, "handleInstall: success; resource = " + path + ", destination = " + installLocation.toString());
+ return;
+ }
+ Log.v(TAG, "handleInstall: aborting (unable to copy resource); resource = " + path + ", destination = " + installLocation.toString());
+ }
+
+ private void handleUninstall(Intent intent) {
+ String module = intent.getStringExtra(AnodeReceiver.MODULE);
+
+ /* if no module was specified, it is an error */
+ if(module == null || module.isEmpty()) {
+ Log.v(TAG, "AnodeService.onHandleUninstall: no module specified");
+ return;
+ }
+
+ File moduleLocation = ModuleUtils.getModuleFile(module, ModuleUtils.TYPE_UNKNOWN);
+ if(!moduleLocation.exists()) {
+ Log.v(TAG, "AnodeService.onHandleUninstall: specified module does not exist: " + module + "; looking for " + moduleLocation.toString());
+ return;
+ }
+ if(!moduleLocation.delete()) {
+ Log.v(TAG, "AnodeService.onHandleUninstall: unable to delete: " + module + "; attempting to delete " + moduleLocation.toString());
+ return;
+ }
+ }
}
View
8 app/src/org/meshpoint/anode/Constants.java
@@ -0,0 +1,8 @@
+package org.meshpoint.anode;
+
+public interface Constants {
+
+ public static final String RESOURCE_DIR = "/data/data/org.meshpoint.anode/uriCache";
+ public static final String MODULE_DIR = "/data/data/org.meshpoint.anode/node_modules";
+ public static final String APP_DIR = "/data/data/org.meshpoint.anode/app";
+}
View
78 app/src/org/meshpoint/anode/util/ArgProcessor.java
@@ -1,20 +1,13 @@
package org.meshpoint.anode.util;
-import java.io.File;
-import java.io.FileOutputStream;
import java.io.IOException;
-import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
-import java.security.MessageDigest;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
-import org.apache.http.HttpEntity;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.impl.client.DefaultHttpClient;
+import org.meshpoint.anode.Constants;
import android.os.Bundle;
import android.util.Log;
@@ -47,31 +40,29 @@
private static String TAG = "anode::ArgsProcessor";
private static final String GET_PREFIX = "get:";
- private static final String RESOURCE_DIR = "/data/data/org.meshpoint.anode/uriCache";
- private static final int HASH_LEN = 20;
private Bundle extras;
- private String cmdline;
+ private String text;
private Map<String, URI> uriMap;
private Map<String, String> filenameMap;
/**
* Constructs an instance of ArgProcessor
* @param extras an optional bundle containing the mapping parameters
- * @param cmdline the commandline to process
+ * @param text the string to process
*/
- public ArgProcessor(Bundle extras, String cmdline) {
+ public ArgProcessor(Bundle extras, String text) {
this.extras = extras;
- this.cmdline = cmdline;
+ this.text = text;
uriMap = new HashMap<String, URI>();
filenameMap = new HashMap<String, String>();
}
/**
- * Process the commandline
- * @return the processed commandline, with
+ * Process the text string
+ * @return the processed string, with downloaded resource names substituted
*/
- public String[] process() {
+ public String processString() {
if(extras != null) {
/* extract list of args to get */
try {
@@ -81,7 +72,7 @@ public ArgProcessor(Bundle extras, String cmdline) {
String rawUri = extras.getString(key);
String rawKey = key.substring(GET_PREFIX.length());
URI uri = new URI(rawUri);
- String filename = getResourceUriHash(rawUri);
+ String filename = ModuleUtils.getResourceUriHash(rawUri);
uriMap.put(rawKey, uri);
filenameMap.put(rawKey, filename);
}
@@ -91,63 +82,28 @@ public ArgProcessor(Bundle extras, String cmdline) {
return null;
}
- /* get target directory for downloaded assets */
- File resourceDir = new File(RESOURCE_DIR);
- resourceDir.mkdirs();
-
/* download each asset */
for(String key : uriMap.keySet()) {
try {
- HttpClient http = new DefaultHttpClient();
- HttpGet request = new HttpGet();
- request.setURI(uriMap.get(key));
- HttpEntity entity = http.execute(request).getEntity();
- InputStream in = entity.getContent();
- FileOutputStream out = new FileOutputStream(new File(resourceDir, filenameMap.get(key)));
- byte[] buf = new byte[1024];
- int read;
- while((read = in.read(buf)) != -1) {
- out.write(buf, 0, read);
- }
- in.close();
- out.flush();
- out.close();
+ ModuleUtils.getResource(uriMap.get(key), filenameMap.get(key));
} catch(IOException e) {
Log.v(TAG, "process exception: aborting; exception: " + e + "; resource = " + uriMap.get(key).toString());
return null;
}
}
/* process the commandline */
- String resourcePath = resourceDir.getAbsolutePath() + '/';
for(String key : filenameMap.keySet()) {
- cmdline = cmdline.replace("%" + key, resourcePath + filenameMap.get(key));
+ text = text.replace("%" + key, Constants.RESOURCE_DIR + '/' + filenameMap.get(key));
}
}
-
- /* split the commandline at whitespace */
- return cmdline.split("\\s");
- }
-
- private String getResourceUriHash(String id) {
- try {
- MessageDigest sha = MessageDigest.getInstance("SHA-1");
- sha.update(id.getBytes("iso-8859-1"));
- return digest2Hex(sha.digest());
- }
- catch(Exception e) {
- return null;
- }
+ return text;
}
- private String digest2Hex(byte[] digest) {
- StringBuilder hash = new StringBuilder(HASH_LEN * 2);
- final String hexChars = "0123456789abcdef";
- for(int i = 0; i < HASH_LEN; i++) {
- hash.append(hexChars.charAt((digest[i] & 0xF0) >> 4))
- .append(hexChars.charAt((digest[i] & 0x0F)));
- }
- return hash.toString();
+ public String[] processArray() {
+ /* split the commandline at whitespace */
+ processString();
+ return text.split("\\s");
}
-
+
}
View
185 app/src/org/meshpoint/anode/util/ModuleUtils.java
@@ -0,0 +1,185 @@
+package org.meshpoint.anode.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.security.MessageDigest;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.meshpoint.anode.Constants;
+
+import android.util.Log;
+
+public class ModuleUtils {
+ private static String TAG = "anode::ModuleUtils";
+
+ /* module types */
+ public static final int TYPE_UNKNOWN = -1;
+ public static final int TYPE_JS = 0;
+ public static final int TYPE_NODE = 1;
+ public static final int TYPE_UNPACK = 2;
+ public static final int TYPE_ZIP = TYPE_UNPACK;
+ public static final int TYPE_TARBALL = 3;
+ private static final int TYPE_MAX = 4;
+
+ private static final String[] extensions = new String[]{".js", ".node", ".zip", ".tar.gz"};
+
+ /* for hashing names for tmp files */
+ private static final int HASH_LEN = 20;
+
+ /* cache dir for tmp and downloaded resources */
+ private static File resourceDir = new File(Constants.RESOURCE_DIR);
+ private static File moduleDir = new File(Constants.MODULE_DIR);
+
+ public static int guessModuleType(String filename) {
+ for(int i = 0; i < TYPE_MAX; i++) {
+ if(filename.endsWith(extensions[i]))
+ return i;
+ }
+ return TYPE_UNKNOWN;
+ }
+
+ public static String getExtensionForType(int type) {
+ return extensions[type];
+ }
+
+ public static File getModuleFile(String module, int type) {
+ if(type < TYPE_UNPACK)
+ module += extensions[type];
+ return new File(moduleDir, module);
+ }
+
+ public static boolean deleteModule(String module, int type) {
+ File installLocation = null;
+ if(type == TYPE_UNKNOWN) {
+ if(!(installLocation = new File(moduleDir, module)).exists()) {
+ for(int i = 0; i < TYPE_UNPACK; i++) {
+ if((installLocation = new File(moduleDir, module)).exists())
+ break;
+ }
+ }
+ } else {
+ installLocation = getModuleFile(module, type);
+ }
+ return (installLocation != null && installLocation.exists()) ? deleteFile(installLocation) : false;
+ }
+
+ public static boolean deleteFile(File location) {
+ boolean result = true;
+ if(location.exists()) {
+ if(location.isDirectory()) {
+ result = deleteDir(location);
+ } else {
+ result = location.delete();
+ }
+ }
+ return result;
+ }
+
+ private static boolean deleteDir(File location) {
+ for (String child : location.list()) {
+ boolean result = deleteFile(new File(location, child));
+ if (!result) {
+ return false;
+ }
+ }
+ return location.delete();
+ }
+
+ public static boolean copyFile(File src, File dest) {
+ boolean result = true;
+ if(src.isDirectory()) {
+ result = copyDir(src, dest);
+ } else {
+ try {
+ int count;
+ byte[] buf = new byte[1024];
+ FileInputStream fis = new FileInputStream(src);
+ FileOutputStream fos = new FileOutputStream(dest);
+ while ((count = fis.read(buf, 0, 1024)) != -1)
+ fos.write(buf, 0, count);
+ } catch(IOException e) {
+ Log.v(TAG, "moveFile exception: aborting; exception: " + e + "; src = " + src.toString() + "; dest = " + dest.toString());
+ return false;
+ }
+ }
+ return result;
+ }
+
+ private static boolean copyDir(File src, File dest) {
+ dest.mkdir();
+ for (String child : src.list()) {
+ boolean result = copyFile(new File(src, child), new File(dest, child));
+ if (!result) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static File unpack(File moduleResource, String moduleName, int type) throws IOException {
+ /* create temp dir to unpack; assume no hash collision */
+ String tmpDirName = moduleName + extensions[type] + "-tmp";
+ File result = new File(resourceDir, tmpDirName);
+ if(!result.isDirectory() && !result.mkdir())
+ throw new IOException("Unable to create tmp directory to unpack: " + result.toString());
+
+ if(type == TYPE_ZIP) {
+ (new ZipExtractor(moduleResource, result)).extract();
+ } else if(type == TYPE_TARBALL) {
+ (new TarExtractor(moduleResource, result)).extract();
+ } else {
+ Log.v(TAG, "ModuleUtils.unpack(): aborting (internal error)");
+ result = null;
+ }
+ return result;
+ }
+
+ public static File getResource(URI httpUri, String filename) throws IOException {
+ /* download */
+ HttpClient http = new DefaultHttpClient();
+ HttpGet request = new HttpGet();
+ request.setURI(httpUri);
+ HttpEntity entity = http.execute(request).getEntity();
+ InputStream in = entity.getContent();
+ File destination = new File(resourceDir, filename);
+ FileOutputStream out = new FileOutputStream(destination);
+ byte[] buf = new byte[1024];
+ int read;
+ while((read = in.read(buf)) != -1) {
+ out.write(buf, 0, read);
+ }
+ in.close();
+ out.flush();
+ out.close();
+ return destination;
+ }
+
+ public static String getResourceUriHash(String id) {
+ try {
+ MessageDigest sha = MessageDigest.getInstance("SHA-1");
+ sha.update(id.getBytes("iso-8859-1"));
+ return digest2Hex(sha.digest());
+ }
+ catch(Exception e) {
+ return null;
+ }
+ }
+
+ private static String digest2Hex(byte[] digest) {
+ StringBuilder hash = new StringBuilder(HASH_LEN * 2);
+ final String hexChars = "0123456789abcdef";
+ for(int i = 0; i < HASH_LEN; i++) {
+ hash.append(hexChars.charAt((digest[i] & 0xF0) >> 4))
+ .append(hexChars.charAt((digest[i] & 0x0F)));
+ }
+ return hash.toString();
+ }
+
+}
View
55 app/src/org/meshpoint/anode/util/TarExtractor.java
@@ -0,0 +1,55 @@
+package org.meshpoint.anode.util;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.zip.GZIPInputStream;
+
+import org.xeustechnologies.jtar.TarEntry;
+import org.xeustechnologies.jtar.TarInputStream;
+
+public class TarExtractor {
+
+ private File src, dest;
+
+ TarExtractor(File src, File dest) {
+ this.src = src;
+ this.dest = dest;
+ }
+
+ public void extract() throws IOException {
+ /* first extract the tar file */
+ File tarFile = new File(src.getAbsolutePath() + ".tar");
+ byte[] buf = new byte[1024];
+ GZIPInputStream zis = null;
+ zis = new GZIPInputStream(new FileInputStream(src));
+ FileOutputStream tarfos = new FileOutputStream(tarFile);
+ int count;
+ while ((count = zis.read(buf, 0, 1024)) != -1)
+ tarfos.write(buf, 0, count);
+ tarfos.close();
+ zis.close();
+
+ /* now unpack the tar */
+ TarInputStream tis = new TarInputStream(new BufferedInputStream(new FileInputStream(tarFile)));
+ TarEntry entry;
+ while((entry = tis.getNextEntry()) != null) {
+
+ FileOutputStream fos = new FileOutputStream(new File(dest, entry.getName()));
+ BufferedOutputStream dest = new BufferedOutputStream(fos);
+ while((count = tis.read(buf)) != -1)
+ dest.write(buf, 0, count);
+
+ dest.flush();
+ dest.close();
+ }
+ tis.close();
+
+ /* delete the tar file */
+ tarFile.delete();
+ }
+
+}
View
43 app/src/org/meshpoint/anode/util/ZipExtractor.java
@@ -0,0 +1,43 @@
+package org.meshpoint.anode.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+public class ZipExtractor {
+
+ private File src, dest;
+
+ ZipExtractor(File src, File dest) {
+ this.src = src;
+ this.dest = dest;
+ }
+
+ public void extract() throws IOException {
+ int count;
+ byte[] buf = new byte[1024];
+ ZipInputStream zis = null;
+ ZipEntry zipentry;
+ zis = new ZipInputStream(new FileInputStream(src));
+
+ while ((zipentry = zis.getNextEntry()) != null) {
+ String entryName = zipentry.getName();
+ File entryFile = new File(dest, entryName);
+ File parentDir = new File(entryFile.getParent());
+ if(!parentDir.isDirectory() && !parentDir.mkdirs())
+ throw new IOException("ZipExtractor.unpack(): unable to create directory");
+
+ FileOutputStream fos = new FileOutputStream(entryFile);
+ while ((count = zis.read(buf, 0, 1024)) != -1)
+ fos.write(buf, 0, count);
+
+ fos.close();
+ zis.closeEntry();
+ }
+ zis.close();
+ }
+
+}

0 comments on commit a4e33fc

Please sign in to comment.