 
                        
        
                        
        org.apache.myfaces.trinidadbuild.plugin.jdeveloper.JDeveloperMojo 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.myfaces.trinidadbuild.plugin.jdeveloper;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.Resource;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.util.DirectoryScanner;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
import org.codehaus.plexus.util.xml.Xpp3DomWriter;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
/**
 * @version $Id$
 * @goal jdev
 * @execute phase=process-resources
 * @requiresDependencyResolution test
 * @description Goal which generates the JDeveloper Workspace
 */
public class JDeveloperMojo extends AbstractMojo
{
  /**
   * @parameter
   */
  private String[] libraries;
  /**
   * @parameter
   */
  private File[] sourceRoots;
  /**
   * @parameter
   */
  private File[] testSourceRoots;
  /**
   * @parameter
   */
  private File[] resourceRoots;
  /**
   * @parameter
   */
  private File[] testResourceRoots;
  /**
   * @parameter expression="${force}"
   */
  private boolean force;
  /**
   * @parameter expression="10.1.3.0.4"
   * @required
   * @readonly
   */
  private String release;
  /**
   * @parameter expression="${project}"
   * @required
   * @readonly
   */
  private MavenProject project;
  /**
   * @parameter expression="${reactorProjects}"
   * @required
   * @readonly
   */
  private List reactorProjects;
  /**
   * Execute the Mojo.
   */
  public void execute() throws MojoExecutionException
  {
    try
    {
      generateWorkspace();
      generateProject();
      generateTestProject();
    }
    catch (IOException e)
    {
      throw new MojoExecutionException(e.getMessage());
    }
  }
  private void generateWorkspace() throws MojoExecutionException, IOException
  {
    if (!project.getCollectedProjects().isEmpty())
    {
      getLog().info("Generating JDeveloper " + release +
                    " workspace: " + project.getArtifactId());
      File workspaceFile = getJWorkspaceFile(project);
      try
      {
        Xpp3Dom workspaceDOM = readWorkspaceDOM(workspaceFile);
        replaceProjects(workspaceFile.getParentFile(), workspaceDOM);
        writeDOM(workspaceFile, workspaceDOM);
      }
      catch (XmlPullParserException e)
      {
        throw new MojoExecutionException("Error generating project", e);
      }
    }
  }
  private void generateProject() throws IOException, MojoExecutionException
  {
    if (!"pom".equals(project.getPackaging()))
    {
      File projectFile = getJProjectFile(project);
      // TODO: read configuration for war:war goal
      File webappDir = new File(project.getBasedir(), "src/main/webapp");
      // TODO: read configuration for compiler:complie goal
      File outputDir = new File(project.getBuild().getDirectory(), "classes");
      MavenProject executionProject = project.getExecutionProject();
      List compileSourceRoots = executionProject.getCompileSourceRoots();
      if (sourceRoots != null)
      {
        for (int i=0; i < sourceRoots.length; i++)
        {
          compileSourceRoots.add(sourceRoots[i].getAbsolutePath());
        }
      }
      List compileResourceRoots = executionProject.getResources();
      if (resourceRoots != null)
      {
        for (int i=0; i < resourceRoots.length; i++)
        {
          Resource resource = new Resource();
          resource.setDirectory(resourceRoots[i].getAbsolutePath());
          compileResourceRoots.add(resource);
        }
      }
      getLog().info("Generating JDeveloper " + release +
                    " Project " + project.getArtifactId());
      // Note: include "compile", "provided", "system" and "runtime" scopes
      Set compileArtifacts = new LinkedHashSet();
      compileArtifacts.addAll(project.getCompileArtifacts());
      compileArtifacts.addAll(project.getRuntimeArtifacts());
      // Note: separate "runtime" vs. "compile" dependencies in JDeveloper?
      generateProject(projectFile,
                      project.getArtifactId(),
                      project.getPackaging(),
                      project.getDependencies(),
                      new ArrayList(compileArtifacts),
                      compileSourceRoots,
                      compileResourceRoots,
                      Collections.singletonList(webappDir.getPath()),
                      outputDir);
    }
  }
  private void generateTestProject() throws IOException, MojoExecutionException
  {
    if (!"pom".equals(project.getPackaging()))
    {
      File projectFile = getJProjectTestFile(project);
      File webappDir = new File(project.getBasedir(), "src/test/webapp");
      // TODO: read configuration for compiler:testCompile goal
      File outputDir = new File(project.getBuild().getDirectory(), "test-classes");
      // self dependency needed for test project
      List testDependencies = new ArrayList(project.getTestDependencies());
      Dependency selfDependency = new Dependency();
      selfDependency.setArtifactId(project.getArtifactId());
      selfDependency.setGroupId(project.getGroupId());
      selfDependency.setType(project.getPackaging());
      testDependencies.add(selfDependency);
      MavenProject executionProject = project.getExecutionProject();
      List compileSourceRoots = executionProject.getTestCompileSourceRoots();
      if (testSourceRoots != null)
      {
        for (int i=0; i < testSourceRoots.length; i++)
        {
          compileSourceRoots.add(testSourceRoots[i].getAbsolutePath());
        }
      }
      List compileResourceRoots = executionProject.getTestResources();
      if (testResourceRoots != null)
      {
        for (int i=0; i < testResourceRoots.length; i++)
        {
          Resource resource = new Resource();
          resource.setDirectory(testSourceRoots[i].getAbsolutePath());
          compileResourceRoots.add(resource);
        }
      }
      getLog().info("Generating JDeveloper " + release +
                    " Project " + project.getArtifactId() + "-test");
      // Note: all artifacts implicitly included in "test" scope
      generateProject(projectFile,
                      project.getArtifactId() + "-test",
                      project.getPackaging(),
                      testDependencies,
                      project.getTestArtifacts(),
                      compileSourceRoots,
                      compileResourceRoots,
                      Collections.singletonList(webappDir.getPath()),
                      outputDir);
    }
  }
  private void generateProject(
    File   projectFile,
    String projectName,
    String packaging,
    List   dependencies,
    List   artifacts,
    List   sourceRoots,
    List   resourceRoots,
    List   webSourceRoots,
    File   outputDir) throws IOException, MojoExecutionException
  {
    try
    {
      File projectDir = projectFile.getParentFile();
      Xpp3Dom projectDOM = readProjectDOM(projectFile);
      replaceWebappInfo(projectName, projectDOM);
      replaceSourcePaths(projectDir, sourceRoots, resourceRoots, projectDOM);
      //replaceResourcePaths(projectDir, resourceRoots, projectDOM);
      replaceWebSourcePaths(projectDir, webSourceRoots, projectDOM);
      replaceDependencies(projectDir, dependencies, projectDOM);
      replaceLibraries(projectDir, artifacts, projectDOM);
      replaceOutputDirectory(projectDir, outputDir, projectDOM);
      writeDOM(projectFile, projectDOM);
      if ("war".equals(packaging))
        copyTagLibraries(projectDir, dependencies, artifacts);
    }
    catch (XmlPullParserException e)
    {
      throw new MojoExecutionException("Error generating project", e);
    }
  }
  private void replaceProjects(
    File    workspaceDir,
    Xpp3Dom workspaceDOM) throws XmlPullParserException
  {
    // /jws:workspace
    //   /list[@n="listOfChildren"]
    Xpp3Dom sourceDOM = workspaceDOM.getChild("list");
    // 
    //    
    Xpp3Dom targetDOM = new Xpp3Dom("list");
    for (Iterator i = project.getCollectedProjects().iterator(); i.hasNext();)
    {
      MavenProject collectedProject = (MavenProject)i.next();
      File projectFile = getJProjectFile(collectedProject);
      targetDOM.addChild(createProjectReferenceDOM(workspaceDir, projectFile));
      File testProjectFile = getJProjectTestFile(collectedProject);
      targetDOM.addChild(createProjectReferenceDOM(workspaceDir, testProjectFile));
    }
    // TODO: use a better merge algorithm
    removeChildren(sourceDOM);
    // make sure to pass Boolean.FALSE to allow
    // multiple child elements with the same name
    Xpp3Dom.mergeXpp3Dom(sourceDOM, targetDOM, Boolean.FALSE);
  }
  private void replaceWebSourcePaths(
    File    projectDir,
    List    sourceRoots,
    Xpp3Dom projectDOM) throws XmlPullParserException
  {
    // /jpr:project
    //   /hash[@n="oracle.jdeveloper.model.J2eeSettings"]
    //     /hash[@n="webContentSet"]
    //       /list[@n="url-path"]
    Xpp3Dom pathsDOM =
      findNamedChild(projectDOM, "hash", "oracle.jdeveloper.model.J2eeSettings");
    Xpp3Dom contentSetDOM =
      findNamedChild(pathsDOM, "hash", "webContentSet");
    Xpp3Dom sourceDOM =
      findNamedChild(contentSetDOM, "list", "url-path");
    //
    // 
    //   
    //     
// 
    //
     // sort the artifacts
     Collections.sort(artifacts, new Comparator() {
       public int compare(Object a, Object b)
       {
         Artifact arta = (Artifact)a;
         Artifact artb = (Artifact)b;
         return arta.getId().compareTo(artb.getId());
       }
     });
    List libraryRefs = new LinkedList();
    for (Iterator i = artifacts.iterator(); i.hasNext();)
    {
      Artifact artifact = (Artifact)i.next();
      if (!isDependentProject(artifact.getDependencyConflictId()))
      {
        String id = artifact.getId();
        String path = getRelativeFile(projectDir, artifact.getFile());
        // libraryReferences entry
        Xpp3Dom hashDOM = new Xpp3Dom("hash");
        Xpp3Dom listDOM = new Xpp3Dom("list");
        listDOM.setAttribute("n", "classPath");
        Xpp3Dom urlDOM = new Xpp3Dom("url");
        urlDOM.setAttribute("path", path);
        urlDOM.setAttribute("jar-entry", "");
        listDOM.addChild(urlDOM);
        hashDOM.addChild(listDOM);
        Xpp3Dom valueDOM = new Xpp3Dom("value");
        valueDOM.setAttribute("n", "deployedByDefault");
        valueDOM.setAttribute("v", "true");
        hashDOM.addChild(valueDOM);
        valueDOM = new Xpp3Dom("value");
        valueDOM.setAttribute("n", "description");
        valueDOM.setAttribute("v", id);
        hashDOM.addChild(valueDOM);
        valueDOM = new Xpp3Dom("value");
        valueDOM.setAttribute("n", "id");
        valueDOM.setAttribute("v", id);
        hashDOM.addChild(valueDOM);
        targetDefsDOM.addChild(hashDOM);
        libraryRefs.add(id);
      }
    }
    // add manually defined libraries
    if (libraries != null)
    {
      for (int i=0; i < libraries.length; i++)
      {
        libraryRefs.add(0, libraries[i]);
      }
    }
    //
    // libraryReferences
    //
    // 
    //    
    //
    Collections.sort(libraryRefs);
    for (Iterator i = libraryRefs.iterator(); i.hasNext();)
    {
      String id = (String)i.next();
      // libraryDefinitions entry
      Xpp3Dom hashDOM = new Xpp3Dom("hash");
      Xpp3Dom valueDOM = new Xpp3Dom("value");
      valueDOM.setAttribute("n", "id");
      valueDOM.setAttribute("v", id);
      hashDOM.addChild(valueDOM);
      valueDOM = new Xpp3Dom("value");
      valueDOM.setAttribute("n", "isJDK");
      valueDOM.setAttribute("v", "false");
      hashDOM.addChild(valueDOM);
      targetRefsDOM.addChild(hashDOM);
    }
    // First, add JSP Runtime dependency if src/main/webapp exists
    // TODO: use a better merge algorithm
    removeChildren(sourceDefsDOM);
    removeChildren(sourceRefsDOM);
    // make sure to pass Boolean.FALSE to allow
    // multiple child elements with the same name
    Xpp3Dom.mergeXpp3Dom(sourceDefsDOM, targetDefsDOM, Boolean.FALSE);
    Xpp3Dom.mergeXpp3Dom(sourceRefsDOM, targetRefsDOM, Boolean.FALSE);
  }
  private void copyTagLibraries(
    File projectDir,
    List dependencies,
    List artifacts) throws IOException
  {
    File targetDir = new File(projectDir, "src/main/webapp/WEB-INF");
    for (Iterator i = dependencies.iterator(); i.hasNext();)
    {
      Dependency dependency = (Dependency)i.next();
      MavenProject dependentProject = findDependentProject(dependency.getManagementKey());
      if (dependentProject != null)
      {
        List resourceRoots = dependentProject.getResources();
        for (Iterator j = resourceRoots.iterator(); j.hasNext();)
        {
          Resource resource = (Resource)j.next();
          String resourceRoot = resource.getDirectory();
          File resourceDirectory = new File(resourceRoot);
          if (resourceDirectory.exists())
          {
            DirectoryScanner scanner = new DirectoryScanner();
            scanner.setBasedir(resourceRoot);
            scanner.addDefaultExcludes();
            scanner.setIncludes(new String[] { "META-INF/*.tld" });
            scanner.scan();
            String[] tldFiles = scanner.getIncludedFiles();
            for (int k=0; k < tldFiles.length; k++)
            {
              File sourceFile = new File(resourceDirectory, tldFiles[k]);
              File targetFile = new File(targetDir, sourceFile.getName());
              if (targetFile.exists())
                targetFile.delete();
              FileUtils.copyFile(sourceFile, targetFile);
            }
          }
        }
      }
    }
    Map sourceMap = new TreeMap();
    for (Iterator i = artifacts.iterator(); i.hasNext();)
    {
      Artifact artifact = (Artifact)i.next();
      if (!isDependentProject(artifact.getDependencyConflictId()) &&
          "jar".equals(artifact.getType()))
      {
        File file = artifact.getFile();
        JarFile jarFile = new JarFile(file);
        Enumeration jarEntries = jarFile.entries();
        while (jarEntries.hasMoreElements())
        {
          JarEntry jarEntry = (JarEntry)jarEntries.nextElement();
          String name = jarEntry.getName();
          if (name.startsWith("META-INF/") && name.endsWith(".tld"))
          {
             List taglibs = (List) sourceMap.get(name);
             if (taglibs == null)
             {
                taglibs = new ArrayList();
                sourceMap.put(name, taglibs);
             }
             taglibs.add(file);
          }
        }
      }
    }
    for (Iterator i = sourceMap.entrySet().iterator(); i.hasNext();)
    {
      Map.Entry e = (Map.Entry) i.next();
      List taglibs = (List) e.getValue();
      String name = (String) e.getKey();
      
      for (Iterator ti = taglibs.iterator(); ti.hasNext();)
      {
        File file = (File) ti.next();
        File sourceFile = new File(name);
        StringBuffer buff = new StringBuffer(sourceFile.getName());
        if (taglibs.size() > 1)
        {
          String jarName = file.getName().substring(0, file.getName().length() - ".jar".length());
          buff.insert(buff.length() - ".tld".length(), "-" + jarName);
        }
        URL jarURL = file.toURL();
        URL sourceURL = new URL("jar:" + jarURL.toExternalForm() + "!/" + name);
        File targetFile = new File(targetDir, buff.toString());
        if (targetFile.exists())
          targetFile.delete();
        FileUtils.copyURLToFile(sourceURL, targetFile);
        targetFile.setReadOnly();
      }
    }
  }
  
  private void replaceOutputDirectory(
    File    projectDir,
    File    outputDir,
    Xpp3Dom projectDOM) throws XmlPullParserException
  {
    // /jpr:project
    //   /hash[@n="oracle.jdevimpl.config.JProjectPaths"]
    //       /url[@n="outputDirectory"]
    Xpp3Dom projectPathsDOM =
      findNamedChild(projectDOM, "hash", "oracle.jdevimpl.config.JProjectPaths");
    Xpp3Dom sourceDOM =
      findNamedChild(projectPathsDOM, "url", "outputDirectory");
    //
    // © 2015 - 2025 Weber Informatics LLC | Privacy Policy