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.util;
18
19 import java.util.Locale;
20
21 /**
22  * Utility class to manage context names so there is one place where the
23  * conversions between baseName, path and version take place.
24  */

25 public final class ContextName {
26     public static final String ROOT_NAME = "ROOT";
27     private static final String VERSION_MARKER = "##";
28     private static final String FWD_SLASH_REPLACEMENT = "#";
29
30     private final String baseName;
31     private final String path;
32     private final String version;
33     private final String name;
34
35
36     /**
37      * Creates an instance from a context name, display name, base name,
38      * directory name, WAR name or context.xml name.
39      *
40      * @param name  The name to use as the basis for this object
41      * @param stripFileExtension    If a .war or .xml file extension is present
42      *                              at the end of the provided name should it be
43      *                              removed?
44      */

45     public ContextName(String name, boolean stripFileExtension) {
46
47         String tmp1 = name;
48
49         // Convert Context names and display names to base names
50
51         // Strip off any leading "/"
52         if (tmp1.startsWith("/")) {
53             tmp1 = tmp1.substring(1);
54         }
55
56         // Replace any remaining /
57         tmp1 = tmp1.replaceAll("/", FWD_SLASH_REPLACEMENT);
58
59         // Insert the ROOT name if required
60         if (tmp1.startsWith(VERSION_MARKER) || "".equals(tmp1)) {
61             tmp1 = ROOT_NAME + tmp1;
62         }
63
64         // Remove any file extensions
65         if (stripFileExtension &&
66                 (tmp1.toLowerCase(Locale.ENGLISH).endsWith(".war") ||
67                         tmp1.toLowerCase(Locale.ENGLISH).endsWith(".xml"))) {
68             tmp1 = tmp1.substring(0, tmp1.length() -4);
69         }
70
71         baseName = tmp1;
72
73         String tmp2;
74         // Extract version number
75         int versionIndex = baseName.indexOf(VERSION_MARKER);
76         if (versionIndex > -1) {
77             version = baseName.substring(versionIndex + 2);
78             tmp2 = baseName.substring(0, versionIndex);
79         } else {
80             version = "";
81             tmp2 = baseName;
82         }
83
84         if (ROOT_NAME.equals(tmp2)) {
85             path = "";
86         } else {
87             path = "/" + tmp2.replaceAll(FWD_SLASH_REPLACEMENT, "/");
88         }
89
90         if (versionIndex > -1) {
91             this.name = path + VERSION_MARKER + version;
92         } else {
93             this.name = path;
94         }
95     }
96
97     /**
98      * Construct an instance from a path and version.
99      *
100      * @param path      Context path to use
101      * @param version   Context version to use
102      */

103     public ContextName(String path, String version) {
104         // Path should never be null, '/' or '/ROOT'
105         if (path == null || "/".equals(path) || "/ROOT".equals(path)) {
106             this.path = "";
107         } else {
108             this.path = path;
109         }
110
111         // Version should never be null
112         if (version == null) {
113             this.version = "";
114         } else {
115             this.version = version;
116         }
117
118         // Name is path + version
119         if ("".equals(this.version)) {
120             name = this.path;
121         } else {
122             name = this.path + VERSION_MARKER + this.version;
123         }
124
125         // Base name is converted path + version
126         StringBuilder tmp = new StringBuilder();
127         if ("".equals(this.path)) {
128             tmp.append(ROOT_NAME);
129         } else {
130             tmp.append(this.path.substring(1).replaceAll("/",
131                     FWD_SLASH_REPLACEMENT));
132         }
133         if (this.version.length() > 0) {
134             tmp.append(VERSION_MARKER);
135             tmp.append(this.version);
136         }
137         this.baseName = tmp.toString();
138     }
139
140     public String getBaseName() {
141         return baseName;
142     }
143
144     public String getPath() {
145         return path;
146     }
147
148     public String getVersion() {
149         return version;
150     }
151
152     public String getName() {
153         return name;
154     }
155
156     public String getDisplayName() {
157         StringBuilder tmp = new StringBuilder();
158         if ("".equals(path)) {
159             tmp.append('/');
160         } else {
161             tmp.append(path);
162         }
163
164         if (!"".equals(version)) {
165             tmp.append(VERSION_MARKER);
166             tmp.append(version);
167         }
168
169         return tmp.toString();
170     }
171
172     @Override
173     public String toString() {
174         return getDisplayName();
175     }
176
177
178     /**
179      * Extract the final component of the given path which is assumed to be a
180      * base name and generate a {@link ContextName} from that base name.
181      *
182      * @param path The path that ends in a base name
183      *
184      * @return the {@link ContextName} generated from the given base name
185      */

186     public static ContextName extractFromPath(String path) {
187         // Convert '\' to '/'
188         path = path.replaceAll("\\\\""/");
189         // Remove trailing '/'. Use while just in case a value ends in ///
190         while (path.endsWith("/")) {
191             path = path.substring(0, path.length() - 1);
192         }
193
194         int lastSegment = path.lastIndexOf('/');
195         if (lastSegment > 0) {
196             path = path.substring(lastSegment + 1);
197         }
198
199         return new ContextName(path, true);
200     }
201 }
202