jp.gr.java_conf.petit_lycee.subsonico.MethodConstants.java Source code

Java tutorial

Introduction

Here is the source code for jp.gr.java_conf.petit_lycee.subsonico.MethodConstants.java

Source

package jp.gr.java_conf.petit_lycee.subsonico;

import android.util.Base64;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Stack;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import jp.gr.java_conf.petit_lycee.utils.StringUtil;

class MethodConstants {
    public static final String PING = "ping";
    public static final String GET_LICENSE = "getLicense";
    public static final String GET_INDEXES = "getIndexes";
    public static final String GET_MUSIC_DIRECTORY = "getMusicDirectory";
    public static final String GET_ALBUM = "getAlbum";
    public static final String GET_SONG = "getSong";
    public static final String STREAM = "stream";
}

/***
 * Subsonic???
 */
class SubsonicXMLHandler extends DefaultHandler {

    private Stack<ArrayList<Entry>> stack;
    private SubsonicException subsEx = null;
    private SubsonicResponse response;

    public boolean isError() {
        return subsEx != null;
    }

    public SubsonicException getException() {
        return subsEx;
    }

    public SubsonicResponse getResponse() {
        return response;
    }

    public void startDocument() {
        subsEx = null;
        response = new SubsonicResponse();
        response.setEntryList(new ArrayList<Entry>());
        stack = new Stack<ArrayList<Entry>>();
        stack.push(response.getEntryList());
    }

    private Field getField(@SuppressWarnings("rawtypes") Class cls, String fieldName) throws NoSuchFieldException {
        try {
            return cls.getDeclaredField(fieldName);
        } catch (NoSuchFieldException e) {
            @SuppressWarnings("rawtypes")
            Class super_cls = cls.getSuperclass();
            //????
            //??
            if (super_cls != null && super_cls.getPackage().equals(cls.getPackage())) {
                return getField(super_cls, fieldName);
            }
            throw e;
        }
    }

    /***
     * ???????
     * int,boolean,String,Date??
     * @param obj 
     * @param attrs attributes
     */
    private void setValues(Object obj, org.xml.sax.Attributes attrs) {
        for (int i = 0; i < attrs.getLength(); i++) {
            try {
                Field field = getField(obj.getClass(), attrs.getLocalName(i));
                field.setAccessible(true);

                String attr_value = attrs.getValue(i);
                if (field.getType() == boolean.class) {
                    field.setBoolean(obj, Boolean.valueOf(attr_value));
                } else if (field.getType() == int.class) {
                    field.setInt(obj, Integer.parseInt(attr_value));
                } else if (field.getType() == String.class) {
                    field.set(obj, attr_value);
                } else if (field.getType() == Date.class) {
                    String format = "yyyy-MM-dd'T'HH:mm:ss";
                    field.set(obj, StringUtil.toDate(attr_value, format));
                }
            } catch (Exception ignored) {
            }
        }
    }

    public void startElement(String namespaceURI, String localName, String qName,
            org.xml.sax.Attributes attributes) {

        ResponseElement elem = null;

        //element????
        //(error????)
        if (qName.equals("subsonic-response")) {
            //set response data
            response.setStatus(attributes.getValue("status"));
            response.setVersion(attributes.getValue("version"));
            if (!"ok".equals(response.getStatus())) {
                subsEx = new SubsonicException();
            }
        } else if (qName.equals("error")) {
            if (subsEx != null)
                setValues(subsEx, attributes);

        } else if (qName.equals("directory")) {
            Directory p = new Directory();
            p.setDir(true);
            elem = p;

        } else if (qName.equals("index")) {
            elem = new Index();

        } else if (qName.equals("child")) {
            int spam = attributes.getIndex("isDir");
            if (spam >= 0 && attributes.getValue(spam).equals("true")) {
                elem = new Directory();
            } else {
                elem = new Media();
            }

        } else if (qName.equals("artist")) {
            elem = new Directory();
        } else if (qName.equals("song")) {
            elem = new Media();
        } else if (qName.equals("license")) {
            elem = new License();
        }

        if (elem != null) {
            setValues(elem, attributes);
            if (elem instanceof Entry) {
                Entry etr = (Entry) elem;
                ArrayList<Entry> list = stack.peek();
                list.add(etr);
                stack.push(etr.children);
            }
        }
    }

    public void endElement(String namespaceURI, String localName, String qName) {
        if (qName.equals("directory") || qName.equals("index") || qName.equals("child") || qName.equals("artist")
                || qName.equals("song")) {

            stack.pop();
        }
    }
}

public class SubsonicAccessor {
    private String top_url;// = "http://ore-no-server/rest/ping.view?v=1.1.0&c=myapp";
    private String user_id;
    private String passwd;
    private String api_version = "1.8.0";
    private String app_name = "subsonico";

    private int max_bit_rate = 320;

    public void setTop_url(String top_url) {
        if (!top_url.endsWith("/")) {
            top_url += "/";
        }
        this.top_url = top_url;
    }

