Package org.jboss.forge.addon.maven.projects

Source Code of org.jboss.forge.addon.maven.projects.MavenFacetImpl$UncloseableStreamHandler

/*
* Copyright 2012 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Eclipse Public License version 1.0, available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.jboss.forge.addon.maven.projects;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;

import javax.inject.Inject;

import org.apache.maven.cli.MavenCli;
import org.apache.maven.model.Model;
import org.apache.maven.model.building.ModelProblem;
import org.apache.maven.model.building.ModelProblem.Severity;
import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
import org.apache.maven.project.ProjectBuildingException;
import org.apache.maven.project.ProjectBuildingRequest;
import org.apache.maven.project.ProjectBuildingResult;
import org.jboss.forge.addon.facets.AbstractFacet;
import org.jboss.forge.addon.maven.projects.util.NativeSystemCall;
import org.jboss.forge.addon.maven.resources.MavenModelResource;
import org.jboss.forge.addon.projects.Project;
import org.jboss.forge.addon.projects.ProjectFacet;
import org.jboss.forge.addon.resource.DirectoryResource;
import org.jboss.forge.addon.resource.ResourceFactory;
import org.jboss.forge.furnace.manager.maven.MavenContainer;
import org.jboss.forge.furnace.util.OperatingSystemUtils;
import org.jboss.forge.furnace.util.Strings;

/**
* Implementation of {@link MavenFacet}
*
* @author <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a>
* @author <a href="ggastald@redhat.com">George Gastaldi</a>
*/
public class MavenFacetImpl extends AbstractFacet<Project> implements ProjectFacet, MavenFacet
{
   private static final Logger log = Logger.getLogger(MavenFacetImpl.class.getName());

   @Inject
   private ResourceFactory factory;

   @Inject
   private MavenBuildManager buildManager;

   public ProjectBuildingRequest getRequest()
   {
      return buildManager.getProjectBuildingRequest();
   }

   public ProjectBuildingRequest getOfflineRequest()
   {
      return buildManager.getProjectBuildingRequest(isInstalled());
   }

   public ProjectBuildingRequest getBuildingRequest(final boolean offline)
   {
      return buildManager.getProjectBuildingRequest(offline);
   }

   @Override
   public boolean install()
   {
      if (!isInstalled())
      {
         MavenModelResource pom = getModelResource();
         if (!pom.createNewFile())
            throw new IllegalStateException("Could not create POM file.");
         pom.setContents(createDefaultPOM());
      }
      return isInstalled();
   }

   private String createDefaultPOM()
   {
      MavenXpp3Writer writer = new MavenXpp3Writer();
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      org.apache.maven.project.MavenProject mavenProject = new org.apache.maven.project.MavenProject();
      mavenProject.setModelVersion("4.0.0");
      try
      {
         writer.write(baos, mavenProject.getModel());
         return baos.toString();
      }
      catch (IOException e)
      {
         // Should not happen
         throw new RuntimeException("Failed to create default pom.xml", e);
      }
   }

   @Override
   public MavenModelResource getModelResource()
   {
      return getFaceted().getRoot().getChild("pom.xml").reify(MavenModelResource.class);
   }

   @Override
   public boolean isInstalled()
   {
      MavenModelResource pom = getModelResource();
      return pom != null && pom.exists();
   }

   @Override
   public Model getModel()
   {
      return getModelResource().getCurrentModel();
   }

   @Override
   public void setModel(final Model pom)
   {
      MavenXpp3Writer writer = new MavenXpp3Writer();
      ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
      MavenModelResource modelResource = getModelResource();
      try (Writer fw = new OutputStreamWriter(outputStream))
      {
         writer.write(fw, pom);
         modelResource.setContents(outputStream.toString());
      }
      catch (IOException e)
      {
         throw new RuntimeException("Could not write POM file: " + modelResource.getFullyQualifiedName(), e);
      }
      finally
      {
         buildManager.evictFromCache(modelResource);
      }
   }

