PageRenderTime 40ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/jtopen-7.8/src/com/ibm/as400/access/IFSListAttrsRep.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 437 lines | 248 code | 64 blank | 125 comment | 38 complexity | 830358c50cb79276c61f56cfe9ead9e9 MD5 | raw file
  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // JTOpen (IBM Toolbox for Java - OSS version)
  4. //
  5. // Filename: IFSListAttrsRep.java
  6. //
  7. // The source code contained herein is licensed under the IBM Public License
  8. // Version 1.0, which has been approved by the Open Source Initiative.
  9. // Copyright (C) 1997-2004 International Business Machines Corporation and
  10. // others. All rights reserved.
  11. //
  12. ///////////////////////////////////////////////////////////////////////////////
  13. package com.ibm.as400.access;
  14. import java.io.UnsupportedEncodingException;
  15. import java.util.Hashtable;
  16. /**
  17. List file attributes reply.
  18. **/
  19. class IFSListAttrsRep extends IFSDataStream
  20. {
  21. // Used for debugging only. This should always be false for production.
  22. // When this is false, all debug code will theoretically compile out. @A3a
  23. private static final boolean DEBUG = false;
  24. static final int FILE = 1;
  25. static final int DIRECTORY = 2;
  26. static final int SYMBOLIC_LINK = 3;
  27. static final int AS400_OBJECT = 4;
  28. static final int DEVICE_FIFO = 5;
  29. static final int DEVICE_CHAR = 6;
  30. static final int DEVICE_BLOCK = 7;
  31. static final int SOCKET = 8;
  32. static final int FA_READONLY = 0x01; //@D1a
  33. static final int FA_HIDDEN = 0x02; //@D1a
  34. static final int FA_SYSTEM = 0x04; //@D1a
  35. static final int FA_DIRECTORY = 0x10;
  36. static final int FA_ARCHIVE = 0x20; //@D1a
  37. static final int OA_NONE = IFSListAttrsReq.OA_NONE;
  38. static final int OA1 = IFSListAttrsReq.OA1;
  39. static final int OA2 = IFSListAttrsReq.OA2;
  40. private static final int TEMPLATE_LENGTH_OFFSET = 16;
  41. private static final int HEADER_LENGTH = 20;
  42. private static final int LLCP_LENGTH = 6;
  43. // Note: The following offsets are valid only if template length >= 61.
  44. private static final int CREATE_DATE_OFFSET = 22;
  45. private static final int MODIFY_DATE_OFFSET = 30;
  46. private static final int ACCESS_DATE_OFFSET = 38;
  47. private static final int FILE_SIZE_OFFSET = 46;
  48. private static final int FIXED_ATTRS_OFFSET = 50;
  49. private static final int OBJECT_TYPE_OFFSET = 54;
  50. private static final int NUM_EXT_ATTRS_OFFSET = 56;
  51. private static final int BYTES_EA_NAMES_OFFSET = 58;
  52. private static final int BYTES_EA_VALUES_OFFSET = 62;
  53. private static final int VERSION_NUMBER_OFFSET = 66;
  54. private static final int AMOUNT_ACCESSED_OFFSET = 70;
  55. private static final int ACCESS_HISTORY_OFFSET = 72;
  56. private static final int NAME_CCSID_OFFSET = 73; // CCSID of the file/path name
  57. private static final int CHECKOUT_CCSID_OFFSET = 75;
  58. private static final int RESTART_ID_OFFSET = 77;
  59. // Additional fields if datastreamLevel >= 8:
  60. private static final int LARGE_FILE_SIZE_OFFSET = 81;
  61. private static final int SYMBOLIC_LINK_OFFSET = 91;
  62. /**
  63. Construct a list file attributes reply.
  64. **/
  65. IFSListAttrsRep()
  66. {
  67. }
  68. /**
  69. Generate a new instance of this type.
  70. @return a reference to the new instance
  71. **/
  72. public Object getNewDataStream()
  73. {
  74. return new IFSListAttrsRep();
  75. }
  76. /**
  77. Get the date/time that the file was last accessed.
  78. @return the date/time (measured as milliseconds since midnight January 1, 1970) of the last access
  79. **/
  80. long getAccessDate()
  81. {
  82. return getDate(ACCESS_DATE_OFFSET);
  83. }
  84. /**
  85. Get the CCSID value for the IFS file on the server.
  86. @return the CCSID value for the IFS file on the server
  87. **/
  88. int getCCSID(int datastreamLevel) // @A1A
  89. {
  90. // Get the 'CCSID of the object' field from the OA2 structure in the reply.
  91. return getObjAttrs2().getCCSID(datastreamLevel);
  92. }
  93. /**
  94. Get the date/time that the file was created.
  95. @return the date/time (measured as milliseconds since midnight January 1, 1970) of creation
  96. **/
  97. long getCreationDate()
  98. {
  99. return getDate(CREATE_DATE_OFFSET);
  100. }
  101. /**
  102. Get the extended attribute values, as a hashtable.
  103. @return The extended attribute values.
  104. **/
  105. Hashtable getExtendedAttributeValues()
  106. {
  107. Hashtable results = new Hashtable();
  108. // The offset to the start of the "optional/variable section" depends on the datastream level.
  109. int optionalSectionOffset = HEADER_LENGTH + get16bit(TEMPLATE_LENGTH_OFFSET);
  110. // Step through the optional fields, looking for the "EA list" field (code point 0x0009).
  111. int curLL_offset = optionalSectionOffset;
  112. int curLL = get32bit(curLL_offset); // list length
  113. int curCP = get16bit(curLL_offset+4); // code point
  114. int eaListOffset; // offset to start of Extended Attr list
  115. while (curCP != 0x0009 && (curLL_offset+curLL+6 <= data_.length))
  116. {
  117. curLL_offset += curLL;
  118. curLL = get32bit(curLL_offset);
  119. curCP = get16bit(curLL_offset+4);
  120. }
  121. if (curCP == 0x0009)
  122. {
  123. // We found the start of the Extended Attributes list.
  124. eaListOffset = curLL_offset; // offset to "EA List Length" field
  125. }
  126. else
  127. {
  128. if (Trace.isTraceOn()) Trace.log(Trace.DIAGNOSTIC, "No Extended Attributes were returned.");
  129. return results; // empty hashtable
  130. }
  131. byte[] eaVal = null;
  132. int eaCount = get16bit(eaListOffset+6); // number of EA structures returned
  133. if (DEBUG) System.out.println("DEBUG Number of EA structures returned: " + eaCount);
  134. // Advance the offset, to point to the start of first repeating EA struct.
  135. int offset = eaListOffset+8;
  136. for (int i=0; i<eaCount; i++)
  137. {
  138. int eaCcsid = get16bit(offset); // The 2-byte CCSID for the EA name.
  139. int eaNameLL= get16bit(offset+2); // The 2-byte length of the EA name.
  140. // Note: eaNameLL does *not* include length of the LL field itself.
  141. //int eaFlags = get16bit(offset+4); // The flags for the EA.
  142. int eaValLL = get32bit(offset+6); // The 4-byte length of the EA value.
  143. // Note: eaValLL includes the 4 "mystery bytes" that precede the name.
  144. byte[] eaName = new byte[eaNameLL]; // The EA name.
  145. System.arraycopy(data_, offset+10, eaName, 0, eaNameLL);
  146. if (eaValLL <= 4)
  147. {
  148. if (DEBUG) System.out.println("DEBUG Warning: eaValLL<=4: " + eaValLL);
  149. }
  150. else
  151. {
  152. eaVal = new byte[eaValLL-4]; // omit the 4 leading mystery bytes
  153. System.arraycopy(data_, offset+10+eaNameLL+4, eaVal, 0, eaValLL-4);
  154. try
  155. {
  156. String eaNameString = CharConverter.byteArrayToString(eaCcsid, eaName);
  157. results.put(eaNameString, eaVal);
  158. if (Trace.isTraceOn()) Trace.log(Trace.DIAGNOSTIC, "Extended Attribute returned: " + eaNameString, eaVal);
  159. }
  160. catch (java.io.UnsupportedEncodingException e) { Trace.log(Trace.ERROR, e); }
  161. }
  162. // Advance the offset, to point to the start of next EA struct.
  163. offset += (10 + eaNameLL + eaValLL);
  164. }
  165. return results;
  166. }
  167. /**
  168. Get the fixed attributes.
  169. @return fixed attributes
  170. **/
  171. int getFixedAttributes()
  172. {
  173. return(get32bit(FIXED_ATTRS_OFFSET));
  174. }
  175. /**
  176. Get the date/time that the file was last modified.
  177. @return the date/time (measured as milliseconds since midnight January 1, 1970) of the last modification
  178. **/
  179. long getModificationDate()
  180. {
  181. return getDate(MODIFY_DATE_OFFSET);
  182. }
  183. /**
  184. Get the file name.
  185. @return the file name
  186. **/
  187. byte[] getName()
  188. {
  189. // Assume that the "File Name" field is at the beginning of the Optional Section.
  190. int file_name_LL_offset = HEADER_LENGTH + get16bit(TEMPLATE_LENGTH_OFFSET);
  191. int length = get32bit( file_name_LL_offset) - 6;
  192. if (DEBUG && length < 0) {
  193. Trace.log(Trace.ERROR, "Error getting file name: Value at name-length offset is too small.");
  194. throw new InternalErrorException(InternalErrorException.UNKNOWN);
  195. }
  196. byte[] name = new byte[length];
  197. System.arraycopy(data_, 6+file_name_LL_offset, name, 0, length);
  198. // Note: Actual filename starts after the 6-byte LL CP, hence the "6+".
  199. return name;
  200. }
  201. /**
  202. Returns the first OA1* structure (minus the LLCP) returned in the reply.
  203. @parm type Type of attributes (OA1 or OA2).
  204. @exception InternalErrorException If the reply contains no OA1* structure.
  205. **/
  206. IFSObjAttrs1 getObjAttrs1()
  207. {
  208. return new IFSObjAttrs1(getObjAttrBytes(OA1));
  209. }
  210. /**
  211. Returns the first OA2* structure (minus the LLCP) returned in the reply.
  212. @parm type Type of attributes (OA1 or OA2).
  213. @exception InternalErrorException If the reply contains no OA2* structure.
  214. **/
  215. IFSObjAttrs2 getObjAttrs2()
  216. {
  217. return new IFSObjAttrs2(getObjAttrBytes(OA2));
  218. }
  219. /**
  220. Returns the first OA* structure of the specified type (minus the LLCP) returned in the reply.
  221. @parm type Type of attributes (OA1 or OA2).
  222. @exception InternalErrorException If the reply contains no OA* structure of the specified type.
  223. **/
  224. private final byte[] getObjAttrBytes(int type)
  225. {
  226. if (type == OA_NONE) return null;
  227. // Find the first OA structure in the reply's "Optional/Variable Section".
  228. int offset = HEADER_LENGTH + get16bit(TEMPLATE_LENGTH_OFFSET);
  229. int oaCodePoint = (type == OA1 ? 0x0010 : 0x000F); // OA1: CP == 0x0010; OA2: CP == 0x000F
  230. byte[] buf = null;
  231. while (buf == null && offset < data_.length)
  232. {
  233. // Look for an LLCP with a CP value that specifies an OA* structure.
  234. int length = get32bit(offset); // Get the LL value.
  235. short codePoint = (short)get16bit(offset + 4); // Get the CP value.
  236. if (codePoint == oaCodePoint) { // We found an OA* of the desired type.
  237. int OAlength = length - LLCP_LENGTH; // Exclude the LLCP.
  238. buf = new byte[OAlength];
  239. System.arraycopy(data_, offset + LLCP_LENGTH, buf, 0, OAlength);
  240. }
  241. else { // not what we're looking for, so keep looking
  242. offset += length; // skip to next LLCP
  243. }
  244. }
  245. if (buf == null) {
  246. Trace.log(Trace.ERROR, "The reply does not contain an OA"+type+ " structure.");
  247. throw new InternalErrorException(InternalErrorException.UNKNOWN);
  248. }
  249. return buf;
  250. }
  251. /**
  252. Determine the object type (file, directory, etc.)
  253. @return the object type
  254. **/
  255. int getObjectType()
  256. {
  257. return get16bit(OBJECT_TYPE_OFFSET);
  258. }
  259. /**
  260. Get the value of the file's "Owner Name" attribute.
  261. **/
  262. String getOwnerName(int systemCcsid) throws UnsupportedEncodingException
  263. {
  264. // Assume that this reply has an "Optional/Variable" section, and that it contains an "Object Attribute 1" structure.
  265. return getObjAttrs1().getOwnerName(systemCcsid);
  266. }
  267. // @B7a
  268. /**
  269. Get the owner's "user ID" number for the IFS file on the server.
  270. @return the owner's user ID number for the IFS file on the server
  271. **/
  272. long getOwnerUID() // @C0c
  273. {
  274. // Get the 'Owner user ID' field from the OA2 structure in the reply.
  275. return getObjAttrs2().getOwnerUID();
  276. }
  277. // @C3a
  278. /**
  279. Get the restart identifier.
  280. @return the restart identifier
  281. **/
  282. byte[] getRestartID()
  283. {
  284. byte[] restartID = new byte[4];
  285. System.arraycopy(data_, RESTART_ID_OFFSET, restartID, 0, restartID.length);
  286. return restartID;
  287. }
  288. /**
  289. Determine the file size (in bytes).
  290. @return the file size
  291. **/
  292. long getSize(int datastreamLevel) // @B8c
  293. {
  294. // Datastream level 8 added a "Large File Size" field.
  295. if (datastreamLevel < 8 || datastreamLevel == 0xF4F4) {
  296. // We need to suppress sign-extension, just in case the leftmost bit is on.
  297. int size = get32bit( FILE_SIZE_OFFSET); // @B8c
  298. return ((long)size) & 0xffffffffL; // @B8c
  299. }
  300. else {
  301. return (get64bit( LARGE_FILE_SIZE_OFFSET ));
  302. }
  303. }
  304. //@C1a
  305. /**
  306. Get the length of the file (8 bytes).
  307. @return length of the file
  308. **/
  309. long getSize8Bytes(/*int datastreamLevel*/)
  310. {
  311. long fileSize = 0L;
  312. int optionalSectionOffset = HEADER_LENGTH + get16bit(TEMPLATE_LENGTH_OFFSET);
  313. // Step through the optional fields, looking for the "8-byte file size" field (code point 0x0014).
  314. int curLL_offset = optionalSectionOffset;
  315. int curLL = get32bit(curLL_offset);
  316. int curCP = get16bit(curLL_offset+4);
  317. while (curCP != 0x0014 && (curLL_offset+curLL+6 <= data_.length))
  318. {
  319. curLL_offset += curLL;
  320. curLL = get32bit(curLL_offset);
  321. curCP = get16bit(curLL_offset+4);
  322. }
  323. if (curCP == 0x0014)
  324. {
  325. // We found the 8-byte file size optional attribute that we requested.
  326. fileSize = get64bit(curLL_offset+6);
  327. }
  328. else
  329. {
  330. // Didn't find it. The server goofed up and didn't send it to us.
  331. Trace.log(Trace.ERROR, "Error getting 8-byte file size: Optional field was not returned.");
  332. throw new InternalErrorException(InternalErrorException.UNKNOWN);
  333. }
  334. return fileSize;
  335. }
  336. /**
  337. Determine whether the object is a symbolic link.
  338. @return true if object is a symbolic link;
  339. false if not a symbolic link (or if could not determine).
  340. **/
  341. boolean isSymbolicLink(int datastreamLevel)
  342. {
  343. boolean result = false;
  344. // Note: The symlink field was added to the reply datastream in DSL 8.
  345. if (datastreamLevel < 8 || datastreamLevel == 0xF4F4) {
  346. Trace.log(Trace.WARNING, "Could not determine whether file is a symbolic link.");
  347. }
  348. else {
  349. byte fieldValue = data_[SYMBOLIC_LINK_OFFSET];
  350. switch (fieldValue)
  351. {
  352. case 0:
  353. result = false;
  354. break;
  355. case 1:
  356. result = true;
  357. break;
  358. default:
  359. Trace.log(Trace.ERROR, "Internal error, unexpected value in symbolic link field: ", fieldValue);
  360. break;
  361. }
  362. }
  363. return result;
  364. }
  365. /**
  366. Generates a hash code for this data stream.
  367. @return the hash code
  368. **/
  369. public int hashCode()
  370. {
  371. return 0x8005;
  372. }
  373. }