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.net.URL;
29  import java.net.URLClassLoader;
30  import java.util.logging.Handler;
31  import java.util.logging.Level;
32  import java.util.logging.SimpleFormatter;
33  
34  import org.apache.maven.cli.logging.Slf4jConfiguration;
35  import org.apache.maven.cli.logging.Slf4jConfigurationFactory;
36  import org.apache.maven.shared.utils.logging.MessageUtils;
37  import org.codehaus.plexus.logging.console.ConsoleLogger;
38  import org.slf4j.ILoggerFactory;
39  import org.slf4j.Logger;
40  import org.slf4j.LoggerFactory;
41  import org.slf4j.bridge.SLF4JBridgeHandler;
42  
43  abstract class Executor
44  {
45      private static final Logger LOG = LoggerFactory.getLogger( Executor.class );
46  
47      /**
48       * This holds a strong reference in case we configured the logger to
49       * redirect to slf4j. See {@link #showPmdLog}. Without a strong reference,
50       * the logger might be garbage collected and the redirect to slf4j is gone.
51       */
52      private java.util.logging.Logger julLogger;
53  
54      protected void setupPmdLogging( boolean showPmdLog, boolean colorizedLog, String logLevel )
55      {
56          MessageUtils.setColorEnabled( colorizedLog );
57  
58          if ( !showPmdLog )
59          {
60              return;
61          }
62  
63          java.util.logging.Logger logger = java.util.logging.Logger.getLogger( "net.sourceforge.pmd" );
64  
65          boolean slf4jBridgeAlreadyAdded = false;
66          for ( Handler handler : logger.getHandlers() )
67          {
68              if ( handler instanceof SLF4JBridgeHandler )
69              {
70                  slf4jBridgeAlreadyAdded = true;
71                  break;
72              }
73          }
74  
75          if ( slf4jBridgeAlreadyAdded )
76          {
77              return;
78          }
79  
80          SLF4JBridgeHandler handler = new SLF4JBridgeHandler();
81          SimpleFormatter formatter = new SimpleFormatter();
82          handler.setFormatter( formatter );
83          logger.setUseParentHandlers( false );
84          logger.addHandler( handler );
85          handler.setLevel( Level.ALL );
86          logger.setLevel( Level.ALL );
87          julLogger = logger;
88          julLogger.fine( "Configured jul-to-slf4j bridge for " + logger.getName() );
89      }
90  
91      protected void setupLogLevel( String logLevel )
92      {
93          ILoggerFactory slf4jLoggerFactory = LoggerFactory.getILoggerFactory();
94          Slf4jConfiguration slf4jConfiguration = Slf4jConfigurationFactory
95                  .getConfiguration( slf4jLoggerFactory );
96          if ( "debug".equals( logLevel ) )
97          {
98              slf4jConfiguration
99                      .setRootLoggerLevel( Slf4jConfiguration.Level.DEBUG );
100         }
101         else if ( "info".equals( logLevel ) )
102         {
103             slf4jConfiguration
104                     .setRootLoggerLevel( Slf4jConfiguration.Level.INFO );
105         }
106         else
107         {
108             slf4jConfiguration
109                     .setRootLoggerLevel( Slf4jConfiguration.Level.ERROR );
110         }
111         slf4jConfiguration.activate();
112     }
113 
114     protected static String buildClasspath()
115     {
116         StringBuilder classpath = new StringBuilder();
117 
118         // plugin classpath needs to come first
119         ClassLoader pluginClassloader = Executor.class.getClassLoader();
120         buildClasspath( classpath, pluginClassloader );
121 
122         ClassLoader coreClassloader = ConsoleLogger.class.getClassLoader();
123         buildClasspath( classpath, coreClassloader );
124 
125         return classpath.toString();
126     }
127 
128     private static void buildClasspath( StringBuilder classpath, ClassLoader cl )
129     {
130         if ( cl instanceof URLClassLoader )
131         {
132             for ( URL url : ( (URLClassLoader) cl ).getURLs() )
133             {
134                 String urlString = url.toString();
135                 if ( urlString.startsWith( "file:" ) )
136                 {
137                     String f = urlString.substring( 5 ); //  strip "file:"
138                     classpath.append( f ).append( File.pathSeparatorChar );
139                 }
140             }
141         }
142     }
143 
144     protected static class ProcessStreamHandler implements Runnable
145     {
146         private static final int BUFFER_SIZE = 8192;
147 
148         private final BufferedInputStream in;
149         private final BufferedOutputStream out;
150 
151         public static void start( InputStream in, OutputStream out )
152         {
153             Thread t = new Thread( new ProcessStreamHandler( in, out ) );
154             t.start();
155         }
156 
157         private ProcessStreamHandler( InputStream in, OutputStream out )
158         {
159             this.in = new BufferedInputStream( in );
160             this.out = new BufferedOutputStream( out );
161         }
162 
163         @Override
164         public void run()
165         {
166             byte[] buffer = new byte[BUFFER_SIZE];
167             try
168             {
169                 int count = in.read( buffer );
170                 while ( count != -1 )
171                 {
172                     out.write( buffer, 0, count );
173                     out.flush();
174                     count = in.read( buffer );
175                 }
176                 out.flush();
177             }
178             catch ( IOException e )
179             {
180                 LOG.error( e.getMessage(), e );
181             }
182         }
183     }
184 }