namehandler.java
来自「java版ace,java程序员值得一看」· Java 代码 · 共 474 行
JAVA
474 行
/************************************************* * * = PACKAGE * netsvcs.Naming * * = FILENAME * NameHandler.java * *************************************************/package JACE.netsvcs.Naming;import java.net.SocketException;import java.io.*;import java.util.*;import JACE.OS.*;import JACE.Connection.*;import JACE.Reactor.*;import JACE.SOCK_SAP.*;import JACE.netsvcs.Handler;/** * Handlers interaction between a client (NameProxy) and the naming * service database. Created by NameAcceptor to handle requests. * <P> * In general, the user binds a name to a (value, type) pair. The type is just * treated as just another String (in the C++ version the name and value are * arrays of 16 bit data types and the type is an array of 8 bit chars). * <P> * For this to work in the hash table scheme, the type and value are wrapped in * a ValueType class defined as a nested top level class within the * NameHandler. * <P> * This is compatible with the C++ ACE remote name service. * *@see JACE.netsvcs.Naming.NameAcceptor *@see JACE.netsvcs.Naming.NameRequest *@see JACE.netsvcs.Naming.NameReply * *@author Everett Anderson */public class NameHandler extends Handler{ /** * Constructor * * @param mapping Hash table created in NameAcceptor */ public NameHandler (Hashtable mapping) { this.mapping_ = mapping; } /** * Read in the given NameRequest and calls dispatch. */ public void processRequest (Object request) throws SocketException, EOFException, IOException { NameRequest nameRequest = (NameRequest)request; nameRequest.streamInFrom (peer ().dataInputStream ()); this.dispatch (nameRequest); } /** * Create a new instance of NameRequest. */ public Object newRequest () { return new NameRequest (); } /** * This is the point at which a request is sent to the various methods * that fulfill it. It switches on the request type -- bind, * rebind, resolve, etc. * *@param nameRequest The request to respond to */ void dispatch (NameRequest nameRequest) throws IOException { NameAcceptor parent = (NameAcceptor)parent (); // Call the various other member functions based on the // message type of the request -- bind, rebind, etc. switch (nameRequest.requestType()) { case NameRequest.BIND: this.bind(nameRequest, false); parent.modifiedMapping (true); break; case NameRequest.REBIND: this.bind(nameRequest, true); parent.modifiedMapping (true); break; case NameRequest.RESOLVE: this.resolve(nameRequest); break; case NameRequest.UNBIND: this.unbind(nameRequest); parent.modifiedMapping (true); break; case NameRequest.LIST_NAMES: this.listByName(nameRequest.name(), false); break; case NameRequest.LIST_VALUES: this.listByValue(nameRequest.name(), false); break; case NameRequest.LIST_TYPES: this.listByType(nameRequest.name(), false); break; case NameRequest.LIST_NAME_ENTRIES: this.listByName(nameRequest.name(), true); break; case NameRequest.LIST_VALUE_ENTRIES: this.listByValue(nameRequest.name(), true); break; case NameRequest.LIST_TYPE_ENTRIES: this.listByType(nameRequest.name(), true); break; default: ACE.ERROR("Unknown type: " + nameRequest.requestType()); // Send a failure message. This will only work if the other // side is expecting something like a NameReply rather than // a NameRequest. It would've been better to have everything // use NameRequests to avoid this kind of thing. NameReply reply = new NameReply (NameReply.FAILURE, 0); reply.streamOutTo(peer ().dataOutputStream ()); break; } } /** * * Bind a name and a (value, type) pair. All this data is given in the * NameRequest from the client. Returns a NameReply back to the client * with either Reply.SUCCESS or Reply.FAILURE as the type. * *@param request NameRequest given by the client *@param rebind Is this a rebind or not? */ void bind (NameRequest request, boolean rebind) throws IOException { // The hash table entries consists of (String name, ValueType data) // pairs, so create the appropriate ValueType ValueType vt = new ValueType(request.type(), request.value()); // Reply to tell sender of success or failure NameReply reply = new NameReply(); // If it's a rebind request, overwrite the old entry. If the key doesn't // exist, add it. If it does exist and it's not a bind request, return // a failure code via a NameReply. if ((rebind) || (!this.mapping_.containsKey(request.name()))) { ACE.DEBUG ("Binding: " + request.name() + " and " + vt.value_); // Add/Update the entry in the hash table this.mapping_.put(request.name(), vt); // Set the reply code to success reply.type(NameReply.SUCCESS); } else { ACE.DEBUG ("Key " + request.name() + " already exists"); // Set reply code to failure reply.type(NameReply.FAILURE); // reply error code unused as far as I know } reply.streamOutTo(peer ().dataOutputStream ()); } /** * Given a name, this looks up and returns the type and value. This is * done by sending back a full NameRequest with the correct info. If * there is a problem, an "empty" NameRequest is returned -- it has no * name, type, or value fields. * *@param request NameRequest sent by the client (has the name to lookup) */ void resolve (NameRequest request) throws IOException { // A NameRequest is also used in response NameRequest result; // If the requested name is in the hash table, return the data if (this.mapping_.containsKey(request.name())) { // Get the data pair based on the name ValueType vt = (ValueType)this.mapping_.get(request.name()); ACE.DEBUG("Good resolve: " + vt.value_); // Fill the reply structure result = new NameRequest(NameRequest.RESOLVE, null, vt.value_, vt.type_, null); } else { // Otherwise return a null response result = new NameRequest(NameRequest.RESOLVE, null, null, null, null); } result.streamOutTo (peer ().dataOutputStream ()); } /** * * Given a name, remove its entry in the mapping. Returns a NameReply * to the client with NameReply.SUCCESS or NameReply.FAILURE. * *@param request NameRequest from the client (has the name to remove) */ void unbind (NameRequest request) throws IOException { NameReply reply = new NameReply(); // If the given key isn't in the table, return an error // Otherwise remove it. Uses a NameReply to respond. if (!this.mapping_.containsKey(request.name())) reply.type(NameReply.FAILURE); else { this.mapping_.remove(request.name()); reply.type(NameReply.SUCCESS); } // Send the reply out to the socket reply.streamOutTo (peer ().dataOutputStream ()); } /** * * Given a pattern string (given in NameRequest's name field), this * finds all the entries in the mapping which have a name that begins with * the string. Each one is sent back separately via a NameRequest, and this * sequence is followed by a blank NameRequest. * *@param pattern Pattern to find (what result names should * begin with) *@param completeLookup Should the value and type be returned as well? */ void listByName (String pattern, boolean completeLookup) throws IOException { // Get a listing of all the keys in the hash table Enumeration enum = this.mapping_.keys(); // References used in the loop String name; ValueType vt; // A NameRequest is used to return each item corresponding to the pattern. NameRequest result = new NameRequest((completeLookup ? NameRequest.LIST_NAMES : NameRequest.LIST_NAME_ENTRIES), null, null, null, null); // Keep ourselves safe from null pointer exceptions if (pattern == null) pattern = new String(""); // Scan through all the elements while (enum.hasMoreElements()) { // Get a key name = (String)enum.nextElement(); // Does it fit the pattern? if (name.startsWith(pattern)) { // Set the result name result.name(name); // Only make another hash table request if the user // wants all the data if (completeLookup) { // Get data from the hash table vt = (ValueType)mapping_.get(name); // Set the rest of the data result.type(vt.type_); result.value(vt.value_); } // Send it to the socket result.streamOutTo (peer ().dataOutputStream ()); } } // Send final null message result.name(null); result.type(null); result.value(null); result.requestType(NameRequest.MAX_ENUM); result.streamOutTo (peer ().dataOutputStream ()); } /** * * Given a pattern string (given in NameRequest's name field), this * finds all the entries in the mapping which have a type that begins with * the string. Each one is sent back separately via a NameRequest, and this * sequence is followed by a blank NameRequest. * *@param pattern Pattern to find (what result types should * begin with) *@param completeLookup Should the value be returned as well? This is * only used to decide between LIST_TYPES and * LIST_TYPE_ENTRIES since we might as well send * back both if we look them up together. */ void listByType (String pattern, boolean completeLookup) throws IOException { // Get a listing of all the keys in the hash table Enumeration enum = this.mapping_.keys(); // References used in the loop String name; ValueType vt; // A NameRequest is used to return each item corresponding to the pattern. NameRequest result = new NameRequest((completeLookup ? NameRequest.LIST_TYPES : NameRequest.LIST_TYPE_ENTRIES), null, null, null, null); // Keep ourselves safe from null pointer exceptions if (pattern == null) pattern = new String(""); // Scan through all the elements while (enum.hasMoreElements()) { // Get a key name = (String)enum.nextElement(); // Have to get all the data for this entry to compare vt = (ValueType)mapping_.get(name); // Does it fit the pattern? if (vt.type_ != null) if (vt.type_.startsWith(pattern)) { // Set the result values result.name(name); result.type(vt.type_); result.value(vt.value_); // Send it out to the socket result.streamOutTo (peer ().dataOutputStream ()); } } // Send final null message result.name(null); result.type(null); result.value(null); result.requestType(NameRequest.MAX_ENUM); result.streamOutTo (peer ().dataOutputStream ()); } /** * * Given a pattern string (given in NameRequest's name field), this * finds all the entries in the mapping which have a value that begins with * the string. Each one is sent back separately via a NameRequest, and this * sequence is followed by a blank NameRequest. * *@param pattern Pattern to find (what result values should * begin with) *@param completeLookup Should the value be returned as well? This is * only used to decide between LIST_TYPES and * LIST_TYPE_ENTRIES since we might as well send * back both if we look them up together. */ void listByValue (String pattern, boolean completeLookup) throws IOException { // Get a listing of all the keys in the hash table Enumeration enum = this.mapping_.keys(); // References used in the loop String name; ValueType vt; // A NameRequest is used to return each item corresponding to the pattern. NameRequest result = new NameRequest((completeLookup ? NameRequest.LIST_VALUES : NameRequest.LIST_VALUE_ENTRIES), null, null, null, null); // Keep ourselves safe from null pointer exceptions if (pattern == null) pattern = new String(""); // Scan through all the elements while (enum.hasMoreElements()) { // Get a key name = (String)enum.nextElement(); // Have to get all the data for this entry to compare vt = (ValueType)mapping_.get(name); // Does it fit the pattern? if (vt.value_ != null) if (vt.value_.startsWith(pattern)) { // Set the result values result.name(name); result.type(vt.type_); result.value(vt.value_); // Send it out to the socket result.streamOutTo (peer ().dataOutputStream ()); } } // Send final null message result.name(null); result.type(null); result.value(null); result.requestType(NameRequest.MAX_ENUM); result.streamOutTo (peer ().dataOutputStream ()); } // References to the hash table and the timer queue private Hashtable mapping_; /** * A simple wrapper to keep the type and value together in * the hash table. */ static class ValueType implements Serializable { /** * Constructor * *@param type Type string to include *@param value Value string to include */ ValueType(String type, String value) { this.type_ = type; this.value_ = value; } public String type_; public String value_; }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?