vgritsenko    2004/02/12 19:34:18

  Modified:    .        status.xml
               config   web.xml
               java/src/org/apache/xindice/client/xmldb/xmlrpc
                        CollectionImpl.java DatabaseImpl.java
               tools/jetty/conf main.xml
  Added:       tools/jetty/conf realm.properties
  Log:
  Add support for server-level basic http authentication
  
  Revision  Changes    Path
  1.32      +3 -0      xml-xindice/status.xml
  
  Index: status.xml
  ===================================================================
  RCS file: /home/cvs/xml-xindice/status.xml,v
  retrieving revision 1.31
  retrieving revision 1.32
  diff -u -r1.31 -r1.32
  --- status.xml        12 Feb 2004 03:12:18 -0000      1.31
  +++ status.xml        13 Feb 2004 03:34:17 -0000      1.32
  @@ -70,6 +70,9 @@
       <changes>
           <release version="1.1b4-dev" date="February 11 2004">
               <action dev="VG" type="update">
  +                Xindice server and XML-RPC driver support basic HTTP 
authentication.
  +            </action>
  +            <action dev="VG" type="update">
                   Xindice managed driver class renamed to DatabaseImpl and 
supports
                   same configuration parameters as embedded driver.
                   Xindice managed driver supports multiple database instances.
  
  
  
  1.11      +27 -2     xml-xindice/config/web.xml
  
  Index: web.xml
  ===================================================================
  RCS file: /home/cvs/xml-xindice/config/web.xml,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- web.xml   8 Feb 2004 01:11:34 -0000       1.10
  +++ web.xml   13 Feb 2004 03:34:17 -0000      1.11
  @@ -58,4 +58,29 @@
       <servlet-name>xindice</servlet-name>
       <url-pattern>/</url-pattern>
     </servlet-mapping>
  +
  +  <!--
  +    - Security constraint on the Xindice WebApp allows to protect
  +    - Xindice XML-RPC server with Basic HTTP Authentication.
  +    -
  +    - In addition to this configuration, servlet engine should have
  +    - "xindice" realm configuration. For Jetty config, see 
tools/jetty/main.xml
  +    -
  +  <security-constraint>
  +    <web-resource-collection>
  +      <web-resource-name>Xindice Server</web-resource-name>
  +      <url-pattern>/</url-pattern>
  +    </web-resource-collection>
  +    <auth-constraint>
  +      <role-name>xindice</role-name>
  +    </auth-constraint>
  +  </security-constraint>
  +  <login-config>
  +    <auth-method>BASIC</auth-method>
  +    <realm-name>xindice</realm-name>
  +  </login-config>
  +  <security-role>
  +    <role-name>xindice</role-name>
  +  </security-role>
  +   -->
   </web-app>
  
  
  
  1.44      +32 -60    
xml-xindice/java/src/org/apache/xindice/client/xmldb/xmlrpc/CollectionImpl.java
  
  Index: CollectionImpl.java
  ===================================================================
  RCS file: 
/home/cvs/xml-xindice/java/src/org/apache/xindice/client/xmldb/xmlrpc/CollectionImpl.java,v
  retrieving revision 1.43
  retrieving revision 1.44
  diff -u -r1.43 -r1.44
  --- CollectionImpl.java       8 Feb 2004 02:43:02 -0000       1.43
  +++ CollectionImpl.java       13 Feb 2004 03:34:17 -0000      1.44
  @@ -47,7 +47,6 @@
   import javax.xml.parsers.DocumentBuilderFactory;
   import java.io.IOException;
   import java.io.StringReader;
  -import java.net.MalformedURLException;
   import java.util.Hashtable;
   import java.util.Vector;
   import java.util.StringTokenizer;
  @@ -65,16 +64,6 @@
       private static final Log log = LogFactory.getLog(CollectionImpl.class);
   
       /**
  -     * Host and port number of the database server
  -     */
  -    private String hostPort;
  -
  -    /**
  -     * Location of the XML-RPC service in the web server
  -     */
  -    private String serviceLocation;
  -
  -    /**
        * The XML-RPC client stub, connected to the server
        */
       private XmlRpcClient client = null;
  @@ -83,53 +72,24 @@
        * Creates new <code>CollectionImpl</code> instance representing 
