1 /* 2 * Copyright (C) 2007 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 17 package org.apache.harmony.dalvik.ddmc; 18 19 import java.nio.ByteBuffer; 20 import java.nio.ByteOrder; 21 22 /** 23 * Handle a chunk of data sent from a DDM server. 24 * 25 * To handle a chunk type, sub-class ChunkHandler and register your class 26 * with DdmServer. 27 */ 28 public abstract class ChunkHandler { 29 30 public static final ByteOrder CHUNK_ORDER = ByteOrder.BIG_ENDIAN; 31 32 public static final int CHUNK_FAIL = type("FAIL"); 33 34 35 public ChunkHandler() {} 36 37 /** 38 * Called when the DDM server connects. The handler is allowed to 39 * send messages to the server. 40 */ 41 public abstract void connected(); 42 43 /** 44 * Called when the DDM server disconnects. Can be used to disable 45 * periodic transmissions or clean up saved state. 46 */ 47 public abstract void disconnected(); 48 49 /** 50 * Handle a single chunk of data. "request" includes the type and 51 * the chunk payload. 52 * 53 * Returns a response in a Chunk. 54 */ 55 public abstract Chunk handleChunk(Chunk request); 56 57 /** 58 * Create a FAIL chunk. The "handleChunk" methods can use this to 59 * return an error message when they are not able to process a chunk. 60 */ 61 public static Chunk createFailChunk(int errorCode, String msg) { 62 if (msg == null) 63 msg = ""; 64 65 ByteBuffer out = ByteBuffer.allocate(8 + msg.length() * 2); 66 out.order(ChunkHandler.CHUNK_ORDER); 67 out.putInt(errorCode); 68 out.putInt(msg.length()); 69 putString(out, msg); 70 71 return new Chunk(CHUNK_FAIL, out); 72 } 73 74 /** 75 * Utility function to wrap a ByteBuffer around a Chunk. 76 */ 77 public static ByteBuffer wrapChunk(Chunk request) { 78 ByteBuffer in; 79 80 in = ByteBuffer.wrap(request.data, request.offset, request.length); 81 in.order(CHUNK_ORDER); 82 return in; 83 } 84 85 86 /** 87 * Utility function to copy a String out of a ByteBuffer. 88 * 89 * This is here because multiple chunk handlers can make use of it, 90 * and there's nowhere better to put it. 91 */ 92 public static String getString(ByteBuffer buf, int len) { 93 char[] data = new char[len]; 94 for (int i = 0; i < len; i++) 95 data[i] = buf.getChar(); 96 return new String(data); 97 } 98 99 /** 100 * Utility function to copy a String into a ByteBuffer. 101 */ 102 public static void putString(ByteBuffer buf, String str) { 103 int len = str.length(); 104 for (int i = 0; i < len; i++) 105 buf.putChar(str.charAt(i)); 106 } 107 108 /** 109 * Convert a 4-character string to a 32-bit type. 110 */ 111 public static int type(String typeName) { 112 if (typeName.length() != 4) { 113 throw new IllegalArgumentException("Bad type name: " + typeName); 114 } 115 int result = 0; 116 for (int i = 0; i < 4; ++i) { 117 result = ((result << 8) | (typeName.charAt(i) & 0xff)); 118 } 119 return result; 120 } 121 122 /** 123 * Convert an integer type to a 4-character string. 124 */ 125 public static String name(int type) 126 { 127 char[] ascii = new char[4]; 128 129 ascii[0] = (char) ((type >> 24) & 0xff); 130 ascii[1] = (char) ((type >> 16) & 0xff); 131 ascii[2] = (char) ((type >> 8) & 0xff); 132 ascii[3] = (char) (type & 0xff); 133 134 return new String(ascii); 135 } 136 137 } 138