1   package org.codehaus.mojo.rmic;
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  import org.apache.maven.plugin.logging.Log;
26  import org.codehaus.plexus.compiler.CompilerException;
27  import org.codehaus.plexus.util.StringUtils;
28  
29  import java.io.File;
30  import java.io.OutputStream;
31  import java.lang.reflect.Constructor;
32  import java.lang.reflect.InvocationTargetException;
33  import java.lang.reflect.Method;
34  import java.net.URL;
35  import java.net.URLClassLoader;
36  import java.util.ArrayList;
37  import java.util.List;
38  
39  
40  
41  
42  abstract class AbstractRmiCompiler implements RmiCompiler
43  {
44      private Log logger;
45  
46      
47      private static ClassLoaderFacade classLoaderFacade = new ClassLoaderFacadeImpl();
48  
49      public void setLog( Log log )
50      {
51          logger = log;
52      }
53  
54      public Log getLog()
55      {
56          return logger;
57      }
58  
59      
60  
61  
62  
63      static ClassLoaderFacade getClassLoaderFacade()
64      {
65          return classLoaderFacade;
66      }
67  
68      
69  
70  
71  
72  
73  
74      public void execute( RmiCompilerConfiguration rmiConfig )
75          throws RmiCompilerException
76      {
77          
78          
79          
80  
81          List<String> arguments = new ArrayList<>();
82  
83          List<String> classpathList = rmiConfig.getClasspathEntries();
84          if ( classpathList.size() > 0 )
85          {
86              arguments.add( "-classpath" );
87              arguments.add( buildClasspath( classpathList ) );
88          }
89  
90          arguments.add( "-d" );
91          arguments.add( rmiConfig.getOutputLocation() );
92  
93          if ( rmiConfig.getVersion() != null )
94          {
95              arguments.add( "-v" + rmiConfig.getVersion() );
96          }
97  
98          if ( rmiConfig.isIiop() )
99          {
100             arguments.add( "-iiop" );
101 
102             if ( rmiConfig.isPoa() )
103             {
104                 arguments.add( "-poa" );
105             }
106             if ( rmiConfig.isNoLocalStubs() )
107             {
108                 arguments.add( "-nolocalstubs" );
109             }
110         }
111         else
112         {
113             if ( rmiConfig.isPoa() )
114             {
115                 throw new RmiCompilerException( "IIOP must be enabled in order to use the POA option" );
116             }
117 
118         }
119 
120         if ( rmiConfig.isIdl() )
121         {
122             arguments.add( "-idl" );
123             if ( rmiConfig.isNoValueMethods() )
124             {
125                 arguments.add( "-noValueMethods" );
126             }
127         }
128 
129         if ( rmiConfig.isKeep() )
130         {
131             arguments.add( "-keep" );
132         }
133 
134         if ( getLog().isDebugEnabled() || rmiConfig.isVerbose() )
135         {
136             arguments.add( "-verbose" );
137         }
138         else if ( rmiConfig.isNowarn() )
139         {
140             arguments.add( "-nowarn" );
141         }
142 
143         for ( File remoteClass : rmiConfig.getSourceFiles() )
144         {
145             arguments.add( fileToClassName( remoteClass.getPath() ) );
146         }
147 
148         String[] args = arguments.toArray( new String[arguments.size()] );
149 
150         if ( getLog().isDebugEnabled() )
151         {
152             getLog().debug( "rmic arguments: " );
153 
154             for ( String arg : args )
155             {
156                 getLog().debug( arg );
157             }
158         }
159 
160         try
161         {
162             compileInProcess( args );
163         }
164         catch ( CompilerException e )
165         {
166             throw new RmiCompilerException( e.getMessage(), e );
167         }
168     }
169 
170     private String buildClasspath( List<String> classpathList )
171     {
172         StringBuilder classpath = new StringBuilder( classpathList.get( 0 ) );
173         for ( int i = 1; i < classpathList.size(); i++ )
174         {
175             classpath.append( File.pathSeparator ).append( classpathList.get( i ) );
176         }
177 
178         return classpath.toString();
179     }
180 
181     private static String fileToClassName( String classFileName )
182     {
183         return StringUtils.replace( StringUtils.replace( classFileName, ".class", "" ), File.separator, "." );
184     }
185 
186     protected void compileInProcess( String[] args )
187         throws CompilerException
188     {
189         final Class<?> mainClass = createMainClass();
190         final Thread thread = Thread.currentThread();
191         final ClassLoader contextClassLoader = thread.getContextClassLoader();
192         thread.setContextClassLoader( mainClass.getClassLoader() );
193         try
194         {
195             compileInProcess0( mainClass, args );
196         }
197         finally
198         {
199             thread.setContextClassLoader( contextClassLoader );
200         }
201     }
202 
203     protected abstract Class<?> createMainClass()
204         throws CompilerException;
205 
206     private static void compileInProcess0( Class<?> rmicMainClass, String[] args )
207         throws CompilerException
208     {
209         try
210         {
211             Constructor<?> constructor = rmicMainClass.getConstructor( OutputStream.class, String.class );
212 
213             Object main = constructor.newInstance( System.out, "rmic" );
214 
215             Method compile = rmicMainClass.getMethod( "compile", String[].class );
216 
217             compile.invoke( main, new Object[] { args } );
218         }
219         catch ( NoSuchMethodException | IllegalAccessException | IllegalArgumentException
220                 | InstantiationException | InvocationTargetException e )
221         {
222             throw new CompilerException( "Error while executing the compiler.", e );
223         }
224     }
225 
226     
227 
228 
229     interface ClassLoaderFacade
230     {
231         
232 
233 
234 
235 
236         void prependUrls( URL... urls );
237 
238         
239 
240 
241 
242 
243 
244 
245         Class<?> loadClass( String rmiCompilerClass ) throws ClassNotFoundException;
246     }
247 
248     
249 
250 
251     private static class ClassLoaderFacadeImpl implements ClassLoaderFacade
252     {
253         ClassLoader classLoader = getClass().getClassLoader();
254 
255         public void prependUrls( URL... urls )
256         {
257             classLoader = new URLClassLoader( urls, classLoader );
258         }
259 
260         public Class<?> loadClass( String rmiCompilerClass ) throws ClassNotFoundException
261         {
262             return classLoader.loadClass( rmiCompilerClass );
263         }
264 
265     }
266 }