1
/*___INFO__MARK_BEGIN__*/
2
/*************************************************************************
4
* The Contents of this file are made available subject to the terms of
5
* the Sun Industry Standards Source License Version 1.2
7
* Sun Microsystems Inc., March, 2001
10
* Sun Industry Standards Source License Version 1.2
11
* =================================================
12
* The contents of this file are subject to the Sun Industry Standards
13
* Source License Version 1.2 (the "License"); You may not use this file
14
* except in compliance with the License. You may obtain a copy of the
15
* License at http://gridengine.sunsource.net/Gridengine_SISSL_license.html
17
* Software provided under this License is provided on an "AS IS" basis,
18
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
19
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
20
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
21
* See the License for the specific provisions governing your rights and
22
* obligations concerning the Software.
24
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
26
* Copyright: 2001 by Sun Microsystems, Inc.
28
* All Rights Reserved.
30
************************************************************************/
31
/*___INFO__MARK_END__*/
33
package com.sun.grid.jgdi.util.shell.editor;
35
import com.sun.grid.jgdi.JGDIException;
36
//import com.sun.grid.jgdi.configuration.AbstractUser;
37
import com.sun.grid.jgdi.configuration.ClusterQueue;
38
import com.sun.grid.jgdi.configuration.ClusterQueueImpl;
39
import com.sun.grid.jgdi.configuration.Configuration;
40
import com.sun.grid.jgdi.configuration.ConfigurationElement;
41
import com.sun.grid.jgdi.configuration.ConfigurationElementImpl;
42
import com.sun.grid.jgdi.configuration.Util;
43
import com.sun.grid.jgdi.configuration.GEObject;
44
import com.sun.grid.jgdi.configuration.reflect.ClassDescriptor;
45
import com.sun.grid.jgdi.configuration.reflect.DefaultListPropertyDescriptor;
46
import com.sun.grid.jgdi.configuration.reflect.DefaultMapListPropertyDescriptor;
47
import com.sun.grid.jgdi.configuration.reflect.DefaultMapPropertyDescriptor;
48
import com.sun.grid.jgdi.configuration.reflect.PropertyDescriptor;
49
import com.sun.grid.jgdi.configuration.reflect.SimplePropertyDescriptor;
50
import com.sun.grid.jgdi.configuration.xml.XMLUtil;
51
import com.sun.grid.jgdi.JGDI;
52
import com.sun.grid.jgdi.configuration.ShareTreeImpl;
53
import java.io.IOException;
54
import java.util.ArrayList;
55
import java.util.Iterator;
56
import java.util.List;
60
* GEObject editor is a class for editing any GEObject based on text. This text
61
* will be parsed. If it's format is valid atrributes that were provided will be
62
* updated based on the values next to the attribute.
64
* Less coding when creating a new GeObject:
66
* <CODE>ClusterQueue geObj = new ClusterQueue(true);
67
* GEObjectEditor.updateObjectWithText(jgdi, geObj, "name test\n acl user1 user2\n xacl user3");
69
* GEObjectEditor.updateObjectWithText(geObj, "name test\n acl user1 user2\n xacl user3");
70
* jgdi.addClusterQueue(geObj);</CODE>
72
* Only difference between these methods is that whenJGDI reference is passed attributes
73
* are checked if they are known to Grid Engine and their structure is more advaced,
75
* Such as can have ...
77
* While when not passing JGDI reference, new Objects are created with default values.
78
* This can lead to unexpected behaviour when you try to update already existing object
79
* or even create a new one.
81
* <B>RECOMMENDED IS TO USE <CODE>updateObjectWithText(JGDI jgdi, GEObject obj, String text)</CODE> method.</B>
83
* Modifying existing GEObjects:
85
* <CODE>ClusterQueue geObj = jgdi.getClusterQueue("test");
86
* GEObjectEditor.updateObjectWithText(jgdi, geObj, "xacl user4");
87
* jgdi.updateClusterQueue(geObj);</CODE>
89
public class GEObjectEditor {
91
private static final int ELEMENT_NAME = 10;
92
private static final int ELEMENT_VALUE = 11;
95
* Updates GEObject based on the text. Text is parsed and if correct, object is updated.
96
* Creates new objects where necessary, based on values provided in text, therefore
97
* it is recommended to use method <CODE>updateObjectWithText(JGDI jgdi, GEObject obj, String text)</CODE>
98
* that retrieves these objects from Grid Engine instead.
100
public static <T extends GEObject> T updateObjectWithText(T obj, String text) {
101
return doUpdate(null, obj, text);
105
* Updates GEObject based on the text. Text is parsed and if correct, object is updated.
106
* Retrives objects from Grid Engine where necessary.
107
* Recommended method.
109
public static <T extends GEObject> T updateObjectWithText(JGDI jgdi, T obj, String text) {
111
throw new IllegalArgumentException("JGDI is NULL");
113
return doUpdate(jgdi, obj, text);
116
private static <T extends GEObject> T doUpdate(JGDI jgdi, T obj, String text) {
117
PropertyDescriptor pd;
121
throw new IllegalArgumentException("GEObject is NULL");
123
if (text.startsWith(XMLUtil.HEADER)) {
124
throw new UnsupportedOperationException("XML based editing not yet implemented!!!");
127
Map propertyMap = null;
128
if (obj instanceof ShareTreeImpl) {
129
obj = (T) EditorParser.parseShareTreeText(text);
131
propertyMap = EditorParser.parsePlainText(obj, text, " ");
132
for (Iterator iter=propertyMap.keySet().iterator(); iter.hasNext();) {
134
line = (String) propertyMap.get(key);
135
updatePropertyValue(jgdi, obj, key, line);
138
} catch (IOException ex) {
139
ex.printStackTrace();
145
private static <T extends GEObject> void updatePropertyValue(JGDI jgdi, T obj, Object key, String values) throws JGDIException {
146
if (key instanceof SimplePropertyDescriptor) {
147
updateSimpleProperty(jgdi, obj, (SimplePropertyDescriptor)key, values);
148
} else if (key instanceof DefaultListPropertyDescriptor) {
149
updateListProperty(jgdi, obj, (DefaultListPropertyDescriptor)key, values);
150
} else if (key instanceof DefaultMapPropertyDescriptor) {
151
updateMapProperty(jgdi, obj, (DefaultMapPropertyDescriptor)key, values);
152
} else if (key instanceof DefaultMapListPropertyDescriptor) {
153
updateMapListProperty(jgdi, obj, (DefaultMapListPropertyDescriptor)key, values);
154
//For CONFIGURATION objects
155
} else if (obj instanceof Configuration && key instanceof String) {
156
Configuration c = (Configuration) obj;
157
ConfigurationElement ce = new ConfigurationElementImpl();
158
ce.setName((String) key);
159
//TODO LP: Find out expected behaviour! Can values contain list of ConfigElems?
160
ce.setValue(values.trim());
162
//TODO LP: Need to exit if we get can't resolve hostname. Otherwise we get stacktrace for each element.
163
//Also if should be reworked to return correct error code (1).
164
jgdi.updateConfiguration(c);
166
new IllegalArgumentException("Unknown descriptor type=\""+key.getClass().getName()+
167
"\" for object type "+obj.getClass().getName());
171
private static void updateSimpleProperty(JGDI jgdi, GEObject obj, SimplePropertyDescriptor pd, String value) {
172
String type = pd.getPropertyType().getName();
173
Object val = EditorUtil.getParsedValueAsObject(jgdi, pd.getPropertyName(), type, value);
174
if (obj.getClass().getSimpleName().equals("CheckpointImpl") && val == null) {
177
pd.setValue(obj, val);
180
private static void updateListProperty(JGDI jgdi, GEObject obj, DefaultListPropertyDescriptor pd, String values) {
181
String type = pd.getPropertyType().getName();
182
String[] elems = values.split(" ");
185
for (int i = 0; i < elems.length; i++) {
186
value = EditorUtil.getParsedValueAsObject(jgdi, pd.getPropertyName(), type, elems[i]);
193
private static void updateMapProperty(JGDI jgdi, GEObject obj, DefaultMapPropertyDescriptor pd, String values) {
194
String attr = pd.getPropertyName();
195
String key, elem=null;
197
String[] elems = values.substring(1,values.length()-1).split("] \\[");
200
for (int i=0; i < elems.length; i++) {
202
//Get a key for the map
203
int keyEndPos = elem.indexOf('=');
204
key = elem.substring(0, keyEndPos);
205
elem = elem.substring(keyEndPos+1, elem.length());
206
//ClusterQueue - QTYPE we already have the int value as String, so we don't convert
207
if (attr.equalsIgnoreCase("qtype")) {
208
pd.put(obj, key, Integer.valueOf(elem));
211
//TODO Should there be a 'val = getParsedValue(elem)' or map is just String
212
val = EditorUtil.getParsedValueAsObject(jgdi, pd.getPropertyName(), pd.getPropertyType().getName(), elem);
213
val = EditorUtil.translateStringValueToObject(val);
214
//TODO LP: Since we do pd.removeAll() this works as setting null value, but some GEObjects expect to have default value set to null!
215
//LP: Temp fix for some objects
216
String cls = obj.getClass().getSimpleName();
217
boolean putNullValue = (
218
//cls.equals("ExecHost") ||
219
cls.equals("ClusterQueueImpl") //calendar NONE => needs @/=null
221
if (val != null || putNullValue) {
222
pd.put(obj, key, val);
227
private static void updateOneMapListEntry(JGDI jgdi, GEObject obj, DefaultMapListPropertyDescriptor pd, String key, String elem) {
228
String type = pd.getPropertyType().getName();
229
String[] elems, subElems;
232
boolean isCurrentElemMap;
233
//Get elements from the line
234
elems = elem.split(" ");
235
//Set new value for each of them
236
for (int i=0; i < elems.length; i++) {
237
isCurrentElemMap = EditorParser.isMap(elems[i]);
238
if (isCurrentElemMap) {
239
subElems = elems[i].split("=");
240
//name = subElems[0];
241
strVal = (String) EditorUtil.translateStringValueToObject(subElems[1]);
242
if (strVal == null) {
245
val = EditorUtil.getParsedValueAsObject(jgdi, pd.getPropertyName(), type, elems[i]);
249
if (obj instanceof TestGEObject) {
250
val = subElems[0]+"="+strVal; //TODO LP: Check the tests
254
val = EditorUtil.getParsedValueAsObject(jgdi, pd.getPropertyName(), type, name);
255
//Add only 1 NULL value for default key
257
if (!key.equals(EditorUtil.VALUE_DEFAULT)) {
260
List l = pd.getList(obj, key);
261
if (l != null && l.size() > 0) {
267
pd.addEmpty(obj, key);
269
pd.add(obj, key, val);
274
private static void updateMapListProperty(JGDI jgdi, GEObject obj, DefaultMapListPropertyDescriptor pd, String values) {
275
String key, elem=null;
276
String[] elems = values.substring(1,values.length()-1).split("] \\[");
279
for (int i=0; i < elems.length; i++) {
281
//Get a key for the map
282
int keyEndPos = elem.indexOf('=');
283
key = elem.substring(0, keyEndPos);
284
elem = elem.substring(keyEndPos+1, elem.length());
285
updateOneMapListEntry(jgdi, obj, pd, key, elem);
291
* Retrives all properties known to JGDI for specified GEObject as text. Each property on one line.
293
public static String getAllPropertiesAsText(GEObject obj) {
294
return getPropertiesAsText(obj, EditorUtil.PROPERTIES_ALL);
298
* Retrives configurable properties for specified GEObject as text. Each property on one line.
300
public static String getConfigurablePropertiesAsText(GEObject obj) {
301
return getPropertiesAsText(obj, EditorUtil.PROPERTIES_CONFIGURABLE);
305
* Retrives read-only properties for specified GEObject as text. Each property on one line.
307
public static String getReadOnlyPropertiesAsText(GEObject obj) {
308
return getPropertiesAsText(obj, EditorUtil.PROPERTIES_READ_ONLY);
311
public static String getPropertiesAsText(GEObject obj, int propScope) {
316
StringBuilder sb = new StringBuilder();
317
PropertyDescriptor pd;
318
List subNames = null, subValues = null;
319
for (Iterator iter = getProperties(obj, propScope).iterator(); iter.hasNext();) {
320
pd = (PropertyDescriptor) iter.next();
321
subNames = getStretchedElementNames(obj, pd);
322
if (subNames.size() > 0) {
323
for (Iterator it = subNames.iterator(); it.hasNext(); ) {
324
maxLen = Math.max(maxLen, ((String)it.next()).length());
327
name = EditorUtil.java2cName(obj, pd.getPropertyName());
328
maxLen = Math.max(maxLen, name.length());
332
for (Iterator iter = getProperties(obj, propScope).iterator(); iter.hasNext();) {
333
pd = (PropertyDescriptor) iter.next();
334
subNames = getStretchedElementNames(obj, pd);
335
if (subNames.size() > 0) {
336
subValues = getStretchedElementValues(obj, pd);
337
if (subNames.size() != subValues.size()) {
338
throw new IllegalArgumentException("Unknown error: Expecting name x value lists of a same size! Got sizes "+subNames.size()+" and "+subValues.size());
340
for (int j=0; j < subNames.size(); j++ ) {
341
name = (String) subNames.get(j);
342
value = (String)subValues.get(j);
344
for (int i=name.length(); i<maxLen; i++) {
347
sb.append(" "+value+"\n");
350
name = EditorUtil.java2cName(obj, pd.getPropertyName());
351
value = EditorUtil.translateObjectToStringValue(pd.getPropertyName(), EditorUtil.getPropertyValue(obj, pd));
353
for (int i=name.length(); i<maxLen; i++) {
357
sb.append(spaces+value+"\n");
360
return sb.toString();
363
public static String getPropertyAsText(GEObject obj, int propScope, String propName) throws JGDIException {
368
StringBuilder sb = new StringBuilder();
369
List subNames = null, subValues = null;
370
PropertyDescriptor pd = getProperty(obj, propScope, propName);
372
throw new JGDIException("JGDI Error: Attribute \""+propName+"\" does not exits in "+obj.getName());
374
subNames = getStretchedElementNames(obj, pd);
375
if (subNames.size() > 0) {
376
subValues = getStretchedElementValues(obj, pd);
377
if (subNames.size() != subValues.size()) {
378
throw new IllegalArgumentException("Unknown error: Expecting name x value lists of a same size! Got sizes " + subNames.size() + " and " + subValues.size());
380
for (int j = 0; j < subNames.size(); j++) {
381
name = (String) subNames.get(j);
382
value = (String) subValues.get(j);
384
for (int i = name.length(); i < maxLen; i++) {
387
sb.append(" " + value + "\n");
390
name = EditorUtil.java2cName(obj, pd.getPropertyName());
391
value = EditorUtil.translateObjectToStringValue(pd.getPropertyName(), EditorUtil.getPropertyValue(obj, pd));
393
for (int i = name.length(); i < maxLen; i++) {
397
sb.append(spaces + value + "\n");
399
return sb.toString();
402
private static List getStretchedElementNames(GEObject obj, PropertyDescriptor pd) {
403
return getStretchedElementList(obj, pd, ELEMENT_NAME);
405
private static List getStretchedElementValues(GEObject obj, PropertyDescriptor pd) {
406
return getStretchedElementList(obj, pd, ELEMENT_VALUE);
409
private static List getStretchedElementList(GEObject obj, PropertyDescriptor pd, int type) {
410
List list = new ArrayList();
412
if (obj instanceof Configuration) {
413
String name = EditorUtil.java2cName(obj, pd.getPropertyName());
414
if (name.equals("entries")) {
415
Iterator iter = ((Configuration)obj).getEntriesList().iterator();
416
ConfigurationElement elem = null;
417
while (iter.hasNext()) {
418
elem = (ConfigurationElement) iter.next();
421
list.add(elem.getName());
424
list.add(elem.getValue());
427
throw new IllegalArgumentException("Invalid element type: "+type+"!");
435
static List<PropertyDescriptor> getAllProperties(GEObject obj) {
436
return getProperties(obj, EditorUtil.PROPERTIES_ALL);
438
static List getConfigurableProperties(GEObject obj) {
439
return getProperties(obj, EditorUtil.PROPERTIES_CONFIGURABLE);
441
static List getReadOnlyProperties(GEObject obj) {
442
return getProperties(obj, EditorUtil.PROPERTIES_READ_ONLY);
445
static List getProperties(GEObject obj, int propScope) {
446
List<PropertyDescriptor> propList = new ArrayList<PropertyDescriptor>();
447
ClassDescriptor cd = Util.getDescriptor(obj.getClass());
448
for (PropertyDescriptor pd : cd.getProperties()) {
449
if (EditorUtil.doNotDisplayAttr(obj, pd, propScope)) {
452
if (isValidPropertyType(pd, propScope)) {
459
static PropertyDescriptor getProperty(GEObject obj, int propScope, String name) {
460
List<PropertyDescriptor> propList = new ArrayList<PropertyDescriptor>();
461
ClassDescriptor cd = Util.getDescriptor(obj.getClass());
462
PropertyDescriptor pd = cd.getProperty(EditorUtil.unifyClientNamesWithAttr(obj, name));
466
if (EditorUtil.doNotDisplayAttr(obj, pd, propScope)) {
469
if (isValidPropertyType(pd, propScope)) {
475
static boolean isValidPropertyType(PropertyDescriptor pd, int propScope) {
477
case EditorUtil.PROPERTIES_ALL:
479
case EditorUtil.PROPERTIES_CONFIGURABLE:
480
return pd.isConfigurable();
481
case EditorUtil.PROPERTIES_READ_ONLY:
482
return pd.isReadOnly();
484
throw new IllegalArgumentException("Invalid property scope specifier!");
488
public static void main(String[] args) {
489
ClusterQueue geObject = new ClusterQueueImpl(true);
490
System.out.println(GEObjectEditor.getConfigurablePropertiesAsText(geObject));
491
System.out.println(GEObjectEditor.getReadOnlyPropertiesAsText(geObject));
492
System.out.println(GEObjectEditor.getAllPropertiesAsText(geObject));
b'\\ No newline at end of file'