package org.mortbay.ijetty.console;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.BaseColumns;
import android.provider.MediaStore;
import android.util.Config;
import android.util.Log;
/**
* MediaRestServlet
*
* /console/rest/media/[type]/[location]/[id][?action=x]
*
* type: image, audio, video
* location: internal, external
* action: embed
*
*
* /console/rest/media/image/internal/3
* Retrieves info about image 3 from internal storage
*
* /console/rest/media/image
* Retrieves info on all images from internal and external storage
*
* /console/rest/media/[type]/[location]/[id]?action=embed
* Generates html page that embeds a media player for the media
*
*/
public class MediaRestServlet extends HttpServlet
{
private static final String TAG = "MediaRstSrvlt";
public static final String __PG_START_PARAM = "pgStart";
public static final String __PG_SIZE_PARAM = "pgSize";
public static final int __DEFAULT_PG_START = 0;
public static final int __DEFAULT_PG_SIZE = 10;
private ContentResolver resolver;
private Context context;
public class MediaCollection extends DatabaseCollection
{
public MediaCollection(Cursor cursor)
{
super(cursor);
}
/**
* @param cursor
* @param startPos number of rows to skip
* @param limit number of rows to return
*/
public MediaCollection(Cursor cursor, int startPos, int limit)
{
super(cursor, startPos, limit);
}
@Override
public ContentValues cursorToValues(Cursor cursor)
{
ContentValues values = new ContentValues();
String val;
val = cursor.getString(cursor.getColumnIndex(android.provider.BaseColumns._ID));
values.put(android.provider.BaseColumns._ID,val);
int idx = -1;
idx = cursor.getColumnIndex(MediaStore.MediaColumns.TITLE);
if (idx > -1)
values.put(MediaStore.MediaColumns.TITLE, cursor.getString(idx));
idx = cursor.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME);
if (idx > -1)
values.put(MediaStore.MediaColumns.DISPLAY_NAME, cursor.getString(idx));
idx = cursor.getColumnIndex(MediaStore.MediaColumns.MIME_TYPE);
if (idx > -1)
values.put(MediaStore.MediaColumns.MIME_TYPE, cursor.getString(idx));
idx = cursor.getColumnIndex(MediaStore.MediaColumns.SIZE);
if (idx > -1)
values.put(MediaStore.MediaColumns.SIZE, cursor.getString(idx));
idx = cursor.getColumnIndex(MediaStore.Audio.AudioColumns.IS_MUSIC);
if (idx > -1)
{
int music = cursor.getInt(idx);
if (music > 0)
{
idx = cursor.getColumnIndex(MediaStore.Audio.AudioColumns.ARTIST);
if (idx > -1)
values.put(MediaStore.Audio.AudioColumns.ARTIST,cursor.getString(idx));
idx = cursor.getColumnIndex(MediaStore.Audio.AudioColumns.ALBUM);
if (idx > -1)
values.put(MediaStore.Audio.AudioColumns.ALBUM, cursor.getString(idx));
}
}
return values;
}
}
@Override
public void init(ServletConfig config) throws ServletException
{
super.init(config);
resolver = (ContentResolver)getServletContext().getAttribute("org.mortbay.ijetty.contentResolver");
context = (Context)getServletContext().getAttribute("org.mortbay.ijetty.context");
}
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
String pathInfo = request.getPathInfo();
if (pathInfo == null)
{
Log.w(TAG,"pathInfo was null, returning 404");
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
}
if (Config.LOGD)
{
Log.d(TAG,"PathInfo: " + pathInfo);
}
String type = null;
String location = null;
String id = null;
String action = null;
StringTokenizer strtok = new StringTokenizer(pathInfo,"/");
if (strtok.hasMoreElements())
{
type = strtok.nextToken();
}
if (strtok.hasMoreElements())
{
location = strtok.nextToken();
}
if (strtok.hasMoreElements())
{
id = strtok.nextToken();
}
doGetJson(request,response,type,location,id);
}
/**
* A request from the Javascript asking for some JSON describing the type of media being requested.
*
* @param request
* the incoming servlet request
* @param response
* the outgoing servlet response
* @param type
* the type of media interested in (<code>image</code>, <code>audio</code>, or <code>video</code>)
* @param location internal/external
* @param id optional id of specific item to retrieve
* @throws ServletException
* @throws IOException
*/
public void doGetJson(HttpServletRequest request, HttpServletResponse response, String type, String location, String id) throws ServletException, IOException
{
response.setContentType("application/json; charset=utf-8");
PrintWriter writer = response.getWriter();
if (id != null)
{
//TODO decide if we want to support this
//Get metadata about a specific media item
/*
Uri uri = MediaType.getContentUriByType(type, location);
Uri content = Uri.withAppendedPath(uri,id);
Cursor cur = null;
try
{
cur = resolver.query(uri,null,null,null,null);
if (cur != null && cur.getCount() == 1)
{
StringBuilder builder = new StringBuilder();
toJson(cur, uri, builder, type, location);
writer.print(builder.toString());
}
}
finally
{
if (cur != null)
cur.close();
}
*/
}
else
{
//Get (a page of) media items of a certain type and location
String tmp = request.getParameter(__PG_START_PARAM);
int pgStart = (tmp == null ? -1 : Integer.parseInt(tmp.trim()));
tmp = request.getParameter(__PG_SIZE_PARAM);
int pgSize = (tmp == null ? -1 : Integer.parseInt(tmp.trim()));
Uri mediaUri = MediaType.getContentUriByType(type, location);
StringBuilder builder = new StringBuilder();
//Get all of the applicable collections (ie both internal and external for a given type)
MediaCollection collection = null;
writer.println ("{");
try
{
collection = new MediaCollection (resolver.query(mediaUri,null,null,null, MediaStore.MediaColumns.TITLE+" ASC"), pgStart, pgSize);
writer.println("\"total\": "+collection.getTotal()+", ");
writer.println("\"media\": ");
writer.print("[ ");
ContentValues media = null;
int count = pgSize;
while ((pgSize <= 0 || count-- > 0) && (media = collection.next()) != null)
{
builder.setLength(0); // clear buffer
toJson(media, mediaUri, builder, type, location);
Log.d(TAG,builder.toString());
writer.print(builder.toString());
if (collection.hasNext())
{
writer.print(",");
}
}
writer.print(" ]");
}
finally
{
writer.println("}");
collection.close();
}
}
}
private void toJson(ContentValues media, Uri contenturi, StringBuilder builder, String type, String location)
{
builder.append("{");
builder.append(" \"type\":").append(safeJson(type));
builder.append(",\"location\":").append(safeJson(location));
builder.append(",\"id\":").append(safeJson(media.getAsInteger(BaseColumns._ID)));
builder.append(",\"title\":").append(safeJson(media.getAsString(MediaStore.MediaColumns.TITLE)));
builder.append(",\"displayname\":").append(safeJson(media.getAsString(MediaStore.MediaColumns.DISPLAY_NAME)));
builder.append(",\"mimetype\":").append(safeJson(media.getAsString(MediaStore.MediaColumns.MIME_TYPE)));
builder.append(",\"size\":").append(safeJson(media.getAsString(MediaStore.MediaColumns.SIZE)));
if ((contenturi == MediaStore.Audio.Media.EXTERNAL_CONTENT_URI) || (contenturi == MediaStore.Audio.Media.INTERNAL_CONTENT_URI))
{
String tmp = media.getAsString(MediaStore.Audio.AudioColumns.ARTIST);
if (tmp != null)
builder.append(",\"artist\":").append(safeJson(tmp));
tmp = media.getAsString(MediaStore.Audio.AudioColumns.ALBUM);
if (tmp != null)
builder.append(",\"album\":").append(safeJson(tmp));
}
builder.append("}");
}
private String safeJson(Number num)
{
if (num == null)
{
return "";
}
return num.toString();
}
private String safeJson(String str)
{
if (str == null)
{
return "\"\"";
}
return "\"" + str.replaceAll("'","\\'") + "\"";
}
}