DrmUtils.java revision c7b3ccc564448cb4b918728421f9402bc18278c5
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.drm;
18
19import java.io.BufferedInputStream;
20import java.io.File;
21import java.io.FileInputStream;
22import java.io.FileNotFoundException;
23import java.io.FileOutputStream;
24import java.io.IOException;
25import java.io.InputStream;
26import java.io.OutputStream;
27import java.util.HashMap;
28import java.util.Iterator;
29
30/**
31 * The utility class used in the DRM Framework. This inclueds APIs for file operations
32 * and ExtendedMetadataParser for parsing extended metadata BLOB in DRM constraints.
33 *
34 */
35public class DrmUtils {
36    /* Should be used when we need to read from local file */
37    /* package */ static byte[] readBytes(String path) throws IOException {
38        File file = new File(path);
39        return readBytes(file);
40    }
41
42    /* Should be used when we need to read from local file */
43    /* package */ static byte[] readBytes(File file) throws IOException {
44        FileInputStream inputStream = new FileInputStream(file);
45        BufferedInputStream bufferedStream = new BufferedInputStream(inputStream);
46        byte[] data = null;
47
48        try {
49            int length = bufferedStream.available();
50            if (length > 0) {
51                data = new byte[length];
52                // read the entire data
53                bufferedStream.read(data);
54             }
55        } finally {
56            quiteDispose(bufferedStream);
57            quiteDispose(inputStream);
58        }
59        return data;
60    }
61
62    /* package */ static void writeToFile(final String path, byte[] data) throws IOException {
63        /* check for invalid inputs */
64        FileOutputStream outputStream = null;
65
66        if (null != path && null != data) {
67            try {
68                outputStream = new FileOutputStream(path);
69                outputStream.write(data);
70            } finally {
71                quiteDispose(outputStream);
72            }
73        }
74    }
75
76    /* package */ static void removeFile(String path) throws IOException {
77        File file = new File(path);
78        file.delete();
79    }
80
81    private static void quiteDispose(InputStream stream) {
82        try {
83            if (null != stream) {
84                stream.close();
85            }
86        } catch (IOException e) {
87            // no need to care, at least as of now
88        }
89    }
90
91    private static void quiteDispose(OutputStream stream) {
92        try {
93            if (null != stream) {
94                stream.close();
95            }
96        } catch (IOException e) {
97            // no need to care
98        }
99    }
100
101    /**
102     * Get an instance of ExtendedMetadataParser to be used for parsing
103     * extended metadata BLOB in DRM constraints. <br>
104     *
105     * extendedMetadata BLOB is retrieved by specifing
106     * key DrmStore.ConstraintsColumns.EXTENDED_METADATA.
107     *
108     * @param extendedMetadata BLOB in which key-value pairs of extended metadata are embedded.
109     *
110     */
111    public static ExtendedMetadataParser getExtendedMetadataParser(byte[] extendedMetadata) {
112        return new ExtendedMetadataParser(extendedMetadata);
113    }
114
115    /**
116     * Utility parser to parse the extended meta-data embedded inside DRM constraints<br><br>
117     *
118     * Usage example<br>
119     * byte[] extendedMetadata<br>
120     * &nbsp;&nbsp;&nbsp;&nbsp; =
121     *         constraints.getAsByteArray(DrmStore.ConstraintsColumns.EXTENDED_METADATA);<br>
122     * ExtendedMetadataParser parser = getExtendedMetadataParser(extendedMetadata);<br>
123     * Iterator keyIterator = parser.keyIterator();<br>
124     * while (keyIterator.hasNext()) {<br>
125     *     &nbsp;&nbsp;&nbsp;&nbsp;String extendedMetadataKey = keyIterator.next();<br>
126     *     &nbsp;&nbsp;&nbsp;&nbsp;String extendedMetadataValue =
127     *             parser.get(extendedMetadataKey);<br>
128     * }
129     */
130    public static class ExtendedMetadataParser {
131        HashMap<String, String> mMap = new HashMap<String, String>();
132
133        private int readByte(byte[] constraintData, int arrayIndex) {
134            //Convert byte[] into int.
135            return (int)constraintData[arrayIndex];
136        }
137
138        private String readMultipleBytes(
139                byte[] constraintData, int numberOfBytes, int arrayIndex) {
140            byte[] returnBytes = new byte[numberOfBytes];
141            for (int j = arrayIndex, i = 0; j < arrayIndex + numberOfBytes; j++,i++) {
142                returnBytes[i] = constraintData[j];
143            }
144            return new String(returnBytes);
145        }
146
147        /*
148         * This will parse the following format
149         * KeyLengthValueLengthKeyValueKeyLength1ValueLength1Key1Value1..\0
150         */
151        private ExtendedMetadataParser(byte[] constraintData) {
152            //Extract KeyValue Pair Info, till terminator occurs.
153            int index = 0;
154
155            while (index < constraintData.length) {
156                //Parse Key Length
157                int keyLength = readByte(constraintData, index);
158                index++;
159
160                //Parse Value Length
161                int valueLength = readByte(constraintData, index);
162                index++;
163
164                //Fetch key
165                String strKey = readMultipleBytes(constraintData, keyLength, index);
166                index += keyLength;
167
168                //Fetch Value
169                String strValue = readMultipleBytes(constraintData, valueLength, index);
170                if (strValue.equals(" ")) {
171                    strValue = "";
172                }
173                index += valueLength;
174                mMap.put(strKey, strValue);
175            }
176        }
177
178        public Iterator<String> iterator() {
179            return mMap.values().iterator();
180        }
181
182        public Iterator<String> keyIterator() {
183            return mMap.keySet().iterator();
184        }
185
186        public String get(String key) {
187            return mMap.get(key);
188        }
189    }
190}
191
192