X-Git-Url: https://juplo.de/gitweb/?p=website;a=blobdiff_plain;f=dist%2Fhibernate4-maven-plugin-1.0.1%2Fxref%2Fde%2Fjuplo%2Fplugins%2Fhibernate4%2FHbm2DdlMojo.html;fp=dist%2Fhibernate4-maven-plugin-1.0.1%2Fxref%2Fde%2Fjuplo%2Fplugins%2Fhibernate4%2FHbm2DdlMojo.html;h=6ebc04279ae59f57ab59b4fb78545cdf8359c9b2;hp=0000000000000000000000000000000000000000;hb=a53595184bd6e57bdc45292cc92c393c4e2dfe6e;hpb=c48c9ee0e9faa89a4c0a5323b367b9f5a6abe602 diff --git a/dist/hibernate4-maven-plugin-1.0.1/xref/de/juplo/plugins/hibernate4/Hbm2DdlMojo.html b/dist/hibernate4-maven-plugin-1.0.1/xref/de/juplo/plugins/hibernate4/Hbm2DdlMojo.html new file mode 100644 index 00000000..6ebc0427 --- /dev/null +++ b/dist/hibernate4-maven-plugin-1.0.1/xref/de/juplo/plugins/hibernate4/Hbm2DdlMojo.html @@ -0,0 +1,784 @@ + + + + +Hbm2DdlMojo xref + + + +
View Javadoc
+
+1   package de.juplo.plugins.hibernate4;
+2   
+3   /*
+4    * Copyright 2001-2005 The Apache Software Foundation.
+5    *
+6    * Licensed under the Apache License, Version 2.0 (the "License");
+7    * you may not use this file except in compliance with the License.
+8    * You may obtain a copy of the License at
+9    *
+10   *      http://www.apache.org/licenses/LICENSE-2.0
+11   *
+12   * Unless required by applicable law or agreed to in writing, software
+13   * distributed under the License is distributed on an "AS IS" BASIS,
+14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+15   * See the License for the specific language governing permissions and
+16   * limitations under the License.
+17   */
+18  
+19  import com.pyx4j.log4j.MavenLogAppender;
+20  import java.io.File;
+21  import java.io.FileInputStream;
+22  import java.io.FileOutputStream;
+23  import java.io.IOException;
+24  import java.io.InputStream;
+25  import java.io.ObjectInputStream;
+26  import java.io.ObjectOutputStream;
+27  import java.math.BigInteger;
+28  import java.net.URL;
+29  import java.net.URLClassLoader;
+30  import java.security.MessageDigest;
+31  import java.sql.Connection;
+32  import java.sql.Driver;
+33  import java.sql.DriverManager;
+34  import java.sql.DriverPropertyInfo;
+35  import java.sql.SQLException;
+36  import java.sql.SQLFeatureNotSupportedException;
+37  import java.util.Comparator;
+38  import java.util.Enumeration;
+39  import java.util.HashMap;
+40  import java.util.HashSet;
+41  import java.util.List;
+42  import java.util.Map;
+43  import java.util.Map.Entry;
+44  import java.util.Properties;
+45  import java.util.Set;
+46  import java.util.TreeSet;
+47  import java.util.logging.Logger;
+48  import javax.persistence.Embeddable;
+49  import javax.persistence.Entity;
+50  import javax.persistence.MappedSuperclass;
+51  import org.apache.maven.plugin.AbstractMojo;
+52  import org.apache.maven.plugin.MojoExecutionException;
+53  import org.apache.maven.plugin.MojoFailureException;
+54  import org.apache.maven.project.MavenProject;
+55  import org.hibernate.cfg.Configuration;
+56  import org.hibernate.tool.hbm2ddl.SchemaExport;
+57  import org.hibernate.tool.hbm2ddl.SchemaExport.Type;
+58  import org.hibernate.tool.hbm2ddl.Target;
+59  import org.scannotation.AnnotationDB;
+60  
+61  
+62  /**
+63   * Goal which extracts the hibernate-mapping-configuration and
+64   * exports an according SQL-database-schema.
+65   *
+66   * @goal export
+67   * @phase process-classes
+68   * @threadSafe
+69   * @requiresDependencyResolution runtime
+70   */
+71  public class Hbm2DdlMojo extends AbstractMojo
+72  {
+73    public final static String EXPORT_SKIPPED_PROPERTY = "hibernate.export.skipped";
+74  
+75    public final static String DRIVER_CLASS = "hibernate.connection.driver_class";
+76    public final static String URL = "hibernate.connection.url";
+77    public final static String USERNAME = "hibernate.connection.username";
+78    public final static String PASSWORD = "hibernate.connection.password";
+79    public final static String DIALECT = "hibernate.dialect";
+80  
+81    private final static String MD5S = "schema.md5s";
+82  
+83    /**
+84     * The maven project.
+85     * <p>
+86     * Only needed internally.
+87     *
+88     * @parameter expression="${project}"
+89     * @required
+90     * @readonly
+91     */
+92    private MavenProject project;
+93  
+94    /**
+95     * Build-directory.
+96     * <p>
+97     * Only needed internally.
+98     *
+99     * @parameter expression="${project.build.directory}"
+100    * @required
+101    * @readonly
+102    */
+103   private String buildDirectory;
+104 
+105   /**
+106    * Classes-Directory to scan.
+107    * <p>
+108    * This parameter defaults to the maven build-output-directory for classes.
+109    * Additonally, all dependencies are scanned for annotated classes.
+110    *
+111    * @parameter expression="${project.build.outputDirectory}"
+112    */
+113   private String outputDirectory;
+114 
+115   /**
+116    * Wether to scan test-classes too, or not.
+117    * <p>
+118    * If this parameter is set to <code>true</code> the test-classes of the
+119    * artifact will be scanned for hibernate-annotated classes additionally.
+120    *
+121    * @parameter expression="${hibernate.export.scann_testclasses}" default-value="false"
+122    */
+123   private boolean scanTestClasses;
+124 
+125   /**
+126    * Test-Classes-Directory to scan.
+127    * <p>
+128    * This parameter defaults to the maven build-output-directory for
+129    * test-classes.
+130    * <p>
+131    * This parameter is only used, when <code>scanTestClasses</code> is set
+132    * to <code>true</code>!
+133    *
+134    * @parameter expression="${project.build.testOutputDirectory}"
+135    */
+136   private String testOutputDirectory;
+137 
+138   /**
+139    * Skip execution
+140    * <p>
+141    * If set to <code>true</code>, the execution is skipped.
+142    * <p>
+143    * A skipped excecution is signaled via the maven-property
+144    * <code>${hibernate.export.skipped}</code>.
+145    * <p>
+146    * The excecution is skipped automatically, if no modified or newly added
+147    * annotated classes are found and the dialect was not changed.
+148    *
+149    * @parameter expression="${maven.test.skip}" default-value="false"
+150    */
+151   private boolean skip;
+152 
+153   /**
+154    * Force execution
+155    * <p>
+156    * Force execution, even if no modified or newly added annotated classes
+157    * where found and the dialect was not changed.
+158    * <p>
+159    * <code>skip</code> takes precedence over <code>force</code>.
+160    *
+161    * @parameter expression="${hibernate.export.force}" default-value="false"
+162    */
+163   private boolean force;
+164 
+165   /**
+166    * SQL-Driver name.
+167    *
+168    * @parameter expression="${hibernate.connection.driver_class}
+169    */
+170   private String driverClassName;
+171 
+172   /**
+173    * Database URL.
+174    *
+175    * @parameter expression="${hibernate.connection.url}"
+176    */
+177   private String url;
+178 
+179   /**
+180    * Database username
+181    *
+182    * @parameter expression="${hibernate.connection.username}"
+183    */
+184   private String username;
+185 
+186   /**
+187    * Database password
+188    *
+189    * @parameter expression="${hibernate.connection.password}"
+190    */
+191   private String password;
+192 
+193   /**
+194    * Hibernate dialect.
+195    *
+196    * @parameter expression="${hibernate.dialect}"
+197    */
+198   private String hibernateDialect;
+199 
+200   /**
+201    * Path to Hibernate configuration file.
+202    *
+203    * @parameter default-value="${project.build.outputDirectory}/hibernate.properties"
+204    */
+205   private String hibernateProperties;
+206 
+207   /**
+208    * Target of execution:
+209    * <ul>
+210    *   <li><strong>NONE</strong> do nothing - just validate the configuration (forces excecution, signals skip)</li>
+211    *   <li><strong>EXPORT</strong> create database (<strong>DEFAULT!</strong>. forces excecution, signals skip)</li>
+212    *   <li><strong>SCRIPT</strong> export schema to SQL-script</li>
+213    *   <li><strong>BOTH</strong></li>
+214    * </ul>
+215    * @parameter expression="${hibernate.export.target}" default-value="EXPORT"
+216    */
+217   private String target;
+218 
+219   /**
+220    * Type of execution.
+221    * <ul>
+222    *   <li><strong>NONE</strong> do nothing - just validate the configuration</li>
+223    *   <li><strong>CREATE</strong> create database-schema</li>
+224    *   <li><strong>DROP</strong> drop database-schema</li>
+225    *   <li><strong>BOTH</strong> (<strong>DEFAULT!</strong>)</li>
+226    * </ul>
+227    * @parameter expression="${hibernate.export.type}" default-value="BOTH"
+228    */
+229   private String type;
+230 
+231   /**
+232    * Output file.
+233    *
+234    * @parameter expression="${hibernate.export.schema.filename}" default-value="${project.build.directory}/schema.sql"
+235    */
+236   private String outputFile;
+237 
+238   /**
+239    * Delimiter in output-file.
+240    *
+241    * @parameter expression="${hibernate.export.schema.delimiter}" default-value=";"
+242    */
+243   private String delimiter;
+244 
+245   /**
+246    * Format output-file.
+247    *
+248    * @parameter expression="${hibernate.export.schema.format}" default-value="true"
+249    */
+250   private boolean format;
+251 
+252 
+253   @Override
+254   public void execute()
+255     throws
+256       MojoFailureException,
+257       MojoExecutionException
+258   {
+259     if (skip)
+260     {
+261       getLog().info("Exectuion of hibernate4-maven-plugin:export was skipped!");
+262       project.getProperties().setProperty(EXPORT_SKIPPED_PROPERTY, "true");
+263       return;
+264     }
+265 
+266     File dir = new File(outputDirectory);
+267     if (!dir.exists())
+268       throw new MojoExecutionException("Cannot scan for annotated classes in " + outputDirectory + ": directory does not exist!");
+269 
+270     Map<String,String> md5s;
+271     boolean modified = false;
+272     File saved = new File(buildDirectory + File.separator + MD5S);
+273 
+274     if (saved.exists())
+275     {
+276       try
+277       {
+278         FileInputStream fis = new FileInputStream(saved);
+279         ObjectInputStream ois = new ObjectInputStream(fis);
+280         md5s = (HashMap<String,String>)ois.readObject();
+281         ois.close();
+282       }
+283       catch (Exception e)
+284       {
+285         md5s = new HashMap<String,String>();
+286         getLog().warn("Cannot read timestamps from saved: " + e);
+287       }
+288     }
+289     else
+290     {
+291       md5s = new HashMap<String,String>();
+292       try
+293       {
+294         saved.createNewFile();
+295       }
+296       catch (IOException e)
+297       {
+298         getLog().warn("Cannot create saved for timestamps: " + e);
+299       }
+300     }
+301 
+302     ClassLoader classLoader = null;
+303     try
+304     {
+305       getLog().debug("Creating ClassLoader for project-dependencies...");
+306       List<String> classpathFiles = project.getCompileClasspathElements();
+307       if (scanTestClasses)
+308         classpathFiles.addAll(project.getTestClasspathElements());
+309       URL[] urls = new URL[classpathFiles.size()];
+310       for (int i = 0; i < classpathFiles.size(); ++i)
+311       {
+312         getLog().debug("Dependency: " + classpathFiles.get(i));
+313         urls[i] = new File(classpathFiles.get(i)).toURI().toURL();
+314       }
+315       classLoader = new URLClassLoader(urls, getClass().getClassLoader());
+316     }
+317     catch (Exception e)
+318     {
+319       getLog().error("Error while creating ClassLoader!", e);
+320       throw new MojoExecutionException(e.getMessage());
+321     }
+322 
+323     Set<Class<?>> classes =
+324         new TreeSet<Class<?>>(
+325             new Comparator<Class<?>>() {
+326               @Override
+327               public int compare(Class<?> a, Class<?> b)
+328               {
+329                 return a.getName().compareTo(b.getName());
+330               }
+331             }
+332           );
+333 
+334     try
+335     {
+336       AnnotationDB db = new AnnotationDB();
+337       getLog().info("Scanning directory " + outputDirectory + " for annotated classes...");
+338       URL dirUrl = dir.toURI().toURL();
+339       db.scanArchives(dirUrl);
+340       if (scanTestClasses)
+341       {
+342         dir = new File(testOutputDirectory);
+343         if (!dir.exists())
+344           throw new MojoExecutionException("Cannot scan for annotated test-classes in " + testOutputDirectory + ": directory does not exist!");
+345         getLog().info("Scanning directory " + testOutputDirectory + " for annotated classes...");
+346         dirUrl = dir.toURI().toURL();
+347         db.scanArchives(dirUrl);
+348       }
+349 
+350       Set<String> classNames = new HashSet<String>();
+351       if (db.getAnnotationIndex().containsKey(Entity.class.getName()))
+352         classNames.addAll(db.getAnnotationIndex().get(Entity.class.getName()));
+353       if (db.getAnnotationIndex().containsKey(MappedSuperclass.class.getName()))
+354         classNames.addAll(db.getAnnotationIndex().get(MappedSuperclass.class.getName()));
+355       if (db.getAnnotationIndex().containsKey(Embeddable.class.getName()))
+356         classNames.addAll(db.getAnnotationIndex().get(Embeddable.class.getName()));
+357 
+358       MessageDigest digest = java.security.MessageDigest.getInstance("MD5");
+359       for (String name : classNames)
+360       {
+361         Class<?> annotatedClass = classLoader.loadClass(name);
+362         classes.add(annotatedClass);
+363         InputStream is =
+364             annotatedClass
+365                 .getResourceAsStream(annotatedClass.getSimpleName() + ".class");
+366         byte[] buffer = new byte[1024*4]; // copy data in 4MB-chunks
+367         int i;
+368         while((i = is.read(buffer)) > -1)
+369           digest.update(buffer, 0, i);
+370         is.close();
+371         byte[] bytes = digest.digest();
+372         BigInteger bi = new BigInteger(1, bytes);
+373         String newMd5 = String.format("%0" + (bytes.length << 1) + "x", bi);
+374         String oldMd5 = !md5s.containsKey(name) ? "" : md5s.get(name);
+375         if (!newMd5.equals(oldMd5))
+376         {
+377           getLog().debug("Found new or modified annotated class: " + name);
+378           modified = true;
+379           md5s.put(name, newMd5);
+380         }
+381         else
+382         {
+383           getLog().debug(oldMd5 + " -> class unchanged: " + name);
+384         }
+385       }
+386     }
+387     catch (ClassNotFoundException e)
+388     {
+389       getLog().error("Error while adding annotated classes!", e);
+390       throw new MojoExecutionException(e.getMessage());
+391     }
+392     catch (Exception e)
+393     {
+394       getLog().error("Error while scanning!", e);
+395       throw new MojoFailureException(e.getMessage());
+396     }
+397 
+398     if (classes.isEmpty())
+399       throw new MojoFailureException("No annotated classes found in directory " + outputDirectory);
+400 
+401     getLog().debug("Detected classes with mapping-annotations:");
+402     for (Class<?> annotatedClass : classes)
+403       getLog().debug("  " + annotatedClass.getName());
+404 
+405 
+406     Properties properties = new Properties();
+407 
+408     /** Try to read configuration from properties-file */
+409     try
+410     {
+411       File file = new File(hibernateProperties);
+412       if (file.exists())
+413       {
+414         getLog().info("Reading properties from file " + hibernateProperties + "...");
+415         properties.load(new FileInputStream(file));
+416       }
+417       else
+418         getLog().info("No hibernate-properties-file found! (Checked path: " + hibernateProperties + ")");
+419     }
+420     catch (IOException e)
+421     {
+422       getLog().error("Error while reading properties!", e);
+423       throw new MojoExecutionException(e.getMessage());
+424     }
+425 
+426     /** Overwrite values from propertie-file or set, if given */
+427     if (driverClassName != null)
+428     {
+429       if (properties.containsKey(DRIVER_CLASS))
+430         getLog().debug(
+431             "Overwriting property " +
+432             DRIVER_CLASS + "=" + properties.getProperty(DRIVER_CLASS) +
+433             " with the value " + driverClassName
+434           );
+435       else
+436         getLog().debug("Using the value " + driverClassName);
+437       properties.setProperty(DRIVER_CLASS, driverClassName);
+438     }
+439     if (url != null)
+440     {
+441       if (properties.containsKey(URL))
+442         getLog().debug(
+443             "Overwriting property " +
+444             URL + "=" + properties.getProperty(URL) +
+445             " with the value " + url
+446           );
+447       else
+448         getLog().debug("Using the value " + url);
+449       properties.setProperty(URL, url);
+450     }
+451     if (username != null)
+452     {
+453       if (properties.containsKey(USERNAME))
+454         getLog().debug(
+455             "Overwriting property " +
+456             USERNAME + "=" + properties.getProperty(USERNAME) +
+457             " with the value " + username
+458           );
+459       else
+460         getLog().debug("Using the value " + username);
+461       properties.setProperty(USERNAME, username);
+462     }
+463     if (password != null)
+464     {
+465       if (properties.containsKey(PASSWORD))
+466         getLog().debug(
+467             "Overwriting property " +
+468             PASSWORD + "=" + properties.getProperty(PASSWORD) +
+469             " with the value " + password 
+470           );
+471       else
+472         getLog().debug("Using the value " + password);
+473       properties.setProperty(PASSWORD, password);
+474     }
+475     if (hibernateDialect != null)
+476     {
+477       if (properties.containsKey(DIALECT))
+478         getLog().debug(
+479             "Overwriting property " +
+480             DIALECT + "=" + properties.getProperty(DIALECT) +
+481             " with the value " + hibernateDialect
+482           );
+483       else
+484         getLog().debug("Using the value " + hibernateDialect);
+485       properties.setProperty(DIALECT, hibernateDialect);
+486     }
+487 
+488     /** The generated SQL varies with the dialect! */
+489     if (md5s.containsKey(DIALECT))
+490     {
+491       String dialect = properties.getProperty(DIALECT);
+492       if (md5s.get(DIALECT).equals(dialect))
+493         getLog().debug("SQL-dialect unchanged.");
+494       else
+495       {
+496         getLog().debug("SQL-dialect changed: " + dialect);
+497         modified = true;
+498         md5s.put(DIALECT, dialect);
+499       }
+500     }
+501     else
+502     {
+503       modified = true;
+504       md5s.put(DIALECT, properties.getProperty(DIALECT));
+505     }
+506 
+507     if (properties.isEmpty())
+508     {
+509       getLog().error("No properties set!");
+510       throw new MojoFailureException("Hibernate-Configuration is missing!");
+511     }
+512 
+513     Configuration config = new Configuration();
+514     config.setProperties(properties);
+515     getLog().debug("Adding annotated classes to hibernate-mapping-configuration...");
+516     for (Class<?> annotatedClass : classes)
+517     {
+518       getLog().debug("Class " + annotatedClass);
+519       config.addAnnotatedClass(annotatedClass);
+520     }
+521 
+522     Target target = null;
+523     try
+524     {
+525       target = Target.valueOf(this.target.toUpperCase());
+526     }
+527     catch (IllegalArgumentException e)
+528     {
+529       getLog().error("Invalid value for configuration-option \"target\": " + this.target);
+530       getLog().error("Valid values are: NONE, SCRIPT, EXPORT, BOTH");
+531       throw new MojoExecutionException("Invalid value for configuration-option \"target\"");
+532     }
+533     Type type = null;
+534     try
+535     {
+536       type = Type.valueOf(this.type.toUpperCase());
+537     }
+538     catch (IllegalArgumentException e)
+539     {
+540       getLog().error("Invalid value for configuration-option \"type\": " + this.type);
+541       getLog().error("Valid values are: NONE, CREATE, DROP, BOTH");
+542       throw new MojoExecutionException("Invalid value for configuration-option \"type\"");
+543     }
+544 
+545     if (target.equals(Target.SCRIPT) || target.equals(Target.NONE))
+546     {
+547       project.getProperties().setProperty(EXPORT_SKIPPED_PROPERTY, "true");
+548     }
+549     if (
+550         !modified
+551         && !target.equals(Target.SCRIPT)
+552         && !target.equals(Target.NONE)
+553         && !force
+554       )
+555     {
+556       getLog().info("No modified annotated classes found and dialect unchanged.");
+557       getLog().info("Skipping schema generation!");
+558       project.getProperties().setProperty(EXPORT_SKIPPED_PROPERTY, "true");
+559       return;
+560     }
+561 
+562     getLog().info("Gathered hibernate-configuration (turn on debugging for details):");
+563     for (Entry<Object,Object> entry : properties.entrySet())
+564       getLog().info("  " + entry.getKey() + " = " + entry.getValue());
+565 
+566     Connection connection = null;
+567     try
+568     {
+569       /**
+570        * The connection must be established outside of hibernate, because
+571        * hibernate does not use the context-classloader of the current
+572        * thread and, hence, would not be able to resolve the driver-class!
+573        */
+574       switch (target)
+575       {
+576         case EXPORT:
+577         case BOTH:
+578           switch (type)
+579           {
+580             case CREATE:
+581             case DROP:
+582             case BOTH:
+583               Class driverClass = classLoader.loadClass(properties.getProperty(DRIVER_CLASS));
+584               getLog().debug("Registering JDBC-driver " + driverClass.getName());
+585               DriverManager.registerDriver(new DriverProxy((Driver)driverClass.newInstance()));
+586               getLog().debug(
+587                   "Opening JDBC-connection to "
+588                   + properties.getProperty(URL)
+589                   + " as "
+590                   + properties.getProperty(USERNAME)
+591                   + " with password "
+592                   + properties.getProperty(PASSWORD)
+593                   );
+594               connection = DriverManager.getConnection(
+595                   properties.getProperty(URL),
+596                   properties.getProperty(USERNAME),
+597                   properties.getProperty(PASSWORD)
+598                   );
+599           }
+600       }
+601     }
+602     catch (ClassNotFoundException e)
+603     {
+604       getLog().error("Dependency for driver-class " + properties.getProperty(DRIVER_CLASS) + " is missing!");
+605       throw new MojoExecutionException(e.getMessage());
+606     }
+607     catch (Exception e)
+608     {
+609       getLog().error("Cannot establish connection to database!");
+610       Enumeration<Driver> drivers = DriverManager.getDrivers();
+611       if (!drivers.hasMoreElements())
+612         getLog().error("No drivers registered!");
+613       while (drivers.hasMoreElements())
+614         getLog().debug("Driver: " + drivers.nextElement());
+615       throw new MojoExecutionException(e.getMessage());
+616     }
+617 
+618     ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
+619     MavenLogAppender.startPluginLog(this);
+620     try
+621     {
+622       /**
+623        * Change class-loader of current thread, so that hibernate can
+624        * see all dependencies!
+625        */
+626       Thread.currentThread().setContextClassLoader(classLoader);
+627 
+628       SchemaExport export = new SchemaExport(config, connection);
+629       export.setOutputFile(outputFile);
+630       export.setDelimiter(delimiter);
+631       export.setFormat(format);
+632       export.execute(target, type);
+633 
+634       for (Object exception : export.getExceptions())
+635         getLog().debug(exception.toString());
+636     }
+637     finally
+638     {
+639       /** Stop Log-Capturing */
+640       MavenLogAppender.endPluginLog(this);
+641 
+642       /** Restore the old class-loader (TODO: is this really necessary?) */
+643       Thread.currentThread().setContextClassLoader(contextClassLoader);
+644 
+645       /** Close the connection */
+646       try
+647       {
+648         if (connection != null)
+649           connection.close();
+650       }
+651       catch (SQLException e)
+652       {
+653         getLog().error("Error while closing connection: " + e.getMessage());
+654       }
+655     }
+656 
+657     /** Write md5-sums for annotated classes to file */
+658     try
+659     {
+660       FileOutputStream fos = new FileOutputStream(saved);
+661       ObjectOutputStream oos = new ObjectOutputStream(fos);
+662       oos.writeObject(md5s);
+663       oos.close();
+664       fos.close();
+665     }
+666     catch (Exception e)
+667     {
+668       getLog().error("Cannot write md5-sums to file: " + e);
+669     }
+670   }
+671 
+672   /**
+673    * Needed, because DriverManager won't pick up drivers, that were not
+674    * loaded by the system-classloader!
+675    * See:
+676    * http://stackoverflow.com/questions/288828/how-to-use-a-jdbc-driver-fromodifiedm-an-arbitrary-location
+677    */
+678   static final class DriverProxy implements Driver
+679   {
+680     private final Driver target;
+681 
+682     DriverProxy(Driver target)
+683     {
+684       if (target == null)
+685         throw new NullPointerException();
+686       this.target = target;
+687     }
+688 
+689     public java.sql.Driver getTarget()
+690     {
+691       return target;
+692     }
+693 
+694     @Override
+695     public boolean acceptsURL(String url) throws SQLException
+696     {
+697       return target.acceptsURL(url);
+698     }
+699 
+700     @Override
+701     public java.sql.Connection connect(
+702         String url,
+703         java.util.Properties info
+704       )
+705       throws
+706         SQLException
+707     {
+708       return target.connect(url, info);
+709     }
+710 
+711     @Override
+712     public int getMajorVersion()
+713     {
+714       return target.getMajorVersion();
+715     }
+716 
+717     @Override
+718     public int getMinorVersion()
+719     {
+720       return target.getMinorVersion();
+721     }
+722 
+723     @Override
+724     public DriverPropertyInfo[] getPropertyInfo(
+725         String url,
+726         Properties info
+727       )
+728       throws
+729         SQLException
+730     {
+731       return target.getPropertyInfo(url, info);
+732     }
+733 
+734     @Override
+735     public boolean jdbcCompliant()
+736     {
+737       return target.jdbcCompliant();
+738     }
+739 
+740     /**
+741      * This Method cannot be annotated with @Override, becaus the plugin
+742      * will not compile then under Java 1.6!
+743      */
+744     public Logger getParentLogger() throws SQLFeatureNotSupportedException
+745     {
+746       throw new SQLFeatureNotSupportedException("Not supported, for backward-compatibility with Java 1.6");
+747     }
+748 
+749     @Override
+750     public String toString()
+751     {
+752       return "Proxy: " + target;
+753     }
+754 
+755     @Override
+756     public int hashCode()
+757     {
+758       return target.hashCode();
+759     }
+760 
+761     @Override
+762     public boolean equals(Object obj)
+763     {
+764       if (!(obj instanceof DriverProxy))
+765         return false;
+766       DriverProxy other = (DriverProxy) obj;
+767       return this.target.equals(other.target);
+768     }
+769   }
+770 }
+
+
+ +