You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by Richard Sitze <rs...@us.ibm.com> on 2002/08/21 17:49:01 UTC

[discovery] URL's, Java 1.2... problem.

[I find long subject lines difficult to parse quickly, so I'm changing 
it.. my apologies if this habit confuses people]

>I am very much thinking to add more support for discovery of non-class
>resources.

+/-1  It's clear that if we keep this code, then that is the right 
direction to go.  See previous note on proposed package for resources.

BUT...  getResources() is unique to Java 1.2.  We are suppose to be 
backward compatible with 1.1.8.  An original goal of mine was to use this 
WITHIN commons-logging LogFactory (supports 1.1.8+).  That means we cannot 
use commons-logging internally (and it would be nice to), because we would 
be introducing a circular dependency.  Note that a dependency ALREADY 
exists because we use commons-logging in the test code.

It may be time to (re)evaluate this position.

I'm thinking that the services already offered by 'discovery' are 
sufficient for APPLICATION developers looking to pull in pluggable 
modules.

For more sophisticated tooling and frameworks, your services work is 
clearly a better direction.


So many choice.. buffet today:

(a) drop 1.1.8 entirely?
(b) drop the services work, or find alternatives?
(c) cut a release that supports 1.1.8 (that presumes that we can all agree 
that the service is usable as-is :-) and then move on?
(d) use commons-logging internally or let commons-logging use discovery?
(e) other?

<ras>


*******************************************
Richard A. Sitze
IBM WebSphere WebServices Development


Richard Sitze wrote:

 
> That's fairly straight forward.  The URL is the URL of the
> META-INF/services/my.package.ServiceName, and the loader is the loader

It is actually the base URL, pointing to the JAR. ( see the ../../.. ).

> that found that file (NOT necessarily the loader that might load the
> class, though that raises interesting questions).  I don't yet have a 
clue
> why you want that information.. but OK.

The URL - mostly for information purpose. The loader - in order to make
it easy to create a class/instance when it is needed ( otherwise I would
have to search again).

I am very much thinking to add more support for discovery of non-class
resources.


