All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.openjpa.tools.maven.AbstractOpenJpaMojo Maven / Gradle / Ivy

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.openjpa.tools.maven;


import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.apache.openjpa.lib.util.Options;
import org.codehaus.plexus.util.FileUtils;

/**
 * Base class for  OpenJPA maven tasks.
 *
 * @version $Id$
 */
public abstract class AbstractOpenJpaMojo extends AbstractMojo
{
    /**
     * The working directory for putting persistence.xml and
     * other stuff into if we need to.
     */
    @Parameter(property="openjpa.workdir", defaultValue="${project.build.directory}/openjpa-work", required=true)
    protected File workDir;

    /**
     * Location where persistence-enabled classes are located.
     */
    @Parameter(property="openjpa.classes", defaultValue="${project.build.outputDirectory}", required=true)
    protected File classes;

    /**
     * Comma separated list of includes to scan searchDir to pass to the jobs.
     * This may be used to restrict the OpenJPA tasks to e.g. a single package which
     * contains all the entities.
     */
    @Parameter(defaultValue="**/*.class")
    private String includes;

    /**
     * Comma separated list of excludes to scan searchDir to pass to the jobs.
     * This option may be used to stop OpenJPA tasks from scanning non-JPA classes
     * (which usually leads to warnings such as "Type xxx has no metadata")
     */
    @Parameter(defaultValue="")
    private String excludes;

    /**
     * Additional properties passed to the OpenJPA tools.
     */
    @Parameter
    private Properties toolProperties;

    /**
     * Used if a non-default file location for the persistence.xml should be used
     * If not specified, the default one in META-INF/persistence.xml will be used.
     * Since openjpa-2.3.0 this can also be a resource location. In prior releases
     * it was only possible to specify a file location.
     */
    @Parameter
    private String persistenceXmlFile;

    /**
     * An optional PersistenceUnit name.
     * If not specified then OpenJPA will run against 'all anchors'.
     * Means it will use all persistenceunits of all persistence.xml files it finds.
     */
    @Parameter(defaultValue="${openjpa.persistenceUnitName}")
    private String persistenceUnitName;