   /*
    * POM manipulation methods
    */
   public synchronized ProjectBuildingResult getProjectBuildingResult() throws ProjectBuildingException
   {
      return buildManager.getProjectBuildingResult(getModelResource());
   }

   @Override
   public Map<String, String> getProperties()
   {
      Map<String, String> result = new HashMap<>();

      try
      {
         Properties properties = getProjectBuildingResult().getProject().getProperties();
         for (Entry<Object, Object> o : properties.entrySet())
         {
            result.put((String) o.getKey(), (String) o.getValue());
         }
      }
      catch (Exception e)
      {
         log.log(Level.WARNING, "Failed to resolve properties in [" + getModelResource().getFullyQualifiedName() + "].");
         log.log(Level.FINE, "Failed to resolve properties in Project [" + getModelResource().getFullyQualifiedName()
                  + "].", e);
      }

      return result;
   }

   @Override
   public String resolveProperties(String input)
   {
      String result = input;
      try
      {
         if (input != null)
         {
            Properties properties = getProjectBuildingResult().getProject().getProperties();

            for (Entry<Object, Object> e : properties.entrySet())
            {
               String key = "\\$\\{" + e.getKey().toString() + "\\}";
               Object value = e.getValue();
               result = result.replaceAll(key, value.toString());
            }
         }
      }
      catch (Exception e)
      {
         log.log(Level.WARNING, "Failed to resolve properties in [" + getModelResource().getFullyQualifiedName()
                  + "] for input value [" + input + "].");
         log.log(Level.FINE, "Failed to resolve properties in Project [" + getModelResource().getFullyQualifiedName()
                  + "].", e);
      }

      return result;
   }

   @Override
   public boolean executeMavenEmbedded(final List<String> parameters)
   {
      return executeMavenEmbedded(parameters.toArray(new String[parameters.size()]));
   }

   public boolean executeMavenEmbedded(final String[] parms)
   {
      return executeMavenEmbedded(System.out, System.err, parms);
   }

   @Override
   public boolean executeMavenEmbedded(List<String> parameters, PrintStream out, PrintStream err)
   {
      return executeMavenEmbedded(out, err, parameters.toArray(new String[parameters.size()]));
   }

   public boolean executeMavenEmbedded(final PrintStream out, final PrintStream err, String[] arguments)
   {
      List<String> list = new ArrayList<>();
      // FORGE-1912: Maven settings are not being set in embedded maven
      if (System.getProperty(MavenContainer.ALT_USER_SETTINGS_XML_LOCATION) != null)
      {
         list.add("-s");
         list.add(System.getProperty(MavenContainer.ALT_USER_SETTINGS_XML_LOCATION));
      }
      else if (System.getProperty(MavenContainer.ALT_GLOBAL_SETTINGS_XML_LOCATION) != null)
      {
         list.add("-s");
         list.add(System.getProperty(MavenContainer.ALT_GLOBAL_SETTINGS_XML_LOCATION));
      }
      if (arguments != null)
      {
         list.addAll(Arrays.asList(arguments));
      }
      return doExecuteMavenEmbedded(out, err, list);
   }

   /**
    * The embedded maven CLI uses the java logging API to output the log. <br/>
    * Since we never write the log to the console, we need register a logging handler.
    *
    * @author <a href="ggastald@redhat.com">George Gastaldi</a>
    */
   private boolean doExecuteMavenEmbedded(final PrintStream out, final PrintStream err, final List<String> list)
   {
      // Have we asked for quiet mode?
      final boolean quiet = list.contains("-q") || list.contains("--quiet");
      final String[] params = list.toArray(new String[list.size()]);
      // Get root logger. Yes, it is an empty logger, Logger.getGlobal() doesn't work here
      final Logger globalLogger = Logger.getLogger(Strings.EMPTY);
      final Handler outHandler = new UncloseableStreamHandler(out, quiet);
      try
      {
         globalLogger.addHandler(outHandler);
         int returnCode = new MavenCli().doMain(params, getFaceted().getRoot().getFullyQualifiedName(), out, err);
         return returnCode == 0;
      }
      finally
      {
         globalLogger.removeHandler(outHandler);
      }
   }