> JAXP (and by extension the scheme I'm trying to expose) does allow the
> service to be overloaded, so how do you account for that action with 
your
> scheme?  How do you generalize for services found by System (or other)
> properties?  It doesn't apply.

JAXP is very interesting. You have an array of ServiceInfo[] ( ordered by 
the class loader ). The caller can apply any 'preferences' it has and 
select a parser ( look at system properties and jaxp.propeties ) .

The problem is that it is extremely hard and complex to create a generic
API to represent the preferences. At the same time it is extremely easy
for the caller to actually code that - with few ifs in a specific order.

And this part is actually not very 'interesting' from discovery point 
of view. I think the search order is much better and cleaner to be coded 
in 
the caller. 

Back to JAXP, the caller could also take each ServiceInfo and instantiate
the class, then check for example if schema is supported ( or another
capability ). I know it's not part of the spec, but it would be nice to 
have.


Costin

> 
> <ras>
> 
> *******************************************
> Richard A. Sitze
> IBM WebSphere WebServices Development
> 
> 
> costin      2002/08/16 23:36:11
> 
>   Added:       discovery/src/java/org/apache/commons/discovery
>                         ServiceDiscovery12.java ServiceDiscovery.java
>                         ServiceDiscoveryTask.java
>   Log:
>   Some draft code - to better explain what I mean :-)
> 
>   It seems to work - haven't started with the JDK1.1 yet. There are
>   some techniques to support 1.1 - but right not that's not the
>   biggest priority. The 1.1 impl will be in a ServiceDiscovery11,
>   to avoid introspection and ugly code in the 'normal' part.
> 
>   Revision  Changes    Path
>   1.1
> jakarta-
> 
commons/discovery/src/java/org/apache/commons/discovery/ServiceDiscovery12.
> java
> 
>   Index: ServiceDiscovery12.java
>   ===================================================================
>   /*
>    * 
====================================================================
>    *
>    * The Apache Software License, Version 1.1
>    *
>    * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
>    * reserved.
>    *
>    * Redistribution and use in source and binary forms, with or without
>    * modification, are permitted provided that the following conditions
>    * are met:
>    *
>    * 1. Redistributions of source code must retain the above copyright
>    *    notice, this list of conditions and the following disclaimer.
>    *
>    * 2. Redistributions in binary form must reproduce the above 
copyright
>    *    notice, this list of conditions and the following disclaimer in
>    *    the documentation and/or other materials provided with the
>    *    distribution.
>    *
>    * 3. The end-user documentation included with the redistribution, if
>    *    any, must include the following acknowlegement:
>    *       "This product includes software developed by the
>    *        Apache Software Foundation (http://www.apache.org/)."
>    *    Alternately, this acknowlegement may appear in the software
> itself,
>    *    if and wherever such third-party acknowlegements normally 
appear.
>    *
>    * 4. The names "The Jakarta Project", "Commons", and "Apache Software
>    *    Foundation" must not be used to endorse or promote products
> derived
>    *    from this software without prior written permission. For written
>    *    permission, please contact apache@apache.org.
>    *
>    * 5. Products derived from this software may not be called "Apache"
>    *    nor may "Apache" appear in their names without prior written
>    *    permission of the Apache Group.
>    *
>    * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
>    * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
>    * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
>    * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
>    * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
>    * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
>    * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
>    * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
>    * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
>    * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
>    * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
>    * SUCH DAMAGE.
>    * 
====================================================================
>    *
>    * This software consists of voluntary contributions made by many
>    * individuals on behalf of the Apache Software Foundation.  For more
>    * information on the Apache Software Foundation, please see
>    * <http://www.apache.org/>.
>    *
>    */
> 
>   package org.apache.commons.discovery;
> 
>   import java.io.*;
>   import java.util.*;
>   import java.net.*;
> 
>   /**
>    * Version for 1.2+ VMs.
>    *
>    * @author Richard A. Sitze
>    * @author Craig R. McClanahan
>    * @author Costin Manolache
>    */
>   public class ServiceDiscovery12 extends ServiceDiscovery
>   {
>       /** Construct a new service discoverer
>        */
>       protected ServiceDiscovery12() {
>       }
> 
>       /** Convenience method to find the thread class loader.
>        *  Usefull in jdk1.1, to avoid other introspection hacks.
>        */
>       public ClassLoader getThreadClassLoader() {
>           return Thread.currentThread().getContextClassLoader();
>       }
> 
>       public ServiceInfo[] findServices( String name ) {
>           // use each loader to find if META-INF/services.
>           // find all resources, etc.
> 
>           Vector results = new Vector();
> 
>           String servicePropertyFile = ServiceDiscovery.SERVICE_HOME +
> name;
> 
>           // For each loader
>           for( int i=0; i<classLoaders.size() ; i++ ) {
>               ClassLoader loader=(ClassLoader)classLoaders.elementAt(i);
> 
>               Enumeration enum=null;
>               try {
>                   enum=loader.getResources( servicePropertyFile );
>               } catch( IOException ex ) {
>                   ex.printStackTrace();
>               }
>               if( enum==null ) continue;
> 
>               while( enum.hasMoreElements() ) {
>                   try {
>                       URL url=(URL)enum.nextElement();
> 
>                       URL baseURL=new URL( url, "../../.." );
>                       System.out.println("XXX BaseURL " + baseURL + " " 
+
> url );
> 
>                       InputStream is = url.openStream();
> 
>                       if( is != null ) {
>                           try {
>                               // This code is needed by EBCDIC and other
> strange systems.
>                               // It's a fix for bugs reported in xerces
>                               BufferedReader rd;
>                               try {
>                                   rd = new BufferedReader(new
> InputStreamReader(is, "UTF-8"));
>                               } catch
> (java.io.UnsupportedEncodingException e) {
>                                   rd = new BufferedReader(new
> InputStreamReader(is));
>                               }
> 
>                               try {
>                                   String serviceImplName;
>                                   while( (serviceImplName = 
rd.readLine())
> != null) {
>                                       serviceImplName.trim();
>                                       if( "".equals(serviceImplName) )
>                                           continue;
>                                       if( serviceImplName.startsWith( 
"#"
> ))
>                                           continue;
>                                       ServiceInfo sinfo=new 
ServiceInfo();
>                                       sinfo.setImplName( serviceImplName
> );
>                                       sinfo.setLoader( loader );
>                                       sinfo.setURL( baseURL );
>                                       System.out.println("XXX " +
> sinfo.toString());
>                                   }
>                               } finally {
>                                   rd.close();
>                               }
>                           } finally {
>                               is.close();
>                           }
>                       }
>                   } catch (MalformedURLException ex) {
>                       ex.printStackTrace();
>                   } catch (IOException ioe) {
>                       ; // ignore
>                   }
>               }
>           }
> 
>           ServiceInfo resultA[]=new ServiceInfo[ results.size() ];
>           results.copyInto( resultA );
>           return resultA;
>       }
>   }
> 
> 
> 
>   1.1
> jakarta-
> 
commons/discovery/src/java/org/apache/commons/discovery/ServiceDiscovery.
> java
> 
>   Index: ServiceDiscovery.java
>   ===================================================================
>   /*
>    * 
====================================================================
>    *
>    * The Apache Software License, Version 1.1
>    *
>    * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
>    * reserved.
>    *
>    * Redistribution and use in source and binary forms, with or without
>    * modification, are permitted provided that the following conditions
>    * are met:
>    *
>    * 1. Redistributions of source code must retain the above copyright
>    *    notice, this list of conditions and the following disclaimer.
>    *
>    * 2. Redistributions in binary form must reproduce the above 
copyright
>    *    notice, this list of conditions and the following disclaimer in
>    *    the documentation and/or other materials provided with the
>    *    distribution.
>    *
>    * 3. The end-user documentation included with the redistribution, if
>    *    any, must include the following acknowlegement:
>    *       "This product includes software developed by the
>    *        Apache Software Foundation (http://www.apache.org/)."
>    *    Alternately, this acknowlegement may appear in the software
> itself,
>    *    if and wherever such third-party acknowlegements normally 
appear.
>    *
>    * 4. The names "The Jakarta Project", "Commons", and "Apache Software
>    *    Foundation" must not be used to endorse or promote products
> derived
>    *    from this software without prior written permission. For written
>    *    permission, please contact apache@apache.org.
>    *
>    * 5. Products derived from this software may not be called "Apache"
>    *    nor may "Apache" appear in their names without prior written
>    *    permission of the Apache Group.
>    *
>    * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
>    * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
>    * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
>    * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
>    * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
>    * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
>    * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
>    * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
>    * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
>    * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
>    * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
>    * SUCH DAMAGE.
>    * 
====================================================================
>    *
>    * This software consists of voluntary contributions made by many
>    * individuals on behalf of the Apache Software Foundation.  For more
>    * information on the Apache Software Foundation, please see
>    * <http://www.apache.org/>.
>    *
>    */
> 
>   package org.apache.commons.discovery;
> 
>   import java.io.BufferedReader;
>   import java.io.IOException;
>   import java.io.InputStream;
>   import java.io.InputStreamReader;
>   import java.util.Properties;
>   import java.util.Vector;
> 
> 
>   /**
>    * <p>Implement the JDK1.3 'Service Provider' specification.
>    * ( http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html )
>    * </p>
>    *
>    * This class supports any VM, including JDK1.1. If a higher VM is
>    * detected a more efficient and complete implementation will be used.
>    *
>    * The caller will first configure the discoverer by adding ( in the
> desired
>    * order ) all the places to look for the META-INF/services. Currently
>    * we support loaders.
>    *
>    * The findServices() method will check every loader.
>    *
>    * Note. On JDK1.1 there is no getResources() method. We emulate this 
by
>    * using introspection and doing the lookup ourself, using the list of
> URLs.
>    * If the loader has a method getResources(), it'll be used. If not,
> we'll look
>    * for a method named getURLs().
>    *
>    * @author Richard A. Sitze
>    * @author Craig R. McClanahan
>    * @author Costin Manolache
>    */
>   public abstract class ServiceDiscovery
>   {
>       protected static final String SERVICE_HOME = "META-INF/services/";
> 
>       protected Vector classLoaders=new Vector();
> 
>       /** Construct a new service discoverer
>        */
>       protected ServiceDiscovery() {
>       }
> 
>       public static ServiceDiscovery getServiceDiscovery() {
>           // This is _not_ singleton.
>           return new ServiceDiscovery12();
>           // XXX Check if JDK1.1 is used and return the specific version
>       }
> 
>       /** Specify a new class loader to be used in searching.
>        *   The order of loaders determines the order of the result.
>        *  It is recommended to add the most specific loaders first.
>        */
>       public void addClassLoader(ClassLoader loader) {
>           classLoaders.addElement( loader );
>       }
> 
>       /** Convenience method to find the thread class loader.
>        *  Usefull in jdk1.1, to avoid other introspection hacks.
>        */
>       public abstract ClassLoader getThreadClassLoader();
> 
>       public abstract ServiceInfo[] findServices( String name );
> 
>   }
> 
> 
> 
>   1.1
> jakarta-
> 
commons/discovery/src/java/org/apache/commons/discovery/ServiceDiscoveryTask.
> java
> 
>   Index: ServiceDiscoveryTask.java
>   ===================================================================
>   /*
>    * 
====================================================================
>    *
>    * The Apache Software License, Version 1.1
>    *
>    * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
>    * reserved.
>    *
>    * Redistribution and use in source and binary forms, with or without
>    * modification, are permitted provided that the following conditions
>    * are met:
>    *
>    * 1. Redistributions of source code must retain the above copyright
>    *    notice, this list of conditions and the following disclaimer.
>    *
>    * 2. Redistributions in binary form must reproduce the above 
copyright
>    *    notice, this list of conditions and the following disclaimer in
>    *    the documentation and/or other materials provided with the
>    *    distribution.
>    *
>    * 3. The end-user documentation included with the redistribution, if
>    *    any, must include the following acknowlegement:
>    *       "This product includes software developed by the
>    *        Apache Software Foundation (http://www.apache.org/)."
>    *    Alternately, this acknowlegement may appear in the software
> itself,
>    *    if and wherever such third-party acknowlegements normally 
appear.
>    *
>    * 4. The names "The Jakarta Project", "Commons", and "Apache Software
>    *    Foundation" must not be used to endorse or promote products
> derived
>    *    from this software without prior written permission. For written
>    *    permission, please contact apache@apache.org.
>    *
>    * 5. Products derived from this software may not be called "Apache"
>    *    nor may "Apache" appear in their names without prior written
>    *    permission of the Apache Group.
>    *
>    * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
>    * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
>    * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
>    * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
>    * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
>    * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
>    * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
>    * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
>    * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
>    * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
>    * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
>    * SUCH DAMAGE.
>    * 
====================================================================
>    *
>    * This software consists of voluntary contributions made by many
>    * individuals on behalf of the Apache Software Foundation.  For more
>    * information on the Apache Software Foundation, please see
>    * <http://www.apache.org/>.
>    *
>    */
> 
>   package org.apache.commons.discovery;
> 
>   import java.io.BufferedReader;
>   import java.io.IOException;
>   import java.io.InputStream;
>   import java.io.InputStreamReader;
>   import java.util.Properties;
>   import java.util.Vector;
> 
> 
>   /**
>    * Small ant task that will use discovery to locate a particular impl.
>    * and display all values.
>    *
>    * You can execute this and save it with an id, then other classes can
> use it.
>    *
>    * @author Costin Manolache
>    */
>   public class ServiceDiscoveryTask
>   {
>       String name;
>       int debug=0;
>       ServiceInfo drivers[]=null;
> 
>       public void setServiceName(String name ) {
>           this.name=name;
>       }
> 
>       public void setDebug(int i) {
>           this.debug=debug;
>       }
> 
>       public ServiceInfo[] getServiceInfo() {
>           return drivers;
>       }
> 
>       public void execute() throws Exception {
>           System.out.println("XXX ");
>           ServiceDiscovery disc=ServiceDiscovery.getServiceDiscovery();
> 
>           disc.addClassLoader( disc.getThreadClassLoader() );
>           disc.addClassLoader( this.getClass().getClassLoader() );
> 
>           drivers=disc.findServices(name);
> 
>           if( debug > 0 ) {
>               for( int i=0; i<drivers.length; i++ ) {
>                   System.out.println("Found " + drivers[i] );
>               }
>           }
>       }
>   }




