1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * ident "%Z%%M% %I% %E% SMI" 24 * 25 * Copyright 1998-2002 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms. 27 */ 28 29 package com.sun.dhcpmgr.data; 30 31 import java.util.*; 32 import java.text.MessageFormat; 33 34 /** 35 * Macro is a simple data class which encapsulates a macro record in 36 * the dhcptab. See dhcptab(4) for the gory details on macros. 37 * @see DhcptabRecord 38 * @see Option 39 */ 40 public class Macro extends DhcptabRecord implements Cloneable { 41 42 private boolean valueClean = false; 43 private Vector options; 44 45 // Definition for attribute limits 46 public final static short MAX_NAME_SIZE = 128; 47 48 // Value used to edit a boolean symbol of a macro 49 public final static String BOOLEAN_EDIT_VALUE = "_NULL_VALUE_"; 50 51 // Serialization id for this class 52 static final long serialVersionUID = -5255083189703724489L; 53 54 public Macro() { 55 super("", DhcptabRecord.MACRO, ""); 56 options = new Vector(); 57 } 58 59 public Macro(String name) throws ValidationException { 60 this(); 61 setKey(name); 62 } 63 64 public Macro(String name, String expansion) throws ValidationException { 65 this(name, expansion, DhcptabRecord.DEFAULT_SIGNATURE); 66 } 67 68 public Macro(String name, String expansion, String signature) 69 throws ValidationException { 70 this(); 71 setKey(name); 72 setValue(expansion, false, false); 73 setSignature(signature); 74 } 75 76 public void setKey(String name) throws ValidationException { 77 if (name.length() > MAX_NAME_SIZE) { 78 Object [] args = new Object[1]; 79 args[0] = new Short(MAX_NAME_SIZE); 80 MessageFormat form = new MessageFormat( 81 ResourceStrings.getString("macro_key_length")); 82 String msg = form.format(args); 83 throw new ValidationException(msg); 84 } 85 super.setKey(name); 86 } 87 88 public void setValue(String expansion, boolean edit, boolean validate) 89 throws ValidationException { 90 91 StringBuffer symbol = new StringBuffer(); 92 StringBuffer value = new StringBuffer(); 93 boolean inQuote = false; 94 boolean inEscape = false; 95 char c; 96 97 // State list for parsing machine 98 int START = 0; 99 int NAME = 1; 100 int VALUE = 2; 101 int state = !edit ? START : NAME; 102 103 for (int i = 0; i < expansion.length(); ++i) { 104 c = expansion.charAt(i); 105 if (!edit && (state == START)) { 106 // Start of expansion 107 if (c != ':' || expansion.length() == 1) { 108 Object [] args = new Object[1]; 109 args[0] = getKey(); 110 MessageFormat form = new MessageFormat( 111 ResourceStrings.getString("mac_syntax_error")); 112 String msg = form.format(args); 113 throw new ValidationException(msg); 114 } 115 state = NAME; 116 } else if (state == NAME) { 117 // Name of symbol 118 if (c == '=') { 119 state = VALUE; 120 } else if (!edit && (c == ':')) { 121 if (!validate) { 122 storeOption(symbol.toString(), value.toString()); 123 } else { 124 setOption(symbol.toString(), value.toString(), false); 125 } 126 symbol.setLength(0); 127 value.setLength(0); 128 state = NAME; 129 } else { 130 symbol.append(c); 131 } 132 } else if (state == VALUE) { 133 // Value of symbol 134 if (inEscape) { 135 value.append(c); 136 inEscape = false; 137 } else if (c == '\\') { 138 inEscape = true; 139 } else if (c == '"') { 140 inQuote = !inQuote; 141 value.append(c); 142 } else if (inQuote) { 143 value.append(c); 144 } else if (!edit && (c == ':')) { 145 if (!validate) { 146 storeOption(symbol.toString(), value.toString()); 147 } else { 148 setOption(symbol.toString(), value.toString(), false); 149 } 150 symbol.setLength(0); 151 value.setLength(0); 152 state = NAME; 153 } else { 154 value.append(c); 155 } 156 } 157 } 158 159 if (edit) { 160 setOption(symbol.toString(), value.toString(), true); 161 162 valueClean = false; 163 } else { 164 if (state != NAME) { 165 Object [] args = new Object[1]; 166 args[0] = getKey(); 167 MessageFormat form = new MessageFormat( 168 ResourceStrings.getString("mac_syntax_error")); 169 String msg = form.format(args); 170 throw new ValidationException(msg); 171 } 172 super.setValue(expansion); 173 valueClean = true; 174 } 175 } 176 177 public void editOption(String expansion) 178 throws ValidationException { 179 setValue(expansion, true, false); 180 } 181 182 /** 183 * Common method used to set an option value for the macro. 184 * @param symbol name of the option 185 * @param value the option value(if any) 186 * @param edit flag indicating that this is an edit of and existing option 187 */ 188 private void setOption(String symbol, String value, boolean edit) 189 throws ValidationException { 190 191 int index = getOptionIndex(symbol); 192 193 if (value.length() == 0) { 194 195 if (edit) { 196 if (index == -1) { 197 Object [] args = new Object[1]; 198 args[0] = symbol; 199 MessageFormat form = new MessageFormat( 200 ResourceStrings.getString("invalid_option")); 201 String msg = form.format(args); 202 throw new ValidationException(msg); 203 } 204 deleteOptionAt(index); 205 } else { 206 OptionValue option = 207 OptionValueFactory.newOptionValue(symbol, new String()); 208 209 if (option instanceof BogusOptionValue) { 210 Object [] args = new Object[1]; 211 args[0] = symbol; 212 MessageFormat form = new MessageFormat( 213 ResourceStrings.getString("invalid_option")); 214 String msg = form.format(args); 215 throw new ValidationException(msg); 216 } else if (!(option instanceof BooleanOptionValue)) { 217 Object [] args = new Object[1]; 218 args[0] = symbol; 219 MessageFormat form = new MessageFormat( 220 ResourceStrings.getString("not_boolean_option")); 221 String msg = form.format(args); 222 throw new ValidationException(msg); 223 } 224 } 225 226 } else if (edit && value.equals(BOOLEAN_EDIT_VALUE)) { 227 228 OptionValue option = 229 OptionValueFactory.newOptionValue(symbol, new String()); 230 231 if (option instanceof BogusOptionValue) { 232 Object [] args = new Object[1]; 233 args[0] = symbol; 234 MessageFormat form = new MessageFormat( 235 ResourceStrings.getString("invalid_option")); 236 String msg = form.format(args); 237 throw new ValidationException(msg); 238 } else if (!(option instanceof BooleanOptionValue)) { 239 Object [] args = new Object[1]; 240 args[0] = symbol; 241 MessageFormat form = new MessageFormat( 242 ResourceStrings.getString("not_boolean_option")); 243 String msg = form.format(args); 244 throw new ValidationException(msg); 245 } 246 247 if (index == -1) { 248 storeOption(option); 249 } else { 250 // nothing to do - option already turned on 251 } 252 253 } else { 254 255 OptionValue option = 256 OptionValueFactory.newOptionValue(symbol); 257 if (option instanceof BogusOptionValue) { 258 Object [] args = new Object[1]; 259 args[0] = symbol; 260 MessageFormat form = new MessageFormat( 261 ResourceStrings.getString("invalid_option")); 262 String msg = form.format(args); 263 throw new ValidationException(msg); 264 } else if (edit && option instanceof BooleanOptionValue) { 265 Object [] args = new Object[1]; 266 args[0] = symbol; 267 MessageFormat form = new MessageFormat( 268 ResourceStrings.getString("boolean_option")); 269 String msg = form.format(args); 270 throw new ValidationException(msg); 271 } 272 273 if (index == -1) { 274 storeOption(option); 275 } else { 276 option = getOptionAt(index); 277 } 278 option.setValue(value); 279 280 } 281 } 282 283 public void storeOption(OptionValue option) 284 throws ValidationException { 285 options.addElement(option); 286 } 287 288 public void storeOption(String option, Object value) 289 throws ValidationException { 290 options.addElement(OptionValueFactory.newOptionValue(option, value)); 291 } 292 293 // Useful for creating options when standard code values are known. 294 // 295 // XXX 296 // NOTE!!! Do not use this method for now. We need to resolve whether or 297 // not all standard options are going to have unique codes. Today, they do 298 // not. We include internal options as standard and set their codes to 0. 299 // 300 public void storeOption(int code, Object value) throws ValidationException { 301 options.addElement( 302 OptionValueFactory.newOptionValue(StandardOptions.nameForCode(code), 303 value)); 304 } 305 306 public String getValue() { 307 boolean first; 308 if (!valueClean) { 309 // Construct a new value 310 StringBuffer buf = new StringBuffer(); 311 for (Enumeration e = options.elements(); e.hasMoreElements(); ) { 312 OptionValue v = (OptionValue)e.nextElement(); 313 if (v == null) { 314 continue; // Ignore an empty position 315 } 316 buf.append(':'); 317 buf.append(v.toString()); 318 } 319 buf.append(':'); 320 try { 321 super.setValue(buf.toString()); 322 } catch (ValidationException ex) { 323 // Shouldn't happen; ignore it 324 } 325 valueClean = true; 326 } 327 return super.getValue(); 328 } 329 330 public Enumeration elements() { 331 return options.elements(); 332 } 333 334 public OptionValue [] getOptions() { 335 OptionValue [] optArray = new OptionValue[options.size()]; 336 options.copyInto(optArray); 337 return optArray; 338 } 339 340 public OptionValue getOption(String name) { 341 for (Enumeration en = options.elements(); en.hasMoreElements(); ) { 342 OptionValue v = (OptionValue)en.nextElement(); 343 if (name.equals(v.getName())) { 344 return v; 345 } 346 } 347 return null; 348 } 349 350 public int getOptionIndex(String name) { 351 int index = -1; 352 boolean found = false; 353 354 Enumeration en = options.elements(); 355 while (en.hasMoreElements() && !found) { 356 index++; 357 OptionValue v = (OptionValue)en.nextElement(); 358 if (name.equals(v.getName())) { 359 found = true; 360 } 361 } 362 if (!found) { 363 index = -1; 364 } 365 366 return index; 367 } 368 369 public OptionValue getOptionAt(int index) { 370 return (OptionValue)options.elementAt(index); 371 } 372 373 public void setOptionAt(OptionValue v, int index) { 374 if (index >= options.size()) { 375 options.setSize(index + 1); // Grow vector if necessary 376 } 377 options.setElementAt(v, index); 378 } 379 380 public int optionCount() { 381 return options.size(); 382 } 383 384 public void deleteOptionAt(int index) { 385 if (index >= options.size()) { 386 return; 387 } 388 options.removeElementAt(index); 389 } 390 391 public void insertOptionAt(OptionValue v, int index) { 392 options.insertElementAt(v, index); 393 } 394 395 // Make a copy of this macro 396 public Object clone() { 397 Macro m = new Macro(); 398 m.key = key; 399 m.options = new Vector(); 400 for (Enumeration en = options.elements(); en.hasMoreElements(); ) { 401 OptionValue v = (OptionValue)en.nextElement(); 402 m.options.addElement((OptionValue)v.clone()); 403 } 404 m.signature = signature; 405 return m; 406 } 407 408 public String toString() { 409 return (getKey() + " m " + getValue()); 410 } 411 412 // Verify that the options contained in this macro are all valid 413 public void validate() throws ValidationException { 414 for (Enumeration en = options.elements(); en.hasMoreElements(); ) { 415 OptionValue v = (OptionValue)en.nextElement(); 416 if (!v.isValid()) { 417 throw new ValidationException(v.getName()); 418 } 419 } 420 } 421 }