001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018 package org.apache.hadoop.hdfs.web;
019
020 import org.apache.hadoop.fs.*;
021 import org.apache.hadoop.fs.permission.AclEntry;
022 import org.apache.hadoop.fs.permission.AclStatus;
023 import org.apache.hadoop.fs.permission.FsPermission;
024 import org.apache.hadoop.hdfs.DFSUtil;
025 import org.apache.hadoop.hdfs.protocol.*;
026 import org.apache.hadoop.hdfs.protocol.DatanodeInfo.AdminStates;
027 import org.apache.hadoop.hdfs.security.token.block.BlockTokenIdentifier;
028 import org.apache.hadoop.hdfs.security.token.delegation.DelegationTokenIdentifier;
029 import org.apache.hadoop.hdfs.server.namenode.INodeId;
030 import org.apache.hadoop.ipc.RemoteException;
031 import org.apache.hadoop.security.token.Token;
032 import org.apache.hadoop.security.token.TokenIdentifier;
033 import org.apache.hadoop.util.DataChecksum;
034 import org.apache.hadoop.util.StringUtils;
035 import org.mortbay.util.ajax.JSON;
036
037 import java.io.ByteArrayInputStream;
038 import java.io.DataInputStream;
039 import java.io.IOException;
040 import java.util.*;
041
042 /** JSON Utilities */
043 public class JsonUtil {
044 private static final Object[] EMPTY_OBJECT_ARRAY = {};
045 private static final DatanodeInfo[] EMPTY_DATANODE_INFO_ARRAY = {};
046
047 /** Convert a token object to a Json string. */
048 public static String toJsonString(final Token<? extends TokenIdentifier> token
049 ) throws IOException {
050 return toJsonString(Token.class, toJsonMap(token));
051 }
052
053 private static Map<String, Object> toJsonMap(
054 final Token<? extends TokenIdentifier> token) throws IOException {
055 if (token == null) {
056 return null;
057 }
058
059 final Map<String, Object> m = new TreeMap<String, Object>();
060 m.put("urlString", token.encodeToUrlString());
061 return m;
062 }
063
064 /** Convert a Json map to a Token. */
065 public static Token<? extends TokenIdentifier> toToken(
066 final Map<?, ?> m) throws IOException {
067 if (m == null) {
068 return null;
069 }
070
071 final Token<DelegationTokenIdentifier> token
072 = new Token<DelegationTokenIdentifier>();
073 token.decodeFromUrlString((String)m.get("urlString"));
074 return token;
075 }
076
077 /** Convert a Json map to a Token of DelegationTokenIdentifier. */
078 @SuppressWarnings("unchecked")
079 public static Token<DelegationTokenIdentifier> toDelegationToken(
080 final Map<?, ?> json) throws IOException {
081 final Map<?, ?> m = (Map<?, ?>)json.get(Token.class.getSimpleName());
082 return (Token<DelegationTokenIdentifier>)toToken(m);
083 }
084
085 /** Convert a Json map to a Token of BlockTokenIdentifier. */
086 @SuppressWarnings("unchecked")
087 private static Token<BlockTokenIdentifier> toBlockToken(
088 final Map<?, ?> m) throws IOException {
089 return (Token<BlockTokenIdentifier>)toToken(m);
090 }
091
092 /** Convert a Token[] to a JSON array. */
093 private static Object[] toJsonArray(final Token<? extends TokenIdentifier>[] array
094 ) throws IOException {
095 if (array == null) {
096 return null;
097 } else if (array.length == 0) {
098 return EMPTY_OBJECT_ARRAY;
099 } else {
100 final Object[] a = new Object[array.length];
101 for(int i = 0; i < array.length; i++) {
102 a[i] = toJsonMap(array[i]);
103 }
104 return a;
105 }
106 }
107
108 /** Convert a token object to a JSON string. */
109 public static String toJsonString(final Token<? extends TokenIdentifier>[] tokens
110 ) throws IOException {
111 if (tokens == null) {
112 return null;
113 }
114
115 final Map<String, Object> m = new TreeMap<String, Object>();
116 m.put(Token.class.getSimpleName(), toJsonArray(tokens));
117 return toJsonString(Token.class.getSimpleName() + "s", m);
118 }
119
120 /** Convert an Object[] to a List<Token<?>>. */
121 private static List<Token<?>> toTokenList(final Object[] objects) throws IOException {
122 if (objects == null) {
123 return null;
124 } else if (objects.length == 0) {
125 return Collections.emptyList();
126 } else {
127 final List<Token<?>> list = new ArrayList<Token<?>>(objects.length);
128 for(int i = 0; i < objects.length; i++) {
129 list.add(toToken((Map<?, ?>)objects[i]));
130 }
131 return list;
132 }
133 }
134
135 /** Convert a JSON map to a List<Token<?>>. */
136 public static List<Token<?>> toTokenList(final Map<?, ?> json) throws IOException {
137 if (json == null) {
138 return null;
139 }
140
141 final Map<?, ?> m = (Map<?, ?>)json.get(Token.class.getSimpleName() + "s");
142 return toTokenList((Object[])m.get(Token.class.getSimpleName()));
143 }
144
145 /** Convert an exception object to a Json string. */
146 public static String toJsonString(final Exception e) {
147 final Map<String, Object> m = new TreeMap<String, Object>();
148 m.put("exception", e.getClass().getSimpleName());
149 m.put("message", e.getMessage());
150 m.put("javaClassName", e.getClass().getName());
151 return toJsonString(RemoteException.class, m);
152 }
153
154 /** Convert a Json map to a RemoteException. */
155 public static RemoteException toRemoteException(final Map<?, ?> json) {
156 final Map<?, ?> m = (Map<?, ?>)json.get(RemoteException.class.getSimpleName());
157 final String message = (String)m.get("message");
158 final String javaClassName = (String)m.get("javaClassName");
159 return new RemoteException(javaClassName, message);
160 }
161
162 private static String toJsonString(final Class<?> clazz, final Object value) {
163 return toJsonString(clazz.getSimpleName(), value);
164 }
165
166 /** Convert a key-value pair to a Json string. */
167 public static String toJsonString(final String key, final Object value) {
168 final Map<String, Object> m = new TreeMap<String, Object>();
169 m.put(key, value);
170 return JSON.toString(m);
171 }
172
173 /** Convert a FsPermission object to a string. */
174 private static String toString(final FsPermission permission) {
175 return String.format("%o", permission.toShort());
176 }
177
178 /** Convert a string to a FsPermission object. */
179 private static FsPermission toFsPermission(final String s) {
180 return new FsPermission(Short.parseShort(s, 8));
181 }
182
183 static enum PathType {
184 FILE, DIRECTORY, SYMLINK;
185
186 static PathType valueOf(HdfsFileStatus status) {
187 return status.isDir()? DIRECTORY: status.isSymlink()? SYMLINK: FILE;
188 }
189 }
190
191 /** Convert a HdfsFileStatus object to a Json string. */
192 public static String toJsonString(final HdfsFileStatus status,
193 boolean includeType) {
194 if (status == null) {
195 return null;
196 }
197 final Map<String, Object> m = new TreeMap<String, Object>();
198 m.put("pathSuffix", status.getLocalName());
199 m.put("type", PathType.valueOf(status));
200 if (status.isSymlink()) {
201 m.put("symlink", status.getSymlink());
202 }
203
204 m.put("length", status.getLen());
205 m.put("owner", status.getOwner());
206 m.put("group", status.getGroup());
207 m.put("permission", toString(status.getPermission()));
208 m.put("accessTime", status.getAccessTime());
209 m.put("modificationTime", status.getModificationTime());
210 m.put("blockSize", status.getBlockSize());
211 m.put("replication", status.getReplication());
212 m.put("fileId", status.getFileId());
213 m.put("childrenNum", status.getChildrenNum());
214 return includeType ? toJsonString(FileStatus.class, m): JSON.toString(m);
215 }
216
217 /** Convert a Json map to a HdfsFileStatus object. */
218 public static HdfsFileStatus toFileStatus(final Map<?, ?> json, boolean includesType) {
219 if (json == null) {
220 return null;
221 }
222
223 final Map<?, ?> m = includesType ?
224 (Map<?, ?>)json.get(FileStatus.class.getSimpleName()) : json;
225 final String localName = (String) m.get("pathSuffix");
226 final PathType type = PathType.valueOf((String) m.get("type"));
227 final byte[] symlink = type != PathType.SYMLINK? null
228 : DFSUtil.string2Bytes((String)m.get("symlink"));
229
230 final long len = (Long) m.get("length");
231 final String owner = (String) m.get("owner");
232 final String group = (String) m.get("group");
233 final FsPermission permission = toFsPermission((String) m.get("permission"));
234 final long aTime = (Long) m.get("accessTime");
235 final long mTime = (Long) m.get("modificationTime");
236 final long blockSize = (Long) m.get("blockSize");
237 final short replication = (short) (long) (Long) m.get("replication");
238 final long fileId = m.containsKey("fileId") ? (Long) m.get("fileId")
239 : INodeId.GRANDFATHER_INODE_ID;
240 Long childrenNumLong = (Long) m.get("childrenNum");
241 final int childrenNum = (childrenNumLong == null) ? -1
242 : childrenNumLong.intValue();
243 return new HdfsFileStatus(len, type == PathType.DIRECTORY, replication,
244 blockSize, mTime, aTime, permission, owner, group,
245 symlink, DFSUtil.string2Bytes(localName), fileId, childrenNum);
246 }
247
248 /** Convert an ExtendedBlock to a Json map. */
249 private static Map<String, Object> toJsonMap(final ExtendedBlock extendedblock) {
250 if (extendedblock == null) {
251 return null;
252 }
253
254 final Map<String, Object> m = new TreeMap<String, Object>();
255 m.put("blockPoolId", extendedblock.getBlockPoolId());
256 m.put("blockId", extendedblock.getBlockId());
257 m.put("numBytes", extendedblock.getNumBytes());
258 m.put("generationStamp", extendedblock.getGenerationStamp());
259 return m;
260 }
261
262 /** Convert a Json map to an ExtendedBlock object. */
263 private static ExtendedBlock toExtendedBlock(final Map<?, ?> m) {
264 if (m == null) {
265 return null;
266 }
267
268 final String blockPoolId = (String)m.get("blockPoolId");
269 final long blockId = (Long)m.get("blockId");
270 final long numBytes = (Long)m.get("numBytes");
271 final long generationStamp = (Long)m.get("generationStamp");
272 return new ExtendedBlock(blockPoolId, blockId, numBytes, generationStamp);
273 }
274
275 /** Convert a DatanodeInfo to a Json map. */
276 static Map<String, Object> toJsonMap(final DatanodeInfo datanodeinfo) {
277 if (datanodeinfo == null) {
278 return null;
279 }
280
281 // TODO: Fix storageID
282 final Map<String, Object> m = new TreeMap<String, Object>();
283 m.put("ipAddr", datanodeinfo.getIpAddr());
284 // 'name' is equivalent to ipAddr:xferPort. Older clients (1.x, 0.23.x)
285 // expects this instead of the two fields.
286 m.put("name", datanodeinfo.getXferAddr());
287 m.put("hostName", datanodeinfo.getHostName());
288 m.put("storageID", datanodeinfo.getDatanodeUuid());
289 m.put("xferPort", datanodeinfo.getXferPort());
290 m.put("infoPort", datanodeinfo.getInfoPort());
291 m.put("infoSecurePort", datanodeinfo.getInfoSecurePort());
292 m.put("ipcPort", datanodeinfo.getIpcPort());
293
294 m.put("capacity", datanodeinfo.getCapacity());
295 m.put("dfsUsed", datanodeinfo.getDfsUsed());
296 m.put("remaining", datanodeinfo.getRemaining());
297 m.put("blockPoolUsed", datanodeinfo.getBlockPoolUsed());
298 m.put("cacheCapacity", datanodeinfo.getCacheCapacity());
299 m.put("cacheUsed", datanodeinfo.getCacheUsed());
300 m.put("lastUpdate", datanodeinfo.getLastUpdate());
301 m.put("xceiverCount", datanodeinfo.getXceiverCount());
302 m.put("networkLocation", datanodeinfo.getNetworkLocation());
303 m.put("adminState", datanodeinfo.getAdminState().name());
304 return m;
305 }
306
307 private static int getInt(Map<?, ?> m, String key, final int defaultValue) {
308 Object value = m.get(key);
309 if (value == null) {
310 return defaultValue;
311 }
312 return (int) (long) (Long) value;
313 }
314
315 private static long getLong(Map<?, ?> m, String key, final long defaultValue) {
316 Object value = m.get(key);
317 if (value == null) {
318 return defaultValue;
319 }
320 return (long) (Long) value;
321 }
322
323 private static String getString(Map<?, ?> m, String key,
324 final String defaultValue) {
325 Object value = m.get(key);
326 if (value == null) {
327 return defaultValue;
328 }
329 return (String) value;
330 }
331
332 /** Convert a Json map to an DatanodeInfo object. */
333 static DatanodeInfo toDatanodeInfo(final Map<?, ?> m)
334 throws IOException {
335 if (m == null) {
336 return null;
337 }
338
339 // ipAddr and xferPort are the critical fields for accessing data.
340 // If any one of the two is missing, an exception needs to be thrown.
341
342 // Handle the case of old servers (1.x, 0.23.x) sending 'name' instead
343 // of ipAddr and xferPort.
344 Object tmpValue = m.get("ipAddr");
345 String ipAddr = (tmpValue == null) ? null : (String)tmpValue;
346 tmpValue = m.get("xferPort");
347 int xferPort = (tmpValue == null) ? -1 : (int)(long)(Long)tmpValue;
348 if (ipAddr == null) {
349 tmpValue = m.get("name");
350 if (tmpValue != null) {
351 String name = (String)tmpValue;
352 int colonIdx = name.indexOf(':');
353 if (colonIdx > 0) {
354 ipAddr = name.substring(0, colonIdx);
355 xferPort = Integer.parseInt(name.substring(colonIdx +1));
356 } else {
357 throw new IOException(
358 "Invalid value in server response: name=[" + name + "]");
359 }
360 } else {
361 throw new IOException(
362 "Missing both 'ipAddr' and 'name' in server response.");
363 }
364 // ipAddr is non-null & non-empty string at this point.
365 }
366
367 // Check the validity of xferPort.
368 if (xferPort == -1) {
369 throw new IOException(
370 "Invalid or missing 'xferPort' in server response.");
371 }
372
373 // TODO: Fix storageID
374 return new DatanodeInfo(
375 ipAddr,
376 (String)m.get("hostName"),
377 (String)m.get("storageID"),
378 xferPort,
379 (int)(long)(Long)m.get("infoPort"),
380 getInt(m, "infoSecurePort", 0),
381 (int)(long)(Long)m.get("ipcPort"),
382
383 getLong(m, "capacity", 0l),
384 getLong(m, "dfsUsed", 0l),
385 getLong(m, "remaining", 0l),
386 getLong(m, "blockPoolUsed", 0l),
387 getLong(m, "cacheCapacity", 0l),
388 getLong(m, "cacheUsed", 0l),
389 getLong(m, "lastUpdate", 0l),
390 getInt(m, "xceiverCount", 0),
391 getString(m, "networkLocation", ""),
392 AdminStates.valueOf(getString(m, "adminState", "NORMAL")));
393 }
394
395 /** Convert a DatanodeInfo[] to a Json array. */
396 private static Object[] toJsonArray(final DatanodeInfo[] array) {
397 if (array == null) {
398 return null;
399 } else if (array.length == 0) {
400 return EMPTY_OBJECT_ARRAY;
401 } else {
402 final Object[] a = new Object[array.length];
403 for(int i = 0; i < array.length; i++) {
404 a[i] = toJsonMap(array[i]);
405 }
406 return a;
407 }
408 }
409
410 /** Convert an Object[] to a DatanodeInfo[]. */
411 private static DatanodeInfo[] toDatanodeInfoArray(final Object[] objects)
412 throws IOException {
413 if (objects == null) {
414 return null;
415 } else if (objects.length == 0) {
416 return EMPTY_DATANODE_INFO_ARRAY;
417 } else {
418 final DatanodeInfo[] array = new DatanodeInfo[objects.length];
419 for(int i = 0; i < array.length; i++) {
420 array[i] = toDatanodeInfo((Map<?, ?>) objects[i]);
421 }
422 return array;
423 }
424 }
425
426 /** Convert a LocatedBlock to a Json map. */
427 private static Map<String, Object> toJsonMap(final LocatedBlock locatedblock
428 ) throws IOException {
429 if (locatedblock == null) {
430 return null;
431 }
432
433 final Map<String, Object> m = new TreeMap<String, Object>();
434 m.put("blockToken", toJsonMap(locatedblock.getBlockToken()));
435 m.put("isCorrupt", locatedblock.isCorrupt());
436 m.put("startOffset", locatedblock.getStartOffset());
437 m.put("block", toJsonMap(locatedblock.getBlock()));
438 m.put("locations", toJsonArray(locatedblock.getLocations()));
439 m.put("cachedLocations", toJsonArray(locatedblock.getCachedLocations()));
440 return m;
441 }
442
443 /** Convert a Json map to LocatedBlock. */
444 private static LocatedBlock toLocatedBlock(final Map<?, ?> m) throws IOException {
445 if (m == null) {
446 return null;
447 }
448
449 final ExtendedBlock b = toExtendedBlock((Map<?, ?>)m.get("block"));
450 final DatanodeInfo[] locations = toDatanodeInfoArray(
451 (Object[])m.get("locations"));
452 final long startOffset = (Long)m.get("startOffset");
453 final boolean isCorrupt = (Boolean)m.get("isCorrupt");
454 final DatanodeInfo[] cachedLocations = toDatanodeInfoArray(
455 (Object[])m.get("cachedLocations"));
456
457 final LocatedBlock locatedblock = new LocatedBlock(b, locations,
458 null, null, startOffset, isCorrupt, cachedLocations);
459 locatedblock.setBlockToken(toBlockToken((Map<?, ?>)m.get("blockToken")));
460 return locatedblock;
461 }
462
463 /** Convert a LocatedBlock[] to a Json array. */
464 private static Object[] toJsonArray(final List<LocatedBlock> array
465 ) throws IOException {
466 if (array == null) {
467 return null;
468 } else if (array.size() == 0) {
469 return EMPTY_OBJECT_ARRAY;
470 } else {
471 final Object[] a = new Object[array.size()];
472 for(int i = 0; i < array.size(); i++) {
473 a[i] = toJsonMap(array.get(i));
474 }
475 return a;
476 }
477 }
478
479 /** Convert an Object[] to a List of LocatedBlock. */
480 private static List<LocatedBlock> toLocatedBlockList(final Object[] objects
481 ) throws IOException {
482 if (objects == null) {
483 return null;
484 } else if (objects.length == 0) {
485 return Collections.emptyList();
486 } else {
487 final List<LocatedBlock> list = new ArrayList<LocatedBlock>(objects.length);
488 for(int i = 0; i < objects.length; i++) {
489 list.add(toLocatedBlock((Map<?, ?>)objects[i]));
490 }
491 return list;
492 }
493 }
494
495 /** Convert LocatedBlocks to a Json string. */
496 public static String toJsonString(final LocatedBlocks locatedblocks
497 ) throws IOException {
498 if (locatedblocks == null) {
499 return null;
500 }
501
502 final Map<String, Object> m = new TreeMap<String, Object>();
503 m.put("fileLength", locatedblocks.getFileLength());
504 m.put("isUnderConstruction", locatedblocks.isUnderConstruction());
505
506 m.put("locatedBlocks", toJsonArray(locatedblocks.getLocatedBlocks()));
507 m.put("lastLocatedBlock", toJsonMap(locatedblocks.getLastLocatedBlock()));
508 m.put("isLastBlockComplete", locatedblocks.isLastBlockComplete());
509 return toJsonString(LocatedBlocks.class, m);
510 }
511
512 /** Convert a Json map to LocatedBlock. */
513 public static LocatedBlocks toLocatedBlocks(final Map<?, ?> json
514 ) throws IOException {
515 if (json == null) {
516 return null;
517 }
518
519 final Map<?, ?> m = (Map<?, ?>)json.get(LocatedBlocks.class.getSimpleName());
520 final long fileLength = (Long)m.get("fileLength");
521 final boolean isUnderConstruction = (Boolean)m.get("isUnderConstruction");
522 final List<LocatedBlock> locatedBlocks = toLocatedBlockList(
523 (Object[])m.get("locatedBlocks"));
524 final LocatedBlock lastLocatedBlock = toLocatedBlock(
525 (Map<?, ?>)m.get("lastLocatedBlock"));
526 final boolean isLastBlockComplete = (Boolean)m.get("isLastBlockComplete");
527 return new LocatedBlocks(fileLength, isUnderConstruction, locatedBlocks,
528 lastLocatedBlock, isLastBlockComplete);
529 }
530
531 /** Convert a ContentSummary to a Json string. */
532 public static String toJsonString(final ContentSummary contentsummary) {
533 if (contentsummary == null) {
534 return null;
535 }
536
537 final Map<String, Object> m = new TreeMap<String, Object>();
538 m.put("length", contentsummary.getLength());
539 m.put("fileCount", contentsummary.getFileCount());
540 m.put("directoryCount", contentsummary.getDirectoryCount());
541 m.put("quota", contentsummary.getQuota());
542 m.put("spaceConsumed", contentsummary.getSpaceConsumed());
543 m.put("spaceQuota", contentsummary.getSpaceQuota());
544 return toJsonString(ContentSummary.class, m);
545 }
546
547 /** Convert a Json map to a ContentSummary. */
548 public static ContentSummary toContentSummary(final Map<?, ?> json) {
549 if (json == null) {
550 return null;
551 }
552
553 final Map<?, ?> m = (Map<?, ?>)json.get(ContentSummary.class.getSimpleName());
554 final long length = (Long)m.get("length");
555 final long fileCount = (Long)m.get("fileCount");
556 final long directoryCount = (Long)m.get("directoryCount");
557 final long quota = (Long)m.get("quota");
558 final long spaceConsumed = (Long)m.get("spaceConsumed");
559 final long spaceQuota = (Long)m.get("spaceQuota");
560
561 return new ContentSummary(length, fileCount, directoryCount,
562 quota, spaceConsumed, spaceQuota);
563 }
564
565 /** Convert a MD5MD5CRC32FileChecksum to a Json string. */
566 public static String toJsonString(final MD5MD5CRC32FileChecksum checksum) {
567 if (checksum == null) {
568 return null;
569 }
570
571 final Map<String, Object> m = new TreeMap<String, Object>();
572 m.put("algorithm", checksum.getAlgorithmName());
573 m.put("length", checksum.getLength());
574 m.put("bytes", StringUtils.byteToHexString(checksum.getBytes()));
575 return toJsonString(FileChecksum.class, m);
576 }
577
578 /** Convert a Json map to a MD5MD5CRC32FileChecksum. */
579 public static MD5MD5CRC32FileChecksum toMD5MD5CRC32FileChecksum(
580 final Map<?, ?> json) throws IOException {
581 if (json == null) {
582 return null;
583 }
584
585 final Map<?, ?> m = (Map<?, ?>)json.get(FileChecksum.class.getSimpleName());
586 final String algorithm = (String)m.get("algorithm");
587 final int length = (int)(long)(Long)m.get("length");
588 final byte[] bytes = StringUtils.hexStringToByte((String)m.get("bytes"));
589
590 final DataInputStream in = new DataInputStream(new ByteArrayInputStream(bytes));
591 final DataChecksum.Type crcType =
592 MD5MD5CRC32FileChecksum.getCrcTypeFromAlgorithmName(algorithm);
593 final MD5MD5CRC32FileChecksum checksum;
594
595 // Recreate what DFSClient would have returned.
596 switch(crcType) {
597 case CRC32:
598 checksum = new MD5MD5CRC32GzipFileChecksum();
599 break;
600 case CRC32C:
601 checksum = new MD5MD5CRC32CastagnoliFileChecksum();
602 break;
603 default:
604 throw new IOException("Unknown algorithm: " + algorithm);
605 }
606 checksum.readFields(in);
607
608 //check algorithm name
609 if (!checksum.getAlgorithmName().equals(algorithm)) {
610 throw new IOException("Algorithm not matched. Expected " + algorithm
611 + ", Received " + checksum.getAlgorithmName());
612 }
613 //check length
614 if (length != checksum.getLength()) {
615 throw new IOException("Length not matched: length=" + length
616 + ", checksum.getLength()=" + checksum.getLength());
617 }
618
619 return checksum;
620 }
621 /** Convert a AclStatus object to a Json string. */
622 public static String toJsonString(final AclStatus status) {
623 if (status == null) {
624 return null;
625 }
626
627 final Map<String, Object> m = new TreeMap<String, Object>();
628 m.put("owner", status.getOwner());
629 m.put("group", status.getGroup());
630 m.put("stickyBit", status.isStickyBit());
631 m.put("entries", status.getEntries());
632 final Map<String, Map<String, Object>> finalMap =
633 new TreeMap<String, Map<String, Object>>();
634 finalMap.put(AclStatus.class.getSimpleName(), m);
635 return JSON.toString(finalMap);
636 }
637
638 /** Convert a Json map to a AclStatus object. */
639 public static AclStatus toAclStatus(final Map<?, ?> json) {
640 if (json == null) {
641 return null;
642 }
643
644 final Map<?, ?> m = (Map<?, ?>) json.get(AclStatus.class.getSimpleName());
645
646 AclStatus.Builder aclStatusBuilder = new AclStatus.Builder();
647 aclStatusBuilder.owner((String) m.get("owner"));
648 aclStatusBuilder.group((String) m.get("group"));
649 aclStatusBuilder.stickyBit((Boolean) m.get("stickyBit"));
650
651 final Object[] entries = (Object[]) m.get("entries");
652
653 List<AclEntry> aclEntryList = new ArrayList<AclEntry>();
654 for (int i = 0; i < entries.length; i++) {
655 AclEntry aclEntry = AclEntry.parseAclEntry((String) entries[i], true);
656 aclEntryList.add(aclEntry);
657 }
658 aclStatusBuilder.addEntries(aclEntryList);
659 return aclStatusBuilder.build();
660 }
661 }