--
To unsubscribe, e-mail:   <
mailto:commons-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <
mailto:commons-dev-help@jakarta.apache.org>



--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: [discovery] URL's, Java 1.2... problem.

Posted by co...@covalent.net.
On Wed, 21 Aug 2002, Richard Sitze wrote:

> BUT...  getResources() is unique to Java 1.2.  We are suppose to be 
> backward compatible with 1.1.8.  An original goal of mine was to use this 
> WITHIN commons-logging LogFactory (supports 1.1.8+).  That means we cannot 

You may notice that getResources() is used in a class ServiceDiscovery12
and there is a mechanism to return a ServiceDiscovery11 if such VM is 
detected.

The implementation of getResources() on 1.1 is a bit difficult, but 
possible for most class loaders in common use ( eventually with minimal 
changes ). All you need is access to the classpath - and then some
code ( cut&paste from antclassloader or tomcat SimpleClassLoader for 
example ) to split the classpath and implement getResources. Most 
classloaders for 1.1 support a method to get this, or can do it with 
minimal changes. 

In the worse case the code can fall back to getResources - it'll 
still be able to discover the first driver ( which is what 
jaxp/commons-logging do anyway ). 

That means that discovering resources in 1.1 with a class loader that
doesn't provide access to classpath is not possible. Same is true
for supporting dependencies in MANIFEST, and many other things. We 
don't ( and can't ) change anything.


