5
5
* The ASF licenses this file to You under the Apache License, Version 2.0
6
6
* (the "License"); you may not use this file except in compliance with
7
7
* the License. You may obtain a copy of the License at
9
9
* http://www.apache.org/licenses/LICENSE-2.0
11
11
* Unless required by applicable law or agreed to in writing, software
12
12
* distributed under the License is distributed on an "AS IS" BASIS,
13
13
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
14
* See the License for the specific language governing permissions and
15
15
* limitations under the License.
19
17
package org.apache.catalina.startup;
22
19
import java.io.File;
23
20
import java.io.FileInputStream;
24
21
import java.io.FileNotFoundException;
52
49
import org.apache.catalina.deploy.LoginConfig;
53
50
import org.apache.catalina.deploy.SecurityConstraint;
54
51
import org.apache.catalina.util.StringManager;
52
import org.apache.juli.logging.Log;
53
import org.apache.juli.logging.LogFactory;
54
import org.apache.tomcat.util.descriptor.DigesterFactory;
55
import org.apache.tomcat.util.descriptor.XmlErrorHandler;
55
56
import org.apache.tomcat.util.digester.Digester;
56
57
import org.apache.tomcat.util.digester.RuleSet;
57
58
import org.xml.sax.ErrorHandler;
65
66
* @author Craig R. McClanahan
66
67
* @author Jean-Francois Arcand
67
* @version $Id: ContextConfig.java 1228244 2012-01-06 16:09:08Z kkolinko $
68
* @version $Id: ContextConfig.java 1558828 2014-01-16 15:12:59Z markt $
70
public class ContextConfig
71
implements LifecycleListener {
73
protected static org.apache.juli.logging.Log log=
74
org.apache.juli.logging.LogFactory.getLog( ContextConfig.class );
70
public class ContextConfig implements LifecycleListener {
72
protected static Log log = LogFactory.getLog( ContextConfig.class );
75
* The string resources for this package.
77
protected static final StringManager sm =
78
StringManager.getManager(Constants.Package);
76
81
// ----------------------------------------------------- Instance Variables
100
105
* The default web application's context file location.
102
107
protected String defaultContextXml = null;
106
111
* The default web application's deployment descriptor location.
108
113
protected String defaultWebXml = null;
112
117
* Track any fatal errors during startup configuration processing.
118
123
* Any parse error which occurred while parsing XML descriptors.
124
* @deprecated Unused. Will be removed in Tomcat 7.0.x.
120
127
protected SAXParseException parseException = null;
124
131
* Original docBase.
126
133
protected String originalDocBase = null;
130
* The string resources for this package.
137
* Anti-locking docBase. It is a path to a copy of the web application
138
* in the java.io.tmpdir directory. This path is always an absolute one.
132
protected static final StringManager sm =
133
StringManager.getManager(Constants.Package);
140
private File antiLockingDocBase = null;
140
147
protected static Digester contextDigester = null;
144
151
* The <code>Digester</code> we will use to process web application
145
152
* deployment descriptor files.
147
protected static Digester webDigester = null;
151
* The <code>Rule</code> used to parse the web.xml
153
protected static WebRuleSet webRuleSet = new WebRuleSet();
154
protected Digester webDigester = null;
155
protected WebRuleSet webRuleSet = null;
156
158
* Attribute value used to turn on/off XML validation
159
* @deprecated Unused. Will be removed in Tomcat 7.0.x.
158
protected static boolean xmlValidation = false;
162
protected static boolean xmlValidation = false;
162
166
* Attribute value used to turn on/off XML namespace awarenes.
167
* @deprecated Unused. Will be removed in Tomcat 7.0.x.
164
170
protected static boolean xmlNamespaceAware = false;
168
174
* Deployment count.
170
176
protected static long deploymentCount = 0L;
173
179
protected static final LoginConfig DUMMY_LOGIN_CONFIG =
174
180
new LoginConfig("NONE", null, null, null);
177
183
// ------------------------------------------------------------- Properties
181
185
* Return the location of the default deployment descriptor
264
268
} else if (event.getType().equals(StandardContext.AFTER_START_EVENT)) {
265
269
// Restore docBase for management tools
266
270
if (originalDocBase != null) {
267
String docBase = context.getDocBase();
268
271
context.setDocBase(originalDocBase);
269
originalDocBase = docBase;
271
273
} else if (event.getType().equals(Lifecycle.STOP_EVENT)) {
272
if (originalDocBase != null) {
273
String docBase = context.getDocBase();
274
context.setDocBase(originalDocBase);
275
originalDocBase = docBase;
278
275
} else if (event.getType().equals(Lifecycle.INIT_EVENT)) {
291
288
* Process the application classes annotations, if it exists.
293
290
protected void applicationAnnotationsConfig() {
295
292
long t1=System.currentTimeMillis();
297
294
WebAnnotationSet.loadApplicationAnnotations(context);
299
296
long t2=System.currentTimeMillis();
300
297
if (context instanceof StandardContext) {
301
298
((StandardContext) context).setStartupTime(t2-t1+
355
352
if (context instanceof StandardContext) {
356
353
((StandardContext) context).setReplaceWelcomeFiles(true);
356
XmlErrorHandler handler = new XmlErrorHandler();
358
358
webDigester.push(context);
359
webDigester.setErrorHandler(new ContextErrorHandler());
359
webDigester.setErrorHandler(handler);
361
361
if(log.isDebugEnabled()) {
362
362
log.debug("Parsing application web.xml file at " + url.toExternalForm());
365
365
webDigester.parse(is);
367
if (parseException != null) {
367
if (handler.getWarnings().size() > 0 ||
368
handler.getErrors().size() > 0) {
370
handler.logFindings(log, is.getSystemId());
371
373
log.info("No web.xml, using defaults " + context );
517
* Create (if necessary) and return a Digester configured to process the
518
* web application deployment descriptor (web.xml).
520
protected static Digester createWebDigester() {
521
Digester webDigester =
522
createWebXmlDigester(xmlNamespaceAware, xmlValidation);
528
* Create (if necessary) and return a Digester configured to process the
529
* web application deployment descriptor (web.xml).
531
public static Digester createWebXmlDigester(boolean namespaceAware,
532
boolean validation) {
534
Digester webDigester = DigesterFactory.newDigester(xmlValidation,
518
* Create and return a Digester configured to process the
519
* web application deployment descriptor (web.xml).
521
protected void createWebXmlDigester(boolean namespaceAware,
522
boolean validation) {
524
boolean blockExternal = context.getXmlBlockExternal();
526
webRuleSet = new WebRuleSet();
527
webDigester = DigesterFactory.newDigester(validation,
528
namespaceAware, webRuleSet, blockExternal);
529
webDigester.getParser();
542
534
* Create (if necessary) and return a Digester configured to process the
543
535
* context configuration descriptor for an application.
616
608
context.addWatchedResource(file.getAbsolutePath());
618
610
} catch (Exception e) {
619
log.error(sm.getString("contextConfig.defaultMissing")
611
log.error(sm.getString("contextConfig.defaultMissing")
620
612
+ " " + defaultWebXml + " " + file , e);
651
643
stream = new FileInputStream(file);
653
645
} catch (Exception e) {
654
log.error(sm.getString("contextConfig.defaultMissing")
646
log.error(sm.getString("contextConfig.defaultMissing")
655
647
+ " " + resourceName + " " + file , e);
667
659
* Process a default web.xml.
669
protected void processDefaultWebConfig(Digester digester, InputStream stream,
661
protected void processDefaultWebConfig(Digester digester, InputStream stream,
670
662
InputSource source) {
672
664
if (log.isDebugEnabled())
673
log.debug("Processing context [" + context.getName()
665
log.debug("Processing context [" + context.getName()
674
666
+ "] web configuration resource " + source.getSystemId());
676
668
// Process the default web.xml file
677
669
synchronized (digester) {
679
671
source.setByteStream(stream);
681
673
if (context instanceof StandardContext)
682
674
((StandardContext) context).setReplaceWelcomeFiles(true);
683
675
digester.setClassLoader(this.getClass().getClassLoader());
684
676
digester.setUseContextClassLoader(false);
677
XmlErrorHandler handler = new XmlErrorHandler();
685
678
digester.push(context);
686
digester.setErrorHandler(new ContextErrorHandler());
679
digester.setErrorHandler(handler);
687
680
digester.parse(source);
688
if (parseException != null) {
681
if (handler.getWarnings().size() > 0 ||
682
handler.getErrors().size() > 0) {
684
handler.logFindings(log, source.getSystemId());
691
686
} catch (SAXParseException e) {
692
687
log.error(sm.getString("contextConfig.defaultParse"), e);
716
710
* Process the default configuration file, if it exists.
718
712
protected void contextConfig() {
720
714
// Open the default context.xml file, if it exists
721
715
if( defaultContextXml==null && context instanceof StandardContext ) {
722
716
defaultContextXml = ((StandardContext)context).getDefaultContextXml();
735
729
if (context.getConfigFile() != null)
736
730
processContextConfig(new File(context.getConfigFile()), null);
742
736
* Process a context.xml.
744
738
protected void processContextConfig(File baseDir, String resourceName) {
746
740
if (log.isDebugEnabled())
747
log.debug("Processing context [" + context.getName()
741
log.debug("Processing context [" + context.getName()
748
742
+ "] configuration file " + baseDir + " " + resourceName);
750
744
InputSource source = null;
776
770
context.addWatchedResource(file.getAbsolutePath());
778
772
} catch (Exception e) {
779
log.error(sm.getString("contextConfig.contextMissing",
773
log.error(sm.getString("contextConfig.contextMissing",
780
774
resourceName + " " + file) , e);
783
777
if (source == null)
785
779
synchronized (contextDigester) {
787
781
source.setByteStream(stream);
788
782
contextDigester.setClassLoader(this.getClass().getClassLoader());
789
783
contextDigester.setUseContextClassLoader(false);
784
XmlErrorHandler handler = new XmlErrorHandler();
790
785
contextDigester.push(context.getParent());
791
786
contextDigester.push(context);
792
contextDigester.setErrorHandler(new ContextErrorHandler());
787
contextDigester.setErrorHandler(handler);
793
788
contextDigester.parse(source);
794
if (parseException != null) {
789
if (handler.getWarnings().size() > 0 ||
790
handler.getErrors().size() > 0) {
792
handler.logFindings(log, source.getSystemId());
797
794
if (log.isDebugEnabled())
798
log.debug("Successfully processed context [" + context.getName()
795
log.debug("Successfully processed context [" + context.getName()
799
796
+ "] configuration file " + baseDir + " " + resourceName);
800
797
} catch (SAXParseException e) {
801
798
log.error(sm.getString("contextConfig.contextParse",
827
823
* Adjust docBase.
829
825
protected void fixDocBase()
830
826
throws IOException {
832
828
Host host = (Host) context.getParent();
833
829
String appBase = host.getAppBase();
835
831
boolean unpackWARs = true;
836
832
if (host instanceof StandardHost) {
837
unpackWARs = ((StandardHost) host).isUnpackWARs()
833
unpackWARs = ((StandardHost) host).isUnpackWARs()
838
834
&& ((StandardContext) context).getUnpackWAR();
929
925
context.setDocBase(docBase);
934
protected void antiLocking()
937
if ((context instanceof StandardContext)
930
protected void antiLocking() throws IOException {
932
if ((context instanceof StandardContext)
938
933
&& ((StandardContext) context).getAntiResourceLocking()) {
940
935
Host host = (Host) context.getParent();
941
936
String appBase = host.getAppBase();
942
937
String docBase = context.getDocBase();
943
938
if (docBase == null)
945
if (originalDocBase == null) {
946
originalDocBase = docBase;
948
docBase = originalDocBase;
940
originalDocBase = docBase;
950
942
File docBaseFile = new File(docBase);
951
943
if (!docBaseFile.isAbsolute()) {
952
944
File file = new File(appBase);
974
965
if (originalDocBase.toLowerCase().endsWith(".war")) {
975
file = new File(System.getProperty("java.io.tmpdir"),
966
antiLockingDocBase = new File(
967
System.getProperty("java.io.tmpdir"),
976
968
deploymentCount++ + "-" + docBase + ".war");
978
file = new File(System.getProperty("java.io.tmpdir"),
970
antiLockingDocBase = new File(
971
System.getProperty("java.io.tmpdir"),
979
972
deploymentCount++ + "-" + docBase);
974
antiLockingDocBase = antiLockingDocBase.getAbsoluteFile();
982
976
if (log.isDebugEnabled())
983
log.debug("Anti locking context[" + context.getPath()
984
+ "] setting docBase to " + file);
977
log.debug("Anti locking context[" + context.getPath()
978
+ "] setting docBase to " +
979
antiLockingDocBase.getPath());
986
981
// Cleanup just in case an old deployment is lying around
987
ExpandWar.delete(file);
988
if (ExpandWar.copy(docBaseFile, file)) {
989
context.setDocBase(file.getAbsolutePath());
982
ExpandWar.delete(antiLockingDocBase);
983
if (ExpandWar.copy(docBaseFile, antiLockingDocBase)) {
984
context.setDocBase(antiLockingDocBase.getPath());
998
991
* Process a "init" event for this Context.
1000
993
protected void init() {
1001
994
// Called from StandardContext.init()
1003
if (webDigester == null){
1004
webDigester = createWebDigester();
1005
webDigester.getParser();
1008
996
if (contextDigester == null){
1009
997
contextDigester = createContextDigester();
1010
998
contextDigester.getParser();
1014
1002
log.debug(sm.getString("contextConfig.init"));
1015
1003
context.setConfigured(false);
1018
1006
contextConfig();
1022
1010
} catch (IOException e) {
1023
1011
log.error(sm.getString(
1024
1012
"contextConfig.fixDocBase", context.getPath()), e);
1015
createWebXmlDigester(context.getXmlNamespaceAware(),
1016
context.getXmlValidation());
1031
1021
* Process a "before start" event for this Context.
1033
1023
protected synchronized void beforeStart() {
1037
1027
} catch (IOException e) {
1038
1028
log.error(sm.getString("contextConfig.antiLocking"), e);
1045
1035
* Process a "start" event for this Context.
1050
1040
if (log.isDebugEnabled())
1051
1041
log.debug(sm.getString("contextConfig.start"));
1053
// Set properties based on DefaultContext
1054
Container container = context.getParent();
1055
if( !context.getOverride() ) {
1056
if( container instanceof Host ) {
1057
// Reset the value only if the attribute wasn't
1058
// set on the context.
1059
xmlValidation = context.getXmlValidation();
1060
if (!xmlValidation) {
1061
xmlValidation = ((Host)container).getXmlValidation();
1064
xmlNamespaceAware = context.getXmlNamespaceAware();
1065
if (!xmlNamespaceAware){
1067
= ((Host)container).getXmlNamespaceAware();
1070
container = container.getParent();
1074
1043
// Process the default and application web.xml files
1075
1044
defaultWebConfig();
1076
1045
applicationWebConfig();
1225
// Removing sercurity role
1194
// Removing security role
1226
1195
String[] securityRoles = context.findSecurityRoles();
1227
1196
for (i = 0; i < securityRoles.length; i++) {
1228
1197
context.removeSecurityRole(securityRoles[i]);
1263
1232
// Remove (partially) folders and files created by antiLocking
1264
Host host = (Host) context.getParent();
1265
String appBase = host.getAppBase();
1266
String docBase = context.getDocBase();
1267
if ((docBase != null) && (originalDocBase != null)) {
1268
File docBaseFile = new File(docBase);
1269
if (!docBaseFile.isAbsolute()) {
1270
docBaseFile = new File(appBase, docBase);
1233
if (antiLockingDocBase != null) {
1272
1234
// No need to log failure - it is expected in this case
1273
ExpandWar.delete(docBaseFile, false);
1235
ExpandWar.delete(antiLockingDocBase, false);
1282
1244
* Process a "destroy" event for this Context.
1309
1271
for (int j = 0; j < roles.length; j++) {
1310
1272
if (!"*".equals(roles[j]) &&
1311
1273
!context.findSecurityRole(roles[j])) {
1312
log.info(sm.getString("contextConfig.role.auth", roles[j]));
1274
log.warn(sm.getString("contextConfig.role.auth", roles[j]));
1313
1275
context.addSecurityRole(roles[j]);
1321
1283
Wrapper wrapper = (Wrapper) wrappers[i];
1322
1284
String runAs = wrapper.getRunAs();
1323
1285
if ((runAs != null) && !context.findSecurityRole(runAs)) {
1324
log.info(sm.getString("contextConfig.role.runas", runAs));
1286
log.warn(sm.getString("contextConfig.role.runas", runAs));
1325
1287
context.addSecurityRole(runAs);
1327
1289
String names[] = wrapper.findSecurityReferences();
1328
1290
for (int j = 0; j < names.length; j++) {
1329
1291
String link = wrapper.findSecurityReference(names[j]);
1330
1292
if ((link != null) && !context.findSecurityRole(link)) {
1331
log.info(sm.getString("contextConfig.role.link", link));
1293
log.warn(sm.getString("contextConfig.role.link", link));
1332
1294
context.addSecurityRole(link);
1341
1303
* Get config base.
1343
1305
protected File getConfigBase() {
1345
1307
new File(System.getProperty("catalina.base"), "conf");
1346
1308
if (!configBase.exists()) {
1349
1311
return configBase;
1354
1316
protected String getHostConfigPath(String resourceName) {
1355
1317
StringBuffer result = new StringBuffer();
1356
1318
Container container = context;