Java tutorial
/* * PhoneGap is available under *either* the terms of the modified BSD license *or* the * MIT License (2008). See http://opensource.org/licenses/alphabetical for full text. * * Copyright (c) 2005-2010, Nitobi * Copyright (c) 2010, IBM Corporation */ package com.phonegap.file; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.IOException; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import javax.microedition.io.Connector; import javax.microedition.io.file.FileConnection; import net.rim.device.api.io.Base64OutputStream; import net.rim.device.api.io.FileNotFoundException; import net.rim.device.api.io.IOUtilities; import net.rim.device.api.system.Application; import org.json.me.JSONArray; import org.json.me.JSONException; import com.phonegap.api.Plugin; import com.phonegap.api.PluginResult; import com.phonegap.util.Logger; public class FileManager extends Plugin { /** * File related errors. */ public static int NOT_FOUND_ERR = 1; public static int SECURITY_ERR = 2; public static int ABORT_ERR = 3; public static int NOT_READABLE_ERR = 4; public static int ENCODING_ERR = 5; public static int NO_MODIFICATION_ALLOWED_ERR = 6; public static int INVALID_STATE_ERR = 7; public static int SYNTAX_ERR = 8; public static int INVALID_MODIFICATION_ERR = 9; public static int QUOTA_EXCEEDED_ERR = 10; public static int TYPE_MISMATCH_ERR = 11; public static int PATH_EXISTS_ERR = 12; /** * Possible actions. */ protected static final int ACTION_READ_AS_TEXT = 0; protected static final int ACTION_READ_AS_DATA_URL = 1; protected static final int ACTION_WRITE = 2; protected static final int ACTION_TRUNCATE = 3; public PluginResult execute(String action, JSONArray args, String callbackId) { // get parameters String filePath = null; try { filePath = args.getString(0); } catch (JSONException e) { Logger.log(this.getClass().getName() + ": " + e); return new PluginResult(PluginResult.Status.JSONEXCEPTION, "Invalid or missing file parameter"); } // perform specified action int a = getAction(action); if (a == ACTION_READ_AS_TEXT) { String result = null; try { result = readAsText(filePath, args.optString(1)); } catch (FileNotFoundException e) { Logger.log(this.getClass().getName() + ": " + e); return new PluginResult(PluginResult.Status.IOEXCEPTION, Integer.toString(NOT_FOUND_ERR)); } catch (UnsupportedEncodingException e) { Logger.log(this.getClass().getName() + ": " + e); return new PluginResult(PluginResult.Status.IOEXCEPTION, Integer.toString(ENCODING_ERR)); } catch (IOException e) { Logger.log(this.getClass().getName() + ": " + e); return new PluginResult(PluginResult.Status.IOEXCEPTION, Integer.toString(NOT_READABLE_ERR)); } return new PluginResult(PluginResult.Status.OK, result); } else if (a == ACTION_READ_AS_DATA_URL) { String result = null; try { result = readAsDataURL(filePath); } catch (FileNotFoundException e) { Logger.log(this.getClass().getName() + ": " + e); return new PluginResult(PluginResult.Status.IOEXCEPTION, Integer.toString(NOT_FOUND_ERR)); } catch (UnsupportedEncodingException e) { Logger.log(this.getClass().getName() + ": " + e); return new PluginResult(PluginResult.Status.IOEXCEPTION, Integer.toString(ENCODING_ERR)); } catch (IOException e) { Logger.log(this.getClass().getName() + ": " + e); return new PluginResult(PluginResult.Status.IOEXCEPTION, Integer.toString(NOT_READABLE_ERR)); } return new PluginResult(PluginResult.Status.OK, result); } else if (a == ACTION_WRITE) { int bytesWritten = 0; try { // write file data int position = Integer.parseInt(args.optString(2)); bytesWritten = writeFile(filePath, args.getString(1), position); } catch (JSONException e) { Logger.log(this.getClass().getName() + ": " + e); return new PluginResult(PluginResult.Status.JSONEXCEPTION, "File data could not be retrieved."); } catch (IOException e) { Logger.log(this.getClass().getName() + ": " + e); return new PluginResult(PluginResult.Status.IOEXCEPTION, Integer.toString(NO_MODIFICATION_ALLOWED_ERR)); } catch (NumberFormatException e) { Logger.log(this.getClass().getName() + ": " + e); return new PluginResult(PluginResult.Status.ILLEGAL_ARGUMENT_EXCEPTION, Integer.toString(SYNTAX_ERR)); } return new PluginResult(PluginResult.Status.OK, bytesWritten); } else if (a == ACTION_TRUNCATE) { long fileSize = 0; try { // retrieve new file size long size = Long.parseLong(args.getString(1)); fileSize = truncateFile(filePath, size); } catch (JSONException e) { Logger.log(this.getClass().getName() + ": " + e); return new PluginResult(PluginResult.Status.JSONEXCEPTION, "File size must be a number."); } catch (FileNotFoundException e) { Logger.log(this.getClass().getName() + ": " + e); return new PluginResult(PluginResult.Status.IOEXCEPTION, Integer.toString(NOT_FOUND_ERR)); } catch (IOException e) { Logger.log(this.getClass().getName() + ": " + e); return new PluginResult(PluginResult.Status.IOEXCEPTION, Integer.toString(NO_MODIFICATION_ALLOWED_ERR)); } catch (NumberFormatException e) { Logger.log(this.getClass().getName() + ": " + e); return new PluginResult(PluginResult.Status.ILLEGAL_ARGUMENT_EXCEPTION, Integer.toString(SYNTAX_ERR)); } return new PluginResult(PluginResult.Status.OK, fileSize); } // invalid action return new PluginResult(PluginResult.Status.INVALIDACTION, "File: invalid action " + action); } /** * Reads a file and encodes the contents using the specified encoding. * @param filePath Full path of the file to be read * @param encoding Encoding to use for the file contents * @return String containing encoded file contents */ protected String readAsText(String filePath, String encoding) throws FileNotFoundException, UnsupportedEncodingException, IOException { // read the file byte[] blob = readFile(filePath); // return encoded file contents Logger.log(this.getClass().getName() + ": encoding file contents using " + encoding); return new String(blob, encoding); } /** * Read file and return data as a base64 encoded data url. * A data url is of the form: * data:[<mediatype>][;base64],<data> * @param filePath Full path of the file to be read */ protected String readAsDataURL(String filePath) throws FileNotFoundException, IOException { String result = null; // read file byte[] blob = readFile(filePath); // encode file contents using BASE64 encoding ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); Base64OutputStream base64OutputStream = new Base64OutputStream(byteArrayOutputStream); base64OutputStream.write(blob); base64OutputStream.flush(); base64OutputStream.close(); result = byteArrayOutputStream.toString(); // put result in proper form // TODO: determine media type? (not required) String mediaType = ""; result = "data:" + mediaType + ";base64," + result; return result; } /** * Reads file as byte array. * @param filePath Full path of the file to be read * @return file content as a byte array */ protected byte[] readFile(String filePath) throws FileNotFoundException, IOException { byte[] blob = null; DataInputStream dis = null; try { dis = openDataInputStream(filePath); blob = IOUtilities.streamToBytes(dis); } finally { try { if (dis != null) dis.close(); } catch (IOException e) { Logger.log(this.getClass().getName() + ": " + e); } } return blob; } /** * Writes data to the specified file. * @param filePath Full path of file to be written to * @param data Data to be written * @param position Position at which to begin writing */ protected int writeFile(String filePath, String data, int position) throws IOException { FileConnection fconn = null; OutputStream os = null; byte[] bytes = data.getBytes(); try { fconn = (FileConnection) Connector.open(filePath, Connector.READ_WRITE); if (!fconn.exists()) { fconn.create(); } os = fconn.openOutputStream(position); os.write(bytes); } finally { try { if (os != null) os.close(); if (fconn != null) fconn.close(); } catch (IOException e) { Logger.log(this.getClass().getName() + ": " + e); } } return bytes.length; } /** * Changes the length of the specified file. If shortening, data beyond new length * is discarded. * @param fileName The full path of the file to truncate * @param size The size to which the length of the file is to be adjusted * @param the size of the file */ protected long truncateFile(String filePath, long size) throws FileNotFoundException, IOException { long fileSize = 0; FileConnection fconn = null; try { fconn = (FileConnection) Connector.open(filePath, Connector.READ_WRITE); if (!fconn.exists()) { throw new FileNotFoundException(filePath + " not found"); } if (size >= 0) { fconn.truncate(size); } fileSize = fconn.fileSize(); } finally { try { if (fconn != null) fconn.close(); } catch (IOException e) { Logger.log(this.getClass().getName() + ": " + e); } } return fileSize; } /** * Utility function to open a DataInputStream from a file path. * * A file can be referenced with the following protocols: * - System.getProperty("fileconn.dir.*") * - local:/// references files bundled with the application * * @param filePath The full path to the file to open * @return Handle to the DataInputStream */ protected DataInputStream openDataInputStream(final String filePath) throws FileNotFoundException, IOException { FileConnection fconn = null; DataInputStream dis = null; try { if (filePath.startsWith("local:///")) { // Remove local:// from filePath but leave a leading / dis = new DataInputStream(Application.class.getResourceAsStream(filePath.substring(8))); } else { fconn = (FileConnection) Connector.open(filePath, Connector.READ); if (!fconn.exists()) { throw new FileNotFoundException(filePath + " not found"); } dis = fconn.openDataInputStream(); } if (dis == null) { throw new FileNotFoundException(filePath + " not found"); } } finally { try { if (fconn != null) fconn.close(); } catch (IOException e) { Logger.log(this.getClass().getName() + ": " + e); } } return dis; } /** * Returns action to perform. * @param action * @return action to perform */ protected static int getAction(String action) { if ("readAsText".equals(action)) return ACTION_READ_AS_TEXT; if ("readAsDataURL".equals(action)) return ACTION_READ_AS_DATA_URL; if ("write".equals(action)) return ACTION_WRITE; if ("truncate".equals(action)) return ACTION_TRUNCATE; return -1; } }