View Javadoc
1   package org.apache.maven.plugins.pmd.exec;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.BufferedInputStream;
23  import java.io.BufferedOutputStream;
24  import java.io.File;
25  import java.io.IOException;
26  import java.io.InputStream;
27  import java.io.OutputStream;
28  import java.io.UnsupportedEncodingException;
29  import java.net.URL;
30  import java.net.URLClassLoader;
31  import java.net.URLDecoder;
32  import java.nio.charset.StandardCharsets;
33  import java.util.logging.Handler;
34  import java.util.logging.Level;
35  import java.util.logging.SimpleFormatter;
36  
37  import org.apache.maven.cli.logging.Slf4jConfiguration;
38  import org.apache.maven.cli.logging.Slf4jConfigurationFactory;
39  import org.apache.maven.shared.utils.logging.MessageUtils;
40  import org.codehaus.plexus.logging.console.ConsoleLogger;
41  import org.slf4j.ILoggerFactory;
42  import org.slf4j.Logger;
43  import org.slf4j.LoggerFactory;
44  import org.slf4j.bridge.SLF4JBridgeHandler;
45  
46  abstract class Executor
47  {
48      private static final Logger LOG = LoggerFactory.getLogger( Executor.class );
49  
50      /**
51       * This holds a strong reference in case we configured the logger to
52       * redirect to slf4j. See {@link #showPmdLog}. Without a strong reference,
53       * the logger might be garbage collected and the redirect to slf4j is gone.
54       */
55      private java.util.logging.Logger julLogger;
56  
57      protected void setupPmdLogging( boolean showPmdLog, boolean colorizedLog, String logLevel )
58      {
59          MessageUtils.setColorEnabled( colorizedLog );
60  
61          if ( !showPmdLog )
62          {
63              return;
64          }
65  
66          java.util.logging.Logger logger = java.util.logging.Logger.getLogger( "net.sourceforge.pmd" );
67  
68          boolean slf4jBridgeAlreadyAdded = false;
69          for ( Handler handler : logger.getHandlers() )
70          {
71              if ( handler instanceof SLF4JBridgeHandler )
72              {
73                  slf4jBridgeAlreadyAdded = true;
74                  break;
75              }
76          }
77  
78          if ( slf4jBridgeAlreadyAdded )
79          {
80              return;
81          }
82  
83          SLF4JBridgeHandler handler = new SLF4JBridgeHandler();
84          SimpleFormatter formatter = new SimpleFormatter();
85          handler.setFormatter( formatter );
86          logger.setUseParentHandlers( false );
87          logger.addHandler( handler );
88          handler.setLevel( Level.ALL );
89          logger.setLevel( Level.ALL );
90          julLogger = logger;
91          julLogger.fine( "Configured jul-to-slf4j bridge for " + logger.getName() );
92      }
93  
94      protected void setupLogLevel( String logLevel )
95      {
96          ILoggerFactory slf4jLoggerFactory = LoggerFactory.getILoggerFactory();
97          Slf4jConfiguration slf4jConfiguration = Slf4jConfigurationFactory
98                  .getConfiguration( slf4jLoggerFactory );
99          if ( "debug".equals( logLevel ) )
100         {
101             slf4jConfiguration
102                     .setRootLoggerLevel( Slf4jConfiguration.Level.DEBUG );
103         }
104         else if ( "info".equals( logLevel ) )
105         {
106             slf4jConfiguration
107                     .setRootLoggerLevel( Slf4jConfiguration.Level.INFO );
108         }
109         else
110         {
111             slf4jConfiguration
112                     .setRootLoggerLevel( Slf4jConfiguration.Level.ERROR );
113         }
114         slf4jConfiguration.activate();
115     }
116 
117     protected static String buildClasspath()
118     {
119         StringBuilder classpath = new StringBuilder();
120 
121         // plugin classpath needs to come first
122         ClassLoader pluginClassloader = Executor.class.getClassLoader();
123         buildClasspath( classpath, pluginClassloader );
124 
125         ClassLoader coreClassloader = ConsoleLogger.class.getClassLoader();
126         buildClasspath( classpath, coreClassloader );
127 
128         return classpath.toString();
129     }
130 
131     static void buildClasspath( StringBuilder classpath, ClassLoader cl )
132     {
133         if ( cl instanceof URLClassLoader )
134         {
135             for ( URL url : ( (URLClassLoader) cl ).getURLs() )
136             {
137                 if ( "file".equalsIgnoreCase( url.getProtocol() ) )
138                 {
139                     try
140                     {
141                         String filename = URLDecoder.decode( url.getPath(), StandardCharsets.UTF_8.name() );
142                         classpath.append( new File( filename ).getPath() ).append( File.pathSeparatorChar );
143                     }
144                     catch ( UnsupportedEncodingException e )
145                     {
146                         LOG.warn( "Ignoring " + url + " in classpath due to UnsupportedEncodingException", e );
147                     }
148                 }
149             }
150         }
151     }
152 
153     protected static class ProcessStreamHandler implements Runnable
154     {
155         private static final int BUFFER_SIZE = 8192;
156 
157         private final BufferedInputStream in;
158         private final BufferedOutputStream out;
159 
160         public static void start( InputStream in, OutputStream out )
161         {
162             Thread t = new Thread( new ProcessStreamHandler( in, out ) );
163             t.start();
164         }
165 
166         private ProcessStreamHandler( InputStream in, OutputStream out )
167         {
168             this.in = new BufferedInputStream( in );
169             this.out = new BufferedOutputStream( out );
170         }
171 
172         @Override
173         public void run()
174         {
175             byte[] buffer = new byte[BUFFER_SIZE];
176             try
177             {
178                 int count = in.read( buffer );
179                 while ( count != -1 )
180                 {
181                     out.write( buffer, 0, count );
182                     out.flush();
183                     count = in.read( buffer );
184                 }
185                 out.flush();
186             }
187             catch ( IOException e )
188             {
189                 LOG.error( e.getMessage(), e );
190             }
191         }
192     }
193 }