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 int xferPort = getInt(m, "xferPort", -1); 338 Object tmpValue = m.get("ipAddr"); 339 String ipAddr = (tmpValue == null) ? null : (String)tmpValue; 340 if (ipAddr == null) { 341 tmpValue = m.get("name"); 342 if (tmpValue != null) { 343 String name = (String)tmpValue; 344 int colonIdx = name.indexOf(':'); 345 if (colonIdx > 0) { 346 ipAddr = name.substring(0, colonIdx); 347 xferPort = Integer.parseInt(name.substring(colonIdx +1)); 348 } else { 349 throw new IOException( 350 "Invalid value in server response: name=[" + name + "]"); 351 } 352 } else { 353 throw new IOException( 354 "Missing both 'ipAddr' and 'name' in server response."); 355 } 356 // ipAddr is non-null & non-empty string at this point. 357 } 358 359 // Check the validity of xferPort. 360 if (xferPort == -1) { 361 throw new IOException( 362 "Invalid or missing 'xferPort' in server response."); 363 } 364 365 // TODO: Fix storageID 366 return new DatanodeInfo( 367 ipAddr, 368 (String)m.get("hostName"), 369 (String)m.get("storageID"), 370 xferPort, 371 ((Number) m.get("infoPort")).intValue(), 372 getInt(m, "infoSecurePort", 0), 373 ((Number) m.get("ipcPort")).intValue(), 374 375 getLong(m, "capacity", 0l), 376 getLong(m, "dfsUsed", 0l), 377 getLong(m, "remaining", 0l), 378 getLong(m, "blockPoolUsed", 0l), 379 getLong(m, "cacheCapacity", 0l), 380 getLong(m, "cacheUsed", 0l), 381 getLong(m, "lastUpdate", 0l), 382 getLong(m, "lastUpdateMonotonic", 0l), 383 getInt(m, "xceiverCount", 0), 384 getString(m, "networkLocation", ""), 385 AdminStates.valueOf(getString(m, "adminState", "NORMAL"))); 386 } 387 388 /** Convert a DatanodeInfo[] to a Json array. */ 389 private static Object[] toJsonArray(final DatanodeInfo[] array) { 390 if (array == null) { 391 return null; 392 } else if (array.length == 0) { 393 return EMPTY_OBJECT_ARRAY; 394 } else { 395 final Object[] a = new Object[array.length]; 396 for(int i = 0; i < array.length; i++) { 397 a[i] = toJsonMap(array[i]); 398 } 399 return a; 400 } 401 } 402 403 /** Convert an Object[] to a DatanodeInfo[]. */ 404 private static DatanodeInfo[] toDatanodeInfoArray(final List<?> objects) 405 throws IOException { 406 if (objects == null) { 407 return null; 408 } else if (objects.isEmpty()) { 409 return EMPTY_DATANODE_INFO_ARRAY; 410 } else { 411 final DatanodeInfo[] array = new DatanodeInfo[objects.size()]; 412 int i = 0; 413 for (Object object : objects) { 414 array[i++] = toDatanodeInfo((Map<?, ?>) object); 415 } 416 return array; 417 } 418 } 419 420 /** Convert a LocatedBlock to a Json map. */ 421 private static Map<String, Object> toJsonMap(final LocatedBlock locatedblock 422 ) throws IOException { 423 if (locatedblock == null) { 424 return null; 425 } 426 427 final Map<String, Object> m = new TreeMap<String, Object>(); 428 m.put("blockToken", toJsonMap(locatedblock.getBlockToken())); 429 m.put("isCorrupt", locatedblock.isCorrupt()); 430 m.put("startOffset", locatedblock.getStartOffset()); 431 m.put("block", toJsonMap(locatedblock.getBlock())); 432 m.put("locations", toJsonArray(locatedblock.getLocations())); 433 m.put("cachedLocations", toJsonArray(locatedblock.getCachedLocations())); 434 return m; 435 } 436 437 /** Convert a Json map to LocatedBlock. */ 438 private static LocatedBlock toLocatedBlock(final Map<?, ?> m) throws IOException { 439 if (m == null) { 440 return null; 441 } 442 443 final ExtendedBlock b = toExtendedBlock((Map<?, ?>)m.get("block")); 444 final DatanodeInfo[] locations = toDatanodeInfoArray( 445 getList(m, "locations")); 446 final long startOffset = ((Number) m.get("startOffset")).longValue(); 447 final boolean isCorrupt = (Boolean)m.get("isCorrupt"); 448 final DatanodeInfo[] cachedLocations = toDatanodeInfoArray( 449 getList(m, "cachedLocations")); 450 451 final LocatedBlock locatedblock = new LocatedBlock(b, locations, 452 null, null, startOffset, isCorrupt, cachedLocations); 453 locatedblock.setBlockToken(toBlockToken((Map<?, ?>)m.get("blockToken"))); 454 return locatedblock; 455 } 456 457 /** Convert a LocatedBlock[] to a Json array. */ 458 private static Object[] toJsonArray(final List<LocatedBlock> array 459 ) throws IOException { 460 if (array == null) { 461 return null; 462 } else if (array.size() == 0) { 463 return EMPTY_OBJECT_ARRAY; 464 } else { 465 final Object[] a = new Object[array.size()]; 466 for(int i = 0; i < array.size(); i++) { 467 a[i] = toJsonMap(array.get(i)); 468 } 469 return a; 470 } 471 } 472 473 /** Convert an List of Object to a List of LocatedBlock. */ 474 private static List<LocatedBlock> toLocatedBlockList( 475 final List<?> objects) throws IOException { 476 if (objects == null) { 477 return null; 478 } else if (objects.isEmpty()) { 479 return Collections.emptyList(); 480 } else { 481 final List<LocatedBlock> list = new ArrayList<>(objects.size()); 482 for (Object object : objects) { 483 list.add(toLocatedBlock((Map<?, ?>) object)); 484 } 485 return list; 486 } 487 } 488 489 /** Convert LocatedBlocks to a Json string. */ 490 public static String toJsonString(final LocatedBlocks locatedblocks 491 ) throws IOException { 492 if (locatedblocks == null) { 493 return null; 494 } 495 496 final Map<String, Object> m = new TreeMap<String, Object>(); 497 m.put("fileLength", locatedblocks.getFileLength()); 498 m.put("isUnderConstruction", locatedblocks.isUnderConstruction()); 499 500 m.put("locatedBlocks", toJsonArray(locatedblocks.getLocatedBlocks())); 501 m.put("lastLocatedBlock", toJsonMap(locatedblocks.getLastLocatedBlock())); 502 m.put("isLastBlockComplete", locatedblocks.isLastBlockComplete()); 503 return toJsonString(LocatedBlocks.class, m); 504 } 505 506 /** Convert a Json map to LocatedBlock. */ 507 public static LocatedBlocks toLocatedBlocks(final Map<?, ?> json 508 ) throws IOException { 509 if (json == null) { 510 return null; 511 } 512 513 final Map<?, ?> m = (Map<?, ?>)json.get(LocatedBlocks.class.getSimpleName()); 514 final long fileLength = ((Number) m.get("fileLength")).longValue(); 515 final boolean isUnderConstruction = (Boolean)m.get("isUnderConstruction"); 516 final List<LocatedBlock> locatedBlocks = toLocatedBlockList( 517 getList(m, "locatedBlocks")); 518 final LocatedBlock lastLocatedBlock = toLocatedBlock( 519 (Map<?, ?>)m.get("lastLocatedBlock")); 520 final boolean isLastBlockComplete = (Boolean)m.get("isLastBlockComplete"); 521 return new LocatedBlocks(fileLength, isUnderConstruction, locatedBlocks, 522 lastLocatedBlock, isLastBlockComplete, null); 523 } 524 525 /** Convert a ContentSummary to a Json string. */ 526 public static String toJsonString(final ContentSummary contentsummary) { 527 if (contentsummary == null) { 528 return null; 529 } 530 531 final Map<String, Object> m = new TreeMap<String, Object>(); 532 m.put("length", contentsummary.getLength()); 533 m.put("fileCount", contentsummary.getFileCount()); 534 m.put("directoryCount", contentsummary.getDirectoryCount()); 535 m.put("quota", contentsummary.getQuota()); 536 m.put("spaceConsumed", contentsummary.getSpaceConsumed()); 537 m.put("spaceQuota", contentsummary.getSpaceQuota()); 538 return toJsonString(ContentSummary.class, m); 539 } 540 541 /** Convert a Json map to a ContentSummary. */ 542 public static ContentSummary toContentSummary(final Map<?, ?> json) { 543 if (json == null) { 544 return null; 545 } 546 547 final Map<?, ?> m = (Map<?, ?>)json.get(ContentSummary.class.getSimpleName()); 548 final long length = ((Number) m.get("length")).longValue(); 549 final long fileCount = ((Number) m.get("fileCount")).longValue(); 550 final long directoryCount = ((Number) m.get("directoryCount")).longValue(); 551 final long quota = ((Number) m.get("quota")).longValue(); 552 final long spaceConsumed = ((Number) m.get("spaceConsumed")).longValue(); 553 final long spaceQuota = ((Number) m.get("spaceQuota")).longValue(); 554 555 return new ContentSummary.Builder().length(length).fileCount(fileCount). 556 directoryCount(directoryCount).quota(quota).spaceConsumed(spaceConsumed). 557 spaceQuota(spaceQuota).build(); 558 } 559 560 /** Convert a MD5MD5CRC32FileChecksum to a Json string. */ 561 public static String toJsonString(final MD5MD5CRC32FileChecksum checksum) { 562 if (checksum == null) { 563 return null; 564 } 565 566 final Map<String, Object> m = new TreeMap<String, Object>(); 567 m.put("algorithm", checksum.getAlgorithmName()); 568 m.put("length", checksum.getLength()); 569 m.put("bytes", StringUtils.byteToHexString(checksum.getBytes())); 570 return toJsonString(FileChecksum.class, m); 571 } 572 573 /** Convert a Json map to a MD5MD5CRC32FileChecksum. */ 574 public static MD5MD5CRC32FileChecksum toMD5MD5CRC32FileChecksum( 575 final Map<?, ?> json) throws IOException { 576 if (json == null) { 577 return null; 578 } 579 580 final Map<?, ?> m = (Map<?, ?>)json.get(FileChecksum.class.getSimpleName()); 581 final String algorithm = (String)m.get("algorithm"); 582 final int length = ((Number) m.get("length")).intValue(); 583 final byte[] bytes = StringUtils.hexStringToByte((String)m.get("bytes")); 584 585 final DataInputStream in = new DataInputStream(new ByteArrayInputStream(bytes)); 586 final DataChecksum.Type crcType = 587 MD5MD5CRC32FileChecksum.getCrcTypeFromAlgorithmName(algorithm); 588 final MD5MD5CRC32FileChecksum checksum; 589 590 // Recreate what DFSClient would have returned. 591 switch(crcType) { 592 case CRC32: 593 checksum = new MD5MD5CRC32GzipFileChecksum(); 594 break; 595 case CRC32C: 596 checksum = new MD5MD5CRC32CastagnoliFileChecksum(); 597 break; 598 default: 599 throw new IOException("Unknown algorithm: " + algorithm); 600 } 601 checksum.readFields(in); 602 603 //check algorithm name 604 if (!checksum.getAlgorithmName().equals(algorithm)) { 605 throw new IOException("Algorithm not matched. Expected " + algorithm 606 + ", Received " + checksum.getAlgorithmName()); 607 } 608 //check length 609 if (length != checksum.getLength()) { 610 throw new IOException("Length not matched: length=" + length 611 + ", checksum.getLength()=" + checksum.getLength()); 612 } 613 614 return checksum; 615 } 616 /** Convert a AclStatus object to a Json string. */ 617 public static String toJsonString(final AclStatus status) { 618 if (status == null) { 619 return null; 620 } 621 622 final Map<String, Object> m = new TreeMap<String, Object>(); 623 m.put("owner", status.getOwner()); 624 m.put("group", status.getGroup()); 625 m.put("stickyBit", status.isStickyBit()); 626 627 final List<String> stringEntries = new ArrayList<>(); 628 for (AclEntry entry : status.getEntries()) { 629 stringEntries.add(entry.toString()); 630 } 631 m.put("entries", stringEntries); 632 633 FsPermission perm = status.getPermission(); 634 if (perm != null) { 635 m.put("permission", toString(perm)); 636 if (perm.getAclBit()) { 637 m.put("aclBit", true); 638 } 639 if (perm.getEncryptedBit()) { 640 m.put("encBit", true); 641 } 642 } 643 final Map<String, Map<String, Object>> finalMap = 644 new TreeMap<String, Map<String, Object>>(); 645 finalMap.put(AclStatus.class.getSimpleName(), m); 646 647 ObjectMapper mapper = new ObjectMapper(); 648 try { 649 return mapper.writeValueAsString(finalMap); 650 } catch (IOException ignored) { 651 } 652 return null; 653 } 654 655 /** Convert a Json map to a AclStatus object. */ 656 public static AclStatus toAclStatus(final Map<?, ?> json) { 657 if (json == null) { 658 return null; 659 } 660 661 final Map<?, ?> m = (Map<?, ?>) json.get(AclStatus.class.getSimpleName()); 662 663 AclStatus.Builder aclStatusBuilder = new AclStatus.Builder(); 664 aclStatusBuilder.owner((String) m.get("owner")); 665 aclStatusBuilder.group((String) m.get("group")); 666 aclStatusBuilder.stickyBit((Boolean) m.get("stickyBit")); 667 String permString = (String) m.get("permission"); 668 if (permString != null) { 669 final FsPermission permission = toFsPermission(permString, 670 (Boolean) m.get("aclBit"), (Boolean) m.get("encBit")); 671 aclStatusBuilder.setPermission(permission); 672 } 673 final List<?> entries = (List<?>) m.get("entries"); 674 675 List<AclEntry> aclEntryList = new ArrayList<AclEntry>(); 676 for (Object entry : entries) { 677 AclEntry aclEntry = AclEntry.parseAclEntry((String) entry, true); 678 aclEntryList.add(aclEntry); 679 } 680 aclStatusBuilder.addEntries(aclEntryList); 681 return aclStatusBuilder.build(); 682 } 683 684 private static Map<String, Object> toJsonMap(final XAttr xAttr, 685 final XAttrCodec encoding) throws IOException { 686 if (xAttr == null) { 687 return null; 688 } 689 690 final Map<String, Object> m = new TreeMap<String, Object>(); 691 m.put("name", XAttrHelper.getPrefixName(xAttr)); 692 m.put("value", xAttr.getValue() != null ? 693 XAttrCodec.encodeValue(xAttr.getValue(), encoding) : null); 694 return m; 695 } 696 697 private static Object[] toJsonArray(final List<XAttr> array, 698 final XAttrCodec encoding) throws IOException { 699 if (array == null) { 700 return null; 701 } else if (array.size() == 0) { 702 return EMPTY_OBJECT_ARRAY; 703 } else { 704 final Object[] a = new Object[array.size()]; 705 for(int i = 0; i < array.size(); i++) { 706 a[i] = toJsonMap(array.get(i), encoding); 707 } 708 return a; 709 } 710 } 711 712 public static String toJsonString(final List<XAttr> xAttrs, 713 final XAttrCodec encoding) throws IOException { 714 final Map<String, Object> finalMap = new TreeMap<String, Object>(); 715 finalMap.put("XAttrs", toJsonArray(xAttrs, encoding)); 716 ObjectMapper mapper = new ObjectMapper(); 717 return mapper.writeValueAsString(finalMap); 718 } 719 720 public static String toJsonString(final List<XAttr> xAttrs) 721 throws IOException { 722 final List<String> names = Lists.newArrayListWithCapacity(xAttrs.size()); 723 for (XAttr xAttr : xAttrs) { 724 names.add(XAttrHelper.getPrefixName(xAttr)); 725 } 726 ObjectMapper mapper = new ObjectMapper(); 727 String ret = mapper.writeValueAsString(names); 728 final Map<String, Object> finalMap = new TreeMap<String, Object>(); 729 finalMap.put("XAttrNames", ret); 730 return mapper.writeValueAsString(finalMap); 731 } 732 733 public static byte[] getXAttr(final Map<?, ?> json, final String name) 734 throws IOException { 735 if (json == null) { 736 return null; 737 } 738 739 Map<String, byte[]> xAttrs = toXAttrs(json); 740 if (xAttrs != null) { 741 return xAttrs.get(name); 742 } 743 744 return null; 745 } 746 747 public static Map<String, byte[]> toXAttrs(final Map<?, ?> json) 748 throws IOException { 749 if (json == null) { 750 return null; 751 } 752 return toXAttrMap(getList(json, "XAttrs")); 753 } 754 755 public static List<String> toXAttrNames(final Map<?, ?> json) 756 throws IOException { 757 if (json == null) { 758 return null; 759 } 760 761 final String namesInJson = (String) json.get("XAttrNames"); 762 ObjectReader reader = new ObjectMapper().reader(List.class); 763 final List<Object> xattrs = reader.readValue(namesInJson); 764 final List<String> names = 765 Lists.newArrayListWithCapacity(json.keySet().size()); 766 767 for (Object xattr : xattrs) { 768 names.add((String) xattr); 769 } 770 return names; 771 } 772 773 private static Map<String, byte[]> toXAttrMap(final List<?> objects) 774 throws IOException { 775 if (objects == null) { 776 return null; 777 } else if (objects.isEmpty()) { 778 return Maps.newHashMap(); 779 } else { 780 final Map<String, byte[]> xAttrs = Maps.newHashMap(); 781 for (Object object : objects) { 782 Map<?, ?> m = (Map<?, ?>) object; 783 String name = (String) m.get("name"); 784 String value = (String) m.get("value"); 785 xAttrs.put(name, decodeXAttrValue(value)); 786 } 787 return xAttrs; 788 } 789 } 790 791 private static byte[] decodeXAttrValue(String value) throws IOException { 792 if (value != null) { 793 return XAttrCodec.decodeValue(value); 794 } else { 795 return new byte[0]; 796 } 797 } 798}