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 */ 018package org.apache.hadoop.hdfs.web; 019 020import org.apache.hadoop.fs.*; 021import org.apache.hadoop.fs.permission.AclEntry; 022import org.apache.hadoop.fs.permission.AclStatus; 023import org.apache.hadoop.fs.permission.FsPermission; 024import org.apache.hadoop.hdfs.DFSUtil; 025import org.apache.hadoop.hdfs.XAttrHelper; 026import org.apache.hadoop.hdfs.protocol.*; 027import org.apache.hadoop.hdfs.protocol.DatanodeInfo.AdminStates; 028import org.apache.hadoop.hdfs.security.token.block.BlockTokenIdentifier; 029import org.apache.hadoop.hdfs.security.token.delegation.DelegationTokenIdentifier; 030import org.apache.hadoop.hdfs.server.blockmanagement.BlockStoragePolicySuite; 031import org.apache.hadoop.hdfs.server.namenode.INodeId; 032import org.apache.hadoop.ipc.RemoteException; 033import org.apache.hadoop.security.token.Token; 034import org.apache.hadoop.security.token.TokenIdentifier; 035import org.apache.hadoop.util.DataChecksum; 036import org.apache.hadoop.util.StringUtils; 037import org.codehaus.jackson.map.ObjectMapper; 038import org.codehaus.jackson.map.ObjectReader; 039 040import com.google.common.collect.Lists; 041import com.google.common.collect.Maps; 042 043import java.io.ByteArrayInputStream; 044import java.io.DataInputStream; 045import java.io.IOException; 046import java.util.*; 047 048/** JSON Utilities */ 049public class JsonUtil { 050 private static final Object[] EMPTY_OBJECT_ARRAY = {}; 051 private static final DatanodeInfo[] EMPTY_DATANODE_INFO_ARRAY = {}; 052 053 /** Convert a token object to a Json string. */ 054 public static String toJsonString(final Token<? extends TokenIdentifier> token 055 ) throws IOException { 056 return toJsonString(Token.class, toJsonMap(token)); 057 } 058 059 private static Map<String, Object> toJsonMap( 060 final Token<? extends TokenIdentifier> token) throws IOException { 061 if (token == null) { 062 return null; 063 } 064 065 final Map<String, Object> m = new TreeMap<String, Object>(); 066 m.put("urlString", token.encodeToUrlString()); 067 return m; 068 } 069 070 /** Convert a Json map to a Token. */ 071 public static Token<? extends TokenIdentifier> toToken( 072 final Map<?, ?> m) throws IOException { 073 if (m == null) { 074 return null; 075 } 076 077 final Token<DelegationTokenIdentifier> token 078 = new Token<DelegationTokenIdentifier>(); 079 token.decodeFromUrlString((String)m.get("urlString")); 080 return token; 081 } 082 083 /** Convert a Json map to a Token of DelegationTokenIdentifier. */ 084 @SuppressWarnings("unchecked") 085 public static Token<DelegationTokenIdentifier> toDelegationToken( 086 final Map<?, ?> json) throws IOException { 087 final Map<?, ?> m = (Map<?, ?>)json.get(Token.class.getSimpleName()); 088 return (Token<DelegationTokenIdentifier>)toToken(m); 089 } 090 091 /** Convert a Json map to a Token of BlockTokenIdentifier. */ 092 @SuppressWarnings("unchecked") 093 private static Token<BlockTokenIdentifier> toBlockToken( 094 final Map<?, ?> m) throws IOException { 095 return (Token<BlockTokenIdentifier>)toToken(m); 096 } 097 098 /** Convert an exception object to a Json string. */ 099 public static String toJsonString(final Exception e) { 100 final Map<String, Object> m = new TreeMap<String, Object>(); 101 m.put("exception", e.getClass().getSimpleName()); 102 m.put("message", e.getMessage()); 103 m.put("javaClassName", e.getClass().getName()); 104 return toJsonString(RemoteException.class, m); 105 } 106 107 /** Convert a Json map to a RemoteException. */ 108 public static RemoteException toRemoteException(final Map<?, ?> json) { 109 final Map<?, ?> m = (Map<?, ?>)json.get(RemoteException.class.getSimpleName()); 110 final String message = (String)m.get("message"); 111 final String javaClassName = (String)m.get("javaClassName"); 112 return new RemoteException(javaClassName, message); 113 } 114 115 private static String toJsonString(final Class<?> clazz, final Object value) { 116 return toJsonString(clazz.getSimpleName(), value); 117 } 118 119 /** Convert a key-value pair to a Json string. */ 120 public static String toJsonString(final String key, final Object value) { 121 final Map<String, Object> m = new TreeMap<String, Object>(); 122 m.put(key, value); 123 ObjectMapper mapper = new ObjectMapper(); 124 try { 125 return mapper.writeValueAsString(m); 126 } catch (IOException ignored) { 127 } 128 return null; 129 } 130 131 /** Convert a FsPermission object to a string. */ 132 private static String toString(final FsPermission permission) { 133 return String.format("%o", permission.toShort()); 134 } 135 136 /** Convert a string to a FsPermission object. */ 137 private static FsPermission toFsPermission(final String s, Boolean aclBit, 138 Boolean encBit) { 139 FsPermission perm = new FsPermission(Short.parseShort(s, 8)); 140 final boolean aBit = (aclBit != null) ? aclBit : false; 141 final boolean eBit = (encBit != null) ? encBit : false; 142 if (aBit || eBit) { 143 return new FsPermissionExtension(perm, aBit, eBit); 144 } else { 145 return perm; 146 } 147 } 148 149 static enum PathType { 150 FILE, DIRECTORY, SYMLINK; 151 152 static PathType valueOf(HdfsFileStatus status) { 153 return status.isDir()? DIRECTORY: status.isSymlink()? SYMLINK: FILE; 154 } 155 } 156 157 /** Convert a HdfsFileStatus object to a Json string. */ 158 public static String toJsonString(final HdfsFileStatus status, 159 boolean includeType) { 160 if (status == null) { 161 return null; 162 } 163 final Map<String, Object> m = new TreeMap<String, Object>(); 164 m.put("pathSuffix", status.getLocalName()); 165 m.put("type", PathType.valueOf(status)); 166 if (status.isSymlink()) { 167 m.put("symlink", status.getSymlink()); 168 } 169 170 m.put("length", status.getLen()); 171 m.put("owner", status.getOwner()); 172 m.put("group", status.getGroup()); 173 FsPermission perm = status.getPermission(); 174 m.put("permission", toString(perm)); 175 if (perm.getAclBit()) { 176 m.put("aclBit", true); 177 } 178 if (perm.getEncryptedBit()) { 179 m.put("encBit", true); 180 } 181 m.put("accessTime", status.getAccessTime()); 182 m.put("modificationTime", status.getModificationTime()); 183 m.put("blockSize", status.getBlockSize()); 184 m.put("replication", status.getReplication()); 185 m.put("fileId", status.getFileId()); 186 m.put("childrenNum", status.getChildrenNum()); 187 m.put("storagePolicy", status.getStoragePolicy()); 188 ObjectMapper mapper = new ObjectMapper(); 189 try { 190 return includeType ? 191 toJsonString(FileStatus.class, m) : mapper.writeValueAsString(m); 192 } catch (IOException ignored) { 193 } 194 return null; 195 } 196 197 /** Convert a Json map to a HdfsFileStatus object. */ 198 public static HdfsFileStatus toFileStatus(final Map<?, ?> json, boolean includesType) { 199 if (json == null) { 200 return null; 201 } 202 203 final Map<?, ?> m = includesType ? 204 (Map<?, ?>)json.get(FileStatus.class.getSimpleName()) : json; 205 final String localName = (String) m.get("pathSuffix"); 206 final PathType type = PathType.valueOf((String) m.get("type")); 207 final byte[] symlink = type != PathType.SYMLINK? null 208 : DFSUtil.string2Bytes((String)m.get("symlink")); 209 210 final long len = ((Number) m.get("length")).longValue(); 211 final String owner = (String) m.get("owner"); 212 final String group = (String) m.get("group"); 213 final FsPermission permission = toFsPermission((String) m.get("permission"), 214 (Boolean)m.get("aclBit"), (Boolean)m.get("encBit")); 215 final long aTime = ((Number) m.get("accessTime")).longValue(); 216 final long mTime = ((Number) m.get("modificationTime")).longValue(); 217 final long blockSize = ((Number) m.get("blockSize")).longValue(); 218 final short replication = ((Number) m.get("replication")).shortValue(); 219 final long fileId = m.containsKey("fileId") ? 220 ((Number) m.get("fileId")).longValue() : INodeId.GRANDFATHER_INODE_ID; 221 final int childrenNum = getInt(m, "childrenNum", -1); 222 final byte storagePolicy = m.containsKey("storagePolicy") ? 223 (byte) ((Number) m.get("storagePolicy")).longValue() : 224 BlockStoragePolicySuite.ID_UNSPECIFIED; 225 return new HdfsFileStatus(len, type == PathType.DIRECTORY, replication, 226 blockSize, mTime, aTime, permission, owner, group, symlink, 227 DFSUtil.string2Bytes(localName), fileId, childrenNum, null, storagePolicy); 228 } 229 230 /** Convert an ExtendedBlock to a Json map. */ 231 private static Map<String, Object> toJsonMap(final ExtendedBlock extendedblock) { 232 if (extendedblock == null) { 233 return null; 234 } 235 236 final Map<String, Object> m = new TreeMap<String, Object>(); 237 m.put("blockPoolId", extendedblock.getBlockPoolId()); 238 m.put("blockId", extendedblock.getBlockId()); 239 m.put("numBytes", extendedblock.getNumBytes()); 240 m.put("generationStamp", extendedblock.getGenerationStamp()); 241 return m; 242 } 243 244 /** Convert a Json map to an ExtendedBlock object. */ 245 private static ExtendedBlock toExtendedBlock(final Map<?, ?> m) { 246 if (m == null) { 247 return null; 248 } 249 250 final String blockPoolId = (String)m.get("blockPoolId"); 251 final long blockId = ((Number) m.get("blockId")).longValue(); 252 final long numBytes = ((Number) m.get("numBytes")).longValue(); 253 final long generationStamp = 254 ((Number) m.get("generationStamp")).longValue(); 255 return new ExtendedBlock(blockPoolId, blockId, numBytes, generationStamp); 256 } 257 258 /** Convert a DatanodeInfo to a Json map. */ 259 static Map<String, Object> toJsonMap(final DatanodeInfo datanodeinfo) { 260 if (datanodeinfo == null) { 261 return null; 262 } 263 264 // TODO: Fix storageID 265 final Map<String, Object> m = new TreeMap<String, Object>(); 266 m.put("ipAddr", datanodeinfo.getIpAddr()); 267 // 'name' is equivalent to ipAddr:xferPort. Older clients (1.x, 0.23.x) 268 // expects this instead of the two fields. 269 m.put("name", datanodeinfo.getXferAddr()); 270 m.put("hostName", datanodeinfo.getHostName()); 271 m.put("storageID", datanodeinfo.getDatanodeUuid()); 272 m.put("xferPort", datanodeinfo.getXferPort()); 273 m.put("infoPort", datanodeinfo.getInfoPort()); 274 m.put("infoSecurePort", datanodeinfo.getInfoSecurePort()); 275 m.put("ipcPort", datanodeinfo.getIpcPort()); 276 277 m.put("capacity", datanodeinfo.getCapacity()); 278 m.put("dfsUsed", datanodeinfo.getDfsUsed()); 279 m.put("remaining", datanodeinfo.getRemaining()); 280 m.put("blockPoolUsed", datanodeinfo.getBlockPoolUsed()); 281 m.put("cacheCapacity", datanodeinfo.getCacheCapacity()); 282 m.put("cacheUsed", datanodeinfo.getCacheUsed()); 283 m.put("lastUpdate", datanodeinfo.getLastUpdate()); 284 m.put("lastUpdateMonotonic", datanodeinfo.getLastUpdateMonotonic()); 285 m.put("xceiverCount", datanodeinfo.getXceiverCount()); 286 m.put("networkLocation", datanodeinfo.getNetworkLocation()); 287 m.put("adminState", datanodeinfo.getAdminState().name()); 288 return m; 289 } 290 291 private static int getInt(Map<?, ?> m, String key, final int defaultValue) { 292 Object value = m.get(key); 293 if (value == null) { 294 return defaultValue; 295 } 296 return ((Number) value).intValue(); 297 } 298 299 private static long getLong(Map<?, ?> m, String key, final long defaultValue) { 300 Object value = m.get(key); 301 if (value == null) { 302 return defaultValue; 303 } 304 return ((Number) value).longValue(); 305 } 306 307 private static String getString(Map<?, ?> m, String key, 308 final String defaultValue) { 309 Object value = m.get(key); 310 if (value == null) { 311 return defaultValue; 312 } 313 return (String) value; 314 } 315 316 static List<?> getList(Map<?, ?> m, String key) { 317 Object list = m.get(key); 318 if (list instanceof List<?>) { 319 return (List<?>) list; 320 } else { 321 return null; 322 } 323 } 324 325 /** Convert a Json map to an DatanodeInfo object. */ 326 static DatanodeInfo toDatanodeInfo(final Map<?, ?> m) 327 throws IOException { 328 if (m == null) { 329 return null; 330 } 331 332 // ipAddr and xferPort are the critical fields for accessing data. 333 // If any one of the two is missing, an exception needs to be thrown. 334 335 // Handle the case of old servers (1.x, 0.23.x) sending 'name' instead 336 // of ipAddr and xferPort. 337 Object tmpValue = m.get("ipAddr"); 338 String ipAddr = (tmpValue == null) ? null : (String)tmpValue; 339 tmpValue = m.get("xferPort"); 340 int xferPort = (tmpValue == null) ? -1 : (int)(long)(Long)tmpValue; 341 if (ipAddr == null) { 342 tmpValue = m.get("name"); 343 if (tmpValue != null) { 344 String name = (String)tmpValue; 345 int colonIdx = name.indexOf(':'); 346 if (colonIdx > 0) { 347 ipAddr = name.substring(0, colonIdx); 348 xferPort = Integer.parseInt(name.substring(colonIdx +1)); 349 } else { 350 throw new IOException( 351 "Invalid value in server response: name=[" + name + "]"); 352 } 353 } else { 354 throw new IOException( 355 "Missing both 'ipAddr' and 'name' in server response."); 356 } 357 // ipAddr is non-null & non-empty string at this point. 358 } 359 360 // Check the validity of xferPort. 361 if (xferPort == -1) { 362 throw new IOException( 363 "Invalid or missing 'xferPort' in server response."); 364 } 365 366 // TODO: Fix storageID 367 return new DatanodeInfo( 368 ipAddr, 369 (String)m.get("hostName"), 370 (String)m.get("storageID"), 371 xferPort, 372 ((Number) m.get("infoPort")).intValue(), 373 getInt(m, "infoSecurePort", 0), 374 ((Number) m.get("ipcPort")).intValue(), 375 376 getLong(m, "capacity", 0l), 377 getLong(m, "dfsUsed", 0l), 378 getLong(m, "remaining", 0l), 379 getLong(m, "blockPoolUsed", 0l), 380 getLong(m, "cacheCapacity", 0l), 381 getLong(m, "cacheUsed", 0l), 382 getLong(m, "lastUpdate", 0l), 383 getLong(m, "lastUpdateMonotonic", 0l), 384 getInt(m, "xceiverCount", 0), 385 getString(m, "networkLocation", ""), 386 AdminStates.valueOf(getString(m, "adminState", "NORMAL"))); 387 } 388 389 /** Convert a DatanodeInfo[] to a Json array. */ 390 private static Object[] toJsonArray(final DatanodeInfo[] array) { 391 if (array == null) { 392 return null; 393 } else if (array.length == 0) { 394 return EMPTY_OBJECT_ARRAY; 395 } else { 396 final Object[] a = new Object[array.length]; 397 for(int i = 0; i < array.length; i++) { 398 a[i] = toJsonMap(array[i]); 399 } 400 return a; 401 } 402 } 403 404 /** Convert an Object[] to a DatanodeInfo[]. */ 405 private static DatanodeInfo[] toDatanodeInfoArray(final List<?> objects) 406 throws IOException { 407 if (objects == null) { 408 return null; 409 } else if (objects.isEmpty()) { 410 return EMPTY_DATANODE_INFO_ARRAY; 411 } else { 412 final DatanodeInfo[] array = new DatanodeInfo[objects.size()]; 413 int i = 0; 414 for (Object object : objects) { 415 array[i++] = toDatanodeInfo((Map<?, ?>) object); 416 } 417 return array; 418 } 419 } 420 421 /** Convert a LocatedBlock to a Json map. */ 422 private static Map<String, Object> toJsonMap(final LocatedBlock locatedblock 423 ) throws IOException { 424 if (locatedblock == null) { 425 return null; 426 } 427 428 final Map<String, Object> m = new TreeMap<String, Object>(); 429 m.put("blockToken", toJsonMap(locatedblock.getBlockToken())); 430 m.put("isCorrupt", locatedblock.isCorrupt()); 431 m.put("startOffset", locatedblock.getStartOffset()); 432 m.put("block", toJsonMap(locatedblock.getBlock())); 433 m.put("locations", toJsonArray(locatedblock.getLocations())); 434 m.put("cachedLocations", toJsonArray(locatedblock.getCachedLocations())); 435 return m; 436 } 437 438 /** Convert a Json map to LocatedBlock. */ 439 private static LocatedBlock toLocatedBlock(final Map<?, ?> m) throws IOException { 440 if (m == null) { 441 return null; 442 } 443 444 final ExtendedBlock b = toExtendedBlock((Map<?, ?>)m.get("block")); 445 final DatanodeInfo[] locations = toDatanodeInfoArray( 446 getList(m, "locations")); 447 final long startOffset = ((Number) m.get("startOffset")).longValue(); 448 final boolean isCorrupt = (Boolean)m.get("isCorrupt"); 449 final DatanodeInfo[] cachedLocations = toDatanodeInfoArray( 450 getList(m, "cachedLocations")); 451 452 final LocatedBlock locatedblock = new LocatedBlock(b, locations, 453 null, null, startOffset, isCorrupt, cachedLocations); 454 locatedblock.setBlockToken(toBlockToken((Map<?, ?>)m.get("blockToken"))); 455 return locatedblock; 456 } 457 458 /** Convert a LocatedBlock[] to a Json array. */ 459 private static Object[] toJsonArray(final List<LocatedBlock> array 460 ) throws IOException { 461 if (array == null) { 462 return null; 463 } else if (array.size() == 0) { 464 return EMPTY_OBJECT_ARRAY; 465 } else { 466 final Object[] a = new Object[array.size()]; 467 for(int i = 0; i < array.size(); i++) { 468 a[i] = toJsonMap(array.get(i)); 469 } 470 return a; 471 } 472 } 473 474 /** Convert an List of Object to a List of LocatedBlock. */ 475 private static List<LocatedBlock> toLocatedBlockList( 476 final List<?> objects) throws IOException { 477 if (objects == null) { 478 return null; 479 } else if (objects.isEmpty()) { 480 return Collections.emptyList(); 481 } else { 482 final List<LocatedBlock> list = new ArrayList<>(objects.size()); 483 for (Object object : objects) { 484 list.add(toLocatedBlock((Map<?, ?>) object)); 485 } 486 return list; 487 } 488 } 489 490 /** Convert LocatedBlocks to a Json string. */ 491 public static String toJsonString(final LocatedBlocks locatedblocks 492 ) throws IOException { 493 if (locatedblocks == null) { 494 return null; 495 } 496 497 final Map<String, Object> m = new TreeMap<String, Object>(); 498 m.put("fileLength", locatedblocks.getFileLength()); 499 m.put("isUnderConstruction", locatedblocks.isUnderConstruction()); 500 501 m.put("locatedBlocks", toJsonArray(locatedblocks.getLocatedBlocks())); 502 m.put("lastLocatedBlock", toJsonMap(locatedblocks.getLastLocatedBlock())); 503 m.put("isLastBlockComplete", locatedblocks.isLastBlockComplete()); 504 return toJsonString(LocatedBlocks.class, m); 505 } 506 507 /** Convert a Json map to LocatedBlock. */ 508 public static LocatedBlocks toLocatedBlocks(final Map<?, ?> json 509 ) throws IOException { 510 if (json == null) { 511 return null; 512 } 513 514 final Map<?, ?> m = (Map<?, ?>)json.get(LocatedBlocks.class.getSimpleName()); 515 final long fileLength = ((Number) m.get("fileLength")).longValue(); 516 final boolean isUnderConstruction = (Boolean)m.get("isUnderConstruction"); 517 final List<LocatedBlock> locatedBlocks = toLocatedBlockList( 518 getList(m, "locatedBlocks")); 519 final LocatedBlock lastLocatedBlock = toLocatedBlock( 520 (Map<?, ?>)m.get("lastLocatedBlock")); 521 final boolean isLastBlockComplete = (Boolean)m.get("isLastBlockComplete"); 522 return new LocatedBlocks(fileLength, isUnderConstruction, locatedBlocks, 523 lastLocatedBlock, isLastBlockComplete, null); 524 } 525 526 /** Convert a ContentSummary to a Json string. */ 527 public static String toJsonString(final ContentSummary contentsummary) { 528 if (contentsummary == null) { 529 return null; 530 } 531 532 final Map<String, Object> m = new TreeMap<String, Object>(); 533 m.put("length", contentsummary.getLength()); 534 m.put("fileCount", contentsummary.getFileCount()); 535 m.put("directoryCount", contentsummary.getDirectoryCount()); 536 m.put("quota", contentsummary.getQuota()); 537 m.put("spaceConsumed", contentsummary.getSpaceConsumed()); 538 m.put("spaceQuota", contentsummary.getSpaceQuota()); 539 return toJsonString(ContentSummary.class, m); 540 } 541 542 /** Convert a Json map to a ContentSummary. */ 543 public static ContentSummary toContentSummary(final Map<?, ?> json) { 544 if (json == null) { 545 return null; 546 } 547 548 final Map<?, ?> m = (Map<?, ?>)json.get(ContentSummary.class.getSimpleName()); 549 final long length = ((Number) m.get("length")).longValue(); 550 final long fileCount = ((Number) m.get("fileCount")).longValue(); 551 final long directoryCount = ((Number) m.get("directoryCount")).longValue(); 552 final long quota = ((Number) m.get("quota")).longValue(); 553 final long spaceConsumed = ((Number) m.get("spaceConsumed")).longValue(); 554 final long spaceQuota = ((Number) m.get("spaceQuota")).longValue(); 555 556 return new ContentSummary.Builder().length(length).fileCount(fileCount). 557 directoryCount(directoryCount).quota(quota).spaceConsumed(spaceConsumed). 558 spaceQuota(spaceQuota).build(); 559 } 560 561 /** Convert a MD5MD5CRC32FileChecksum to a Json string. */ 562 public static String toJsonString(final MD5MD5CRC32FileChecksum checksum) { 563 if (checksum == null) { 564 return null; 565 } 566 567 final Map<String, Object> m = new TreeMap<String, Object>(); 568 m.put("algorithm", checksum.getAlgorithmName()); 569 m.put("length", checksum.getLength()); 570 m.put("bytes", StringUtils.byteToHexString(checksum.getBytes())); 571 return toJsonString(FileChecksum.class, m); 572 } 573 574 /** Convert a Json map to a MD5MD5CRC32FileChecksum. */ 575 public static MD5MD5CRC32FileChecksum toMD5MD5CRC32FileChecksum( 576 final Map<?, ?> json) throws IOException { 577 if (json == null) { 578 return null; 579 } 580 581 final Map<?, ?> m = (Map<?, ?>)json.get(FileChecksum.class.getSimpleName()); 582 final String algorithm = (String)m.get("algorithm"); 583 final int length = ((Number) m.get("length")).intValue(); 584 final byte[] bytes = StringUtils.hexStringToByte((String)m.get("bytes")); 585 586 final DataInputStream in = new DataInputStream(new ByteArrayInputStream(bytes)); 587 final DataChecksum.Type crcType = 588 MD5MD5CRC32FileChecksum.getCrcTypeFromAlgorithmName(algorithm); 589 final MD5MD5CRC32FileChecksum checksum; 590 591 // Recreate what DFSClient would have returned. 592 switch(crcType) { 593 case CRC32: 594 checksum = new MD5MD5CRC32GzipFileChecksum(); 595 break; 596 case CRC32C: 597 checksum = new MD5MD5CRC32CastagnoliFileChecksum(); 598 break; 599 default: 600 throw new IOException("Unknown algorithm: " + algorithm); 601 } 602 checksum.readFields(in); 603 604 //check algorithm name 605 if (!checksum.getAlgorithmName().equals(algorithm)) { 606 throw new IOException("Algorithm not matched. Expected " + algorithm 607 + ", Received " + checksum.getAlgorithmName()); 608 } 609 //check length 610 if (length != checksum.getLength()) { 611 throw new IOException("Length not matched: length=" + length 612 + ", checksum.getLength()=" + checksum.getLength()); 613 } 614 615 return checksum; 616 } 617 /** Convert a AclStatus object to a Json string. */ 618 public static String toJsonString(final AclStatus status) { 619 if (status == null) { 620 return null; 621 } 622 623 final Map<String, Object> m = new TreeMap<String, Object>(); 624 m.put("owner", status.getOwner()); 625 m.put("group", status.getGroup()); 626 m.put("stickyBit", status.isStickyBit()); 627 628 final List<String> stringEntries = new ArrayList<>(); 629 for (AclEntry entry : status.getEntries()) { 630 stringEntries.add(entry.toString()); 631 } 632 m.put("entries", stringEntries); 633 634 FsPermission perm = status.getPermission(); 635 if (perm != null) { 636 m.put("permission", toString(perm)); 637 if (perm.getAclBit()) { 638 m.put("aclBit", true); 639 } 640 if (perm.getEncryptedBit()) { 641 m.put("encBit", true); 642 } 643 } 644 final Map<String, Map<String, Object>> finalMap = 645 new TreeMap<String, Map<String, Object>>(); 646 finalMap.put(AclStatus.class.getSimpleName(), m); 647 648 ObjectMapper mapper = new ObjectMapper(); 649 try { 650 return mapper.writeValueAsString(finalMap); 651 } catch (IOException ignored) { 652 } 653 return null; 654 } 655 656 /** Convert a Json map to a AclStatus object. */ 657 public static AclStatus toAclStatus(final Map<?, ?> json) { 658 if (json == null) { 659 return null; 660 } 661 662 final Map<?, ?> m = (Map<?, ?>) json.get(AclStatus.class.getSimpleName()); 663 664 AclStatus.Builder aclStatusBuilder = new AclStatus.Builder(); 665 aclStatusBuilder.owner((String) m.get("owner")); 666 aclStatusBuilder.group((String) m.get("group")); 667 aclStatusBuilder.stickyBit((Boolean) m.get("stickyBit")); 668 String permString = (String) m.get("permission"); 669 if (permString != null) { 670 final FsPermission permission = toFsPermission(permString, 671 (Boolean) m.get("aclBit"), (Boolean) m.get("encBit")); 672 aclStatusBuilder.setPermission(permission); 673 } 674 final List<?> entries = (List<?>) m.get("entries"); 675 676 List<AclEntry> aclEntryList = new ArrayList<AclEntry>(); 677 for (Object entry : entries) { 678 AclEntry aclEntry = AclEntry.parseAclEntry((String) entry, true); 679 aclEntryList.add(aclEntry); 680 } 681 aclStatusBuilder.addEntries(aclEntryList); 682 return aclStatusBuilder.build(); 683 } 684 685 private static Map<String, Object> toJsonMap(final XAttr xAttr, 686 final XAttrCodec encoding) throws IOException { 687 if (xAttr == null) { 688 return null; 689 } 690 691 final Map<String, Object> m = new TreeMap<String, Object>(); 692 m.put("name", XAttrHelper.getPrefixName(xAttr)); 693 m.put("value", xAttr.getValue() != null ? 694 XAttrCodec.encodeValue(xAttr.getValue(), encoding) : null); 695 return m; 696 } 697 698 private static Object[] toJsonArray(final List<XAttr> array, 699 final XAttrCodec encoding) throws IOException { 700 if (array == null) { 701 return null; 702 } else if (array.size() == 0) { 703 return EMPTY_OBJECT_ARRAY; 704 } else { 705 final Object[] a = new Object[array.size()]; 706 for(int i = 0; i < array.size(); i++) { 707 a[i] = toJsonMap(array.get(i), encoding); 708 } 709 return a; 710 } 711 } 712 713 public static String toJsonString(final List<XAttr> xAttrs, 714 final XAttrCodec encoding) throws IOException { 715 final Map<String, Object> finalMap = new TreeMap<String, Object>(); 716 finalMap.put("XAttrs", toJsonArray(xAttrs, encoding)); 717 ObjectMapper mapper = new ObjectMapper(); 718 return mapper.writeValueAsString(finalMap); 719 } 720 721 public static String toJsonString(final List<XAttr> xAttrs) 722 throws IOException { 723 final List<String> names = Lists.newArrayListWithCapacity(xAttrs.size()); 724 for (XAttr xAttr : xAttrs) { 725 names.add(XAttrHelper.getPrefixName(xAttr)); 726 } 727 ObjectMapper mapper = new ObjectMapper(); 728 String ret = mapper.writeValueAsString(names); 729 final Map<String, Object> finalMap = new TreeMap<String, Object>(); 730 finalMap.put("XAttrNames", ret); 731 return mapper.writeValueAsString(finalMap); 732 } 733 734 public static byte[] getXAttr(final Map<?, ?> json, final String name) 735 throws IOException { 736 if (json == null) { 737 return null; 738 } 739 740 Map<String, byte[]> xAttrs = toXAttrs(json); 741 if (xAttrs != null) { 742 return xAttrs.get(name); 743 } 744 745 return null; 746 } 747 748 public static Map<String, byte[]> toXAttrs(final Map<?, ?> json) 749 throws IOException { 750 if (json == null) { 751 return null; 752 } 753 return toXAttrMap(getList(json, "XAttrs")); 754 } 755 756 public static List<String> toXAttrNames(final Map<?, ?> json) 757 throws IOException { 758 if (json == null) { 759 return null; 760 } 761 762 final String namesInJson = (String) json.get("XAttrNames"); 763 ObjectReader reader = new ObjectMapper().reader(List.class); 764 final List<Object> xattrs = reader.readValue(namesInJson); 765 final List<String> names = 766 Lists.newArrayListWithCapacity(json.keySet().size()); 767 768 for (Object xattr : xattrs) { 769 names.add((String) xattr); 770 } 771 return names; 772 } 773 774 private static Map<String, byte[]> toXAttrMap(final List<?> objects) 775 throws IOException { 776 if (objects == null) { 777 return null; 778 } else if (objects.isEmpty()) { 779 return Maps.newHashMap(); 780 } else { 781 final Map<String, byte[]> xAttrs = Maps.newHashMap(); 782 for (Object object : objects) { 783 Map<?, ?> m = (Map<?, ?>) object; 784 String name = (String) m.get("name"); 785 String value = (String) m.get("value"); 786 xAttrs.put(name, decodeXAttrValue(value)); 787 } 788 return xAttrs; 789 } 790 } 791 792 private static byte[] decodeXAttrValue(String value) throws IOException { 793 if (value != null) { 794 return XAttrCodec.decodeValue(value); 795 } else { 796 return new byte[0]; 797 } 798 } 799}