/* * 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.start.NonActivatableServiceDescriptor; import com.sun.jini.start.SharedActivatableServiceDescriptor; import com.sun.jini.start.SharedActivationGroupDescriptor; import com.sun.jini.start.ServiceDescriptor; import com.sun.jini.tool.envcheck.AbstractPlugin; import com.sun.jini.tool.envcheck.EnvCheck; import com.sun.jini.tool.envcheck.Plugin; import com.sun.jini.tool.envcheck.Reporter; import com.sun.jini.tool.envcheck.Reporter.Message; import com.sun.jini.tool.envcheck.SubVMTask; import com.sun.jini.tool.envcheck.Util; import java.io.File; import java.io.IOException; import java.net.InetAddress; import java.net.URL; import java.net.URLClassLoader; import java.rmi.activation.ActivationException; import java.rmi.activation.ActivationGroup; import java.rmi.RMISecurityManager; import java.util.ArrayList; import java.util.Enumeration; import java.util.Iterator; import java.util.Properties; import java.util.ResourceBundle; import java.util.Set; import net.jini.config.Configuration; import net.jini.config.ConfigurationException; import net.jini.config.ConfigurationFile; import net.jini.config.ConfigurationProvider; import net.jini.config.NoSuchEntryException; /** * Check that the persistence directory supplied by any * <code>SharedActivatableServiceDescriptor</code>s are either non-existant or * empty. Check is performed in a subtask VM started identically to how the * activation system would have started it. The first entry in the service * configuration named <code>persistenceDirectory</code> is checked. Doesn't * work correctly if multiple services share a configuration. Don't know how to * handle this. */ public class CheckPersistence extends AbstractPlugin { EnvCheck envCheck; /** * Check the persistence directory for every * <code>SharedActivatableServiceDescriptor</code> in the starter * configuration. * * @param envCheck the plugin container */ public void run(EnvCheck envCheck) { this.envCheck = envCheck; ServiceDescriptor[] d = envCheck.getDescriptors(); for (int i = 0; i < d.length; i++) { if (d[i] instanceof SharedActivatableServiceDescriptor) { SharedActivatableServiceDescriptor sd = (SharedActivatableServiceDescriptor) d[i]; checkDirectory(sd); } } } /** * Launch a subtask for the given descriptor to obtain all the * <code>persistenceDirectory</code> entries. Check each * entry found for validity. * * @param sd the descriptor to check, which must be a * <code>SharedActivatableServiceDescriptor</code */ private void checkDirectory(SharedActivatableServiceDescriptor d) { SharedActivationGroupDescriptor gd = envCheck.getGroupDescriptor(); String source = getString("descfor", d.getImplClassName()); Object o = envCheck.launch(d, gd, taskName("GetEntriesTask")); if (o instanceof String[]) { checkEntries((String[]) o, d, source); } else if (o instanceof String) { Message message = new Message(Reporter.WARNING, (String) o, getString("dirExp")); Reporter.print(message, source); } else { handleUnexpectedSubtaskReturn(o, source); } } /** * Check <code>entries</code> for validity. <code>entries</code> * contains a collection of pairs, the first being the fully * qualified name of the <code>persistenceDirectory</code> entry, * and the second being its value. * * @param entries the array of entry/value pairs * @param d the descriptor * @param source the source descriptive text */ private void checkEntries(String[] entries, SharedActivatableServiceDescriptor d, String source) { if (entries.length == 0) { Message message = new Message(Reporter.WARNING, getString("noentry"), getString("dirExp")); Reporter.print(message, source); } for (int i = 0; i < entries.length; i += 2) { String name = entries[i]; String dir = entries[i + 1]; String loopSource = source + ": " + name + "=" + dir; Object lobj = checkDir(dir, d); Message message; if (lobj == null) { message = new Message(Reporter.INFO, getString("dirOK"), getString("dirExp")); Reporter.print(message, loopSource); } else if (lobj instanceof String) { message = new Message(Reporter.ERROR, (String) lobj, getString("dirExp")); Reporter.print(message, loopSource); } else { handleUnexpectedSubtaskReturn(lobj, loopSource); } } } /** * Perform a check on the given persistence directory. * * @param dir the name of the directory to check * @param d the service descriptor * @return <code>null</code> if the specified directory is empty * or non-existant (i.e. OK). Otherwise returns an error message * or <code>Throwable</code> returned by the subtask. */ private Object checkDir(String dir, SharedActivatableServiceDescriptor d) { if (dir == null) { return getString("nulldir"); } String taskName = taskName("CheckDirTask"); String[] args = new String[]{dir}; SharedActivationGroupDescriptor g = envCheck.getGroupDescriptor(); return envCheck.launch(d, g, taskName, args); } /** * Perform directory check with an active security policy in place. */ public static class CheckDirTask implements SubVMTask { private ResourceBundle bundle = Util.getResourceBundle(CheckPersistence.class); public Object run(String[] args) { System.setSecurityManager(new RMISecurityManager()); String dir = args[0]; File dirFile = new File(dir); if (!dirFile.exists()) { return null; // the OK value } if (!dirFile.isDirectory()) { return Util.getString("notadir", bundle, dir); } File[] contents = dirFile.listFiles(); if (contents == null) { // should never happen return Util.getString("emptylist", bundle, dir); } if (contents.length > 0) { return Util.getString("dirnotempty", bundle, dir); } return null; // directory exists but is empty } } /** * The subtask which obtains the list of persistence directory entries. The * arg list is cleaned up, the configuration in obtained, and a String array * of pairs of all entries named <code>persistenceDirectory</code> and * their associated value is returned. */ public static class GetEntriesTask implements SubVMTask { private ResourceBundle bundle = Util.getResourceBundle(CheckPersistence.class); public Object run(String[] args) { try { Configuration config = ConfigurationProvider.getInstance(args); return getEntries(config); } catch (ConfigurationException e) { return Util.getString("configproblem", bundle, e.getMessage()); } catch (Exception e) { return e; } } /** * Obtain all of the <code>persistenceDirectory</code> entries in the * configuration and return them as pairs in a <code>String</code> * array. * * @param conf the configuration to examine * @return the array of entry/value pairs */ private Object getEntries(Configuration conf) { ConfigurationFile cf = (ConfigurationFile) conf; ArrayList list = new ArrayList(); Set names = cf.getEntryNames(); Iterator it = names.iterator(); String s = ""; while (it.hasNext()) { String name = (String) it.next(); s += name + "\n"; int lastDot = name.lastIndexOf(".persistenceDirectory"); if (lastDot > 0) { String component = name.substring(0, lastDot); try { String dir = (String) conf.getEntry(component, "persistenceDirectory", String.class, null); list.add(name); list.add(dir); } catch (ConfigurationException e) { return e; } } } return list.toArray(new String[list.size()]); } } }