   @Override
   public boolean executeMaven(final List<String> parameters)
   {
      return executeMaven(parameters.toArray(new String[parameters.size()]));
   }

   public boolean executeMaven(final String[] selected)
   {
      // return executeMaven(new NullOutputStream(), selected);
      return executeMaven(System.out, selected);
   }

   public boolean executeMaven(final OutputStream out, final String[] arguments)
   {
      List<String> list = new ArrayList<>();
      // FORGE-1912: Maven settings are not being set in embedded maven
      if (System.getProperty(MavenContainer.ALT_USER_SETTINGS_XML_LOCATION) != null)
      {
         list.add("-s");
         list.add(System.getProperty(MavenContainer.ALT_USER_SETTINGS_XML_LOCATION));
      }
      else if (System.getProperty(MavenContainer.ALT_GLOBAL_SETTINGS_XML_LOCATION) != null)
      {
         list.add("-s");
         list.add(System.getProperty(MavenContainer.ALT_GLOBAL_SETTINGS_XML_LOCATION));
      }
      if (arguments != null)
      {
         list.addAll(Arrays.asList(arguments));
      }
      String[] params = list.toArray(new String[list.size()]);
      try
      {
         DirectoryResource directory = getFaceted().getRoot().reify(DirectoryResource.class);
         if (directory == null)
            throw new IllegalStateException("Cannot execute maven build on resources that are not File-based.");
         int returnValue = NativeSystemCall.execFromPath(getMvnCommand(), params, out, directory);
         if (returnValue == 0)
            return true;
         else
            return executeMavenEmbedded(params);
      }
      catch (IOException e)
      {
         return executeMavenEmbedded(params);
      }
   }

   private String getMvnCommand()
   {
      return OperatingSystemUtils.isWindows() ? "mvn.bat" : "mvn";
   }

   @Override
   public DirectoryResource getLocalRepositoryDirectory()
   {
      return factory.create(buildManager.getLocalRepositoryDirectory()).reify(DirectoryResource.class);
   }

   @Override
   public boolean isModelValid()
   {
      try
      {
         boolean valid = true;
         List<ModelProblem> problems = getProjectBuildingResult().getProblems();
         for (ModelProblem problem : problems)
         {
            // It is valid only if all messages are just warnings
            valid &= Severity.WARNING.equals(problem.getSeverity());
         }
         return valid;
      }
      catch (ProjectBuildingException e)
      {
         return false;
      }
   }

   /**
    * A {@link Handler} implementation that writes to a {@link PrintStream}
    *
    * Used in {@link MavenFacetImpl#executeMavenEmbedded(PrintStream, PrintStream, String[])}
    *
    * @author <a href="ggastald@redhat.com">George Gastaldi</a>
    */
   private static class UncloseableStreamHandler extends Handler
   {
      private final PrintStream out;
      private final boolean quiet;

      public UncloseableStreamHandler(PrintStream out, boolean quiet)
      {
         super();
         this.out = out;
         this.quiet = quiet;
      }

      @Override
      public void publish(LogRecord record)
      {
         // Write only if quiet is false
         if (!quiet && isLoggable(record))
         {
            out.printf("[%s] %s%n", record.getLevel(), record.getMessage());
         }
      }

      @Override
      public boolean isLoggable(LogRecord record)
      {
         if (super.isLoggable(record))
         {
            switch (record.getMessage())
            {
            // Avoid unwanted warning messages
            case "setRootLoggerLevel: operation not supported":
            case "reset(): operation not supported":
               break;
            default:
               return true;
            }
         }
         return false;
      }

      @Override
      public void flush()
      {
         out.flush();
      }

      @Override
      public void close()
      {
         // Never close
      }
   }

}
TOP

Related Classes of org.jboss.forge.addon.maven.projects.MavenFacetImpl$UncloseableStreamHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.