javascript and native side of a URL caching plugin + android plugin framework is complete

This commit is contained in:
Dave Johnson
2010-07-28 17:26:23 -07:00
parent 742910f369
commit 2b2b4f5dd4
8 changed files with 290 additions and 24 deletions
@@ -0,0 +1,24 @@
package com.phonegap.api;
import android.content.Context;
public interface Command {
/**
* Executes the request and returns JS code to change client state.
*
* @param action the command to execute
* @return a string with JavaScript code or null
*/
CommandResult execute(String action, String[] args);
/**
* Determines if this command can process a request.
*
* @param action the command to execute
*
* @return true if this command understands the petition
*/
boolean accept(String action);
void setContext(Context ctx);
}
@@ -0,0 +1,80 @@
package com.phonegap.api;
import android.content.Context;
import android.webkit.WebView;
import com.phonegap.DroidGap;
/**
* Given a execution request detects matching {@link Command} and executes it.
*/
public final class CommandManager {
private static final String EXCEPTION_PREFIX = "[PhoneGap] *ERROR* Exception executing command [";
private static final String EXCEPTION_SUFFIX = "]: ";
private Command[] commands;
private final Context ctx;
private final WebView app;
public CommandManager(WebView app, Context ctx) {
this.ctx = ctx;
this.app = app;
}
/**
* Receives a request for execution and fulfills it as long as one of
* the configured {@link Command} can understand it. Command precedence
* is important (just one of them will be executed).
*
* @param instruction any API command
* @return JS code to execute by the client or null
*/
public String exec(final String clazz, final String action, final String callbackId,
final String args, final boolean async) {
CommandResult cr = null;
try {
//final WebView wv = this.app;
final String _callbackId = callbackId;
final String[] aargs = args.split("__PHONEGAP__");
Class c = Class.forName(clazz);
Class[] interfaces = c.getInterfaces();
for (int j=0; j<interfaces.length; j++) {
if (interfaces[j].getName().equals("com.phonegap.api.Command")) {
final Command ci = (Command)c.newInstance();
ci.setContext(this.ctx);
if (async) {
// Run this async on the UI thread
app.post(new Runnable() {
public void run() {
CommandResult cr = ci.execute(action, aargs);
if (cr.getStatus() == 0) {
app.loadUrl("javascript:PhoneGap.callbackSuccess('"+callbackId+"', " + cr.getResult()+ ");");
} else {
app.loadUrl("javascript:PhoneGap.callbackFailure('"+callbackId+"', " + cr.getResult() + ");");
}
}
});
return "";
} else {
cr = ci.execute(action, aargs);
}
}
}
} catch (ClassNotFoundException e) {
cr = new CommandResult(CommandResult.Status.CLASSNOTFOUNDEXCEPTION,
"{ message: 'ClassNotFoundException', status: "+CommandResult.Status.CLASSNOTFOUNDEXCEPTION.ordinal()+" }");
} catch (IllegalAccessException e) {
cr = new CommandResult(CommandResult.Status.ILLEGALACCESSEXCEPTION,
"{ message: 'IllegalAccessException', status: "+CommandResult.Status.ILLEGALACCESSEXCEPTION.ordinal()+" }");
} catch (InstantiationException e) {
cr = new CommandResult(CommandResult.Status.INSTANTIATIONEXCEPTION,
"{ message: 'InstantiationException', status: "+CommandResult.Status.INSTANTIATIONEXCEPTION.ordinal()+" }");
}
// if async we have already returned at this point unless there was an error...
if (async) {
app.loadUrl("javascript:PhoneGap.callbackFailure('"+callbackId+"', " + cr.getResult() + ");");
}
return ( cr != null ? cr.getResult() : "{ status: 0, message: 'all good' }" );
}
}
@@ -0,0 +1,29 @@
package com.phonegap.api;
public class CommandResult {
private final int status;
private final String result;
public CommandResult(Status status, String result) {
this.status = status.ordinal();
this.result = result;
}
public int getStatus() {
return status;
}
public String getResult() {
return result;
}
public enum Status {
OK,
CLASSNOTFOUNDEXCEPTION,
ILLEGALACCESSEXCEPTION,
INSTANTIATIONEXCEPTION,
MALFORMEDURLEXCEPTION,
IOEXCEPTION,
INVALIDACTION
}
}
@@ -0,0 +1,110 @@
package com.phonegap.api.impl;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import android.content.Context;
import com.phonegap.api.Command;
import com.phonegap.api.CommandResult;
public final class Cache implements Command {
private Context ctx;
public boolean accept(String action) {
// TODO Auto-generated method stub
return false;
}
public void setContext(Context ctx) {
this.ctx = ctx;
}
public CommandResult execute(String action, String[] args) {
CommandResult.Status status = CommandResult.Status.OK;
String result = "";
String uri = args[0];
String fileName = md5(uri);
if (action.equals("getCachedPathForURI") && args.length == 1)
{
// First check if the file exists already
String fileDir = ctx.getFilesDir().getAbsolutePath();
String filePath = fileDir + "/" + fileName;
File f = new File(filePath);
// f.exists()
if (false) {
result = "{ file: '"+filePath+"', status: 0 }";
} else {
URL u;
InputStream is = null;
DataInputStream dis;
FileOutputStream out = null;
byte[] buffer = new byte[1024];
int length = -1;
try {
u = new URL(uri);
is = u.openStream(); // throws an IOException
dis = new DataInputStream(new BufferedInputStream(is));
out = ctx.openFileOutput(fileName, Context.MODE_PRIVATE);
while ((length = dis.read(buffer)) != -1) {
out.write(buffer, 0, length);
}
out.flush();
result = "{ file: '"+fileName+"', status: 0 }";
} catch (MalformedURLException e) {
status = CommandResult.Status.MALFORMEDURLEXCEPTION;
result = "{ message: 'MalformedURLException', status: "+status.ordinal()+" }";
} catch (IOException e) {
status = CommandResult.Status.IOEXCEPTION;
result = "{ message: 'IOException', status: "+status.ordinal()+" }";
} finally {
try {
is.close();
out.close();
} catch (IOException e) {
status = CommandResult.Status.IOEXCEPTION;
result = "{ message: 'IOException', status: "+status.ordinal()+" }";
}
}
}
} else {
status = CommandResult.Status.INVALIDACTION;
result = "{ message: 'InvalidAction', status: "+status.ordinal()+" }";
}
return new CommandResult(status, result);
}
public String md5(String s) {
try {
// Create MD5 Hash
MessageDigest digest = java.security.MessageDigest.getInstance("MD5");
digest.update(s.getBytes());
byte messageDigest[] = digest.digest();
// Create Hex String
StringBuffer hexString = new StringBuffer();
for (int i=0; i<messageDigest.length; i++)
hexString.append(Integer.toHexString(0xFF & messageDigest[i]));
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return "";
}
}