Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Public Firebird Java API.
   *
   * 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 name of the author may not be used to endorse or promote products 
  *       derived from this software without specific prior written permission.
  * 
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 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 AUTHOR 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.
  */
 package org.firebirdsql.gds.impl;
 
 
 import java.io.*;
 import java.net.URL;
 import java.util.*;

The class GDSFactory exists to provide a way to obtain objects implementing GDS and Clumplet.

Author(s):
David Jencks
Version:
1.0
 
 public class GDSFactory {
 
     private static final Logger log = LoggerFactory.getLogger(GDSFactory.class,
         false);

    
Class for string comparison in descending order. This effectively puts the shortest JDBC URLs at the end of the list, so the correct default protocol handling can be implemented.
 
     private static class ReversedStringComparator implements Comparator {
 
         public int compare(Object o1Object o2) {
             String s1 = (Stringo1;
             String s2 = (Stringo2;
 
             // note, we compare here s2 to s1,
             // this causes descending sorting
             return s2.compareTo(s1);
         }
 
     }
 
     private static HashSet registeredPlugins = new HashSet();
 
     private static HashMap typeToPluginMap = new HashMap();
 
     private static TreeMap jdbcUrlToPluginMap = new TreeMap(
             new ReversedStringComparator());
 
     private static GDSType defaultType;
 
     // TODO: Replace with explicit initializer from GDSType?
     static {
         // register first all plugins that belong to the same class loader
         // in which this class is loaded
         final List<ClassLoaderclassLoaders = classLoadersForLoading();
         try {
             for (ClassLoader classLoader : classLoaders) {
                 loadPluginsFromClassLoader(classLoader);
             }
         } catch (Exception ex) {
             if ( != null.error("Can't register plugins "ex);
         }
 
         if (.isEmpty()) {
             if ( != null.warn("No plugins loaded from META-INF/services, falling back to fixed registration of default plugins");
             for (ClassLoader classLoader : classLoaders) {
                 loadPluginsFallback(classLoader);
             }
         }
     }

    
List of class loaders to use for loading the GDSFactoryPlugin implementations.

Returns:
Collection of java.lang.ClassLoader instances
    private static List<ClassLoaderclassLoadersForLoading() {
        List<ClassLoaderclassLoaders = new ArrayList<ClassLoader>();
        final ClassLoader classLoader = GDSFactory.class.getClassLoader();
        if (classLoader != null) {
            classLoaders.add(classLoader);
        } else {
            classLoaders.add(ClassLoader.getSystemClassLoader());
        }
        final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
        if (contextClassLoader != null && !classLoaders.contains(contextClassLoader)) {
            classLoaders.add(contextClassLoader);
        }
        return classLoaders;
    }

    
Loads the plugins from a hardcoded list of class names.

This method is intended as a fallback in case the plugins could not be discovered from the META-INF/services/org.firebirdsql.gds.impl.GDSFactoryPlugin file(s). See also issue JDBC-325

    private static void loadPluginsFallback(final ClassLoader classLoader) {
        String[] pluginClasses = new String[] {
                "org.firebirdsql.gds.impl.wire.WireGDSFactoryPlugin",
                "org.firebirdsql.gds.impl.jni.NativeGDSFactoryPlugin",
                "org.firebirdsql.gds.impl.jni.LocalGDSFactoryPlugin",
                "org.firebirdsql.gds.impl.jni.EmbeddedGDSFactoryPlugin",
                "org.firebirdsql.gds.impl.oo.OOGDSFactoryPlugin"
        };
        for (String className : pluginClasses) {
            try {
                Class<?> clazz = classLoader.loadClass(className);
                GDSFactoryPlugin plugin = (GDSFactoryPluginclazz.newInstance();
                registerPlugin(plugin);
            } catch (ClassNotFoundException ex) {
                if ( != null)
                    .error("Can't register plugin" + classNameex);
            } catch (IllegalAccessException ex) {
                if ( != null)
                    .error("Can't register plugin" + classNameex);
            } catch(InstantiationException ex) {
                if ( != null)
                    .error("Can't register plugin" + classNameex);
            }
        }
    }

    
Load all existing plugins from the specified classloader.

Parameters:
classLoader instance of java.lang.ClassLoader.
Throws:
java.io.IOException if I/O error occured.
    private static void loadPluginsFromClassLoader(ClassLoader classLoaderthrows IOException {
        Enumeration res = classLoader.getResources(
            "META-INF/services/" + GDSFactoryPlugin.class.getName());
        if (!res.hasMoreElements() &&  != null) {
            .warn("No GDSFactoryPlugin service file(s) found");
        }
        while (res.hasMoreElements()) {
            URL url = (URLres.nextElement();
            
            InputStreamReader rin = new InputStreamReader(url.openStream());
            BufferedReader bin = new BufferedReader(rin);
            
            try {
                String className;
                while ((className = bin.readLine()) != null) {
                    try {
                        Class<?> clazz = classLoader.loadClass(className);
                        GDSFactoryPlugin plugin = (GDSFactoryPlugin)clazz.newInstance();
                        registerPlugin(plugin);
                    } catch (ClassNotFoundException ex) {
                        if ( != null)
                            .error("Can't register plugin" + classNameex);
                    } catch (IllegalAccessException ex) {
                        if ( != null)
                            .error("Can't register plugin" + classNameex);
                    } catch(InstantiationException ex) {
                        if ( != null)
                            .error("Can't register plugin" + classNameex);
                    }
                }
            } finally {
                bin.close();
            }
        }
    }

    
Register plugin for this factory. Usually there is no need to register plugins, since this happens automatically during initialization of this class. However, there might be a situation when automatic plugin registration does not work.

Parameters:
plugin instance of GDSFactoryPlugin to register.
    public static void registerPlugin(GDSFactoryPlugin plugin) {
        boolean newPlugin = .add(plugin);
        if (!newPlugin)
            return;
        GDSType type = GDSType.registerType(plugin.getTypeName());
        .put(typeplugin);
        // set the default type
        if ( == null = type;
        // register aliases
        String[] aliases = plugin.getTypeAliases();
        for (int i = 0; i < aliases.lengthi++) {
            GDSType aliasType = GDSType.registerType(aliases[i]);
            .put(aliasTypeplugin);
        }
        String[] jdbcUrls = (String[]) plugin.getSupportedProtocols();
        for (int i = 0; i < jdbcUrls.lengthi++) {
            GDSFactoryPlugin otherPlugin = 
                (GDSFactoryPlugin).put(jdbcUrls[i], plugin);
            
            if (otherPlugin == null)
                continue;
            
            if (!otherPlugin.equals(plugin))
                throw new IllegalArgumentException(
                "Duplicate JDBC URL pattern detected: URL " + jdbcUrls[i] + ", " +
                "plugin " + plugin.getTypeName() + ", other plugin " + otherPlugin.getTypeName());
        }
    }

    
Get an instance of the default GDS implemenation.

Returns:
A default GDS instance
    public static GDS getDefaultGDS() {
        return getGDSForType();
    }

    
Get default GDS type.

Returns:
instance of GDSType.
    public static GDSType getDefaultGDSType() {
        return ;
    }

    
Get an instance of the specified implemenation of GDS.

Parameters:
gdsType The type of the GDS instance to be returned
Returns:
A GDS implementation of the given type
    public synchronized static GDS getGDSForType(GDSType gdsType) {
        if (gdsType == nullgdsType = ;
        GDSFactoryPlugin gdsPlugin = (GDSFactoryPlugin
                .get(gdsType);
        if (gdsPlugin == null)
            throw new IllegalArgumentException("Specified GDS type " + gdsType
                    + " is unknown.");
        return gdsPlugin.getGDS();
    }

    
Get connection string for the specified server name, port and database name/path. This method delegates call to the factory plugin corresponding to the specified type.

Parameters:
gdsType instance of GDSType for which connection string should be returned.
server name or IP address of the database server, applies only to IPC and TCP connection modes, in other cases should be null.
port port on which database server opened listening socket, applies to TCP connection mode only, may be null.
path database name or path to the database
Returns:
full connection string that can be passed to org.firebirdsql.gds.GDS.iscAttachDatabase(java.lang.String,org.firebirdsql.gds.IscDbHandle,org.firebirdsql.gds.DatabaseParameterBuffer) method.
Throws:
org.firebirdsql.gds.GDSException if connection string cannot be obtained.
    public static String getDatabasePath(GDSType gdsTypeString server,
            Integer portString paththrows GDSException {
        return getPlugin(gdsType).getDatabasePath(serverportpath);
    }

    
Get path to the database from the specified JDBC URL. This method finds the appropriate plugin and delegates the call to it. Plugin is responsible for the call execution.

Parameters:
gdsType type of the plugin, to which operation will be delegated to.
jdbcUrl JDBC url from which the database path must be extracted.
Returns:
path to the database specified in the JDBC URL.
Throws:
org.firebirdsql.gds.GDSException error when database path cannot be extracted.
    public static String getDatabasePath(GDSType gdsTypeString jdbcUrl)
            throws GDSException {
        return getPlugin(gdsType).getDatabasePath(jdbcUrl);
    }

    
Get collection of the supported JDBC protocols.

Returns:
set of the supported protocols.
    public static Set getSupportedProtocols() {
        return .keySet();
    }

    
Create JDBC URL for the specified GDS type and database path.

Parameters:
gdsType type of the plugin, to which operation will be delegated to.
databasePath path to the database.
Returns:
newly created JDBC URL.
    public static String getJdbcUrl(GDSType gdsTypeString databasePath) {
        return getPlugin(gdsType).getDefaultProtocol() + databasePath;
    }

    
Get GDS type for the specified JDBC URL. This method finds the plugin corresponding to the specified type and delegates the call to it.

Parameters:
jdbcUrl JDBC URL for which GDS type should be obtained.
Returns:
instance of GDSType.
    public static GDSType getTypeForProtocol(String jdbcUrl) {
        for (Iterator iter = .entrySet().iterator(); iter
                .hasNext();) {
            Map.Entry entry = (Map.Entryiter.next();
            String jdbcProtocol = (Stringentry.getKey();
            GDSFactoryPlugin plugin = (GDSFactoryPluginentry.getValue();
            if (jdbcUrl.startsWith(jdbcProtocol)) {
                return GDSType.getType(plugin.getTypeName());
            }
        }
        if ( != null.debug("No protocol match found for url " + jdbcUrl);
        return null;
    }

    
Get class extending the org.firebirdsql.jdbc.AbstractConnection that will be instantiated when new connection is created. This method finds the plugin for the specified type and delegates the call to it.

Parameters:
gdsType instance of GDSType
Returns:
class to instantiate for the database connection.
    public static Class getConnectionClass(GDSType gdsType) {
        return getPlugin(gdsType).getConnectionClass();
    }

    
Get plugin for the specified GDS type.

Parameters:
gdsType GDS type.
Returns:
instance of GDSFactoryPlugin
Throws:
java.lang.IllegalArgumentException if specified type is not known.
    private static GDSFactoryPlugin getPlugin(GDSType gdsType) {
        GDSFactoryPlugin gdsPlugin = (GDSFactoryPlugin
                .get(gdsType);
        if (gdsPlugin == null)
            throw new IllegalArgumentException("Specified GDS type " + gdsType
                    + " is unknown.");
        return gdsPlugin;
    }
New to GrepCode? Check out our FAQ X