connection
        * to server collection.
        *
  -     * @param hostPort hostname and port number in <code>host:port</code> 
format.
  -     *        Port no is optional, in which case HTTP default is assumed.
  -     * @param serviceLocation is the path in the web server's namespace where
  -     *        the XML-RPC service is mounted.  It is <code>null</code> unless
  -     *        the <code>service-location</code> property of
  -     *        <code>org.apache.xindice.client.xmlrpc.DatabaseImpl</code>
  -     *        is set.
  +     * @param client XML-RPC client connected to the Xindice XML-RPC server.
        * @param collPath is the name of the collection to open.
        * @exception XMLDBException thrown if a connection could not be 
established,
        *            because of URL syntax errors, or connection failure, or if 
no
        *            collection with path <code>collPath</code> could be 
located.
        */
  -    public CollectionImpl(String hostPort, String serviceLocation, String 
collPath) throws XMLDBException {
  +    public CollectionImpl(XmlRpcClient client, String collPath) throws 
XMLDBException {
           super(collPath);
  +        this.client = client;
   
  -        this.hostPort = hostPort;
  -        this.serviceLocation = serviceLocation;
  -        String xmlRpcURL = "http://"; + hostPort + serviceLocation;
  -        try {
  -            if (log.isDebugEnabled()) {
  -                log.debug("Using URL: '" + xmlRpcURL + "'");
  -            }
  -            client = new XmlRpcClient(xmlRpcURL);
  -
  -            /* Just check the collection does actually exist */
  -            Hashtable params = new Hashtable();
  -            params.put(RPCDefaultMessage.COLLECTION, collPath);
  -            // TODO: In case of error get error code. Current XMLPRC does 
not provide place for detailed error code.
  -            String exists = (String) 
runRemoteCommand("GetCollectionConfiguration", params);
  -
  -            if (!"yes".equals(exists)) {
  -                throw new XMLDBException(ErrorCodes.NO_SUCH_COLLECTION,
  -                                         "Collection not found: " + 
collPath);
  -            }
  -        } catch (MalformedURLException e) {
  -            client = null;
  -            throw new XMLDBException(ErrorCodes.INVALID_URI, e);
  -        } catch (XMLDBException x) {
  -            throw x;  // propagate any xmldb exception.
  -        } catch (IOException e) {
  -            client = null;
  -            throw new XMLDBException(ErrorCodes.UNKNOWN_ERROR, 
FaultCodes.GEN_GENERAL_ERROR,
  -                                     "Cannot communicate with the server: " 
+ xmlRpcURL, e);
  -        } catch (Exception e) {
  -            client = null;
  -            throw new XMLDBException(ErrorCodes.UNKNOWN_ERROR, 
FaultCodes.JAVA_RUNTIME_ERROR,
  -                                     "Collection not found: " + collPath, e);
  +        /* Just check the collection does actually exist */
  +        Hashtable params = new Hashtable();
  +        params.put(RPCDefaultMessage.COLLECTION, collPath);
  +        String exists = (String) 
runRemoteCommand("GetCollectionConfiguration", params);
  +
  +        if (!"yes".equals(exists)) {
  +            throw new XMLDBException(ErrorCodes.NO_SUCH_COLLECTION,
  +                                     "Collection not found: " + collPath);
           }
       }
   
  @@ -141,16 +101,19 @@
        * @return the return value from the server. Type of return value 
depends on
        *         command.
        *
  -     * @exception Exception thrown if XML-RPC reports an exception.
  +     * @exception XMLDBException thrown if XML-RPC reports an exception.
        */
  -    private Object runRemoteCommand(String cmdName, Hashtable params) throws 
Exception {
  -
  +    private Object runRemoteCommand(String cmdName, Hashtable params) throws 
XMLDBException {
           try {
               params.put(RPCMessageInterface.MESSAGE_PARAM, cmdName);
               Vector v = new Vector();
               v.add(params);
               return ((Hashtable) client.execute("run", 
v)).get(RPCDefaultMessage.RESULT);
           } catch (XmlRpcException e) {
  +            if (log.isDebugEnabled()) {
  +                log.debug("Got XmlRpc exception running command " + cmdName, 
e);
  +            }
  +
               // HACK: Dirty hack to pass at least some diagnostic info 
through XmlRpc
               //       See also RPCMessageInterface.run()
               StringTokenizer st = new StringTokenizer(e.getMessage(), ":");
  @@ -164,7 +127,12 @@
                       // Ignore
                   }
               }
  -            throw e;
  +
  +            throw new XMLDBException(ErrorCodes.UNKNOWN_ERROR, 
FaultCodes.GEN_GENERAL_ERROR,
  +                                     "Failed to execute command '" + cmdName 
+ "' on server: " + client.getURL() + ", message: " + e.getMessage(), e);
  +        } catch (IOException e) {
  +            throw new XMLDBException(ErrorCodes.UNKNOWN_ERROR, 
FaultCodes.GEN_GENERAL_ERROR,
  +                                     "Cannot communicate with the server: " 
+ client.getURL(), e);
           }
       }
   
  @@ -292,12 +260,16 @@
   
       /* see superclass for documentation */
       public boolean isOpen() {
  +
           return (client != null);
       }
   
       /* see superclass for documentation */
       public String getURI() {
  -        return "xmldb:" + DatabaseImpl.DRIVER_NAME + "://" + hostPort + 
collPath;
  +
  +        return "xmldb:" + DatabaseImpl.DRIVER_NAME + "://" +
  +                client.getURL().getHost() + ':' + client.getURL().getPort() +
  +                collPath;
       }
   
       /**
  @@ -319,7 +291,7 @@
           }
   
           try {
  -            return new CollectionImpl(hostPort, serviceLocation, collPath + 
"/" + name);
  +            return new CollectionImpl(client, collPath + "/" + name);
           } catch (XMLDBException e) {
   
               if (e.errorCode == ErrorCodes.NO_SUCH_COLLECTION) {
  @@ -393,7 +365,7 @@
           }
   
           try {
  -            return new CollectionImpl(hostPort, serviceLocation, 
collPath.substring(0, collPath.lastIndexOf('/')));
  +            return new CollectionImpl(client, collPath.substring(0, 
collPath.lastIndexOf('/')));
           } catch (XMLDBException e) {
               if (e.errorCode == ErrorCodes.NO_SUCH_COLLECTION) {
                   // per getParentCollection contract, return null if no parent
  
  
  
  1.22      +128 -38   
xml-xindice/java/src/org/apache/xindice/client/xmldb/xmlrpc/DatabaseImpl.java
  
  Index: DatabaseImpl.java
  ===================================================================
  RCS file: 
/home/cvs/xml-xindice/java/src/org/apache/xindice/client/xmldb/xmlrpc/DatabaseImpl.java,v
  retrieving revision 1.21
  retrieving revision 1.22
  diff -u -r1.21 -r1.22
  --- DatabaseImpl.java 12 Feb 2004 13:11:06 -0000      1.21
  +++ DatabaseImpl.java 13 Feb 2004 03:34:17 -0000      1.22
  @@ -22,20 +22,36 @@
   import org.apache.commons.logging.LogFactory;
   import org.apache.xindice.client.xmldb.CommonConfigurable;
   import org.apache.xmlrpc.XmlRpc;
  +import org.apache.xmlrpc.XmlRpcClient;
   
   import org.xmldb.api.base.Collection;
   import org.xmldb.api.base.Database;
   import org.xmldb.api.base.ErrorCodes;
   import org.xmldb.api.base.XMLDBException;
   
  +import java.net.MalformedURLException;
  +
   /**
  - * implements XML:DB's <code>Database</code> interface using XML-RPC to
  - * communicate with the Xindice server.
  + * Implements XML:DB's <code>Database</code> interface using XML-RPC to 
communicate
  + * with the Xindice XML-RPC server. Usually, this class is not used
  + * directly, but [EMAIL PROTECTED] 
org.apache.xindice.client.xmldb.DatabaseImpl} is used instead.
    *
    * Note this class is a database <em>driver</em>, and one class of this 
database
  - * could be used to connect to <em>many</em> different databases.
  + * could be used to connect to <em>many</em> different databases, on one or
  + * different Xindice XML-RPC servers.
  + *
  + * XML-RPC database driver uses following configuration parameters:
  + * <ul>
  + * <li><strong>service-location</strong>: Specifies path to the Xindice 
server WebApp</li>
  + * <li><strong>xmlrpc-driver</strong>: Specifies name of the SAX parser to 
use</li>
  + * <li><strong>xmlrpc-user</strong>: If server protected with HTTP Basic 
Auth, specifies user name</li>
  + * <li><strong>xmlrpc-password</strong>: If server protected with HTTP Basic 
Auth, specifies password</li>
  + * </ul>
  + *
  + * If one of these parameters is not specified, system properties will be 
used.
    *
    * @author <a href="mailto:[EMAIL PROTECTED]">James Bates</a>
  + * @author <a href="mailto:[EMAIL PROTECTED]">Vadim Gritsenko</a>
    * @version CVS $Revision$, $Date$
    */
   public class DatabaseImpl extends CommonConfigurable implements Database {
  @@ -48,14 +64,14 @@
       private static final String PROP_SERVICE_LOCATION = "service-location";
   
       /**
  -     * Driver property name for the SAX parser xml-rpc will use.
  +     * System property name for the service location
        */
  -    private static final String PROP_XMLRPC_DRIVER = "xmlrpc-driver";
  +    private static final String SYSPROP_SERVICE_LOCATION = 
"xindice.xmlrpc.service-location";
   
       /**
  -     * System property name for the service location
  +     * Driver property name for the SAX parser xml-rpc will use.
        */
  -    private static final String SYSPROP_SERVICE_LOCATION = 
"xindice.xmlrpc.service-location";
  +    private static final String PROP_XMLRPC_DRIVER = "xmlrpc-driver";
   
       /**
        * System property name for the SAX parser xml-rpc will use in case
  @@ -64,6 +80,28 @@
       private static final String SYSPROP_XMLRPC_DRIVER = 
"xindice.xmlrpc.driver";
   
       /**
  +     * Driver property name for the basic authentication user name.
  +     */
  +    private static final String PROP_XMLRPC_USER = "xmlrpc-user";
  +
  +    /**
  +     * System property name for the basic authentication user name in case
  +     * there were no configuration property passed
  +     */
  +    private static final String SYSPROP_XMLRPC_USER = "xindice.xmlrpc.user";
  +
  +    /**
  +     * Driver property name for the basic authentication password.
  +     */
  +    private static final String PROP_XMLRPC_PASSWORD = "xmlrpc-password";
  +
  +    /**
  +     * System property name for the basic authentication password in case
  +     * there were no configuration property passed
  +     */
  +    private static final String SYSPROP_XMLRPC_PASSWORD = 
"xindice.xmlrpc.password";
  +
  +    /**
        * Default value of the xmlrpc-driver property
        */
       private static final String DEFAULT_XMLRPC_DRIVER = "xerces";
  @@ -84,7 +122,7 @@
       private static final String CONFORMANCE_LEVEL = "0";
   
       /**
  -     * Ensures that XML-RPC initialized just once
  +     * Ensures that XML-RPC static properties initialized just once
        */
       private static boolean xmlRpcInitialized;
   
  @@ -93,10 +131,14 @@
        */
       private String serviceLocation;
   
  +    private String basicUser;
  +    private String basicPassword;
  +
  +
       /**
        * Create a new DatabaseImpl object.
        */
  -    public DatabaseImpl() throws XMLDBException {
  +    public DatabaseImpl() {
           super();
       }
   
  @@ -107,7 +149,7 @@
        * @param config from which the initial parameters for this
        *        DatabaseImpl object are copied.
        */
  -    public DatabaseImpl(CommonConfigurable config) throws XMLDBException {
  +    public DatabaseImpl(CommonConfigurable config) {
           super(config);
       }
   
  @@ -129,8 +171,7 @@
       }
   
       /**
  -     * Initialize XML-RPC static properties: encoding, keep-alive, SAX 
driver.
  -     * Initialize XML-RPC service location.
  +     * Initialize XML-RPC library static properties: encoding, keep-alive, 
SAX driver.
        *
        * @throws XMLDBException if specified (or default, if none specified) 
SAX driver
        *         class could not be loaded
  @@ -143,9 +184,10 @@
   
                   /*
                    * Determine the SAXparser the xmlrpc client will use.
  +                 *
                    * In priority order:
                    *   DatabaseImpl xmlrpc-driver property
  -                 *      (passed in the xmlrpcDriver parameter)
  +                 *      (passed in the xmlrpc-driver parameter)
                    *   System property "xindice.xmlrpc.driver"
                    *   Default value "xerces"
                    */
  @@ -170,34 +212,85 @@
   
               xmlRpcInitialized = true;
           }
  +    }
  +
  +    /**
  +     * Initialize XML-RPC service location, basic authentication.
  +     * Create XML-RPC client.
  +     *
  +     * @param hostPort of the Xindice XML-RPC server
  +     * @return XML-RPC client connected to the Xindice server
  +     * @throws XMLDBException
  +     */
  +    private XmlRpcClient connect(String hostPort) throws XMLDBException {
  +
  +        // Initialize XML-RPC static properties
  +        initialize();
   
  -        if (this.serviceLocation == null) {
  -            /*
  -             * Determine the path in the web server to the XML-RPC service.
  -             * In priority order:
  -             *   DatabaseImpl service-location property
  -             *      (passed in the serviceLocation parameter)
  -             *   System property "xindice.xmlrpc.service-location"
  -             *   Default value "/xindice/"
  -             */
  -            serviceLocation = getProperty(PROP_SERVICE_LOCATION);
  +        synchronized (this) {
               if (serviceLocation == null) {
  -                serviceLocation = 
System.getProperty(SYSPROP_SERVICE_LOCATION);
  +
  +                /*
  +                 * Determine the path in the web server to the XML-RPC 
service.
  +                 *
  +                 * In priority order:
  +                 *   DatabaseImpl service-location property
  +                 *      (passed in the serviceLocation parameter)
  +                 *   System property "xindice.xmlrpc.service-location"
  +                 *   Default value "/xindice/"
  +                 */
  +                serviceLocation = getProperty(PROP_SERVICE_LOCATION);
                   if (serviceLocation == null) {
  -                    serviceLocation = DEFAULT_SERVICE_LOCATION;
  +                    serviceLocation = 
System.getProperty(SYSPROP_SERVICE_LOCATION);
  +                    if (serviceLocation == null) {
  +                        serviceLocation = DEFAULT_SERVICE_LOCATION;
  +                    }
                   }
  -            }
   
  -            if (!serviceLocation.startsWith("/")) {
  -                serviceLocation = "/" + serviceLocation;
  -            }
  -            if (!serviceLocation.endsWith("/")) {
  -                serviceLocation = serviceLocation + "/";
  +                if (!serviceLocation.startsWith("/")) {
  +                    serviceLocation = "/" + serviceLocation;
  +                }
  +                if (!serviceLocation.endsWith("/")) {
  +                    serviceLocation = serviceLocation + "/";
  +                }
  +
  +                if (log.isDebugEnabled()) {
  +                    log.debug("Using Service Location: '" + serviceLocation 
+ "'");
  +                }
  +
  +                /*
  +                 * Determine basic authentication parameters
  +                 */
  +                basicUser = getProperty(PROP_XMLRPC_USER);
  +                if (basicUser == null) {
  +                    basicUser = System.getProperty(SYSPROP_XMLRPC_USER);
  +                }
  +
  +                if (basicUser != null) {
  +                    basicPassword = getProperty(PROP_XMLRPC_PASSWORD);
  +                    if (basicPassword == null) {
  +                        basicPassword = 
System.getProperty(SYSPROP_XMLRPC_PASSWORD);
  +                    }
  +                    if (log.isDebugEnabled()) {
  +                        log.debug("Using Basic authentication. User: '" + 
basicUser + "', password: '" + basicPassword + "'");
  +                    }
  +                }
               }
  +        }
   
  +
  +        String xmlRpcURL = "http://"; + hostPort + serviceLocation;
  +        try {
               if (log.isDebugEnabled()) {
  -                log.debug("Using Service Location: '" + serviceLocation + 
"'");
  +                log.debug("Using URI: '" + xmlRpcURL + "'");
               }
  +            XmlRpcClient client = new XmlRpcClient(xmlRpcURL);
  +            if (basicUser != null) {
  +                client.setBasicAuthentication(basicUser, basicPassword);
  +            }
  +            return client;
  +        } catch (MalformedURLException e) {
  +            throw new XMLDBException(ErrorCodes.INVALID_URI, e);
           }
       }
   
  @@ -249,11 +342,8 @@
               hostPort = "127.0.0.1:8888";
           }
   
  -        // Init XML-RPC in case it is not initialized yet. Initialize 
serviceLocation
  -        initialize();
  -
           try {
  -            return new CollectionImpl(hostPort, serviceLocation, collPath);
  +            return new CollectionImpl(connect(hostPort), collPath);
           } catch (XMLDBException e) {
               if (e.errorCode == ErrorCodes.NO_SUCH_COLLECTION) {
                   // per getCollection contract, return null if not found
  
  
  
  1.3       +13 -1     xml-xindice/tools/jetty/conf/main.xml
  
  Index: main.xml
  ===================================================================
  RCS file: /home/cvs/xml-xindice/tools/jetty/conf/main.xml,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- main.xml  4 Aug 2003 02:10:30 -0000       1.2
  +++ main.xml  13 Feb 2004 03:34:18 -0000      1.3
  @@ -27,6 +27,19 @@
       </Arg>
     </Call>
   
  +  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
  +  <!-- Add and configure "xindice" user realm                          -->
  +  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
  +  <Call name="addRealm">
  +    <Arg>
  +      <New class="org.mortbay.http.HashUserRealm">
  +        <Arg>xindice</Arg>
  +        <Arg><SystemProperty name="xindice.home" 
default="."/>/tools/jetty/conf/realm.properties</Arg>
  +        <Set name="Name">xindice</Set>
  +      </New>
  +    </Arg>
  +  </Call>
  +
     <!-- =============================================================== -->
     <!-- Configure the Contexts                                          -->
     <!-- =============================================================== -->
  @@ -48,6 +61,5 @@
       <Arg><SystemProperty name="webapp" default="."/></Arg>
       <Set name="defaultsDescriptor">./tools/jetty/conf/webdefaults.xml</Set>
     </Call>
  -
   
   </Configure>
  
  
  
  1.1                  xml-xindice/tools/jetty/conf/realm.properties
  
  Index: realm.properties
  ===================================================================
  #
  # This is a HashUserRealm defining users passwords and roles.
  # The format is
  # <username>: <password>[,<rolename> ...]
  #
  # Passwords may be clear text, obfuscated or checksummed. The class
  # org.mortbay.util.Password should be used to generate obfuscated
  # passwords or password checksums
  
  xindice: manager, xindice
  
  
  

Reply via email to