001: /*
002: * Copyright 1999,2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.apache.catalina.util;
017:
018: import java.util.HashMap;
019: import java.util.Iterator;
020: import java.util.jar.Manifest;
021: import java.util.jar.Attributes;
022: import java.util.ArrayList;
023:
024: /**
025: * Representation of a Manifest file and its available extensions and
026: * required extensions
027: *
028: * @author Greg Murray
029: * @author Justyna Horwat
030: * @version $Revision: 1.5 $ $Date: 2004/02/27 14:58:50 $
031: *
032: */
033: public class ManifestResource {
034:
035: // ------------------------------------------------------------- Properties
036:
037: // These are the resource types for determining effect error messages
038: public static final int SYSTEM = 1;
039: public static final int WAR = 2;
040: public static final int APPLICATION = 3;
041:
042: private HashMap availableExtensions = null;
043: private ArrayList requiredExtensions = null;
044:
045: private String resourceName = null;
046: private int resourceType = -1;
047:
048: public ManifestResource(String resourceName, Manifest manifest,
049: int resourceType) {
050: this .resourceName = resourceName;
051: this .resourceType = resourceType;
052: processManifest(manifest);
053: }
054:
055: /**
056: * Gets the name of the resource
057: *
058: * @return The name of the resource
059: */
060: public String getResourceName() {
061: return resourceName;
062: }
063:
064: /**
065: * Gets the map of available extensions
066: *
067: * @return Map of available extensions
068: */
069: public HashMap getAvailableExtensions() {
070: return availableExtensions;
071: }
072:
073: /**
074: * Gets the list of required extensions
075: *
076: * @return List of required extensions
077: */
078: public ArrayList getRequiredExtensions() {
079: return requiredExtensions;
080: }
081:
082: // --------------------------------------------------------- Public Methods
083:
084: /**
085: * Gets the number of available extensions
086: *
087: * @return The number of available extensions
088: */
089: public int getAvailableExtensionCount() {
090: return (availableExtensions != null) ? availableExtensions
091: .size() : 0;
092: }
093:
094: /**
095: * Gets the number of required extensions
096: *
097: * @return The number of required extensions
098: */
099: public int getRequiredExtensionCount() {
100: return (requiredExtensions != null) ? requiredExtensions.size()
101: : 0;
102: }
103:
104: /**
105: * Convienience method to check if this <code>ManifestResource</code>
106: * has an requires extensions.
107: *
108: * @return true if required extensions are present
109: */
110: public boolean requiresExtensions() {
111: return (requiredExtensions != null) ? true : false;
112: }
113:
114: /**
115: * Convienience method to check if this <code>ManifestResource</code>
116: * has an extension available.
117: *
118: * @param key extension identifier
119: *
120: * @return true if extension available
121: */
122: public boolean containsExtension(String key) {
123: return (availableExtensions != null) ? availableExtensions
124: .containsKey(key) : false;
125: }
126:
127: /**
128: * Returns <code>true</code> if all required extension dependencies
129: * have been meet for this <code>ManifestResource</code> object.
130: *
131: * @return boolean true if all extension dependencies have been satisfied
132: */
133: public boolean isFulfilled() {
134: if (requiredExtensions == null) {
135: return false;
136: }
137: Iterator it = requiredExtensions.iterator();
138: while (it.hasNext()) {
139: Extension ext = (Extension) it.next();
140: if (!ext.isFulfilled())
141: return false;
142: }
143: return true;
144: }
145:
146: public String toString() {
147:
148: StringBuffer sb = new StringBuffer("ManifestResource[");
149: sb.append(resourceName);
150:
151: sb.append(", isFulfilled=");
152: sb.append(isFulfilled() + "");
153: sb.append(", requiredExtensionCount =");
154: sb.append(getRequiredExtensionCount());
155: sb.append(", availableExtensionCount=");
156: sb.append(getAvailableExtensionCount());
157: switch (resourceType) {
158: case SYSTEM:
159: sb.append(", resourceType=SYSTEM");
160: break;
161: case WAR:
162: sb.append(", resourceType=WAR");
163: break;
164: case APPLICATION:
165: sb.append(", resourceType=APPLICATION");
166: break;
167: }
168: sb.append("]");
169: return (sb.toString());
170: }
171:
172: // -------------------------------------------------------- Private Methods
173:
174: private void processManifest(Manifest manifest) {
175: availableExtensions = getAvailableExtensions(manifest);
176: requiredExtensions = getRequiredExtensions(manifest);
177: }
178:
179: /**
180: * Return the set of <code>Extension</code> objects representing optional
181: * packages that are required by the application associated with the
182: * specified <code>Manifest</code>.
183: *
184: * @param manifest Manifest to be parsed
185: *
186: * @return List of required extensions, or null if the application
187: * does not require any extensions
188: */
189: private ArrayList getRequiredExtensions(Manifest manifest) {
190:
191: Attributes attributes = manifest.getMainAttributes();
192: String names = attributes.getValue("Extension-List");
193: if (names == null)
194: return null;
195:
196: ArrayList extensionList = new ArrayList();
197: names += " ";
198:
199: while (true) {
200:
201: int space = names.indexOf(' ');
202: if (space < 0)
203: break;
204: String name = names.substring(0, space).trim();
205: names = names.substring(space + 1);
206:
207: String value = attributes
208: .getValue(name + "-Extension-Name");
209: if (value == null)
210: continue;
211: Extension extension = new Extension();
212: extension.setExtensionName(value);
213: extension.setImplementationURL(attributes.getValue(name
214: + "-Implementation-URL"));
215: extension.setImplementationVendorId(attributes
216: .getValue(name + "-Implementation-Vendor-Id"));
217: String version = attributes.getValue(name
218: + "-Implementation-Version");
219: extension.setImplementationVersion(version);
220: extension.setSpecificationVersion(attributes.getValue(name
221: + "-Specification-Version"));
222: extensionList.add(extension);
223: }
224: return extensionList;
225: }
226:
227: /**
228: * Return the set of <code>Extension</code> objects representing optional
229: * packages that are bundled with the application associated with the
230: * specified <code>Manifest</code>.
231: *
232: * @param manifest Manifest to be parsed
233: *
234: * @return Map of available extensions, or null if the web application
235: * does not bundle any extensions
236: */
237: private HashMap getAvailableExtensions(Manifest manifest) {
238:
239: Attributes attributes = manifest.getMainAttributes();
240: String name = attributes.getValue("Extension-Name");
241: if (name == null)
242: return null;
243:
244: HashMap extensionMap = new HashMap();
245:
246: Extension extension = new Extension();
247: extension.setExtensionName(name);
248: extension.setImplementationURL(attributes
249: .getValue("Implementation-URL"));
250: extension.setImplementationVendor(attributes
251: .getValue("Implementation-Vendor"));
252: extension.setImplementationVendorId(attributes
253: .getValue("Implementation-Vendor-Id"));
254: extension.setImplementationVersion(attributes
255: .getValue("Implementation-Version"));
256: extension.setSpecificationVersion(attributes
257: .getValue("Specification-Version"));
258:
259: if (!extensionMap.containsKey(extension.getUniqueId())) {
260: extensionMap.put(extension.getUniqueId(), extension);
261: }
262:
263: return extensionMap;
264: }
265:
266: }
|