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.ArrayList;
20 import java.util.jar.Attributes;
21 import java.util.jar.Manifest;
22
23 /**
24 * Representation of a Manifest file and its available extensions and
25 * required extensions
26 *
27 * @author Greg Murray
28 * @author Justyna Horwat
29 */
30 public class ManifestResource {
31
32 // ------------------------------------------------------------- Properties
33
34 // These are the resource types for determining effect error messages
35 public static final int SYSTEM = 1;
36 public static final int WAR = 2;
37 public static final int APPLICATION = 3;
38
39 private ArrayList<Extension> availableExtensions = null;
40 private ArrayList<Extension> requiredExtensions = null;
41
42 private final String resourceName;
43 private final int resourceType;
44
45 public ManifestResource(String resourceName, Manifest manifest,
46 int resourceType) {
47 this.resourceName = resourceName;
48 this.resourceType = resourceType;
49 processManifest(manifest);
50 }
51
52 /**
53 * Gets the name of the resource
54 *
55 * @return The name of the resource
56 */
57 public String getResourceName() {
58 return resourceName;
59 }
60
61 /**
62 * Gets the list of available extensions
63 *
64 * @return List of available extensions
65 */
66 public ArrayList<Extension> getAvailableExtensions() {
67 return availableExtensions;
68 }
69
70 /**
71 * Gets the list of required extensions
72 *
73 * @return List of required extensions
74 */
75 public ArrayList<Extension> getRequiredExtensions() {
76 return requiredExtensions;
77 }
78
79 // --------------------------------------------------------- Public Methods
80
81 /**
82 * Gets the number of available extensions
83 *
84 * @return The number of available extensions
85 */
86 public int getAvailableExtensionCount() {
87 return (availableExtensions != null) ? availableExtensions.size() : 0;
88 }
89
90 /**
91 * Gets the number of required extensions
92 *
93 * @return The number of required extensions
94 */
95 public int getRequiredExtensionCount() {
96 return (requiredExtensions != null) ? requiredExtensions.size() : 0;
97 }
98
99 /**
100 * Returns <code>true</code> if all required extension dependencies
101 * have been meet for this <code>ManifestResource</code> object.
102 *
103 * @return boolean true if all extension dependencies have been satisfied
104 */
105 public boolean isFulfilled() {
106 if (requiredExtensions == null) {
107 return true;
108 }
109 for (Extension ext : requiredExtensions) {
110 if (!ext.isFulfilled()) return false;
111 }
112 return true;
113 }
114
115 @Override
116 public String toString() {
117 StringBuilder sb = new StringBuilder("ManifestResource[");
118 sb.append(resourceName);
119
120 sb.append(", isFulfilled=");
121 sb.append(isFulfilled() +"");
122 sb.append(", requiredExtensionCount =");
123 sb.append(getRequiredExtensionCount());
124 sb.append(", availableExtensionCount=");
125 sb.append(getAvailableExtensionCount());
126 switch (resourceType) {
127 case SYSTEM : sb.append(", resourceType=SYSTEM"); break;
128 case WAR : sb.append(", resourceType=WAR"); break;
129 case APPLICATION : sb.append(", resourceType=APPLICATION"); break;
130 }
131 sb.append("]");
132 return sb.toString();
133 }
134
135
136 // -------------------------------------------------------- Private Methods
137
138 private void processManifest(Manifest manifest) {
139 availableExtensions = getAvailableExtensions(manifest);
140 requiredExtensions = getRequiredExtensions(manifest);
141 }
142
143 /**
144 * Return the set of <code>Extension</code> objects representing optional
145 * packages that are required by the application associated with the
146 * specified <code>Manifest</code>.
147 *
148 * @param manifest Manifest to be parsed
149 *
150 * @return List of required extensions, or null if the application
151 * does not require any extensions
152 */
153 private ArrayList<Extension> getRequiredExtensions(Manifest manifest) {
154
155 Attributes attributes = manifest.getMainAttributes();
156 String names = attributes.getValue("Extension-List");
157 if (names == null)
158 return null;
159
160 ArrayList<Extension> extensionList = new ArrayList<>();
161 names += " ";
162
163 while (true) {
164
165 int space = names.indexOf(' ');
166 if (space < 0)
167 break;
168 String name = names.substring(0, space).trim();
169 names = names.substring(space + 1);
170
171 String value =
172 attributes.getValue(name + "-Extension-Name");
173 if (value == null)
174 continue;
175 Extension extension = new Extension();
176 extension.setExtensionName(value);
177 extension.setImplementationURL
178 (attributes.getValue(name + "-Implementation-URL"));
179 extension.setImplementationVendorId
180 (attributes.getValue(name + "-Implementation-Vendor-Id"));
181 String version = attributes.getValue(name + "-Implementation-Version");
182 extension.setImplementationVersion(version);
183 extension.setSpecificationVersion
184 (attributes.getValue(name + "-Specification-Version"));
185 extensionList.add(extension);
186 }
187 return extensionList;
188 }
189
190 /**
191 * Return the set of <code>Extension</code> objects representing optional
192 * packages that are bundled with the application associated with the
193 * specified <code>Manifest</code>.
194 *
195 * @param manifest Manifest to be parsed
196 *
197 * @return List of available extensions, or null if the web application
198 * does not bundle any extensions
199 */
200 private ArrayList<Extension> getAvailableExtensions(Manifest manifest) {
201
202 Attributes attributes = manifest.getMainAttributes();
203 String name = attributes.getValue("Extension-Name");
204 if (name == null)
205 return null;
206
207 ArrayList<Extension> extensionList = new ArrayList<>();
208
209 Extension extension = new Extension();
210 extension.setExtensionName(name);
211 extension.setImplementationURL(
212 attributes.getValue("Implementation-URL"));
213 extension.setImplementationVendor(
214 attributes.getValue("Implementation-Vendor"));
215 extension.setImplementationVendorId(
216 attributes.getValue("Implementation-Vendor-Id"));
217 extension.setImplementationVersion(
218 attributes.getValue("Implementation-Version"));
219 extension.setSpecificationVersion(
220 attributes.getValue("Specification-Version"));
221
222 extensionList.add(extension);
223
224 return extensionList;
225 }
226
227 }
228