1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17 package org.apache.catalina.startup;
18
19 import java.io.File;
20 import java.io.FileInputStream;
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.net.MalformedURLException;
24 import java.net.URI;
25 import java.net.URISyntaxException;
26 import java.net.URL;
27 import java.nio.file.InvalidPathException;
28
29 import org.apache.tomcat.util.file.ConfigurationSource;
30 import org.apache.tomcat.util.res.StringManager;
31
32 public class CatalinaBaseConfigurationSource implements ConfigurationSource {
33
34     protected static final StringManager sm = StringManager.getManager(Constants.Package);
35
36     private final String serverXmlPath;
37     private final File catalinaBaseFile;
38     private final URI catalinaBaseUri;
39
40     public CatalinaBaseConfigurationSource(File catalinaBaseFile, String serverXmlPath) {
41         this.catalinaBaseFile = catalinaBaseFile;
42         catalinaBaseUri = catalinaBaseFile.toURI();
43         this.serverXmlPath = serverXmlPath;
44     }
45
46     @Override
47     public Resource getServerXml() throws IOException {
48         IOException ioe = null;
49         Resource result = null;
50         try {
51             if (serverXmlPath == null || serverXmlPath.equals(Catalina.SERVER_XML)) {
52                 result = ConfigurationSource.super.getServerXml();
53             } else {
54                 result = getResource(serverXmlPath);
55             }
56         } catch (IOException e) {
57             ioe = e;
58         }
59         if (result == null) {
60             // Compatibility with legacy server-embed.xml location
61             InputStream stream = getClass().getClassLoader().getResourceAsStream("server-embed.xml");
62             if (stream != null) {
63                 try {
64                     result = new Resource(stream, getClass().getClassLoader().getResource("server-embed.xml").toURI());
65                 } catch (URISyntaxException e) {
66                     stream.close();
67                 }
68             }
69         }
70
71         if (result == null && ioe != null) {
72             throw ioe;
73         } else {
74             return result;
75         }
76     }
77
78     @Override
79     public Resource getResource(String name) throws IOException {
80         // Location was originally always a file before URI support was added so
81         // try file first.
82
83         File f = new File(name);
84         if (!f.isAbsolute()) {
85             f = new File(catalinaBaseFile, name);
86         }
87         if (f.isFile()) {
88             return new Resource(new FileInputStream(f), f.toURI());
89         }
90
91         // Try classloader
92         InputStream stream = getClass().getClassLoader().getResourceAsStream(name);
93         if (stream != null) {
94             try {
95                 return new Resource(stream, getClass().getClassLoader().getResource(name).toURI());
96             } catch (InvalidPathException e) {
97                 // Ignore. Some valid file URIs can trigger this.
98                 stream.close();
99             } catch (URISyntaxException e) {
100                 stream.close();
101                 throw new IOException(sm.getString("catalinaConfigurationSource.cannotObtainURL", name), e);
102             }
103         }
104
105         // Then try URI.
106         URI uri = null;
107         try {
108             uri = getURI(name);
109         } catch (IllegalArgumentException e) {
110             throw new IOException(sm.getString("catalinaConfigurationSource.cannotObtainURL", name), e);
111         }
112
113         // Obtain the input stream we need
114         try {
115             URL url = uri.toURL();
116             return new Resource(url.openConnection().getInputStream(), uri);
117         } catch (MalformedURLException e) {
118             throw new IOException(sm.getString("catalinaConfigurationSource.cannotObtainURL", name), e);
119         }
120     }
121
122     @Override
123     public URI getURI(String name) {
124         File f = new File(name);
125         if (!f.isAbsolute()) {
126             f = new File(catalinaBaseFile, name);
127         }
128         if (f.isFile()) {
129             return f.toURI();
130         }
131
132         // Try classloader
133         try {
134             URL resource = getClass().getClassLoader().getResource(name);
135             if (resource != null) {
136                 return resource.toURI();
137             }
138         } catch (Exception e) {
139             // Ignore
140         }
141
142         // Then try URI.
143         // Using resolve() enables the code to handle relative paths that did
144         // not point to a file
145         URI uri;
146         if (catalinaBaseUri != null) {
147             uri = catalinaBaseUri.resolve(name);
148         } else {
149             uri = URI.create(name);
150         }
151         return uri;
152     }
153
154 }
155