/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.sun.jini.tool.envcheck.plugins; import com.sun.jini.tool.envcheck.AbstractPlugin; import com.sun.jini.tool.envcheck.Plugin; import com.sun.jini.tool.envcheck.EnvCheck; import com.sun.jini.tool.envcheck.Reporter; import com.sun.jini.tool.envcheck.Reporter.Message; import com.sun.jini.tool.envcheck.SubVMTask; import java.io.File; import java.io.IOException; import java.net.URLClassLoader; import java.net.URL; import java.util.ArrayList; import java.util.HashSet; import java.util.jar.JarFile; import java.util.jar.Manifest; import java.util.StringTokenizer; import com.sun.jini.start.SharedActivationGroupDescriptor; /** * Check whether <code>jsk-platform.jar</code> is in the classpath * of the command-line being analyzed, and if the activation group * if there is one. */ public class CheckJSKPlatform extends AbstractPlugin { /** the plugin container */ private EnvCheck envCheck; /** classpath components already seen, to avoid circular reference loops */ private HashSet seen = new HashSet(); /** * Check the command line vm and the group, if there is one, * for a classpath containing <code>jsk-platform.jar</code>. * * @param envCheck the plugin container */ public void run(EnvCheck envCheck) { this.envCheck = envCheck; String classpath = envCheck.getJarToRun(); if (classpath != null) { checkPlatform(classpath, getString("jarfile")); } else { classpath = envCheck.getClasspath(); checkPlatform(classpath, getString("cmdline")); } SharedActivationGroupDescriptor gd = envCheck.getGroupDescriptor(); if (gd != null) { classpath = gd.getClasspath(); checkPlatform(classpath, getString("grouppath")); } } /** * Check <code>classpath</code> for the existence of * <code>jsk-platform.jar</code>. * * @param classpath the classpath to check * @param source the source description */ private void checkPlatform(String classpath, String source) { Message message; String[] paths = parseClasspath(classpath, source); for (int i = 0; i < paths.length; i++) { if (paths[i].endsWith("jsk-platform.jar")) { message = new Message(Reporter.INFO, getString("hasplatform"), getString("platformExp")); Reporter.print(message, source); return; } } message = new Message(Reporter.WARNING, getString("noplatform"), getString("platformExp")); Reporter.print(message, source); } /** * Separate each of the components making up the classpath into * separate tokens. For tokens which resolve to jar files, recursively * include their Class-Path manifest entries if defined. Verify * each component for existence and accessibility. */ private String[] parseClasspath(String path, String source) { if (path == null || path.trim().length() == 0) { return new String[0]; } ArrayList list = new ArrayList(); StringTokenizer tok = new StringTokenizer(path, File.pathSeparator); while (tok.hasMoreTokens()) { String item = tok.nextToken(); list.addAll(checkItem(item, source)); } return (String[]) list.toArray(new String[list.size()]); } /** * Checks a component on the classpath for existence and accessibility. * If the item meets these criteria, it is placed in a list which * is returned to the caller. If the item is a JAR file whose manifest * which contains a <code>Class-Path</code> manifest entry, then each * of those items are checked and conditionally added to the list * as well (recursively). If an <code>item</code> has been seen * previously, and empty list is returned immediately. * * @param item the classpath component to verify * @param source the source descriptive text * @return the list containing this item and all items referred to by * this item. */ private ArrayList checkItem(String item, String source) { Message message; ArrayList list = new ArrayList(); if (seen.contains(item)) { return list; } seen.add(item); File itemFile = new File(item); if (!itemFile.exists()) { message = new Message(Reporter.WARNING, getString("nosuchitem", item), null); Reporter.print(message, source); return list; } if (!itemFile.canRead()) { message = new Message(Reporter.WARNING, getString("unreadableitem", item), null); Reporter.print(message, source); return list; } list.add(item); JarFile jar; try { jar = new JarFile(item); } catch (IOException e) { // probably not a zip/jar file return list; } Manifest manifest; try { manifest = jar.getManifest(); if (manifest == null) { return list; } } catch (IOException e) { e.printStackTrace(); return list; } String classPath = manifest.getMainAttributes().getValue("Class-Path"); if (classPath != null) { StringTokenizer tok = new StringTokenizer(classPath); while (tok.hasMoreTokens()) { String fileName = tok.nextToken(); File nextJar = new File(itemFile.getParentFile(), fileName); source = source + ": " + item + " Manifest Class-Path"; list.addAll(checkItem(nextJar.toString(), source)); } } return list; } }