1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 package org.jomc.cli.commands;
32
33 import java.io.File;
34 import java.io.IOException;
35 import java.net.URL;
36 import java.util.Arrays;
37 import java.util.Enumeration;
38 import java.util.Iterator;
39 import java.util.List;
40 import java.util.Locale;
41 import java.util.logging.Level;
42 import javax.xml.bind.JAXBElement;
43 import javax.xml.bind.JAXBException;
44 import javax.xml.bind.Marshaller;
45 import javax.xml.bind.Unmarshaller;
46 import javax.xml.bind.util.JAXBResult;
47 import javax.xml.bind.util.JAXBSource;
48 import javax.xml.transform.Transformer;
49 import javax.xml.transform.TransformerException;
50 import javax.xml.transform.stream.StreamSource;
51 import org.apache.commons.cli.CommandLine;
52 import org.apache.commons.cli.Option;
53 import org.jomc.model.Module;
54 import org.jomc.model.Modules;
55 import org.jomc.model.ObjectFactory;
56 import org.jomc.model.modlet.DefaultModelProvider;
57 import org.jomc.modlet.ModelContext;
58 import org.jomc.modlet.ModelException;
59 import org.jomc.modlet.ModelValidationReport;
60
61
62
63
64
65
66 public final class MergeModulesCommand extends AbstractModelCommand
67 {
68
69
70
71
72 public MergeModulesCommand()
73 {
74 super();
75 }
76
77 @Override
78 public org.apache.commons.cli.Options getOptions()
79 {
80 final org.apache.commons.cli.Options options = super.getOptions();
81 Option option = (Option) Options.DOCUMENT_OPTION.clone();
82 option.setRequired( true );
83 options.addOption( option );
84
85 options.addOption( Options.DOCUMENT_ENCODING_OPTION );
86 options.addOption( Options.STYLESHEET_OPTION );
87
88 option = (Option) Options.MODULE_OPTION.clone();
89 option.setRequired( true );
90 options.addOption( option );
91
92 options.addOption( Options.MODULE_VERSION_OPTION );
93 options.addOption( Options.MODULE_VENDOR_OPTION );
94 options.addOption( Options.MODULE_INCLUDES_OPTION );
95 options.addOption( Options.MODULE_EXCLUDES_OPTION );
96 options.addOption( Options.RESOURCES_OPTION );
97 return options;
98 }
99
100 public String getName()
101 {
102 return "merge-modules";
103 }
104
105 public String getAbbreviatedName()
106 {
107 return "mm";
108 }
109
110 public String getShortDescription( final Locale locale )
111 {
112 return Messages.getMessage( "mergeModulesShortDescription" );
113 }
114
115 public String getLongDescription( final Locale locale )
116 {
117 return null;
118 }
119
120 protected void executeCommand( final CommandLine commandLine ) throws CommandExecutionException
121 {
122 if ( commandLine == null )
123 {
124 throw new NullPointerException( "commandLine" );
125 }
126
127 CommandLineClassLoader classLoader = null;
128
129 try
130 {
131 classLoader = new CommandLineClassLoader( commandLine );
132 final Modules modules = new Modules();
133 final ModelContext context = this.createModelContext( commandLine, classLoader );
134 final String model = this.getModel( commandLine );
135 final Marshaller marshaller = context.createMarshaller( model );
136 final Unmarshaller unmarshaller = context.createUnmarshaller( model );
137
138 if ( !commandLine.hasOption( Options.NO_MODLET_RESOURCE_VALIDATION_OPTION.getOpt() ) )
139 {
140 unmarshaller.setSchema( context.createSchema( model ) );
141 }
142
143 File stylesheetFile = null;
144 if ( commandLine.hasOption( Options.STYLESHEET_OPTION.getOpt() ) )
145 {
146 stylesheetFile = new File( commandLine.getOptionValue( Options.STYLESHEET_OPTION.getOpt() ) );
147 }
148
149 String moduleVersion = null;
150 if ( commandLine.hasOption( Options.MODULE_VERSION_OPTION.getOpt() ) )
151 {
152 moduleVersion = commandLine.getOptionValue( Options.MODULE_VERSION_OPTION.getOpt() );
153 }
154
155 String moduleVendor = null;
156 if ( commandLine.hasOption( Options.MODULE_VENDOR_OPTION.getOpt() ) )
157 {
158 moduleVendor = commandLine.getOptionValue( Options.MODULE_VENDOR_OPTION.getOpt() );
159 }
160
161 if ( commandLine.hasOption( Options.DOCUMENTS_OPTION.getOpt() ) )
162 {
163 for ( final File f : this.getDocumentFiles( commandLine ) )
164 {
165 if ( this.isLoggable( Level.FINEST ) )
166 {
167 this.log( Level.FINEST, Messages.getMessage( "readingResource", f.getAbsolutePath() ), null );
168 }
169
170 Object o = unmarshaller.unmarshal( f );
171 if ( o instanceof JAXBElement<?> )
172 {
173 o = ( (JAXBElement<?>) o ).getValue();
174 }
175
176 if ( o instanceof Module )
177 {
178 modules.getModule().add( (Module) o );
179 }
180 else if ( o instanceof Modules )
181 {
182 modules.getModule().addAll( ( (Modules) o ).getModule() );
183 }
184 else if ( this.isLoggable( Level.WARNING ) )
185 {
186 this.log( Level.WARNING,
187 Messages.getMessage( "failureProcessing", f.getAbsolutePath(), o.toString() ),
188 null );
189
190 }
191 }
192 }
193
194 if ( commandLine.hasOption( Options.CLASSPATH_OPTION.getOpt() ) )
195 {
196 String[] resourceNames = null;
197
198 if ( commandLine.hasOption( Options.RESOURCES_OPTION.getOpt() ) )
199 {
200 resourceNames = commandLine.getOptionValues( Options.RESOURCES_OPTION.getOpt() );
201 }
202
203 if ( resourceNames == null )
204 {
205 resourceNames = new String[]
206 {
207 DefaultModelProvider.getDefaultModuleLocation()
208 };
209 }
210
211 for ( final String resource : resourceNames )
212 {
213 for ( final Enumeration<URL> e = classLoader.getResources( resource ); e.hasMoreElements(); )
214 {
215 final URL url = e.nextElement();
216
217 if ( this.isLoggable( Level.FINEST ) )
218 {
219 this.log( Level.FINEST,
220 Messages.getMessage( "readingResource", url.toExternalForm() ),
221 null );
222
223 }
224
225 Object o = unmarshaller.unmarshal( url );
226 if ( o instanceof JAXBElement<?> )
227 {
228 o = ( (JAXBElement<?>) o ).getValue();
229 }
230
231 if ( o instanceof Module )
232 {
233 modules.getModule().add( (Module) o );
234 }
235 else if ( o instanceof Modules )
236 {
237 modules.getModule().addAll( ( (Modules) o ).getModule() );
238 }
239 else if ( this.isLoggable( Level.WARNING ) )
240 {
241 this.log( Level.WARNING,
242 Messages.getMessage( "failureProcessing", url.toExternalForm(), o.toString() ),
243 null );
244
245 }
246 }
247 }
248 }
249
250 if ( commandLine.hasOption( Options.MODULE_INCLUDES_OPTION.getOpt() ) )
251 {
252 final String[] values = commandLine.getOptionValues( Options.MODULE_INCLUDES_OPTION.getOpt() );
253
254 if ( values != null )
255 {
256 final List<String> includes = Arrays.asList( values );
257
258 for ( final Iterator<Module> it = modules.getModule().iterator(); it.hasNext(); )
259 {
260 final Module m = it.next();
261 if ( !includes.contains( m.getName() ) )
262 {
263 this.log( Level.INFO,
264 Messages.getMessage( "moduleExclusionInfo", m.getName() ),
265 null );
266
267 it.remove();
268 }
269 else
270 {
271 this.log( Level.INFO,
272 Messages.getMessage( "moduleInclusionInfo", m.getName() ),
273 null );
274
275 }
276 }
277 }
278 }
279
280 if ( commandLine.hasOption( Options.MODULE_EXCLUDES_OPTION.getOpt() ) )
281 {
282 final String[] values = commandLine.getOptionValues( Options.MODULE_EXCLUDES_OPTION.getOpt() );
283
284 if ( values != null )
285 {
286 for ( final String exclude : values )
287 {
288 final Module m = modules.getModule( exclude );
289
290 if ( m != null )
291 {
292 this.log( Level.INFO,
293 Messages.getMessage( "moduleExclusionInfo", m.getName() ),
294 null );
295
296 modules.getModule().remove( m );
297 }
298 }
299 }
300 }
301
302 Module classpathModule = null;
303 if ( !commandLine.hasOption( Options.NO_CLASSPATH_RESOLUTION_OPTION.getOpt() ) )
304 {
305 classpathModule = modules.getClasspathModule( Modules.getDefaultClasspathModuleName(), classLoader );
306 if ( classpathModule != null && modules.getModule( Modules.getDefaultClasspathModuleName() ) == null )
307 {
308 modules.getModule().add( classpathModule );
309 }
310 else
311 {
312 classpathModule = null;
313 }
314 }
315
316 final ModelValidationReport validationReport = context.validateModel(
317 model, new JAXBSource( marshaller, new ObjectFactory().createModules( modules ) ) );
318
319 this.log( validationReport, marshaller );
320
321 if ( !validationReport.isModelValid() )
322 {
323 throw new CommandExecutionException( Messages.getMessage( "invalidModel", model ) );
324 }
325
326 if ( classpathModule != null )
327 {
328 modules.getModule().remove( classpathModule );
329 }
330
331 Module mergedModule =
332 modules.getMergedModule( commandLine.getOptionValue( Options.MODULE_OPTION.getOpt() ) );
333
334 mergedModule.setVersion( moduleVersion );
335 mergedModule.setVendor( moduleVendor );
336
337 final File moduleFile = new File( commandLine.getOptionValue( Options.DOCUMENT_OPTION.getOpt() ) );
338
339 if ( stylesheetFile != null )
340 {
341 final Transformer transformer = this.createTransformer( new StreamSource( stylesheetFile ) );
342 final JAXBSource source =
343 new JAXBSource( marshaller, new ObjectFactory().createModule( mergedModule ) );
344
345 final JAXBResult result = new JAXBResult( unmarshaller );
346 unmarshaller.setSchema( null );
347 transformer.transform( source, result );
348
349 if ( result.getResult() instanceof JAXBElement<?>
350 && ( (JAXBElement<?>) result.getResult() ).getValue() instanceof Module )
351 {
352 mergedModule = (Module) ( (JAXBElement<?>) result.getResult() ).getValue();
353 }
354 else
355 {
356 throw new CommandExecutionException( Messages.getMessage( "illegalTransformationResultError",
357 stylesheetFile.getAbsolutePath() ) );
358
359 }
360 }
361
362 marshaller.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE );
363
364 if ( commandLine.hasOption( Options.DOCUMENT_ENCODING_OPTION.getOpt() ) )
365 {
366 marshaller.setProperty( Marshaller.JAXB_ENCODING,
367 commandLine.getOptionValue( Options.DOCUMENT_ENCODING_OPTION.getOpt() ) );
368
369 }
370
371 marshaller.setSchema( context.createSchema( model ) );
372 marshaller.marshal( new ObjectFactory().createModule( mergedModule ), moduleFile );
373
374 if ( this.isLoggable( Level.INFO ) )
375 {
376 this.log( Level.INFO, Messages.getMessage( "writingResource", moduleFile.getAbsolutePath() ), null );
377 }
378
379 classLoader.close();
380 classLoader = null;
381 }
382 catch ( final IOException e )
383 {
384 throw new CommandExecutionException( Messages.getMessage( e ), e );
385 }
386 catch ( final TransformerException e )
387 {
388 String message = Messages.getMessage( e );
389 if ( message == null )
390 {
391 message = Messages.getMessage( e.getException() );
392 }
393
394 throw new CommandExecutionException( message, e );
395 }
396 catch ( final JAXBException e )
397 {
398 String message = Messages.getMessage( e );
399 if ( message == null )
400 {
401 message = Messages.getMessage( e.getLinkedException() );
402 }
403
404 throw new CommandExecutionException( message, e );
405 }
406 catch ( final ModelException e )
407 {
408 throw new CommandExecutionException( Messages.getMessage( e ), e );
409 }
410 finally
411 {
412 try
413 {
414 if ( classLoader != null )
415 {
416 classLoader.close();
417 }
418 }
419 catch ( final IOException e )
420 {
421 this.log( Level.SEVERE, Messages.getMessage( e ), e );
422 }
423 }
424 }
425
426 }