View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership. The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License. You may obtain a copy of the License at
9    * 
10   *      http://www.apache.org/licenses/LICENSE-2.0
11   * 
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.river.tool.envcheck.plugins;
19  
20  import org.apache.river.tool.envcheck.AbstractPlugin;
21  import org.apache.river.tool.envcheck.Plugin;
22  import org.apache.river.tool.envcheck.EnvCheck;
23  import org.apache.river.tool.envcheck.Reporter;
24  import org.apache.river.tool.envcheck.Reporter.Message;
25  import org.apache.river.tool.envcheck.SubVMTask;
26  
27  import java.io.File;
28  import java.io.IOException;
29  import java.net.URLClassLoader;
30  import java.net.URL;
31  import java.util.ArrayList;
32  import java.util.HashSet;
33  import java.util.jar.JarFile;
34  import java.util.jar.Manifest;
35  import java.util.StringTokenizer;
36  
37  import org.apache.river.start.SharedActivationGroupDescriptor;
38  
39  /**
40   * Check whether <code>jsk-platform.jar</code> is in the classpath
41   * of the command-line being analyzed, and if the activation group
42   * if there is one.
43   */
44  public class CheckJSKPlatform extends AbstractPlugin {
45  
46      /** the plugin container */
47      private EnvCheck envCheck;
48  
49      /** classpath components already seen, to avoid circular reference loops */
50      private HashSet seen = new HashSet();
51  
52      /**
53       * Check the command line vm and the group, if there is one,
54       * for a classpath containing <code>jsk-platform.jar</code>.
55       *
56       * @param envCheck the plugin container
57       */
58      public void run(EnvCheck envCheck) {
59          this.envCheck = envCheck;
60  	String classpath = envCheck.getJarToRun();
61  	if (classpath != null) {
62  	    checkPlatform(classpath, getString("jarfile"));
63  	} else {
64  	    classpath = envCheck.getClasspath();
65  	    checkPlatform(classpath, getString("cmdline"));
66  	}
67  	SharedActivationGroupDescriptor gd = envCheck.getGroupDescriptor();
68  	if (gd != null) {
69  	    classpath = gd.getClasspath();
70  	    checkPlatform(classpath, getString("grouppath"));
71  	}
72      }
73  
74      /**
75       * Check <code>classpath</code> for the existence of
76       * <code>jsk-platform.jar</code>.
77       * 
78       * @param classpath the classpath to check
79       * @param source the source description
80       */
81      private void checkPlatform(String classpath, String source) {
82  	Message message;
83  	String[] paths = parseClasspath(classpath, source);
84  	for (int i = 0; i < paths.length; i++) {
85  	    if (paths[i].endsWith("jsk-platform.jar")) {
86  		message = new Message(Reporter.INFO,
87  				      getString("hasplatform"),
88  				      getString("platformExp"));
89  		Reporter.print(message, source);
90  		return;
91  	    }
92  	}
93  	message = new Message(Reporter.WARNING,
94  			      getString("noplatform"),
95  			      getString("platformExp"));
96  	Reporter.print(message, source);
97      }
98  
99      /**
100      * Separate each of the components making up the classpath into
101      * separate tokens. For tokens which resolve to jar files, recursively
102      * include their Class-Path manifest entries if defined. Verify
103      * each component for existence and accessibility.
104      */
105     private String[] parseClasspath(String path, String source) {
106 	if (path == null || path.trim().length() == 0) {
107 	    return new String[0];
108 	}
109 	ArrayList list = new ArrayList();
110 	StringTokenizer tok = new StringTokenizer(path, File.pathSeparator);
111 	while (tok.hasMoreTokens()) {
112 	    String item = tok.nextToken();
113 	    list.addAll(checkItem(item, source));
114 	}
115 	return (String[]) list.toArray(new String[list.size()]);
116     }
117 
118     /**
119      * Checks a component on the classpath for existence and accessibility.
120      * If the item meets these criteria, it is placed in a list which
121      * is returned to the caller. If the item is a JAR file whose manifest
122      * which contains a <code>Class-Path</code> manifest entry, then each
123      * of those items are checked and conditionally added to the list
124      * as well (recursively). If an <code>item</code> has been seen
125      * previously, and empty list is returned immediately.
126      *
127      * @param item the classpath component to verify 
128      * @param source the source descriptive text
129      * @return the list containing this item and all items referred to by
130      *         this item.
131      */
132     private ArrayList checkItem(String item, String source) {
133 	Message message;
134 	ArrayList list = new ArrayList();
135 	if (seen.contains(item)) {
136 	    return list;
137 	}
138 	seen.add(item);
139 	File itemFile = new File(item);
140 	if (!itemFile.exists()) {
141 	    message = new Message(Reporter.WARNING,
142 				  getString("nosuchitem", item),
143 				  null);
144 	    Reporter.print(message, source);
145 	    return list;
146 	}
147 	if (!itemFile.canRead()) {
148 	    message = new Message(Reporter.WARNING,
149 				  getString("unreadableitem", item),
150 				  null);
151 	    Reporter.print(message, source);
152 	    return list;
153 	}
154 	list.add(item);
155 	JarFile jar;
156 	try {
157 	    jar = new JarFile(item);
158 	} catch (IOException e) {  // probably not a zip/jar file
159 	    return list;
160 	}
161 	Manifest manifest;
162 	try {
163 	    manifest = jar.getManifest();
164 	    if (manifest == null) {
165 		return list;
166 	    }
167 	} catch (IOException e) {
168 	    e.printStackTrace();
169 	    return list;
170 	}
171 	String classPath = manifest.getMainAttributes().getValue("Class-Path");
172 	if (classPath != null) {
173 	    StringTokenizer tok = new StringTokenizer(classPath);
174 	    while (tok.hasMoreTokens()) {
175 		String fileName = tok.nextToken();
176 		File nextJar = new File(itemFile.getParentFile(), fileName);
177 		source = source + ": " + item + " Manifest Class-Path";
178 		list.addAll(checkItem(nextJar.toString(), source));
179 	    }
180 	}
181         return list;
182     }
183 }