    /**
     * 

This setting can be used to override any openjpa.ConnectionDriverName set in the * persistence.xml. It can also be used if the persistence.xml contains no connection * information at all.

* * Sample: *

     * <connectionDriverName>com.mchange.v2.c3p0.ComboPooledDataSource</connectionDriverName>
     * 
* * This is most times used in conjunction with {@link #connectionProperties}. */ @Parameter private String connectionDriverName; /** the string used for passing information about the connectionDriverName */ protected static final String OPTION_CONNECTION_DRIVER_NAME = "ConnectionDriverName"; /** *

Used to define the credentials or any other connection properties.

* * Sample: *
     * <connectionProperties>
     *   driverClass=com.mysql.jdbc.Driver,
     *   jdbcUrl=jdbc:mysql://localhost/mydatabase,
     *   user=root,
     *   password=,
     *   minPoolSize=5,
     *   acquireRetryAttempts=3,
     *   maxPoolSize=20
     * </connectionProperties>
     * 
* * This is most times used in conjunction with {@link #connectionDriverName}. */ @Parameter private String connectionProperties; /** the string used for passing information about the connectionProperties */ protected static final String OPTION_CONNECTION_PROPERTIES = "ConnectionProperties"; /** * List of all class path elements that will be searched for the * persistence-enabled classes and resources expected by * PCEnhancer. */ @Parameter(defaultValue="${project.compileClasspathElements}", required=true, readonly=true) protected List compileClasspathElements; /** * Setting this parameter to true will force * the execution of this mojo, even if it would get skipped usually. */ @Parameter(property="forceOpenJpaExecution", defaultValue="false", required=true) private boolean forceMojoExecution; /** * The Maven Project Object */ @Parameter(defaultValue="${project}", required=true, readonly=true) protected MavenProject project; /** the properties option is used for passing information about the persistence.xml file location */ protected static final String OPTION_PROPERTIES_FILE = "propertiesFile"; /** * The properties option is used for passing information about the persistence.xml * classpath resource and the default unit */ protected static final String OPTION_PROPERTIES = "properties"; /** * When true, skip the execution. * @since 1.0 */ @Parameter(defaultValue="false") private boolean skip; /** * default ct */ public AbstractOpenJpaMojo() { super(); } /** * The File where the class files of the entities to enhance reside * @return normaly the entity classes are located in target/classes */ protected File getEntityClasses() { return classes; } /** * This function retrieves the injected classpath elements for the current mojo. * @return List of classpath elements for the compile phase */ protected List getClasspathElements() { return compileClasspathElements; } /** * Get the options for the various OpenJPA tools. * @return populated Options */ protected abstract Options getOptions() throws MojoExecutionException; /** *

Determine if the mojo execution should get skipped.

* This is the case if: *
    *
  • {@link #skip} is true
  • *
  • if the mojo gets executed on a project with packaging type 'pom' and * {@link #forceMojoExecution} is false
  • *
* * @return true if the mojo execution should be skipped. */ protected boolean skipMojo() { if ( skip ) { getLog().info( "Skip sql execution" ); return true; } if ( !forceMojoExecution && project != null && "pom".equals( project.getPackaging() ) ) { getLog().info( "Skipping sql execution for project with packaging type 'pom'" ); return true; } return false; } /** * This function will usually get called by {@link #getOptions()} * @return the Options filled with the initial values */ protected Options createOptions() throws MojoExecutionException { Options opts = new Options(); if ( toolProperties != null ) { opts.putAll( toolProperties ); } String persistenceXmlResource = "META-INF/persistence.xml"; if ( persistenceXmlFile != null && persistenceXmlFile.length() > 0) { fixPersistenceXmlIfNeeded(Thread.currentThread().getContextClassLoader()); opts.put( OPTION_PROPERTIES_FILE, persistenceXmlFile ); getLog().debug("using special persistence XML file: " + persistenceXmlFile); persistenceXmlResource = persistenceXmlFile; } if (persistenceUnitName != null && persistenceUnitName.length() > 0) { opts.put(OPTION_PROPERTIES, persistenceXmlResource + "#" + persistenceUnitName); } else if (!new File(classes, "META-INF/persistence.xml").exists()) { // use default but try from classpath persistenceXmlFile = "META-INF/persistence.xml"; if (!fixPersistenceXmlIfNeeded(Thread.currentThread().getContextClassLoader())) { persistenceXmlFile = null; } else { opts.put( OPTION_PROPERTIES_FILE, persistenceXmlFile ); } } if ( connectionDriverName != null ) { opts.put( OPTION_CONNECTION_DRIVER_NAME, connectionDriverName ); } if ( connectionProperties != null ) { opts.put( OPTION_CONNECTION_PROPERTIES, connectionProperties ); } return opts; } /** * * * @param loader * @throws MojoExecutionException */ private boolean fixPersistenceXmlIfNeeded(final ClassLoader loader) throws MojoExecutionException { return !new File(persistenceXmlFile).exists() && (findPersistenceXmlFromLoader(loader) || findPersistenceXmlInArtifacts(project.getCompileArtifacts()) || findPersistenceXmlInArtifacts(project.getRuntimeArtifacts())); } private boolean findPersistenceXmlFromLoader(final ClassLoader loader) throws MojoExecutionException { final URL url = loader.getResource(persistenceXmlFile); if (url != null) // copy file to be sure to set persistenceXmlFile to a file { final File tmpPersistenceXml = new File(workDir, "persistence" + System.currentTimeMillis() + ".xml"); if (!tmpPersistenceXml.getParentFile().exists() && !tmpPersistenceXml.getParentFile().mkdirs()) { throw new MojoExecutionException("Can't create " + tmpPersistenceXml.getParentFile().getAbsolutePath()); } try { FileUtils.copyURLToFile(url, tmpPersistenceXml); } catch (final IOException e) { throw new MojoExecutionException(e.getMessage(), e); } persistenceXmlFile = tmpPersistenceXml.getAbsolutePath(); return true; } return false; } private boolean findPersistenceXmlInArtifacts(final List artifacts) throws MojoExecutionException { for (final Artifact artifact : artifacts) { final File file = artifact.getFile(); if (file != null && file.exists()) { try // find the persistence.xml using a fake classloader to not need to play with URLs { if (findPersistenceXmlFromLoader(new URLClassLoader(new URL[] { file.toURI().toURL() }, ClassLoader.getSystemClassLoader()))) { return true; } } catch (final MalformedURLException e) { // no-op } } } return false; } /** * This will prepare the current ClassLoader and add all jars and local * classpaths (e.g. target/classes) needed by the OpenJPA task. * * @throws MojoExecutionException on any error inside the mojo */ protected void extendRealmClasspath() throws MojoExecutionException { List urls = new ArrayList<>(); for(String fileName: getClasspathElements()) { File pathElem = new File(fileName); try { URL url = pathElem.toURI().toURL(); urls.add( url ); getLog().debug( "Added classpathElement URL " + url ); } catch ( MalformedURLException e ) { throw new MojoExecutionException( "Error in adding the classpath " + pathElem, e ); } } ClassLoader jpaRealm = new URLClassLoader( (URL[]) urls.toArray( new URL[urls.size()] ), getClass().getClassLoader() ); // set the new ClassLoader as default for this Thread Thread.currentThread().setContextClassLoader( jpaRealm ); } /** * Locates and returns a list of class files found under specified class * directory. * * @return list of class files. * @throws MojoExecutionException if there was an error scanning class file * resources. */ protected List findEntityClassFiles() throws MojoExecutionException { List files = new ArrayList<>(); try { files = (List) FileUtils.getFiles( getEntityClasses(), includes, excludes ); } catch ( IOException e ) { throw new MojoExecutionException( "Error while scanning for '" + includes + "' in " + "'" + getEntityClasses().getAbsolutePath() + "'.", e ); } return files; } /** * @param files List of files * @return the paths of the given files as String[] */ protected String[] getFilePaths( List files ) { String[] args = new String[ files.size() ]; for ( int i = 0; i < files.size(); i++ ) { File file = files.get( i ); args[ i ] = file.getAbsolutePath(); } return args; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy