View Javadoc

1   package org.jscsi.target.scsi.modeSense;
2   
3   
4   import java.nio.ByteBuffer;
5   
6   import org.jscsi.target.scsi.IResponseData;
7   
8   
9   /**
10   * The mode parameter list contains a header, followed by zero or more block descriptors, followed by zero or more
11   * variable-length mode pages.
12   * <p>
13   * This class uses the builder pattern to minimize the number of constructors and to avoid constructor use with a lot of
14   * <code>null</code> parameters.
15   * 
16   * @author Andreas Ergenzinger
17   */
18  public final class ModeParameterList implements IResponseData {
19  
20      /**
21       * The header contains information about the fields that follow.
22       */
23      private final ModeParameterHeader modeParameterHeader;
24  
25      /**
26       * Contains the elements of the list of Logical Block Descriptors.
27       */
28      private final LogicalBlockDescriptor[] logicalBlockDescriptors;
29  
30      /**
31       * Contains the elements of the list of Mode Pages.
32       */
33      private final ModePage[] modePages;
34  
35      /**
36       * Returns a new {@link ModeParameterList} instance based the variables of the <i>builder</i> object. If these
37       * variables are mutually exclusive, then this method will return <code>null</code> instead.
38       * 
39       * @param builder contains all necessary information to create a {@link ModeParameterList} object
40       * @return a new {@link ModeParameterList} or <code>null</code>
41       */
42      public static ModeParameterList build (final ModeParameterListBuilder builder) {
43          if (!builder.checkIntegrity()) return null;
44          // everything is okay, so
45          // - calculate block descriptor length
46          int blockDescriptorLength;
47          if (builder.logicalBlockDescriptors == null)
48              blockDescriptorLength = 0;
49          else {
50              int singleLbdLength;
51              if (builder.longLba)
52                  singleLbdLength = LongLogicalBlockDescriptor.SIZE;
53              else
54                  singleLbdLength = ShortLogicalBlockDescriptor.SIZE;
55              blockDescriptorLength = builder.logicalBlockDescriptors.length * singleLbdLength;
56          }
57          // - calculate mode data length
58          int modeDataLength;
59          // -- calculate contribution of the header without bytes of MODE DATA
60          // LENGTH field
61          if (builder.headerType == HeaderType.MODE_PARAMETER_HEADER_6)
62              modeDataLength = ModeParameterHeader6.SIZE - ModeParameterHeader6.MODE_DATA_LENGTH_FIELD_SIZE;
63          else
64              modeDataLength = ModeParameterHeader10.SIZE - ModeParameterHeader10.MODE_DATA_LENGTH_FIELD_SIZE;
65          // -- add length of logical block descriptors
66          modeDataLength += blockDescriptorLength;
67          // -- add length of mode pages
68          if (builder.modePages != null) for (ModePage mp : builder.modePages)
69              modeDataLength += mp.size();
70  
71          /*
72           * It might be nice to check the values for overflow here, however this is not necessary, since the length of
73           * all available/returned elements will always be less than 256.
74           */
75  
76          ModeParameterHeader modeParameterHeader;
77          if (builder.headerType == HeaderType.MODE_PARAMETER_HEADER_6)
78              modeParameterHeader = new ModeParameterHeader6(modeDataLength, blockDescriptorLength);
79          else
80              modeParameterHeader = new ModeParameterHeader10(modeDataLength, blockDescriptorLength, builder.longLba);
81  
82          // create and return the ModeParameterList
83          return new ModeParameterList(modeParameterHeader, builder.logicalBlockDescriptors, builder.modePages);
84      }
85  
86      private ModeParameterList (final ModeParameterHeader modeParameterHeader, final LogicalBlockDescriptor[] logicalBlockDescriptors, final ModePage[] modePages) {
87          this.modeParameterHeader = modeParameterHeader;
88          this.logicalBlockDescriptors = logicalBlockDescriptors;
89          this.modePages = modePages;
90      }
91  
92      public void serialize (ByteBuffer byteBuffer, int index) {
93  
94          int offset = 0;
95  
96          // serialize header
97          modeParameterHeader.serialize(byteBuffer, index);
98          offset += modeParameterHeader.size();
99  
100         // serialize logical block descriptors
101         if (logicalBlockDescriptors != null) for (LogicalBlockDescriptor lbd : logicalBlockDescriptors) {
102             lbd.serialize(byteBuffer, index + offset);
103             offset += lbd.size();
104         }
105 
106         // serialize mode pages
107         if (modePages != null) for (ModePage mp : modePages) {
108             mp.serialize(byteBuffer, index + offset);
109             offset += mp.size();
110         }
111     }
112 
113     public int size () {
114         // size = header + logical block descriptors + mode pages
115         int size = modeParameterHeader.size();
116         if (logicalBlockDescriptors != null && logicalBlockDescriptors.length > 0) size += logicalBlockDescriptors[0].size() * logicalBlockDescriptors.length;// all
117                                                                                                                                                               // have
118                                                                                                                                                               // the
119                                                                                                                                                               // same
120                                                                                                                                                               // size
121         if (modePages != null) for (ModePage mp : modePages)
122             size += mp.size();
123         return size;
124     }
125 }