DirectoryEdit.java
/*
** Module : DirectoryEdit.java
** Abstract : general purpose interactive directory editor
**
** Copyright (c) 2005-2022, Golden Code Development Corporation.
**
** -#- -I- --Date-- --JPRM-- ----------------------------Description-----------------------------
** 001 NVS 20050428 @21012 Created the initial version which can handle
** editing attribute values and printing.
** 002 NVS 20050505 @21125 The default timeout was too short for LDAP
** directory accesses. Raised it to 60 seconds.
** Rewritten the top level menu. Now the bind()
** operation is done right away and unbind() is
** done when exiting the application.
** 003 NVS 20050518 @21228 Changed top menu to allow empty batch path,
** which is the directory root.
** 004 SIY 20050520 @21265 Rewritten with different menu model, finished
** remaining unimplemented items, added missing
** imported methods, many cleanups and changes
** in the formatting and comments.
** 005 NVS 20050527 @21315 Renamed to DirectoryEdit and promoted to the status of utility.
** 006 NVS 20050902 @22447 New directory based EIR registration puts
** limitations on exported names. "directory"
** group exports are renamed to comply.
** 007 NVS 20050914 @22706 DirectoryEdit is a TTY-based utility and as
** such has to suspend CHARVA on entry.
** 008 NVS 20050920 @22758 Fixed empty command processing and CHARVA detection.
** 009 GES 20070111 @31803 Removed unnecessary use of notifiable. This
** class is currently non-functional but is
** being retained for future re-enablement.
** 010 GES 20070115 @31840 Match minor interface change in base class.
** 011 EVL 20070609 @34005 Adding explicit import of the class
** com.goldencode.p2j.net.Queue to eliminate
** conflict with the same class from java.util
** package to be able to compile for Java 6.
** 012 ECF 20071106 @35904 Replaced Queue with Session.
** 013 ECF 20150715 Replace StringBuffer with StringBuilder.
** 014 ECF 20150828 Enable Java 8.
** 015 TJD 20220504 Java 11 compatibility minor changes
*/
/*
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU Affero General Public License as
** published by the Free Software Foundation, either version 3 of the
** License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU Affero General Public License for more details.
**
** You may find a copy of the GNU Affero GPL version 3 at the following
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
**
** Additional terms under GNU Affero GPL version 3 section 7:
**
** Under Section 7 of the GNU Affero GPL version 3, the following additional
** terms apply to the works covered under the License. These additional terms
** are non-permissive additional terms allowed under Section 7 of the GNU
** Affero GPL version 3 and may not be removed by you.
**
** 0. Attribution Requirement.
**
** You must preserve all legal notices or author attributions in the covered
** work or Appropriate Legal Notices displayed by works containing the covered
** work. You may not remove from the covered work any author or developer
** credit already included within the covered work.
**
** 1. No License To Use Trademarks.
**
** This license does not grant any license or rights to use the trademarks
** Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
** of Golden Code Development Corporation. You are not authorized to use the
** name Golden Code, FWD, or the names of any author or contributor, for
** publicity purposes without written authorization.
**
** 2. No Misrepresentation of Affiliation.
**
** You may not represent yourself as Golden Code Development Corporation or FWD.
**
** You may not represent yourself for publicity purposes as associated with
** Golden Code Development Corporation, FWD, or any author or contributor to
** the covered work, without written authorization.
**
** 3. No Misrepresentation of Source or Origin.
**
** You may not represent the covered work as solely your work. All modified
** versions of the covered work must be marked in a reasonable way to make it
** clear that the modified work is not originating from Golden Code Development
** Corporation or FWD. All modified versions must contain the notices of
** attribution required in this license.
*/
package com.goldencode.p2j.test;
import java.io.*;
import java.util.*;
import com.goldencode.p2j.directory.*;
import com.goldencode.p2j.directory.Base64;
import com.goldencode.p2j.net.*;
/**
* General purpose interactive directory editor.
* <p>
* Note that the use of <code>HighLevelObject</code> is not needed (and is
* a significant amount of useless code) once we move the directory interfaces
* into a <code>RemoteObject</code> approach. Much of this code also exists
* inside the <code>DirectoryEdit</code> class. Very nasty.
*/
public class DirectoryEdit
{
/** Current attribute name */
String attrName = null;
/** Locked branch */
String branch = null;
/** instance of HLO class that provides methods for directory access */
ServerDirectory dir = null;
/** Node menu definition/implementation */
MenuItem[] nodeMenu = new MenuItem[]
{
new MenuItem(" ~. Print menu")
{ void run(String[] args) { menuNodePrint(args); }},
new MenuItem(" ~l List attributes and nodes")
{ void run(String[] args) { menuNodeList(args); }},
new MenuItem(" ~t List attribute definitions")
{ void run(String[] args) { menuNodeListDefs(args); }},
new MenuItem(" ~E node Edit node")
{ void run(String[] args) { menuNodeEdit(args); }},
new MenuItem(" ~C node [class] Create child node")
{ void run(String[] args) { menuNodeCreate(args); }},
new MenuItem(" ~D node Delete child node")
{ void run(String[] args) { menuNodeDelete(args); }},
new MenuItem(" ~M node1 node2 Move node")
{ void run(String[] args) { menuNodeMove(args); }},
new MenuItem(" ~e attribute Edit node attribute")
{ void run(String[] args) { menuNodeEditAttribute(args); }},
new MenuItem(" ~c attribute Create node attribute")
{ void run(String[] args) { menuNodeCreateAttribute(args); }},
new MenuItem(" ~d attribute Delete node attribute")
{ void run(String[] args) { menuNodeDeleteAttribute(args); }},
new MenuItem(" ~q Quit")
{ void run(String[] args) { menuGoTop(args); }},
};
/** Top level menu definition/implementation */
MenuItem[] topMenu = new MenuItem[]
{
new MenuItem(" ~. Print menu")
{ void run(String[] args) { menuNodePrint(args); }},
new MenuItem(" ~b node Open batch for node")
{ void run(String[] args) { menuTopBatch(args); }},
new MenuItem(" ~b Back to batch node")
{ void run(String[] args) { menuNodePrint(args); }},
new MenuItem(" ~c Commit batch")
{ void run(String[] args) { menuTopCommit(args); }},
new MenuItem(" ~r Rollback batch")
{ void run(String[] args) { menuTopRollback(args); }},
new MenuItem(" ~q Quit")
{ void run(String[] args) { menuTopQuit(args); }},
};
/** Attribute editing menu */
private MenuItem[] attrMenu = new MenuItem[]
{
new MenuItem(" ~. Print menu")
{ void run(String[] args) { menuNodePrint(args); }},
new MenuItem(" ~l List values")
{ void run(String[] args) { menuAttrList(args); }},
new MenuItem(" ~e n Edit value n")
{ void run(String[] args) { menuAttrEdit(args); }},
new MenuItem(" ~d n Delete value n")
{ void run(String[] args) { menuAttrDelete(args); }},
new MenuItem(" ~a Add new value")
{ void run(String[] args) { menuAttrAdd(args); }},
new MenuItem(" ~q Quit")
{ void run(String[] args) { menuGoTop(args); }},
};
/**
* Construct an instance.
*
* @param session
* Reference to <code>Session</code>.
*/
public DirectoryEdit(Session session)
{
dir = new ServerDirectory(session);
}
/**
* A shortcut for getting user input.
*
* @return User input as a string. The new line character is not part of
* string.
*/
static String in()
{
StringBuilder sb = new StringBuilder();
char ch = 0;
while (true)
{
try
{
ch = (char)System.in.read();
}
catch (IOException x)
{
break;
}
if (ch == '\n')
break;
sb.append(ch);
}
return new String(sb);
}
/** A shortcut for the System.out.println() */
static void say()
{
System.out.println();
}
/**
* A shortcut for the System.out.println(String).
*
* @param string
* String to print.
*/
static void say(String string)
{
System.out.println(string);
}
/**
* Adds a value to node's attribute.
*
* @param node
* Node name.
* @param attr
* attribute name.
* @param newVal
* new value to be set.
* @return <code>true</code> if operation was successful.
* @throws Exception
* Forwarded from various methods.
*/
boolean addValue(String node, String attr, String newVal)
throws Exception
{
//int i;
String className = getNodeClass(node);
NodeAttribute nAttr = dir.getClassNodeAttribute(className, attr);
if (nAttr == null)
return false;
int type = nAttr.getType();
boolean res = false;
switch (type)
{
case AttributeType.ATTR_INTEGER :
res = dir.addNodeInteger(node, attr, Integer.parseInt(newVal));
break;
case AttributeType.ATTR_BOOLEAN :
Boolean boVal = Boolean.valueOf(newVal);
boolean bVal = boVal.booleanValue();
res = dir.addNodeBoolean(node, attr, bVal);
break;
case AttributeType.ATTR_STRING :
res = dir.addNodeString(node, attr, newVal);
break;
case AttributeType.ATTR_DOUBLE :
res = dir.addNodeDouble(node, attr, Double.parseDouble(newVal));
break;
case AttributeType.ATTR_BYTEARRAY :
res = dir.addNodeByteArray(node, attr,
Base64.base64ToByteArray(newVal));
break;
case AttributeType.ATTR_BITFIELD :
res = dir.addNodeBitField(node, attr, BitField.valueOf(newVal));
break;
case AttributeType.ATTR_BITSELECTOR :
res = dir.addNodeBitSelector(
node,
attr,
(BitSelector)BitSelector.valueOf(newVal));
break;
case AttributeType.ATTR_DATE :
res = dir.addNodeDate(node, attr, DateValue.valueOf(newVal));
break;
case AttributeType.ATTR_TIME :
res = dir.addNodeTime(node, attr, TimeValue.valueOf(newVal));
break;
default:
;
}
return res;
}
/**
* Combine current branch ID and command arguments into resulting node ID.
* <p>
* If command arguments are missing then <code>null</code> is returned
* indicating error, unless returning base branch ID is forced by setting
* <code>force</code> parameter to <code>true</code>.
*
* @param args
* Command arguments.
* @param force
* If set to <code>true</code> then resulting ID is returned
* regardless from the presence of the parameters.
* @return Resulting node ID.
*/
String getFullId(String[] args, boolean force)
{
String node = branch;
if (args != null && args.length > 1)
{
node += "/" + args[1];
return node;
}
return (force) ? node : null;
}
/**
* Get node class name without leading prefix.
*
* @param node
* Node name.
* @return Node object class name.
*/
String getNodeClass(String node)
{
try
{
String className = dir.getNodeClass(node);
if (className != null)
className = className.substring(className.lastIndexOf("/") + 1);
return className;
}
catch (Exception e)
{
return null;
}
}
/**
* Gets the number of values of node's attribute.
*
* @param node
* Node name.
* @param attr
* Attribute name.
* @return Number of values in the specified attribute of specified node.
* @throws Exception
* Forwarded from various methods.
*/
int getNumValues(String node, String attr)
throws Exception
{
//int i;
String className = getNodeClass(node);
NodeAttribute nAttr = dir.getClassNodeAttribute(className, attr);
if (nAttr == null)
return 0;
int type = nAttr.getType();
// getting values
Object[] values = null;
switch (type)
{
case AttributeType.ATTR_INTEGER :
values = dir.getNodeIntegers(node, attr);
break;
case AttributeType.ATTR_BOOLEAN :
values = dir.getNodeBooleans(node, attr);
break;
case AttributeType.ATTR_STRING :
values = dir.getNodeStrings(node, attr);
break;
case AttributeType.ATTR_DOUBLE :
values = dir.getNodeDoubles(node, attr);
break;
case AttributeType.ATTR_BYTEARRAY :
values = dir.getNodeByteArrays(node, attr);
break;
case AttributeType.ATTR_BITFIELD :
values = dir.getNodeBitFields(node, attr);
break;
case AttributeType.ATTR_BITSELECTOR :
values = dir.getNodeBitSelectors(node, attr);
break;
case AttributeType.ATTR_DATE :
values = dir.getNodeDates(node, attr);
break;
case AttributeType.ATTR_TIME :
values = dir.getNodeTimes(node, attr);
break;
default:
;
}
if (values == null)
return 0;
return values.length;
}
/**
* Check note if it is a terminal node and does not allow creation of child
* nodes.
*
* @param nodeId
* Node ID.
* @return <code>true</code> if node is a terminal node.
*/
boolean isNodeTerminal(String nodeId)
{
try
{
String nodeClass = dir.getNodeClass(nodeId);
if (nodeClass != null)
{
Boolean[] res = dir.getNodeBooleans(nodeClass, "terminal");
if (res != null && res[0].booleanValue())
return true;
}
}
catch (Exception e)
{
}
return false;
}
/**
* Lists the batch branch of the directory.
*
* @param startingPoint
* Path (id) of the node to print
* @throws Exception
* Forwarded from various methods.
*/
void listNodes(String startingPoint)
throws Exception
{
printNodeAttrs(startingPoint, 1);
printChildren(startingPoint, 1);
}
/**
* Attribute menu - add attribute value implementation.
*
* @param args
* Command arguments.
*/
void menuAttrAdd(String[] args)
{
if (args == null)
{
//Do nothing, just make Eclipse happy.
}
System.out.print("Enter new attribute value:");
String value = in();
try
{
if (addValue(branch, attrName, value))
say("Value added successfully");
else
say("Operation failed");
}
catch (Exception e)
{
e.printStackTrace(System.out);
}
}
/**
* Attribute menu - delete attribute value implementation.
*
* @param args
* Command arguments.
*/
void menuAttrDelete(String[] args)
{
if (args.length != 2)
{
say("Value index needed");
return;
}
try
{
int n = Integer.parseInt(args[1]);
if (n < 0 || n > (getNumValues(branch, attrName) - 1))
{
say("Invalid index");
return;
}
if (dir.deleteNodeAttributeValue(branch, attrName, n))
say("Value deleted successfully");
else
say("Operation failed");
}
catch (Exception e)
{
e.printStackTrace(System.out);
}
}
/**
* Attribute menu - edit attribute value implementation.
*
* @param args
* Command arguments.
*/
void menuAttrEdit(String[] args)
{
if (args.length != 2)
{
say("Value index needed");
return;
}
try
{
int n = Integer.parseInt(args[1]);
if (n < 0 || n > (getNumValues(branch, attrName) - 1))
{
say("Invalid index");
return;
}
String value = in();
if (setValue(branch, attrName, n, value))
say("Value changed successfully");
else
say("Operation failed");
}
catch (Exception e)
{
e.printStackTrace(System.out);
}
}
/**
* Attribute menu - list attribute value implementation.
*
* @param args
* Command arguments.
*/
void menuAttrList(String[] args)
{
if (args == null)
{
//Do nothing, just make Eclipse happy.
}
try
{
printAttrDef(branch, attrName);
}
catch (Exception e)
{
e.printStackTrace(System.out);
}
}
/**
* Return to previous level of menu.
*
* @param args
* Command arguments (ignored).
*/
void menuGoTop(String[] args)
{
if (args != null && args.length > 1)
say("Redundant parameters ignored");
say("Returning to previous menu");
throw new StopMenu();
}
/**
* Node menu - create object implementation.
*
* @param args
* Parsed command.
*/
void menuNodeCreate(String[] args)
{
String fullId = getFullId(args, false);
if (fullId == null)
{
say("Node ID is required");
return;
}
if (isNodeTerminal(branch))
{
say("Node it terminal. Menu item is disabled.");
}
try
{
String objClass;
if (args.length > 2)
objClass = args[2];
else
{
System.out.print("Enter object class name>");
System.out.flush();
objClass = in();
}
if (!nodeExists("/meta/class/" + objClass))
{
say("Object class does not exists");
return;
}
NodeAttribute[] list = dir.getClassNodeAttributes(objClass);
Vector attrs = new Vector();
Vector unfilled = new Vector();
if (list != null)
{
//Check for presence of the mandatory attributes
for (int i = 0; i < list.length; i++)
{
if(list[i].isMandatory())
{
Object value = null;
Attribute attr = null;
while (true)
{
//say("Object class defines mandatory attribute \"" +
// list[i].getName() + "\" (" + + ")");
printDef(list[i], "Required attribute: ");
System.out.print("Enter value>");
System.out.flush();
String str = in();
value = stringToAttrValue(list[i], str);
if (value != null)
{
attr = new Attribute(list[i], new Object[] {value});
if (attr.isValid())
break;
}
say("Entered value is invalid.");
}
attrs.add(attr);
}
else
{
unfilled.add(list[i]);
}
}
if (unfilled.size() > 0)
{
say("Enter <name value> pairs to add value to the attribute.");
say("Empty string breaks the loop.");
say("Following optional attributes can be added now:");
for (int i = 0; i < unfilled.size(); i++)
{
printDef((NodeAttribute)unfilled.get(i), "" + i + ") ");
}
say();
while (true)
{
Object value;
System.out.print("Enter name and value for attribute>");
System.out.flush();
String[] params = in().split(" ", 2);
if (params[0].equals(""))
break;
String val = null;
if (params.length < 2)
val = ""; //Empty value
else
val = params[1];
//Try to locate attribute in the array of already filled
//ones.
Attribute attr = null;
boolean found = false;
for (int i = 0; i < attrs.size(); i++)
{
Attribute tmpAttr =(Attribute)attrs.get(i);
if(tmpAttr.getName().equals(params[0]))
{
value = stringToAttrValue(tmpAttr.getDefinition(),
val);
attr = new Attribute(tmpAttr);
if (attr.addValue(value) && attr.isValid())
{
say("Added new value to attribute [" + params[0] +
"].");
attrs.set(i, attr);
}
else
say("Entered value is invalid.");
found = true;
break;
}
}
if (found)
continue;
//Try to locate attribute definition
for (int i = 0; i < list.length; i++)
{
if(list[i].getName().equals(params[0]))
{
value = stringToAttrValue(list[i], val);
if (value != null)
{
attr = new Attribute(list[i], new Object[]
{value});
if (attr.isValid())
{
say("Added new attribute [" + params[0] + "].");
attrs.add(attr);
}
else
say("Entered value is invalid.");
found = true;
break;
}
}
}
if (found)
continue;
say("Unknown attribute name [" + params[0] + "].");
}
}
}
boolean rc = false;
if (attrs.size() == 0)
rc = dir.addNode(fullId, objClass, null);
else
rc = dir.addNode(fullId, objClass,
(Attribute[])attrs.toArray(new Attribute[0]));
if (rc)
say("Node created successfully.");
else
say("Node creation failed.");
}
catch (Exception e)
{
e.printStackTrace(System.out);
}
}
/**
* Node menu - create attribute implementation.
*
* @param args
* Parsed command.
*/
void menuNodeCreateAttribute(String[] args)
{
if (args.length != 2)
{
say("Attribute name is required.");
return;
}
System.out.print("Enter attribute value>");
String value = in();
try
{
if (addValue(branch, args[1], value))
say("Attribute value added successfully.");
else
say("Operation failed.");
}
catch (Exception e)
{
e.printStackTrace(System.out);
}
}
/**
* Node menu - delete object implementation.
*
* @param args
* Parsed command.
*/
void menuNodeDelete(String[] args)
{
String fullId = getFullId(args, false);
if (fullId == null)
{
say("Node ID is required.");
return;
}
try
{
if (!nodeExists(fullId))
say(args[1] + " not found.");
else
{
boolean rc = dir.deleteNode(fullId);
if (rc)
say("Node deleted successfully.");
else
say("Operation failed.");
}
}
catch (Exception e)
{
e.printStackTrace(System.out);
}
}
/**
* Node menu - delete attribute implementation.
*
* @param args
* Parsed command.
*/
void menuNodeDeleteAttribute(String[] args)
{
if (args.length != 2)
{
say("Attribute name required.");
return;
}
try
{
if (!printAttrDef(branch, args[1]))
{
say(args[1] + " not found.");
return;
}
if (dir.deleteNodeAttribute(branch, args[1]))
say("Attribute deleted successfully.");
else
say("Operation failed.");
}
catch (Exception e)
{
e.printStackTrace(System.out);
}
}
/**
* Node menu - edit object implementation.
*
* @param args
* Parsed command.
*/
void menuNodeEdit(String[] args)
{
try
{
String nodeId = getFullId(args, false);
if (nodeId == null)
{
say("Node ID is required.");
return;
}
if (!nodeExists(nodeId))
{
say(nodeId + " not found.");
return;
}
String save = branch;
branch = nodeId;
runNodeMenu();
branch = save;
}
catch (Exception e)
{
e.printStackTrace(System.out);
}
}
/**
* Node menu - edit attribute implementation.
*
* @param args
* Parsed command.
*/
void menuNodeEditAttribute(String[] args)
{
if (args.length != 2)
{
say("Attribute name required.");
return;
}
try
{
String className = getNodeClass(branch);
if (className == null)
{
say("Unable to determine node class name.");
return;
}
NodeAttribute nAttr = dir.getClassNodeAttribute(className, args[1]);
if (nAttr == null)
{
say("No such attribute.");
return;
}
attrName = args[1];
run(branch + "." + args[1] + " menu:", attrMenu, null);
attrName = null;
}
catch (Exception e)
{
e.printStackTrace(System.out);
}
}
/**
* Node menu - list attributes and objects implementation.
*
* @param args
* Parsed command.
*/
void menuNodeList(String[] args)
{
try
{
String nodeId = getFullId(args, true);
listNodes(nodeId);
}
catch (Exception e)
{
e.printStackTrace(System.out);
}
}
/**
* Node menu - list definitions of attributes implementation.
*
* @param args
* Parsed command.
*/
void menuNodeListDefs(String[] args)
{
if (args == null)
{
//Do nothing, just make Eclipse happy.
}
try
{
printAttrDefs(branch);
}
catch (Exception e)
{
e.printStackTrace(System.out);
}
}
/**
* Node menu - move node implementation.
*
* @param args
* Parsed command.
*/
void menuNodeMove(String[] args)
{
if (args.length != 3)
{
say("Source node ID and destination node ID are required.");
return;
}
try
{
String fromID = getFullId(args, false);
String toID = args[2];
if (!toID.startsWith("/"))
toID = branch + "/" + toID;
boolean rc = dir.moveNode(fromID, toID);
say("Node moving " + (rc ? "succeeded" : "failed"));
}
catch (Exception e)
{
e.printStackTrace(System.out);
}
}
/**
* Node menu - print menu implementation.
*
* @param args
* Parsed command.
*/
void menuNodePrint(String[] args)
{
//Do nothing
if (args == null)
return;
}
/**
* Top menu - open batch implementation.
*
* @param args
* Command arguments.
*/
void menuTopBatch(String[] args)
{
if (args == null)
{
say("Invalid input.");
return;
}
if (branch != null)
{
runNodeMenu();
return;
}
boolean rc = false;
if (args.length > 1)
branch = args[1];
else
{
if (args[0].length() < 2)
{
say("Node ID is required.");
return;
}
branch = args[0].substring(2).trim();
}
say("Opening batch for " + (branch.equals("") ? "root":branch));
try
{
rc = dir.openBatch(branch);
if (rc)
runNodeMenu();
else
say("Batch open failed.");
}
catch (Exception e)
{
e.printStackTrace(System.out);
}
if (!rc)
branch = null;
}
/**
* Top menu - commit batch implementation.
*
* @param args
* Command arguments.
*/
void menuTopCommit(String[] args)
{
if (args == null)
{
//Do nothing, just make Eclipse happy.
}
if (branch == null)
{
say("Batch is not open.");
return;
}
try
{
if (dir.closeBatch(true))
say("Changes committed successfully.");
else
say("Operation failed.");
}
catch (StopMenu s)
{
throw s;
}
catch (Exception e)
{
e.printStackTrace(System.out);
}
branch = null;
}
/**
* Top menu - quit implementation.
*
* @param args
* Command arguments.
*/
void menuTopQuit(String[] args)
{
if (args == null)
{
//Do nothing, just make Eclipse happy.
}
if (branch != null)
{
say("Batch is still open. Commit or rollback it before exit.");
return;
}
say("Exiting.");
throw new StopMenu();
}
/**
* Top menu - rollback batch implementation.
*
* @param args
* Command arguments.
*/
void menuTopRollback(String[] args)
{
if (args == null)
{
//Do nothing, just make Eclipse happy.
}
if (branch == null)
{
say("Batch is not open.");
return;
}
try
{
if (dir.closeBatch(false))
say("All changes are rolled back.");
else
say("Operation failed.");
}
catch (Exception e)
{
e.printStackTrace(System.out);
}
branch = null;
}
/**
* Check existence of the node.
*
* @param nodeId
* @return <code>true</code> is specified node exists.
* @throws Exception
* Forwarded from underlying call.
*/
boolean nodeExists(String nodeId)
throws Exception
{
return (dir.getNodeClass(nodeId) != null);
}
/**
* Prints information about node's attribute definition.
*
* @param node
* Node name.
* @param attr
* Attribute name.
* @return <code>true</code> if operation was successful.
* @throws Exception
* Forwarded from various methods.
*/
boolean printAttrDef(String node, String attr)
throws Exception
{
int i;
StringBuilder buf = new StringBuilder(80);
String className = getNodeClass(node);
if (className == null)
return false;
NodeAttribute nAttr = dir.getClassNodeAttribute(className, attr);
if (nAttr == null)
return false;
printDef(nAttr, null);
// getting values
Object[] values = null;
switch (nAttr.getType())
{
case AttributeType.ATTR_INTEGER :
values = dir.getNodeIntegers(node, attr);
break;
case AttributeType.ATTR_BOOLEAN :
values = dir.getNodeBooleans(node, attr);
break;
case AttributeType.ATTR_STRING :
values = dir.getNodeStrings(node, attr);
break;
case AttributeType.ATTR_DOUBLE :
values = dir.getNodeDoubles(node, attr);
break;
case AttributeType.ATTR_BYTEARRAY :
values = dir.getNodeByteArrays(node, attr);
break;
case AttributeType.ATTR_BITFIELD :
values = dir.getNodeBitFields(node, attr);
break;
case AttributeType.ATTR_BITSELECTOR :
values = dir.getNodeBitSelectors(node, attr);
break;
case AttributeType.ATTR_DATE :
values = dir.getNodeDates(node, attr);
break;
case AttributeType.ATTR_TIME :
values = dir.getNodeTimes(node, attr);
break;
default:
;
}
say("Values:");
for (i = 0; values != null && i < values.length; i++)
{
buf.append(" " + i + ": ");
buf.append(values[i].toString());
say(buf.toString());
}
return true;
}
/**
* Print definitions of attributes for the specified node.
*
* @param node
* Node ID.
*/
void printAttrDefs(String node)
{
try
{
String className = getNodeClass(node);
if (className == null)
{
say("Unable to determine node class");
return;
}
NodeAttribute[] attrs = dir.getClassNodeAttributes(className);
say("Node [" + node + "] object class is \"" + className +"\".");
if (attrs == null || attrs.length == 0)
{
say("Object class does not define attributes.");
return;
}
say("Object class defines following attributes:");
for (int i = 0; i < attrs.length; i++)
{
printDef(attrs[i], " " + i + ") ");
}
say();
}
catch (Exception e)
{
e.printStackTrace(System.out);
}
}
/**
* Prints information about node's children nodes.
*
* @param node
* Node name.
* @param level
* Nesting/indentation level.
* @throws Exception
* Forwarded from various methods.
*/
void printChildren(String node, int level)
throws Exception
{
String[] nodes = dir.enumerateNodes(node);
int numNodes = nodes == null ? 0 : nodes.length;
StringBuilder sb = new StringBuilder();
int i = 0;
for (i = 0; i < level; i++)
sb.append(" ");
say(sb.toString() + "Child nodes:");
for (i = 0; i < numNodes; i++)
{
say(sb.toString() + i + ") " + nodes[i]);
}
}
/**
* Print instance of <code>NodeAttribute</code> in human-readable form.
*
* @param nAttr
* Instance of the <code>NodeAttribute</code> to print.
* @param prefix
* Optional prefix to print before attribute definition.
*/
void printDef(NodeAttribute nAttr, String prefix)
{
StringBuilder buf = new StringBuilder(80);
int type = nAttr.getType();
if (prefix != null)
buf.append(prefix);
buf.append("\"" + nAttr.getName() + "\" is ");
buf.append(AttributeType.toString(type));
buf.append(",");
if (nAttr.isMandatory())
buf.append(" mandatory,");
else
buf.append(" optional,");
if (nAttr.isMultiple())
buf.append(" multi-valued");
else
buf.append(" single-valued");
say(buf.toString());
}
/**
* Prints information about a single node.
*
* @param path
* Path (id) of the parent node.
* @param node
* Node name.
* @param level
* Nesting/indentation level.
* @throws Exception
* Forwarded from various methods.
*/
void printNode(String path, String node, int level)
throws Exception
{
int i;
StringBuilder buf = new StringBuilder(80);
for (i = 0; i < level; i++)
buf.append(" ");
buf.append(node);
buf.append(" {class = <");
node = path + "/" + node;
String name = dir.getNodeClass(node);
buf.append(name);
buf.append(">}");
say(buf.toString());
printNodeAttrs(node, level);
printChildren(node, level);
}
/**
* Prints information about node's attributes.
*
* @param node
* Node name.
* @param level
* Nesting/indentation level.
* @throws Exception
* Forwarded from various methods.
*/
void printNodeAttrs(String node, int level)
throws Exception
{
int i;
StringBuilder buf = new StringBuilder(80);
for (i = 0; i < level; i++)
buf.append(" ");
String prefix = buf.toString();
Attribute[] attr = dir.getNodeAttributes(node);
if (attr != null)
{
for (i = 0; i < attr.length; i++)
{
Object val = attr[i].getValue(0);
if (val == null)
continue;
if (val instanceof byte[])
val = Base64.byteArrayToBase64((byte[])val);
StringBuilder buf2 = new StringBuilder();
buf2.append(prefix);
buf2.append(" #attribute ");
buf2.append(attr[i].getName());
buf2.append(" = {");
buf2.append(val.toString());
for (int j = 1; val != null; j++)
{
val = attr[i].getValue(j);
if (val != null)
{
if (val instanceof byte[])
val = Base64.byteArrayToBase64((byte[])val);
buf2.append(", ");
buf2.append(val.toString());
}
}
buf2.append("}");
say(buf2.toString());
}
}
}
/** Main entry point */
void run()
{
try
{
if (!dir.bind())
{
say("Binding to directory failed");
return;
}
run("Top menu:", topMenu, null);
if (!dir.unbind())
say("Unbinding from directory failed");
}
catch (Exception e)
{
e.printStackTrace(System.out);
}
}
/**
* Menu list processing routine.
*
* @param text
* Message which will be printed before menu.
* @param menu
* List of menu items.
* @param comment
* Additional comment message to display after menu.
*/
void run(String text, MenuItem[] menu, String comment)
{
try
{
while (true)
{
//Draw menu
say();
say(text);
for (int i = 0; i < menu.length; i++)
say(menu[i].getText());
say();
if (comment != null)
{
say(comment);
say();
}
System.out.print("Enter command>");
System.out.flush();
boolean found = false;
String input = in();
if (input.length() == 0)
continue;
char ch = input.charAt(0);
for (int i = 0; i < menu.length; i++)
{
if (menu[i].getHotKey() == ch)
{
found = true;
String[] res = input.split(" ");
res[0] = input;
menu[i].run(res);
}
}
if (!found)
say("Invalid command [" + input + "]");
}
}
catch (StopMenu e)
{
}
}
/**
* Prepare message and call node menu.
*/
void runNodeMenu()
{
String message = null;
if (isNodeTerminal(branch))
message = "Node is terminal, menu item 'C node [class]' is disabled";
run((branch.equals("") ? "root" : branch) + " node menu:", nodeMenu,
message);
}
/**
* Sets a value of node's attribute.
*
* @param node
* Node name.
* @param attr
* Attribute name.
* @param n
* Value index.
* @param newVal
* New value to be set.
* @return <code>true</code> if operation was successful.
* @throws Exception
* Forwarded from various methods.
*/
boolean setValue(String node, String attr, int n, String newVal)
throws Exception
{
//int i;
String className = getNodeClass(node);
NodeAttribute nAttr = dir.getClassNodeAttribute(className, attr);
if (nAttr == null)
return false;
int type = nAttr.getType();
boolean res = false;
switch (type)
{
case AttributeType.ATTR_INTEGER :
res = dir.setNodeInteger(node, attr, n, Integer.parseInt(newVal));
break;
case AttributeType.ATTR_BOOLEAN :
Boolean boVal = Boolean.valueOf(newVal);
boolean bVal = boVal.booleanValue();
res = dir.setNodeBoolean(node, attr, n, bVal);
break;
case AttributeType.ATTR_STRING :
res = dir.setNodeString(node, attr, n, newVal);
break;
case AttributeType.ATTR_DOUBLE :
res = dir.setNodeDouble(node, attr, n, Double.parseDouble(newVal));
break;
case AttributeType.ATTR_BYTEARRAY :
res = dir.setNodeByteArray(node, attr, n,
Base64.base64ToByteArray(newVal));
break;
case AttributeType.ATTR_BITFIELD :
res = dir.setNodeBitField(node, attr, n, BitField.valueOf(newVal));
break;
case AttributeType.ATTR_BITSELECTOR :
res = dir.setNodeBitSelector(
node,
attr,
n,
(BitSelector)BitSelector.valueOf(newVal));
break;
case AttributeType.ATTR_DATE :
res = dir.setNodeDate(node, attr, n, DateValue.valueOf(newVal));
break;
case AttributeType.ATTR_TIME :
res = dir.setNodeTime(node, attr, n, TimeValue.valueOf(newVal));
break;
default:
;
}
return res;
}
/**
* Convert given string value into attribute value using attribute type
* information.
*
* @param list
* Attribute definition list.
* @param str
* Source string.
* @return Converted value.
*/
Object stringToAttrValue(NodeAttribute list, String str)
{
Object value = null;
switch(list.getType())
{
case AttributeType.ATTR_STRING :
value = str;
break;
case AttributeType.ATTR_BYTEARRAY :
value = Base64.base64ToByteArray(str);
break;
case AttributeType.ATTR_INTEGER :
value = Integer.valueOf(str, 10);
break;
case AttributeType.ATTR_BOOLEAN :
value = Boolean.valueOf(str);
break;
case AttributeType.ATTR_DOUBLE :
value = Double.valueOf(str);
break;
case AttributeType.ATTR_BITFIELD :
value = BitField.valueOf(str);
break;
case AttributeType.ATTR_BITSELECTOR :
value = BitSelector.valueOf(str);
break;
case AttributeType.ATTR_DATE :
value = DateValue.valueOf(str);
break;
case AttributeType.ATTR_TIME :
value = TimeValue.valueOf(str);
break;
}
return value;
}
/**
* Simple command line harness.
*/
public static void main(String[] args)
{
// TODO: this application is non-functional at this time, we need to
// 1. prepare the bootstrap config
// 2. make our connection and get our queue
// 3. start the queue
Session session = null;
try
{
DirectoryEdit app = new DirectoryEdit(session);
try
{
app.run();
}
catch (Exception x)
{
say("Exception in topMenu(): " + x);
x.printStackTrace(System.err);
}
}
catch (Exception e)
{
e.printStackTrace(System.out);
System.exit(-1);
}
}
/**
* HLO which will map server entry points into local object.
*/
public static class ServerDirectory
extends HighLevelObject
{
/** Group of exported methods which will be used for testing */
static final String GROUP = "directory";
/** RoutingKey for addNodeBitField() method */
private RoutingKey addNodeBitFieldKey = null;
/** RoutingKey for addNodeBitSelector() method */
private RoutingKey addNodeBitSelectorKey = null;
/** RoutingKey for addNodeBoolean() method */
private RoutingKey addNodeBooleanKey = null;
/** RoutingKey for addNodeByteArray() method */
private RoutingKey addNodeByteArrayKey = null;
/** RoutingKey for addNodeDate() method */
private RoutingKey addNodeDateKey = null;
/** RoutingKey for addNodeDouble() method */
private RoutingKey addNodeDoubleKey = null;
/** RoutingKey for addNodeInteger() method */
private RoutingKey addNodeIntegerKey = null;
/** RoutingKey for addNode() method */
private RoutingKey addNodeKey = null;
/** RoutingKey for addNodeString() method */
private RoutingKey addNodeStringKey = null;
/** RoutingKey for addNodeTime() method */
private RoutingKey addNodeTimeKey = null;
/** RoutingKey for bind() method */
private RoutingKey bindKey = null;
/** RoutingKey for closeBatch() method */
private RoutingKey closeBatchKey = null;
/** RoutingKey for deleteNodeAttribute() method */
private RoutingKey deleteNodeAttributeKey = null;
/** RoutingKey for deleteNodeAttributeValue() method */
private RoutingKey deleteNodeAttrValueKey = null;
/** RoutingKey for deleteNode() method */
private RoutingKey deleteNodeKey = null;
/** RoutingKey for enumerateNodes() method */
private RoutingKey enumNodesKey = null;
/** RoutingKey for getClassNodeAttribute() method */
private RoutingKey getClassNodeAttrKey = null;
/** RoutingKey for getClassNodeAttributes() method */
private RoutingKey getClassNodeAttrsKey = null;
/** RoutingKey for getNodeAttributes() method */
private RoutingKey getNodeAttrsKey = null;
/** RoutingKey for getNodeBitFields() method */
private RoutingKey getNodeBitFieldsKey = null;
/** RoutingKey for getNodeBitSelectors() method */
private RoutingKey getNodeBitSelectorsKey = null;
/** RoutingKey for getNodeBooleans() method */
private RoutingKey getNodeBooleansKey = null;
/** RoutingKey for getNodeByteArrays() method */
private RoutingKey getNodeByteArraysKey = null;
/** RoutingKey for getNodeClass() method */
private RoutingKey getNodeClassKey = null;
/** RoutingKey for getNodeDates() method */
private RoutingKey getNodeDatesKey = null;
/** RoutingKey for getNodeDoubles() method */
private RoutingKey getNodeDoublesKey = null;
/** RoutingKey for getNodeIntegers() method */
private RoutingKey getNodeIntegersKey = null;
/** RoutingKey for getNodeStrings() method */
private RoutingKey getNodeStringsKey = null;
/** RoutingKey for getNodeTimes() method */
private RoutingKey getNodeTimesKey = null;
/** RoutingKey for moveNode() method */
private RoutingKey moveNodeKey = null;
/** RoutingKey for openBatch() method */
private RoutingKey openBatchKey = null;
/** RoutingKey for setNodeBitField() method */
private RoutingKey setNodeBitFieldKey = null;
/** RoutingKey for setNodeBitSelector() method */
private RoutingKey setNodeBitSelectorKey = null;
/** RoutingKey for setNodeBoolean() method */
private RoutingKey setNodeBooleanKey = null;
/** RoutingKey for setNodeByteArray() method */
private RoutingKey setNodeByteArrayKey = null;
/** RoutingKey for setNodeDate() method */
private RoutingKey setNodeDateKey = null;
/** RoutingKey for setNodeDouble() method */
private RoutingKey setNodeDoubleKey = null;
/** RoutingKey for setNodeInteger() method */
private RoutingKey setNodeIntegerKey = null;
/** RoutingKey for setNodeString() method */
private RoutingKey setNodeStringKey = null;
/** RoutingKey for setNodeTime() method */
private RoutingKey setNodeTimeKey = null;
/** RoutingKey for unbind() method */
private RoutingKey unbindKey = null;
/**
* Construct an HLO using provided instance of the <code>Queue</code>.
*
* @param session
* Properly initialized session.
*/
ServerDirectory(Session session)
{
super(session, 60000);
}
/**
* Add new node of specified class with specified ID. For node
* initialization list of attributes and corresponding list of attribute
* values should be provided. The presence of the mandatory attributes
* in the lists is obligatory.
*
* @param nodeId
* Node name.
* @param nodeClass
* Node class name.
* @param data
* A list of the attributes.
* @return <code>true</code> if operation was successful and
* <code>false</code> otherwise.
* @throws Exception
* Forwarded from the remote method.
*/
public boolean addNode(String nodeId, String nodeClass, Attribute[] data)
throws Exception
{
if (addNodeKey == null)
addNodeKey = getKey(GROUP, "addnode");
if (addNodeKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[] { nodeId, nodeClass, data };
Object result = transact(addNodeKey, parms);
return ((Boolean)result).booleanValue();
}
/**
* Add new <code>BitField</code> value to the attribute.
*
* @param nodeId
* Node identifier.
* @param name
* Attribute name.
* @param value
* New value for the attribute variable.
* @return <code>true</code> is operation is successful and
* <code>false</code> otherwise.
* @throws Exception
* Forwarded from the remote method.
*/
public boolean addNodeBitField(String nodeId, String name,
BitField value)
throws Exception
{
if (addNodeBitFieldKey == null)
addNodeBitFieldKey = getKey(GROUP, "addnodebitfield");
if (addNodeBitFieldKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[]
{
nodeId, name, value
};
Object result = transact(addNodeBitFieldKey, parms);
return ((Boolean)result).booleanValue();
}
/**
* Add new <code>BitSelector</code> value to the attribute.
*
* @param nodeId
* Node identifier.
* @param name
* Attribute name.
* @param value
* New value for the attribute variable.
* @return <code>true</code> is operation is successful and
* <code>false</code> otherwise.
* @throws Exception
* Forwarded from the remote method.
*/
public boolean addNodeBitSelector(String nodeId, String name,
BitSelector value)
throws Exception
{
if (addNodeBitSelectorKey == null)
addNodeBitSelectorKey = getKey(GROUP, "addnodebitselector");
if (addNodeBitSelectorKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[]
{
nodeId, name, value
};
Object result = transact(addNodeBitSelectorKey, parms);
return ((Boolean)result).booleanValue();
}
/**
* Add new <code>boolean</code> value to the attribute.
*
* @param nodeId
* Node identifier.
* @param name
* Attribute name.
* @param value
* New value for the attribute variable.
* @return <code>true</code> is operation is successful and
* <code>false</code> otherwise.
* @throws Exception
* Forwarded from the remote method.
*/
public boolean addNodeBoolean(String nodeId, String name, boolean value)
throws Exception
{
if (addNodeBooleanKey == null)
addNodeBooleanKey = getKey(GROUP, "addnodeboolean");
if (addNodeBooleanKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[]
{
nodeId, name, Boolean.valueOf(value)
};
Object result = transact(addNodeBooleanKey, parms);
return ((Boolean)result).booleanValue();
}
/**
* Add new <code>byte[]</code> value to the attribute.
*
* @param nodeId
* Node identifier.
* @param name
* Attribute name.
* @param value
* New value for the attribute variable.
* @return <code>true</code> is operation is successful and
* <code>false</code> otherwise.
* @throws Exception
* Forwarded from the remote method.
*/
public boolean addNodeByteArray(String nodeId, String name, byte[] value)
throws Exception
{
if (addNodeByteArrayKey == null)
addNodeByteArrayKey = getKey(GROUP, "addnodebytearray");
if (addNodeByteArrayKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[]
{
nodeId, name, value
};
Object result = transact(addNodeByteArrayKey, parms);
return ((Boolean)result).booleanValue();
}
/**
* Add new <code>DateValue</code> value to the attribute.
*
* @param nodeId
* Node identifier.
* @param name
* Attribute name.
* @param value
* New value for the attribute variable.
* @return <code>true</code> is operation is successful and
* <code>false</code> otherwise.
* @throws Exception
* Forwarded from the remote method.
*/
public boolean addNodeDate(String nodeId, String name, DateValue value)
throws Exception
{
if (addNodeDateKey == null)
addNodeDateKey = getKey(GROUP, "addnodedate");
if (addNodeDateKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[]
{
nodeId, name, value
};
Object result = transact(addNodeDateKey, parms);
return ((Boolean)result).booleanValue();
}
/**
* Add new <code>Double</code> value to the attribute.
*
* @param nodeId
* Node identifier.
* @param name
* Attribute name.
* @param value
* New value for the attribute variable.
* @return <code>true</code> is operation is successful and
* <code>false</code> otherwise.
* @throws Exception
* Forwarded from the remote method.
*/
public boolean addNodeDouble(String nodeId, String name, double value)
throws Exception
{
if (addNodeDoubleKey == null)
addNodeDoubleKey = getKey(GROUP, "addnodedouble");
if (addNodeDoubleKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[]
{
nodeId, name, Double.valueOf(value)
};
Object result = transact(addNodeDoubleKey, parms);
return ((Boolean)result).booleanValue();
}
/**
* Add new <code>int</code> value to the attribute.
*
* @param nodeId
* Node identifier.
* @param name
* Attribute name.
* @param value
* New value for the attribute variable.
* @return <code>true</code> is operation is successful and
* <code>false</code> otherwise.
* @throws Exception
* Forwarded from the remote method.
*/
public boolean addNodeInteger(String nodeId, String name, int value)
throws Exception
{
if (addNodeIntegerKey == null)
addNodeIntegerKey = getKey(GROUP, "addnodeinteger");
if (addNodeIntegerKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[]
{
nodeId, name, Integer.valueOf(value)
};
Object result = transact(addNodeIntegerKey, parms);
return ((Boolean)result).booleanValue();
}
/**
* Add new <code>String</code> value to the attribute.
*
* @param nodeId
* Node identifier.
* @param name
* Attribute name.
* @param value
* New value for the attribute variable.
* @return <code>true</code> is operation is successful and
* <code>false</code> otherwise.
* @throws Exception
* Forwarded from the remote method.
*/
public boolean addNodeString(String nodeId, String name, String value)
throws Exception
{
if (addNodeStringKey == null)
addNodeStringKey = getKey(GROUP, "addnodestring");
if (addNodeStringKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[]
{
nodeId, name, value
};
Object result = transact(addNodeStringKey, parms);
return ((Boolean)result).booleanValue();
}
/**
* Add new <code>TimeValue</code> value to the attribute.
*
* @param nodeId
* Node identifier.
* @param name
* Attribute name.
* @param value
* New value for the attribute variable.
* @return <code>true</code> is operation is successful and
* <code>false</code> otherwise.
* @throws Exception
* Forwarded from the remote method.
*/
public boolean addNodeTime(String nodeId, String name, TimeValue value)
throws Exception
{
if (addNodeTimeKey == null)
addNodeTimeKey = getKey(GROUP, "addnodetime");
if (addNodeTimeKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[]
{
nodeId, name, value
};
Object result = transact(addNodeTimeKey, parms);
return ((Boolean)result).booleanValue();
}
/**
* Binds to the directory.
*
* @return <code>true</code> is operation is successful and
* <code>false</code> otherwise.
* @throws Exception
* Forwarded from the remote method.
*/
public boolean bind()
throws Exception
{
if (bindKey == null)
bindKey = getKey(GROUP, "bind");
if (bindKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[] {};
Object result = transact(bindKey, parms);
return ((Boolean)result).booleanValue();
}
/**
* Closes the currently open editing batch.
*
* @param disposition
* true if committing, false otherwise
* @return true or false
* @throws Exception
* Forwarded from the remote method.
*/
public boolean closeBatch(boolean disposition)
throws Exception
{
if (closeBatchKey == null)
closeBatchKey = getKey(GROUP, "closebatch");
if (closeBatchKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[]
{
Boolean.valueOf(disposition)
};
Object result = transact(closeBatchKey, parms);
return ((Boolean)result).booleanValue();
}
/**
* Remove specified node from the directory (unless node has children).
*
* @param nodeId
* Node identifier.
* @return <code>true</code> if operation was successful and
* <code>false</code> otherwise.
* @throws Exception
* Forwarded from the remote method.
*/
public boolean deleteNode(String nodeId)
throws Exception
{
if (deleteNodeKey == null)
deleteNodeKey = getKey(GROUP, "deletenode");
if (deleteNodeKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[]
{
nodeId
};
Object result = transact(deleteNodeKey, parms);
return ((Boolean)result).booleanValue();
}
/**
* Remove whole node attribute.
*
* @param nodeId
* Node name.
* @param name
* Attribute name.
* @return <code>true</code> if operation was successful and
* <code>false</code> otherwise.
* @throws Exception
* Forwarded from the remote method.
*/
public boolean deleteNodeAttribute(String nodeId, String name)
throws Exception
{
if (deleteNodeAttributeKey == null)
deleteNodeAttributeKey = getKey(GROUP, "deletenodeattribute");
if (deleteNodeAttributeKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[]
{
nodeId, name
};
Object result = transact(deleteNodeAttributeKey, parms);
return ((Boolean)result).booleanValue();
}
/**
* Remove particular value from the node attribute. Note that removing
* last value from the attribute deletes entire attribute unless
* attribute is marked mandatory.
*
* @param nodeId
* Node name.
* @param name
* Attribute name.
* @param index
* Attribute value index.
* @return <code>true</code> if operation was successful and
* <code>false</code> otherwise.
* @throws Exception
* Forwarded from the remote method.
*/
public boolean deleteNodeAttributeValue(String nodeId, String name,
int index)
throws Exception
{
if (deleteNodeAttrValueKey == null)
deleteNodeAttrValueKey = getKey(GROUP, "deletenodeattributevalue");
if (deleteNodeAttrValueKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[] { nodeId, name, Integer.valueOf(index) };
Object result = transact(deleteNodeAttrValueKey, parms);
return ((Boolean)result).booleanValue();
}
/**
* Enumerates all children nodes of a node.
*
* @param nodeId
* Node name
* @return Array of children node IDs
* @throws Exception
* Forwarded from the remote method.
*/
public String[] enumerateNodes(String nodeId)
throws Exception
{
if (enumNodesKey == null)
enumNodesKey = getKey(GROUP, "enumeratenodes");
if (enumNodesKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[] { nodeId };
Object result = transact(enumNodesKey, parms);
return (String[])result;
}
/**
* Gets NodeAttribute structure for the specified attribute.
*
* @param className
* Object Class name.
* @param name
* Object Class attribute name.
* @return An instance of <code>NodeAttribute</code> which describes
* specified attribute or <code>null</code> if no such object
* class or attribute name.
* @throws Exception
* Forwarded from the remote method.
*/
public NodeAttribute getClassNodeAttribute(String className, String name)
throws Exception
{
if (getClassNodeAttrKey == null)
getClassNodeAttrKey = getKey(GROUP, "getclassnodeattribute");
if (getClassNodeAttrKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[] { className, name };
Object result = transact(getClassNodeAttrKey, parms);
return (NodeAttribute)result;
}
/**
* Generate an array of <code>NodeAttribute</code> structures for the
* all attributes defined for the node class. Note that since these
* instances of <code>NodeAttribute</code> are not attached to
* particular instance of <code>Attribute</code>, information about
* number of the values assigned to the attribute is incorrect. The
* purpose of this method is to create new attributes.
*
* @param className
* Object Class name.
* @return An array of <code>NodeAttribute</code> instances which
* describe attributes of node or <code>null</code> if no such
* object class or attributes defined for the class.
* @throws Exception
* Forwarded from the remote method.
*/
public NodeAttribute[] getClassNodeAttributes(String className)
throws Exception
{
if (getClassNodeAttrsKey == null)
getClassNodeAttrsKey = getKey(GROUP, "getclassnodeattributes");
if (getClassNodeAttrsKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[] { className };
Object result = transact(getClassNodeAttrsKey, parms);
return (NodeAttribute[])result;
}
/**
* Reads all attributes of a node.
*
* @param nodeId
* Node name
* @return Array of node attributes
* @throws Exception
* Forwarded from the remote method.
*/
public Attribute[] getNodeAttributes(String nodeId)
throws Exception
{
if (getNodeAttrsKey == null)
getNodeAttrsKey = getKey(GROUP, "getnodeattributes");
if (getNodeAttrsKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[] { nodeId };
Object result = transact(getNodeAttrsKey, parms);
return (Attribute[])result;
}
/**
* Gets all <code>BitField</code> attribute values for specified node
* ID.
*
* @param nodeId
* Node identifier.
* @param name
* Attribute name.
* @return Values of the attribute
* @throws Exception
* Forwarded from the remote method.
*/
public BitField[] getNodeBitFields(String nodeId, String name)
throws Exception
{
if (getNodeBitFieldsKey == null)
getNodeBitFieldsKey = getKey(GROUP, "getnodebitfields");
if (getNodeBitFieldsKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[] { nodeId, name };
Object result = transact(getNodeBitFieldsKey, parms);
return (BitField[])result;
}
/**
* Gets all <code>BitSelector</code> attribute values for specified
* node ID.
*
* @param nodeId
* Node identifier.
* @param name
* Attribute name.
* @return Values of the attribute
* @throws Exception
* Forwarded from the remote method.
*/
public BitSelector[] getNodeBitSelectors(String nodeId, String name)
throws Exception
{
if (getNodeBitSelectorsKey == null)
getNodeBitSelectorsKey = getKey(GROUP, "getnodebitselectors");
if (getNodeBitSelectorsKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[] { nodeId, name };
Object result = transact(getNodeBitSelectorsKey, parms);
return (BitSelector[])result;
}
/**
* Gets all <code>Boolean</code> attribute values for specified node
* ID.
*
* @param nodeId
* Node identifier.
* @param name
* Attribute name.
* @return Values of the attribute
* @throws Exception
* Forwarded from the remote method.
*/
public Boolean[] getNodeBooleans(String nodeId, String name)
throws Exception
{
if (getNodeBooleansKey == null)
getNodeBooleansKey = getKey(GROUP, "getnodebooleans");
if (getNodeBooleansKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[] { nodeId, name };
Object result = transact(getNodeBooleansKey, parms);
return (Boolean[])result;
}
/**
* Gets all <code>ByteArray</code> attribute values for specified node
* ID.
*
* @param nodeId
* Node identifier.
* @param name
* Attribute name.
* @return Values of the attribute
* @throws Exception
* Forwarded from the remote method.
*/
public byte[][] getNodeByteArrays(String nodeId, String name)
throws Exception
{
if (getNodeByteArraysKey == null)
getNodeByteArraysKey = getKey(GROUP, "getnodebytearrays");
if (getNodeByteArraysKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[] { nodeId, name };
Object result = transact(getNodeByteArraysKey, parms);
return (byte[][])result;
}
/**
* Queries the object class name of a node.
*
* @param nodeId
* Node name
* @return Class name of this node
* @throws Exception
* Forwarded from the remote method.
*/
public String getNodeClass(String nodeId)
throws Exception
{
if (getNodeClassKey == null)
getNodeClassKey = getKey(GROUP, "getnodeclass");
if (getNodeClassKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[] { nodeId };
Object result = transact(getNodeClassKey, parms);
return (String)result;
}
/**
* Gets all <code>Date</code> attribute values for specified node ID.
*
* @param nodeId
* Node identifier.
* @param name
* Attribute name.
* @return Values of the attribute
* @throws Exception
* Forwarded from the remote method.
*/
public DateValue[] getNodeDates(String nodeId, String name)
throws Exception
{
if (getNodeDatesKey == null)
getNodeDatesKey = getKey(GROUP, "getnodedates");
if (getNodeDatesKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[] { nodeId, name };
Object result = transact(getNodeDatesKey, parms);
return (DateValue[])result;
}
/**
* Gets all <code>Double</code> attribute values for specified node
* ID.
*
* @param nodeId
* Node identifier.
* @param name
* Attribute name.
* @return Values of the attribute
* @throws Exception
* Forwarded from the remote method.
*/
public Double[] getNodeDoubles(String nodeId, String name)
throws Exception
{
if (getNodeDoublesKey == null)
getNodeDoublesKey = getKey(GROUP, "getnodedoubles");
if (getNodeDoublesKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[] { nodeId, name };
Object result = transact(getNodeDoublesKey, parms);
return (Double[])result;
}
/**
* Gets all <code>Integer</code> attribute values for specified node
* ID.
*
* @param nodeId
* Node identifier.
* @param name
* Attribute name.
* @return Values of the attribute
* @throws Exception
* Forwarded from the remote method.
*/
public Integer[] getNodeIntegers(String nodeId, String name)
throws Exception
{
if (getNodeIntegersKey == null)
getNodeIntegersKey = getKey(GROUP, "getnodeintegers");
if (getNodeIntegersKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[] { nodeId, name };
Object result = transact(getNodeIntegersKey, parms);
return (Integer[])result;
}
/**
* Gets all <code>String</code> attribute values for specified node
* ID.
*
* @param nodeId
* Node identifier.
* @param name
* Attribute name.
* @return Values of the attribute
* @throws Exception
* Forwarded from the remote method.
*/
public String[] getNodeStrings(String nodeId, String name)
throws Exception
{
if (getNodeStringsKey == null)
getNodeStringsKey = getKey(GROUP, "getnodestrings");
if (getNodeStringsKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[] { nodeId, name };
Object result = transact(getNodeStringsKey, parms);
return (String[])result;
}
/**
* Gets all <code>Time</code> attribute values for specified node ID.
*
* @param nodeId
* Node identifier.
* @param name
* Attribute name.
* @return Values of the attribute
* @throws Exception
* Forwarded from the remote method.
*/
public TimeValue[] getNodeTimes(String nodeId, String name)
throws Exception
{
if (getNodeTimesKey == null)
getNodeTimesKey = getKey(GROUP, "getnodetimes");
if (getNodeTimesKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[] { nodeId, name };
Object result = transact(getNodeTimesKey, parms);
return (TimeValue[])result;
}
/**
* Renames the existing object, specified by nodeId, or moves it to a
* different location. The parent object of the newId should exist and
* allow for children creation.
*
* @param nodeId
* An ID of the node to move.
* @param newId
* The desired new location of the node.
* @return <code>true</code> is operation is successful and
* <code>false</code> otherwise.
* @throws Exception
* Forwarded from the remote method.
*/
public boolean moveNode(String nodeId, String newId)
throws Exception
{
if (moveNodeKey == null)
moveNodeKey = getKey(GROUP, "movenode");
if (moveNodeKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[] { nodeId, newId };
Object result = transact(moveNodeKey, parms);
return ((Boolean)result).booleanValue();
}
/**
* Opens an editing batch.
*
* @param nodeId
* Node specifying directory branch to open
* @return <code>true</code> is operation is successful and
* <code>false</code> otherwise.
* @throws Exception
* Forwarded from the remote method.
*/
public boolean openBatch(String nodeId)
throws Exception
{
if (openBatchKey == null)
openBatchKey = getKey(GROUP, "openbatch");
if (openBatchKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[] { nodeId };
Object result = transact(openBatchKey, parms);
return ((Boolean)result).booleanValue();
}
/**
* Set <code>BitField</code> attribute value for specified node ID,
* attribute name and index.
*
* @param nodeId
* Node identifier.
* @param name
* Attribute name.
* @param index
* Index of the value to retrieve.
* @param value
* New value for the attribute variable.
* @return <code>true</code> is operation is successful and
* <code>false</code> otherwise.
* @throws Exception
* Forwarded from the remote method.
*/
public boolean setNodeBitField(String nodeId, String name, int index,
BitField value)
throws Exception
{
if (setNodeBitFieldKey == null)
setNodeBitFieldKey = getKey(GROUP, "setnodebitfield4");
if (setNodeBitFieldKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[] { nodeId, name, Integer.valueOf(index),
value };
Object result = transact(setNodeBitFieldKey, parms);
return ((Boolean)result).booleanValue();
}
/**
* Set <code>BitSelector</code> attribute value for specified node ID,
* attribute name and index.
*
* @param nodeId
* Node identifier.
* @param name
* Attribute name.
* @param index
* Index of the value to retrieve.
* @param value
* New value for the attribute variable.
* @return <code>true</code> is operation is successful and
* <code>false</code> otherwise.
* @throws Exception
* Forwarded from the remote method.
*/
public boolean setNodeBitSelector(String nodeId, String name,
int index, BitSelector value)
throws Exception
{
if (setNodeBitSelectorKey == null)
setNodeBitSelectorKey = getKey(GROUP, "setnodebitselector4");
if (setNodeBitSelectorKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[] { nodeId, name, Integer.valueOf(index),
value};
Object result = transact(setNodeBitSelectorKey, parms);
return ((Boolean)result).booleanValue();
}
/**
* Set <code>boolean</code> attribute value for specified node ID,
* attribute name and index.
*
* @param nodeId
* Node identifier.
* @param name
* Attribute name.
* @param index
* Index of the value to retrieve.
* @param value
* New value for the attribute variable.
* @return <code>true</code> is operation is successful and
* <code>false</code> otherwise.
* @throws Exception
* Forwarded from the remote method.
*/
public boolean setNodeBoolean(String nodeId, String name, int index,
boolean value)
throws Exception
{
if (setNodeBooleanKey == null)
setNodeBooleanKey = getKey(GROUP, "setnodeboolean4");
if (setNodeBooleanKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[]
{
nodeId, name, Integer.valueOf(index), Boolean.valueOf(value)
};
Object result = transact(setNodeBooleanKey, parms);
return ((Boolean)result).booleanValue();
}
/**
* Set <code>byte[]</code> attribute value for specified node ID,
* attribute name and index.
*
* @param nodeId
* Node identifier.
* @param name
* Attribute name.
* @param index
* Index of the value to retrieve.
* @param value
* New value for the attribute variable.
* @return <code>true</code> is operation is successful and
* <code>false</code> otherwise.
* @throws Exception
* Forwarded from the remote method.
*/
public boolean setNodeByteArray(String nodeId, String name, int index,
byte[] value)
throws Exception
{
if (setNodeByteArrayKey == null)
setNodeByteArrayKey = getKey(GROUP, "setnodebytearray4");
if (setNodeByteArrayKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[]
{
nodeId, name, Integer.valueOf(index), value
};
Object result = transact(setNodeByteArrayKey, parms);
return ((Boolean)result).booleanValue();
}
/**
* Set <code>DateValue</code> attribute value for specified node ID,
* attribute name and index.
*
* @param nodeId
* Node identifier.
* @param name
* Attribute name.
* @param index
* Index of the value to retrieve.
* @param value
* New value for the attribute variable.
* @return <code>true</code> is operation is successful and
* <code>false</code> otherwise.
* @throws Exception
* Forwarded from the remote method.
*/
public boolean setNodeDate(String nodeId, String name, int index,
DateValue value)
throws Exception
{
if (setNodeDateKey == null)
setNodeDateKey = getKey(GROUP, "setnodedate4");
if (setNodeDateKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[] { nodeId, name, Integer.valueOf(index),
value };
Object result = transact(setNodeDateKey, parms);
return ((Boolean)result).booleanValue();
}
/**
* Set <code>double</code> attribute value for specified node ID,
* attribute name and index.
*
* @param nodeId
* Node identifier.
* @param name
* Attribute name.
* @param index
* Index of the value to retrieve.
* @param value
* New value for the attribute variable.
* @return <code>true</code> is operation is successful and
* <code>false</code> otherwise.
* @throws Exception
* Forwarded from the remote method.
*/
public boolean setNodeDouble(String nodeId, String name, int index,
double value)
throws Exception
{
if (setNodeDoubleKey == null)
setNodeDoubleKey = getKey(GROUP, "setnodedouble4");
if (setNodeDoubleKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[]
{
nodeId, name, Integer.valueOf(index), Double.valueOf(value)
};
Object result = transact(setNodeDoubleKey, parms);
return ((Boolean)result).booleanValue();
}
/**
* Set <code>int</code> attribute value for specified node ID,
* attribute name and index.
*
* @param nodeId
* Node identifier.
* @param name
* Attribute name.
* @param index
* Index of the value to retrieve.
* @param value
* New value for the attribute variable.
* @return <code>true</code> is operation is successful and
* <code>false</code> otherwise.
* @throws Exception
* Forwarded from the remote method.
*/
public boolean setNodeInteger(String nodeId, String name, int index,
int value)
throws Exception
{
if (setNodeIntegerKey == null)
setNodeIntegerKey = getKey(GROUP, "setnodeinteger4");
if (setNodeIntegerKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[]
{
nodeId, name, Integer.valueOf(index), Integer.valueOf(value)
};
Object result = transact(setNodeIntegerKey, parms);
return ((Boolean)result).booleanValue();
}
/**
* Set <code>String</code> attribute value for specified node ID,
* attribute name and index.
*
* @param nodeId
* Node identifier.
* @param name
* Attribute name.
* @param index
* Index of the value to retrieve.
* @param value
* New value for the attribute variable.
* @return <code>true</code> is operation is successful and
* <code>false</code> otherwise.
* @throws Exception
* Forwarded from the remote method.
*/
public boolean setNodeString(String nodeId, String name, int index,
String value)
throws Exception
{
if (setNodeStringKey == null)
setNodeStringKey = getKey(GROUP, "setnodestring4");
if (setNodeStringKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[]
{
nodeId, name, Integer.valueOf(index), value
};
Object result = transact(setNodeStringKey, parms);
return ((Boolean)result).booleanValue();
}
/**
* Set <code>TimeValue</code> attribute value for specified node ID,
* attribute name and index.
*
* @param nodeId
* Node identifier.
* @param name
* Attribute name.
* @param index
* Index of the value to retrieve.
* @param value
* New value for the attribute variable.
* @return <code>true</code> is operation is successful and
* <code>false</code> otherwise.
* @throws Exception
* Forwarded from the remote method.
*/
public boolean setNodeTime(String nodeId, String name, int index,
TimeValue value)
throws Exception
{
if (setNodeTimeKey == null)
setNodeTimeKey = getKey(GROUP, "setnodetime4");
if (setNodeTimeKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[]
{
nodeId, name, Integer.valueOf(index), value
};
Object result = transact(setNodeTimeKey, parms);
return ((Boolean)result).booleanValue();
}
/**
* Unbinds from directory service.
*
* @return <code>true</code> is operation is successful and
* <code>false</code> otherwise.
* @throws Exception
* Forwarded from the remote method.
*/
public boolean unbind()
throws Exception
{
if (unbindKey == null)
unbindKey = getKey(GROUP, "unbind");
if (unbindKey == null)
throw new Exception("unresolvable remote export");
Object[] parms = new Object[] {};
Object result = transact(unbindKey, parms);
return ((Boolean)result).booleanValue();
}
}
/**
* Single menu item.
*/
abstract class MenuItem
{
/** Menu item selection key */
char hotkey;
/** Menu item text */
String text;
/**
* Construct an instance with given menu text. Menu item text must
* contain a menu item selection key marked by leading tilde (~)
* character. For example: <br>
* <code>First menu item - ~a</code> will mark <b>a </b> as selection
* key.
*
* @param text
* Menu item text.
*/
MenuItem(String text)
{
prepareText(text);
}
/**
* Get menu item selection key.
*
* @return Menu item selection key.
*/
public char getHotKey()
{
return hotkey;
}
/**
* Get menu item text with making tilde removed.
*
* @return Menu item text.
*/
public String getText()
{
return text;
}
/**
* Worker routing which is executed when menu item is selected.
*
* @param args
* Array of tokens retrieved from the user input.
*/
abstract void run(String[] args);
/**
* Process menu item text and retrieve selection key. Then marker (~) is
* removed.
*
* @param str
* Menu item text.
* @throws RuntimeException
* If menu item does not contain proper marker.
*/
private void prepareText(String str)
{
int pos = str.indexOf('~');
if (pos < 0 || pos >= (str.length() - 1))
throw new RuntimeException("Menu item [" + str
+ "] does not have hot key.");
hotkey = str.charAt(pos + 1);
text = str.substring(0, pos) + str.substring(pos + 1);
}
}
/**
* Special exception used to break menu processing loop. <br>
* Since only few (usually one from the entire list) menu item throws this
* exception <code>RuntimeException</code> is used as a base because it
* does not need to be declared in each method.
*/
static class StopMenu
extends RuntimeException
{
/**
* Construct an empty exception.
*/
StopMenu()
{
super();
}
}
}