    public void setPasswd(String passwd) {
        this.passwd = passwd;
    }

    public void setUser_id(String user_id) {
        this.user_id = user_id;
    }

    SubsonicResponse parseResponseXML(InputStream is)
            throws SubsonicException, IOException, SAXException, ParserConfigurationException {

        SubsonicXMLHandler handler = new SubsonicXMLHandler();
        SAXParserFactory factory = SAXParserFactory.newInstance();

        SAXParser parser = factory.newSAXParser();
        parser.parse(is, handler);
        if (handler.isError()) {
            throw handler.getException();
        }
        return handler.getResponse();
    }

    /***
     * ?????
     * todo:stream???
     */
    SubsonicResponse getSubsonicResponse(String req, ArrayList<BasicNameValuePair> params)
            throws SubsonicException {
        HttpResponse res;

        final String error_code = "XX";
        try {
            res = getServerResponse(req, params);
        } catch (IOException e) {
            throw new SubsonicException(error_code, e.getMessage());
        }
        try {
            HttpEntity entity = res.getEntity();
            return parseResponseXML(entity.getContent());
        } catch (SubsonicException e) {
            throw e;
        } catch (Exception e) {
            throw new SubsonicException(error_code, e.getMessage());
        }
    }

    private String getRequestUrl(String reqMethod, List<BasicNameValuePair> param) {
        StringBuilder sb = new StringBuilder();
        sb.append(top_url);
        sb.append("rest/");
        sb.append(reqMethod);
        sb.append(".view?");
        sb.append("v=");
        sb.append(api_version);
        sb.append("&c=");
        sb.append(app_name);

        if (param != null) {
            sb.append("&");
            sb.append(URLEncodedUtils.format(param, "UTF-8"));
        }
        return sb.toString();
    }

    private HttpResponse getServerResponse(String reqMethod, List<BasicNameValuePair> params) throws IOException {
        String url = getRequestUrl(reqMethod, params);
        HttpGet method = new HttpGet(url);

        DefaultHttpClient client = new DefaultHttpClient();

        // ?
        String tmp = Base64.encodeToString((user_id + ":" + passwd).getBytes(), Base64.NO_WRAP);
        method.setHeader("Authorization", "Basic " + tmp);

        HttpResponse response = client.execute(method);
        int status = response.getStatusLine().getStatusCode();
        if (status == HttpStatus.SC_OK) {
            return response;
        } else {
            //TODO:?
            return null;
        }
    }

    /***
     * Used to test connectivity with the server. Takes no extra parameters.
     * @return SubsonicResponse
     * @throws SubsonicException
     */
    public SubsonicResponse ping() throws SubsonicException {
        return getSubsonicResponse(MethodConstants.PING, null);
    }

    /***
     * Get details about the software license.
     * @return SubsonicResponse
     * @throws SubsonicException
     */
    public SubsonicResponse getLicense() throws SubsonicException {
        return getSubsonicResponse(MethodConstants.GET_LICENSE, null);
    }

    /***
     * Returns an indexed structure of all artists.
     * @return SubsonicResponse
     * @throws SubsonicException
     */
    public SubsonicResponse getIndexes() throws SubsonicException {
        return getSubsonicResponse(MethodConstants.GET_INDEXES, null);
    }

    /***
     * Returns a listing of all files in a music directory. Typically used to get list of albums for an artist, or list of songs for an album.
     * @param id identifies the music folder
     * @return SubsonicResponse
     * @throws SubsonicException
     */
    public SubsonicResponse getMusicDirectory(String id) throws SubsonicException {
        ArrayList<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
        params.add(new BasicNameValuePair("id", id));

        return getSubsonicResponse(MethodConstants.GET_MUSIC_DIRECTORY, params);
    }

    /***
     * Returns details for an album, including a list of songs. This method organizes music according to ID3 tags.
     * @param id album'ID
     * @return SubsonicResponse
     * @throws SubsonicException
     */
    public SubsonicResponse getAlbum(String id) throws SubsonicException {
        ArrayList<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();

        params.add(new BasicNameValuePair("id", id));
        return getSubsonicResponse(MethodConstants.GET_ALBUM, params);
    }

    /***
     * Returns details for a song.
     * @param id the song ID
     * @return SubsonicResponse
     * @throws SubsonicException
     */
    public SubsonicResponse getSong(String id) throws SubsonicException {
        ArrayList<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
        params.add(new BasicNameValuePair("id", id));
        return getSubsonicResponse(MethodConstants.GET_SONG, params);
    }

    /***
     * Streams a given media file.
     * @param id id the file to stream.
     * @return a response from Server
     * @throws SubsonicException
     */
    public SubsonicResponse stream(String id) throws SubsonicException {
        ArrayList<BasicNameValuePair> params = new ArrayList();
        params.add(new BasicNameValuePair("id", id));
        return getSubsonicResponse(MethodConstants.STREAM, params);
    }
}