> use commons-logging internally (and it would be nice to), because we would 
> be introducing a circular dependency.  Note that a dependency ALREADY 
> exists because we use commons-logging in the test code.

If we keep the code simple, we can avoid using logging in our code
( and use exceptions  ). The test code is a separate package / issue - it 
may depend on junit or any other packages, that shouldn't count as 
'circular'. 


> I'm thinking that the services already offered by 'discovery' are 
> sufficient for APPLICATION developers looking to pull in pluggable 
> modules.

If the 's' at the end of modules was intentional - I agree.
I don't think discovery is that usefull if it is used to locate 
a single pluggable component - even if this can be used in some
cases ( like jaxp and logging ). And I certainly don't think it 
can/should try to abstract a preference-selection mechanism or
semantics for the discovered resources.

> For more sophisticated tooling and frameworks, your services work is 
> clearly a better direction.

I don't know about 'sophisticated' - I am thinking about ant and tomcat, 
and I'm trying to simplify some things. If it ends up 'sophisticated',
then it's a failure :-)


> So many choice.. buffet today:
> 
> (a) drop 1.1.8 entirely?
-1. Keep it low priority for now ( until we finish the APIs and get things
stable ), but it can and should be done. 

> (b) drop the services work, or find alternatives?

Not sure what you mean.

> (c) cut a release that supports 1.1.8 (that presumes that we can all agree 
> that the service is usable as-is :-) and then move on?

See (a)

> (d) use commons-logging internally or let commons-logging use discovery?

-0 on using commons-logging - +1 on commons-logging using discovery.

If we end up with a circular dependency it'll only mean that discovery and
logging must allways be bundled. Not very nice for those who just don't
want to use commons-logging - but they probably won't use discovery 
either, or if they want they should get involved.

Costin


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>