1 package org.apache.tomcat.maven.plugin.tomcat7.run;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 import org.apache.catalina.Context;
22 import org.apache.catalina.Host;
23 import org.apache.catalina.LifecycleException;
24 import org.apache.catalina.Wrapper;
25 import org.apache.catalina.connector.Connector;
26 import org.apache.catalina.core.StandardContext;
27 import org.apache.catalina.loader.WebappLoader;
28 import org.apache.catalina.realm.MemoryRealm;
29 import org.apache.catalina.servlets.DefaultServlet;
30 import org.apache.catalina.startup.Catalina;
31 import org.apache.catalina.startup.CatalinaProperties;
32 import org.apache.catalina.startup.Tomcat;
33 import org.apache.catalina.valves.AccessLogValve;
34 import org.apache.commons.io.IOUtils;
35 import org.apache.commons.lang.StringUtils;
36 import org.apache.maven.artifact.Artifact;
37 import org.apache.maven.artifact.factory.ArtifactFactory;
38 import org.apache.maven.artifact.repository.ArtifactRepository;
39 import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
40 import org.apache.maven.artifact.resolver.ArtifactResolutionException;
41 import org.apache.maven.artifact.resolver.ArtifactResolver;
42 import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
43 import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
44 import org.apache.maven.artifact.versioning.VersionRange;
45 import org.apache.maven.execution.MavenSession;
46 import org.apache.maven.plugin.MojoExecutionException;
47 import org.apache.maven.plugin.MojoFailureException;
48 import org.apache.maven.plugins.annotations.Component;
49 import org.apache.maven.plugins.annotations.Parameter;
50 import org.apache.maven.project.MavenProject;
51 import org.apache.naming.NamingEntry;
52 import org.apache.naming.resources.FileDirContext;
53 import org.apache.tomcat.maven.common.config.AbstractWebapp;
54 import org.apache.tomcat.maven.common.run.EmbeddedRegistry;
55 import org.apache.tomcat.maven.common.run.ExternalRepositoriesReloadableWebappLoader;
56 import org.apache.tomcat.maven.plugin.tomcat7.AbstractTomcat7Mojo;
57 import org.codehaus.plexus.archiver.ArchiverException;
58 import org.codehaus.plexus.archiver.UnArchiver;
59 import org.codehaus.plexus.archiver.manager.ArchiverManager;
60 import org.codehaus.plexus.archiver.manager.NoSuchArchiverException;
61 import org.codehaus.plexus.classworlds.ClassWorld;
62 import org.codehaus.plexus.classworlds.realm.ClassRealm;
63 import org.codehaus.plexus.classworlds.realm.DuplicateRealmException;
64 import org.codehaus.plexus.util.DirectoryScanner;
65 import org.codehaus.plexus.util.FileUtils;
66 import org.w3c.dom.Document;
67 import org.w3c.dom.NamedNodeMap;
68 import org.w3c.dom.Node;
69 import org.xml.sax.SAXException;
70
71 import javax.naming.NamingException;
72 import javax.servlet.ServletException;
73 import javax.xml.parsers.DocumentBuilder;
74 import javax.xml.parsers.DocumentBuilderFactory;
75 import javax.xml.parsers.ParserConfigurationException;
76 import javax.xml.stream.XMLInputFactory;
77 import javax.xml.stream.XMLStreamConstants;
78 import javax.xml.stream.XMLStreamException;
79 import javax.xml.stream.XMLStreamReader;
80 import java.io.File;
81 import java.io.FileInputStream;
82 import java.io.FileNotFoundException;
83 import java.io.FileOutputStream;
84 import java.io.IOException;
85 import java.net.MalformedURLException;
86 import java.net.URL;
87 import java.util.ArrayList;
88 import java.util.Collection;
89 import java.util.Collections;
90 import java.util.Iterator;
91 import java.util.List;
92 import java.util.Map;
93 import java.util.Properties;
94 import java.util.Set;
95
96
97
98
99
100 public abstract class AbstractRunMojo
101 extends AbstractTomcat7Mojo
102 {
103
104
105
106
107
108
109
110 @Component
111 protected ArtifactFactory factory;
112
113
114
115
116 @Parameter( defaultValue = "${localRepository}", required = true, readonly = true )
117 private ArtifactRepository local;
118
119
120
121
122 @Component
123 protected ArtifactResolver resolver;
124
125
126
127
128
129
130
131
132 @Parameter( defaultValue = "${project.packaging}", required = true, readonly = true )
133 private String packaging;
134
135
136
137
138 @Parameter( defaultValue = "${project.build.directory}/tomcat" )
139 private File configurationDir;
140
141
142
143
144
145 @Parameter( property = "maven.tomcat.port", defaultValue = "8080" )
146 private int port;
147
148
149
150
151
152
153
154
155
156 @Parameter( property = "maven.tomcat.ajp.port", defaultValue = "0" )
157 private int ajpPort;
158
159
160
161
162
163
164
165
166
167
168
169
170
171 @Parameter( property = "maven.tomcat.ajp.protocol", defaultValue = "org.apache.coyote.ajp.AjpProtocol" )
172 private String ajpProtocol;
173
174
175
176
177
178
179
180
181
182 @Parameter( property = "maven.tomcat.httpsPort", defaultValue = "0" )
183 private int httpsPort;
184
185
186
187
188
189
190 @Parameter( property = "maven.tomcat.uriEncoding", defaultValue = "ISO-8859-1" )
191 private String uriEncoding;
192
193
194
195
196
197
198 @Parameter
199 private Map<String, String> systemProperties;
200
201
202
203
204
205
206 @Parameter( property = "maven.tomcat.additionalConfigFilesDir", defaultValue = "${basedir}/src/main/tomcatconf" )
207 private File additionalConfigFilesDir;
208
209
210
211
212
213
214 @Parameter( property = "maven.tomcat.serverXml" )
215 private File serverXml;
216
217
218
219
220
221
222 @Parameter( property = "maven.tomcat.webXml" )
223 private File tomcatWebXml;
224
225
226
227
228
229
230
231 @Parameter( property = "maven.tomcat.fork", defaultValue = "false" )
232 private boolean fork;
233
234
235
236
237
238
239
240
241
242
243
244
245
246 @Parameter( property = "maven.tomcat.addContextWarDependencies", defaultValue = "false" )
247 private boolean addContextWarDependencies;
248
249
250
251
252
253
254 @Component
255 protected MavenProject project;
256
257
258
259
260
261
262 @Component
263 private ArchiverManager archiverManager;
264
265
266
267
268
269
270 @Parameter( property = "tomcat.useSeparateTomcatClassLoader", defaultValue = "false" )
271 protected boolean useSeparateTomcatClassLoader;
272
273
274
275
276 @Parameter( defaultValue = "${plugin.artifacts}", required = true )
277 private List<Artifact> pluginArtifacts;
278
279
280
281
282
283
284 @Parameter( property = "tomcat.ignorePackaging", defaultValue = "false" )
285 private boolean ignorePackaging;
286
287
288
289
290
291
292 @Parameter
293 private String keystoreFile;
294
295
296
297
298
299
300 @Parameter
301 private String keystorePass;
302
303
304
305
306
307
308 @Parameter( defaultValue = "JKS" )
309 private String keystoreType;
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324 @Parameter( property = "maven.tomcat.useNaming", defaultValue = "true" )
325 private boolean useNaming;
326
327
328
329
330
331
332
333
334 @Parameter( property = "maven.tomcat.contextReloadable", defaultValue = "false" )
335 protected boolean contextReloadable;
336
337
338
339
340
341
342
343 @Parameter( property = "maven.tomcat.contextFile" )
344 protected File contextFile;
345
346
347
348
349
350
351
352 @Parameter( property = "maven.tomcat.protocol", defaultValue = "HTTP/1.1" )
353 private String protocol;
354
355
356
357
358
359
360 @Parameter( property = "maven.tomcat.tomcatUsers.file" )
361 private File tomcatUsers;
362
363
364
365
366
367
368 @Parameter( property = "maven.tomcat.tomcatLogging.file" )
369 private File tomcatLoggingFile;
370
371
372
373
374
375
376 @Parameter( property = "maven.tomcat.skip", defaultValue = "false" )
377 protected boolean skip;
378
379
380
381
382
383 @Parameter
384 private List<Webapp> webapps;
385
386
387
388
389
390
391 @Parameter( property = "maven.tomcat.staticContextPath", defaultValue = "/" )
392 private String staticContextPath;
393
394
395
396
397
398
399
400 @Parameter( property = "maven.tomcat.staticContextDocbase" )
401 private String staticContextDocbase;
402
403
404
405
406
407
408 @Parameter
409 protected String classLoaderClass;
410
411 @Parameter( defaultValue = "${session}", readonly = true, required = true )
412 protected MavenSession session;
413
414
415
416
417
418 @Parameter( property = "maven.tomcat.propertiesPortFilePath" )
419 protected String propertiesPortFilePath;
420
421
422
423
424
425
426 @Parameter( property = "maven.tomcat.hostName", defaultValue = "localhost" )
427 protected String hostName;
428
429
430
431
432
433
434
435 @Parameter
436 protected String[] aliases;
437
438
439
440
441
442
443
444
445 private ClassRealm tomcatRealm;
446
447
448
449
450
451
452
453
454 public void execute()
455 throws MojoExecutionException, MojoFailureException
456 {
457 if ( skip )
458 {
459 getLog().info( "skip execution" );
460 return;
461 }
462
463 if ( !isWar() && !addContextWarDependencies && getAdditionalWebapps().isEmpty() )
464 {
465 getLog().info( messagesProvider.getMessage( "AbstractRunMojo.nonWar" ) );
466 return;
467 }
468 ClassLoader originalClassLoader = null;
469 if ( useSeparateTomcatClassLoader )
470 {
471 originalClassLoader = Thread.currentThread().getContextClassLoader();
472 }
473 try
474 {
475 getLog().info( messagesProvider.getMessage( "AbstractRunMojo.runningWar", getWebappUrl() ) );
476
477 initConfiguration();
478 startContainer();
479 if ( !fork )
480 {
481 waitIndefinitely();
482 }
483 }
484 catch ( LifecycleException exception )
485 {
486 throw new MojoExecutionException( messagesProvider.getMessage( "AbstractRunMojo.cannotStart" ), exception );
487 }
488 catch ( IOException exception )
489 {
490 throw new MojoExecutionException(
491 messagesProvider.getMessage( "AbstractRunMojo.cannotCreateConfiguration" ), exception );
492 }
493 catch ( ServletException e )
494 {
495 throw new MojoExecutionException( e.getMessage(), e );
496 }
497 finally
498 {
499 if ( useSeparateTomcatClassLoader )
500 {
501 Thread.currentThread().setContextClassLoader( originalClassLoader );
502 }
503 }
504 }
505
506
507
508
509
510
511
512
513
514
515 protected String getPath()
516 {
517 return path;
518 }
519
520
521
522
523
524
525
526
527
528 protected Context createContext( Tomcat container )
529 throws IOException, MojoExecutionException, ServletException
530 {
531 String contextPath = getPath();
532
533 String baseDir = getDocBase().getAbsolutePath();
534
535 File overridedContextFile = getContextFile();
536
537 if ( overridedContextFile != null && overridedContextFile.exists() )
538 {
539 StandardContext standardContext = parseContextFile( overridedContextFile );
540
541 if ( standardContext.getPath() != null )
542 {
543 contextPath = standardContext.getPath();
544 }
545 if ( standardContext.getDocBase() != null )
546 {
547 baseDir = standardContext.getDocBase();
548 }
549 }
550
551 contextPath = "/".equals( contextPath ) ? "" : contextPath;
552
553 getLog().info( "create webapp with contextPath: " + contextPath );
554
555 Context context = container.addWebapp( contextPath, baseDir );
556
557 context.setResources(
558 new MyDirContext( new File( project.getBuild().getOutputDirectory() ).getAbsolutePath() ) );
559
560 if ( useSeparateTomcatClassLoader )
561 {
562 context.setParentClassLoader( getTomcatClassLoader() );
563 }
564
565 final WebappLoader loader = createWebappLoader();
566
567 context.setLoader( loader );
568
569 if ( overridedContextFile != null )
570 {
571 context.setConfigFile( overridedContextFile.toURI().toURL() );
572 }
573
574 if ( classLoaderClass != null )
575 {
576 loader.setLoaderClass( classLoaderClass );
577 }
578
579 return context;
580
581 }
582
583 protected StandardContext parseContextFile( File file )
584 throws MojoExecutionException
585 {
586 try
587 {
588 StandardContext standardContext = new StandardContext();
589 XMLStreamReader reader = XMLInputFactory.newFactory().createXMLStreamReader( new FileInputStream( file ) );
590
591 int tag = reader.next();
592
593 while ( true )
594 {
595 if ( tag == XMLStreamConstants.START_ELEMENT && StringUtils.equals( "Context", reader.getLocalName() ) )
596 {
597 String path = reader.getAttributeValue( null, "path" );
598 if ( StringUtils.isNotBlank( path ) )
599 {
600 standardContext.setPath( path );
601 }
602
603 String docBase = reader.getAttributeValue( null, "docBase" );
604 if ( StringUtils.isNotBlank( docBase ) )
605 {
606 standardContext.setDocBase( docBase );
607 }
608 }
609 if ( !reader.hasNext() )
610 {
611 break;
612 }
613 tag = reader.next();
614 }
615
616 return standardContext;
617 }
618 catch ( XMLStreamException e )
619 {
620 throw new MojoExecutionException( e.getMessage(), e );
621 }
622 catch ( FileNotFoundException e )
623 {
624 throw new MojoExecutionException( e.getMessage(), e );
625 }
626 }
627
628
629 private static class MyDirContext
630 extends FileDirContext
631 {
632 String buildOutputDirectory;
633
634 MyDirContext( String buildOutputDirectory )
635 {
636 this.buildOutputDirectory = buildOutputDirectory;
637 }
638
639 @Override
640 protected List<NamingEntry> doListBindings( String name )
641 throws NamingException
642 {
643 if ( "/WEB-INF/classes".equals( name ) )
644 {
645 if ( !new File( buildOutputDirectory ).exists() )
646 {
647 return Collections.emptyList();
648 }
649 FileDirContext fileDirContext = new FileDirContext();
650 fileDirContext.setDocBase( buildOutputDirectory );
651 NamingEntry namingEntry = new NamingEntry( "/WEB-INF/classes", fileDirContext, -1 );
652 return Collections.singletonList( namingEntry );
653 }
654
655 return super.doListBindings( name );
656 }
657 }
658
659
660
661
662
663
664
665
666 protected WebappLoader createWebappLoader()
667 throws IOException, MojoExecutionException
668 {
669 if ( useSeparateTomcatClassLoader )
670 {
671 return ( isContextReloadable() )
672 ? new ExternalRepositoriesReloadableWebappLoader( getTomcatClassLoader(), getLog() )
673 : new WebappLoader( getTomcatClassLoader() );
674 }
675
676 return ( isContextReloadable() )
677 ? new ExternalRepositoriesReloadableWebappLoader( Thread.currentThread().getContextClassLoader(), getLog() )
678 : new WebappLoader( Thread.currentThread().getContextClassLoader() );
679 }
680
681
682
683
684
685
686 protected boolean isContextReloadable()
687 throws MojoExecutionException
688 {
689 if ( contextReloadable )
690 {
691 return true;
692 }
693
694 boolean reloadable = false;
695 try
696 {
697 if ( contextFile != null && contextFile.exists() )
698 {
699 DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
700 DocumentBuilder builder = builderFactory.newDocumentBuilder();
701 Document contextDoc = builder.parse( contextFile );
702 contextDoc.getDocumentElement().normalize();
703
704 NamedNodeMap nodeMap = contextDoc.getDocumentElement().getAttributes();
705 Node reloadableAttribute = nodeMap.getNamedItem( "reloadable" );
706
707 reloadable =
708 ( reloadableAttribute != null ) ? Boolean.valueOf( reloadableAttribute.getNodeValue() ) : false;
709 }
710 getLog().debug( "context reloadable: " + reloadable );
711 }
712 catch ( IOException ioe )
713 {
714 getLog().error( "Could not parse file: [" + contextFile.getAbsolutePath() + "]", ioe );
715 }
716 catch ( ParserConfigurationException pce )
717 {
718 getLog().error( "Could not configure XML parser", pce );
719 }
720 catch ( SAXException se )
721 {
722 getLog().error( "Could not parse file: [" + contextFile.getAbsolutePath() + "]", se );
723 }
724
725 return reloadable;
726 }
727
728
729
730
731
732
733
734 protected abstract File getDocBase();
735
736
737
738
739
740
741 protected abstract File getContextFile()
742 throws MojoExecutionException;
743
744
745
746
747
748
749
750
751
752
753 protected boolean isWar()
754 {
755 return "war".equals( packaging ) || ignorePackaging;
756 }
757
758
759
760
761
762
763
764 private URL getWebappUrl()
765 throws MalformedURLException
766 {
767 return new URL( "http", "localhost", port, getPath() );
768 }
769
770
771
772
773
774
775
776
777 private void initConfiguration()
778 throws IOException, MojoExecutionException
779 {
780 if ( configurationDir.exists() )
781 {
782 getLog().info( messagesProvider.getMessage( "AbstractRunMojo.usingConfiguration", configurationDir ) );
783 }
784 else
785 {
786 getLog().info( messagesProvider.getMessage( "AbstractRunMojo.creatingConfiguration", configurationDir ) );
787
788 configurationDir.mkdirs();
789
790 File confDir = new File( configurationDir, "conf" );
791 confDir.mkdir();
792
793 if ( tomcatLoggingFile != null )
794 {
795 FileUtils.copyFile( tomcatLoggingFile, new File( confDir, "logging.properties" ) );
796 }
797 else
798 {
799 copyFile( "/conf/logging.properties", new File( confDir, "logging.properties" ) );
800 }
801
802 copyFile( "/conf/tomcat-users.xml", new File( confDir, "tomcat-users.xml" ) );
803 if ( tomcatWebXml != null )
804 {
805 if ( !tomcatWebXml.exists() )
806 {
807 throw new MojoExecutionException( " tomcatWebXml " + tomcatWebXml.getPath() + " not exists" );
808 }
809
810 FileUtils.copyFile( tomcatWebXml, new File( confDir, "web.xml" ) );
811 }
812 else
813 {
814 copyFile( "/conf/web.xml", new File( confDir, "web.xml" ) );
815 }
816
817 File logDir = new File( configurationDir, "logs" );
818 logDir.mkdir();
819
820 File webappsDir = new File( configurationDir, "webapps" );
821 webappsDir.mkdir();
822
823 if ( additionalConfigFilesDir != null && additionalConfigFilesDir.exists() )
824 {
825 DirectoryScanner scanner = new DirectoryScanner();
826 scanner.addDefaultExcludes();
827 scanner.setBasedir( additionalConfigFilesDir.getPath() );
828 scanner.scan();
829
830 String[] files = scanner.getIncludedFiles();
831
832 if ( files != null && files.length > 0 )
833 {
834 getLog().info( "Coping additional tomcat config files" );
835
836 for ( int i = 0; i < files.length; i++ )
837 {
838 File file = new File( additionalConfigFilesDir, files[i] );
839
840 getLog().info( " copy " + file.getName() );
841
842 FileUtils.copyFileToDirectory( file, confDir );
843 }
844 }
845 }
846 }
847 }
848
849
850
851
852
853
854
855
856 private void copyFile( String fromPath, File toFile )
857 throws IOException
858 {
859 URL fromURL = getClass().getResource( fromPath );
860
861 if ( fromURL == null )
862 {
863 throw new FileNotFoundException( fromPath );
864 }
865
866 FileUtils.copyURLToFile( fromURL, toFile );
867 }
868
869
870
871
872
873
874
875
876 private void startContainer()
877 throws IOException, LifecycleException, MojoExecutionException, ServletException
878 {
879 String previousCatalinaBase = System.getProperty( "catalina.base" );
880
881 try
882 {
883
884
885 setupSystemProperties();
886
887 System.setProperty( "catalina.base", configurationDir.getAbsolutePath() );
888
889 if ( serverXml != null )
890 {
891 if ( !serverXml.exists() )
892 {
893 throw new MojoExecutionException( serverXml.getPath() + " not exists" );
894 }
895
896 Catalina container = new Catalina();
897 container.setUseNaming( this.useNaming );
898 container.setConfig( serverXml.getAbsolutePath() );
899 container.start();
900 EmbeddedRegistry.getInstance().register( container );
901 }
902 else
903 {
904
905 System.setProperty( "java.util.logging.manager", "org.apache.juli.ClassLoaderLogManager" );
906 System.setProperty( "java.util.logging.config.file",
907 new File( configurationDir, "conf/logging.properties" ).toString() );
908
909
910 CatalinaProperties.getProperty( "foo" );
911
912 Tomcat embeddedTomcat = new ExtendedTomcat( configurationDir );
913
914 embeddedTomcat.setBaseDir( configurationDir.getAbsolutePath() );
915 MemoryRealm memoryRealm = new MemoryRealm();
916
917 if ( tomcatUsers != null )
918 {
919 if ( !tomcatUsers.exists() )
920 {
921 throw new MojoExecutionException( " tomcatUsers " + tomcatUsers.getPath() + " not exists" );
922 }
923 getLog().info( "use tomcat-users.xml from " + tomcatUsers.getAbsolutePath() );
924 memoryRealm.setPathname( tomcatUsers.getAbsolutePath() );
925 }
926
927 embeddedTomcat.setDefaultRealm( memoryRealm );
928
929 Context ctx = createContext( embeddedTomcat );
930
931 if ( useNaming )
932 {
933 embeddedTomcat.enableNaming();
934 }
935
936 embeddedTomcat.getHost().setAppBase( new File( configurationDir, "webapps" ).getAbsolutePath() );
937
938 if ( hostName != null )
939 {
940 embeddedTomcat.getHost().setName( hostName );
941 }
942 if ( aliases != null )
943 {
944 for ( String alias : aliases )
945 {
946 embeddedTomcat.getHost().addAlias( alias );
947 }
948
949 }
950 createStaticContext( embeddedTomcat, ctx, embeddedTomcat.getHost() );
951
952 Connector connector = new Connector( protocol );
953 connector.setPort( port );
954
955 if ( httpsPort > 0 )
956 {
957 connector.setRedirectPort( httpsPort );
958 }
959
960 connector.setURIEncoding( uriEncoding );
961
962 embeddedTomcat.getService().addConnector( connector );
963
964 embeddedTomcat.setConnector( connector );
965
966 AccessLogValve alv = new AccessLogValve();
967 alv.setDirectory( new File( configurationDir, "logs" ).getAbsolutePath() );
968 alv.setPattern( "%h %l %u %t \"%r\" %s %b %I %D" );
969 embeddedTomcat.getHost().getPipeline().addValve( alv );
970
971
972 Connector httpsConnector = null;
973 if ( httpsPort > 0 )
974 {
975 httpsConnector = new Connector( protocol );
976 httpsConnector.setPort( httpsPort );
977 httpsConnector.setSecure( true );
978 httpsConnector.setProperty( "SSLEnabled", "true" );
979
980 httpsConnector.setProperty( "sslProtocol", "TLS" );
981 if ( keystoreFile != null )
982 {
983 httpsConnector.setAttribute( "keystoreFile", keystoreFile );
984 }
985 if ( keystorePass != null )
986 {
987 httpsConnector.setAttribute( "keystorePass", keystorePass );
988 }
989 if ( keystoreType != null )
990 {
991 httpsConnector.setAttribute( "keystoreType", keystoreType );
992 }
993 embeddedTomcat.getEngine().getService().addConnector( httpsConnector );
994
995 }
996
997
998 Connector ajpConnector = null;
999 if ( ajpPort > 0 )
1000 {
1001 ajpConnector = new Connector( ajpProtocol );
1002 ajpConnector.setPort( ajpPort );
1003 ajpConnector.setURIEncoding( uriEncoding );
1004 embeddedTomcat.getEngine().getService().addConnector( ajpConnector );
1005 }
1006
1007 if ( addContextWarDependencies || !getAdditionalWebapps().isEmpty() )
1008 {
1009 createDependencyContexts( embeddedTomcat );
1010 }
1011
1012 if ( useSeparateTomcatClassLoader )
1013 {
1014 Thread.currentThread().setContextClassLoader( getTomcatClassLoader() );
1015 embeddedTomcat.getEngine().setParentClassLoader( getTomcatClassLoader() );
1016 }
1017
1018 embeddedTomcat.start();
1019
1020 Properties portProperties = new Properties();
1021
1022 portProperties.put( "tomcat.maven.http.port", Integer.toString( connector.getLocalPort() ) );
1023
1024 session.getExecutionProperties().put( "tomcat.maven.http.port",
1025 Integer.toString( connector.getLocalPort() ) );
1026 System.setProperty( "tomcat.maven.http.port", Integer.toString( connector.getLocalPort() ) );
1027
1028 if ( httpsConnector != null )
1029 {
1030 session.getExecutionProperties().put( "tomcat.maven.https.port",
1031 Integer.toString( httpsConnector.getLocalPort() ) );
1032 portProperties.put( "tomcat.maven.https.port", Integer.toString( httpsConnector.getLocalPort() ) );
1033 System.setProperty( "tomcat.maven.https.port", Integer.toString( httpsConnector.getLocalPort() ) );
1034 }
1035
1036 if ( ajpConnector != null )
1037 {
1038 session.getExecutionProperties().put( "tomcat.maven.ajp.port",
1039 Integer.toString( ajpConnector.getLocalPort() ) );
1040 portProperties.put( "tomcat.maven.ajp.port", Integer.toString( ajpConnector.getLocalPort() ) );
1041 System.setProperty( "tomcat.maven.ajp.port", Integer.toString( ajpConnector.getLocalPort() ) );
1042 }
1043 if ( propertiesPortFilePath != null )
1044 {
1045 File propertiesPortsFile = new File( propertiesPortFilePath );
1046 if ( propertiesPortsFile.exists() )
1047 {
1048 propertiesPortsFile.delete();
1049 }
1050 FileOutputStream fileOutputStream = new FileOutputStream( propertiesPortsFile );
1051 try
1052 {
1053 portProperties.store( fileOutputStream, "Apache Tomcat Maven plugin port used" );
1054 }
1055 finally
1056 {
1057 IOUtils.closeQuietly( fileOutputStream );
1058 }
1059 }
1060
1061 EmbeddedRegistry.getInstance().register( embeddedTomcat );
1062
1063 }
1064
1065
1066 }
1067 finally
1068 {
1069 if ( previousCatalinaBase != null )
1070 {
1071 System.setProperty( "catalina.base", previousCatalinaBase );
1072 }
1073 }
1074 }
1075
1076 private List<Webapp> getAdditionalWebapps()
1077 {
1078 if ( webapps == null )
1079 {
1080 return Collections.emptyList();
1081 }
1082 return webapps;
1083 }
1084
1085 protected ClassRealm getTomcatClassLoader()
1086 throws MojoExecutionException
1087 {
1088 if ( this.tomcatRealm != null )
1089 {
1090 return tomcatRealm;
1091 }
1092 try
1093 {
1094 ClassWorld world = new ClassWorld();
1095 ClassRealm root = world.newRealm( "tomcat", Thread.currentThread().getContextClassLoader() );
1096
1097 for ( @SuppressWarnings( "rawtypes" ) Iterator i = pluginArtifacts.iterator(); i.hasNext(); )
1098 {
1099 Artifact pluginArtifact = (Artifact) i.next();
1100
1101 if ( pluginArtifact.getFile() != null )
1102 {
1103 root.addURL( pluginArtifact.getFile().toURI().toURL() );
1104 }
1105
1106 }
1107 tomcatRealm = root;
1108 return root;
1109 }
1110 catch ( DuplicateRealmException e )
1111 {
1112 throw new MojoExecutionException( e.getMessage(), e );
1113 }
1114 catch ( MalformedURLException e )
1115 {
1116 throw new MojoExecutionException( e.getMessage(), e );
1117 }
1118 }
1119
1120 @SuppressWarnings( "unchecked" )
1121 public Set<Artifact> getProjectArtifacts()
1122 {
1123 return project.getArtifacts();
1124 }
1125
1126
1127
1128
1129 private void waitIndefinitely()
1130 {
1131 Object lock = new Object();
1132
1133 synchronized ( lock )
1134 {
1135 try
1136 {
1137 lock.wait();
1138 }
1139 catch ( InterruptedException exception )
1140 {
1141 getLog().warn( messagesProvider.getMessage( "AbstractRunMojo.interrupted" ), exception );
1142 }
1143 }
1144 }
1145
1146
1147
1148
1149
1150 private void setupSystemProperties()
1151 {
1152 if ( systemProperties != null && !systemProperties.isEmpty() )
1153 {
1154 getLog().info( "setting SystemProperties:" );
1155
1156 for ( String key : systemProperties.keySet() )
1157 {
1158 String value = systemProperties.get( key );
1159
1160 if ( value != null )
1161 {
1162 getLog().info( " " + key + "=" + value );
1163 System.setProperty( key, value );
1164 }
1165 else
1166 {
1167 getLog().info( "skip sysProps " + key + " with empty value" );
1168 }
1169 }
1170 }
1171 }
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181 private Collection<Context> createDependencyContexts( Tomcat container )
1182 throws MojoExecutionException, MalformedURLException, ServletException, IOException
1183 {
1184 getLog().info( "Deploying dependency wars" );
1185
1186 List<Context> contexts = new ArrayList<Context>();
1187
1188 ScopeArtifactFilter filter = new ScopeArtifactFilter( "tomcat" );
1189 @SuppressWarnings( "unchecked" ) Set<Artifact> artifacts = project.getArtifacts();
1190 for ( Artifact artifact : artifacts )
1191 {
1192
1193
1194
1195 if ( "war".equals( artifact.getType() ) && !artifact.isOptional() && filter.include( artifact ) )
1196 {
1197 addContextFromArtifact( container, contexts, artifact, "/" + artifact.getArtifactId(), null, false );
1198 }
1199 }
1200
1201 for ( AbstractWebapp additionalWebapp : getAdditionalWebapps() )
1202 {
1203 String contextPath = additionalWebapp.getContextPath();
1204 if ( !contextPath.startsWith( "/" ) )
1205 {
1206 contextPath = "/" + contextPath;
1207 }
1208 addContextFromArtifact( container, contexts, getArtifact( additionalWebapp ), contextPath,
1209 additionalWebapp.getContextFile(), additionalWebapp.isAsWebapp() );
1210 }
1211 return contexts;
1212 }
1213
1214
1215 private void addContextFromArtifact( Tomcat container, List<Context> contexts, Artifact artifact,
1216 String contextPath, File contextXml, boolean asWebApp )
1217 throws MojoExecutionException, MalformedURLException, ServletException, IOException
1218 {
1219 getLog().info( "Deploy warfile: " + String.valueOf( artifact.getFile() ) + " to contextPath: " + contextPath );
1220 File webapps = new File( configurationDir, "webapps" );
1221 File artifactWarDir = new File( webapps, artifact.getArtifactId() );
1222 if ( !artifactWarDir.exists() )
1223 {
1224
1225 artifactWarDir.mkdir();
1226 try
1227 {
1228 UnArchiver unArchiver = archiverManager.getUnArchiver( "zip" );
1229 unArchiver.setSourceFile( artifact.getFile() );
1230 unArchiver.setDestDirectory( artifactWarDir );
1231
1232
1233 unArchiver.extract();
1234 }
1235 catch ( NoSuchArchiverException e )
1236 {
1237 getLog().error( e );
1238 return;
1239 }
1240 catch ( ArchiverException e )
1241 {
1242 getLog().error( e );
1243 return;
1244 }
1245 }
1246
1247
1248 WebappLoader webappLoader = createWebappLoader();
1249 Context context = null;
1250 if ( asWebApp )
1251 {
1252 context = container.addWebapp( contextPath, artifactWarDir.getAbsolutePath() );
1253 }
1254 else
1255 {
1256 context = container.addContext( contextPath, artifactWarDir.getAbsolutePath() );
1257 }
1258 context.setLoader( webappLoader );
1259
1260 File contextFile = contextXml != null ? contextXml : getContextFile();
1261 if ( contextFile != null )
1262 {
1263 context.setConfigFile( contextFile.toURI().toURL() );
1264 }
1265
1266 contexts.add( context );
1267
1268 }
1269
1270 private void createStaticContext( final Tomcat container, Context context, Host host )
1271 {
1272 if ( staticContextDocbase != null )
1273 {
1274 Context staticContext = container.addContext( staticContextPath, staticContextDocbase );
1275 staticContext.setPrivileged( true );
1276 Wrapper servlet = context.createWrapper();
1277 servlet.setServletClass( DefaultServlet.class.getName() );
1278 servlet.setName( "staticContent" );
1279 staticContext.addChild( servlet );
1280 staticContext.addServletMapping( "/", "staticContent" );
1281 host.addChild( staticContext );
1282 }
1283 }
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294 protected Artifact getArtifact( AbstractWebapp additionalWebapp )
1295 throws MojoExecutionException
1296 {
1297
1298 Artifact artifact;
1299 VersionRange vr;
1300 try
1301 {
1302 vr = VersionRange.createFromVersionSpec( additionalWebapp.getVersion() );
1303 }
1304 catch ( InvalidVersionSpecificationException e )
1305 {
1306 getLog().warn( "fail to create versionRange from version: " + additionalWebapp.getVersion(), e );
1307 vr = VersionRange.createFromVersion( additionalWebapp.getVersion() );
1308 }
1309
1310 if ( StringUtils.isEmpty( additionalWebapp.getClassifier() ) )
1311 {
1312 artifact =
1313 factory.createDependencyArtifact( additionalWebapp.getGroupId(), additionalWebapp.getArtifactId(), vr,
1314 additionalWebapp.getType(), null, Artifact.SCOPE_COMPILE );
1315 }
1316 else
1317 {
1318 artifact =
1319 factory.createDependencyArtifact( additionalWebapp.getGroupId(), additionalWebapp.getArtifactId(), vr,
1320 additionalWebapp.getType(), additionalWebapp.getClassifier(),
1321 Artifact.SCOPE_COMPILE );
1322 }
1323
1324 try
1325 {
1326 resolver.resolve( artifact, project.getRemoteArtifactRepositories(), this.local );
1327 }
1328 catch ( ArtifactResolutionException e )
1329 {
1330 throw new MojoExecutionException( "Unable to resolve artifact.", e );
1331 }
1332 catch ( ArtifactNotFoundException e )
1333 {
1334 throw new MojoExecutionException( "Unable to find artifact.", e );
1335 }
1336
1337 return artifact;
1338 }
1339 }