You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@river.apache.org by ni...@apache.org on 2008/12/10 06:09:43 UTC

svn commit: r724973 [1/9] - in /incubator/river/jtsk/skunk/niclas1/tools: ./ src/ src/main/ src/main/java/ src/main/java/com/ src/main/java/com/sun/ src/main/java/com/sun/jini/ src/main/java/com/sun/jini/tool/ src/main/java/com/sun/jini/tool/envcheck/ ...

Author: niclas
Date: Tue Dec  9 21:09:41 2008
New Revision: 724973

URL: http://svn.apache.org/viewvc?rev=724973&view=rev
Log:
A first cut at the modularization of River Experiment. More refactorings to follow. Seems I need a multi-part commit, as SVN is complaining about individual files.

Added:
    incubator/river/jtsk/skunk/niclas1/tools/
    incubator/river/jtsk/skunk/niclas1/tools/pom.xml
    incubator/river/jtsk/skunk/niclas1/tools/src/
    incubator/river/jtsk/skunk/niclas1/tools/src/main/
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/CheckConfigurationFile.java
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/CheckSer.java
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/ClassDep.java
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/ClassDepLoader.java
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/ClassServer.java
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/ComputeDigest.java
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/ComputeHttpmdCodebase.java
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/DebugDynamicPolicyProvider.java
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/JarWrapper.java
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/PreferredListGen.java
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/build.xml
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/envcheck/
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/envcheck/AbstractPlugin.java
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/envcheck/EnvCheck.java
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/envcheck/Plugin.java
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/envcheck/Reporter.java
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/envcheck/SubVM.java
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/envcheck/SubVMTask.java
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/envcheck/Util.java
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/envcheck/package.html
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/envcheck/plugins/
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/envcheck/plugins/CheckActivationSystem.java
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/envcheck/plugins/CheckCodebase.java
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/envcheck/plugins/CheckConfig.java
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/envcheck/plugins/CheckJDK1_4.java
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/envcheck/plugins/CheckJSKPlatform.java
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/envcheck/plugins/CheckJSKPolicy.java
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/envcheck/plugins/CheckJsseProps.java
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/envcheck/plugins/CheckLoggingConfig.java
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/envcheck/plugins/CheckNoLoopback.java
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/envcheck/plugins/CheckPersistence.java
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/envcheck/plugins/CheckPolicy.java
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/envcheck/plugins/FileAccessCheckTask.java
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/envcheck/plugins/resources/
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/envcheck/plugins/resources/checkactivationsystem.properties
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/envcheck/plugins/resources/checkcodebase.properties
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/envcheck/plugins/resources/checkconfig.properties
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/envcheck/plugins/resources/checkjdk1_4.properties
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/envcheck/plugins/resources/checkjskplatform.properties
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/envcheck/plugins/resources/checkjskpolicy.properties
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/envcheck/plugins/resources/checkjsseprops.properties
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/envcheck/plugins/resources/checkloggingconfig.properties
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/envcheck/plugins/resources/checknoloopback.properties
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/envcheck/plugins/resources/checkpersistence.properties
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/envcheck/plugins/resources/checkpolicy.properties
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/envcheck/resources/
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/envcheck/resources/envcheck.properties
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/package.html
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/resources/
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/resources/checkconfig.properties
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/resources/checkser.properties
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/resources/classdep.properties
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/resources/classserver.properties
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/resources/computecodebase.properties
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/resources/computedigest.properties
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/resources/jarwrapper.properties
    incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/resources/preflistgen.properties
    incubator/river/jtsk/skunk/niclas1/tools/src/main/resources/
    incubator/river/jtsk/skunk/niclas1/tools/src/main/resources/manifest/
    incubator/river/jtsk/skunk/niclas1/tools/src/main/resources/manifest/tools/
    incubator/river/jtsk/skunk/niclas1/tools/src/main/resources/manifest/tools/META-INF/
    incubator/river/jtsk/skunk/niclas1/tools/src/main/resources/manifest/tools/META-INF/services/
    incubator/river/jtsk/skunk/niclas1/tools/src/main/resources/manifest/tools/META-INF/services/com.sun.jini.tool.envcheck.Plugin
    incubator/river/jtsk/skunk/niclas1/tools/src/test/
    incubator/river/jtsk/skunk/niclas1/tools/src/test/java/
    incubator/river/jtsk/skunk/niclas1/tools/src/test/resources/

Added: incubator/river/jtsk/skunk/niclas1/tools/pom.xml
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/tools/pom.xml?rev=724973&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/tools/pom.xml (added)
+++ incubator/river/jtsk/skunk/niclas1/tools/pom.xml Tue Dec  9 21:09:41 2008
@@ -0,0 +1,29 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.river.service</groupId>
+    <artifactId>master-services</artifactId>
+    <version>10.0-SNAPSHOT</version>
+  </parent>
+  <groupId>org.apache.river.service</groupId>
+  <artifactId>river-tools</artifactId>
+  <name>Apache River - Tools</name>
+  <packaging>jar</packaging>
+  <version>10.0-SNAPSHOT</version>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.river.api</groupId>
+      <artifactId>river-url</artifactId>
+      <version>10.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.river.service</groupId>
+      <artifactId>river-start</artifactId>
+      <version>10.0-SNAPSHOT</version>
+    </dependency>
+
+  </dependencies>
+</project>

Added: incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/CheckConfigurationFile.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/CheckConfigurationFile.java?rev=724973&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/CheckConfigurationFile.java (added)
+++ incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/CheckConfigurationFile.java Tue Dec  9 21:09:41 2008
@@ -0,0 +1,956 @@
+/*
+ * 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;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.io.Reader;
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.text.MessageFormat;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.MissingResourceException;
+import java.util.Properties;
+import java.util.ResourceBundle;
+import java.util.Set;
+import java.util.StringTokenizer;
+import net.jini.config.Configuration;
+import net.jini.config.ConfigurationException;
+import net.jini.config.ConfigurationFile;
+import net.jini.config.ConfigurationProvider;
+
+/**
+ * Checks the format of the source for a {@link ConfigurationFile}. The source
+ * is specified with either a file, URL, or standard input, as well as with
+ * override options. The checks include syntax and static type checking, and
+ * require access to any application types mentioned in the source. <p>
+ *
+ * The following items are discussed below:
+ *
+ * <ul>
+ * <li> <a href="#entry_desc">Entry description files</a>
+ * <li> {@linkplain #main Command line options}
+ * <li> <a href="#examples">Examples for running CheckConfigurationFile</a>
+ * </ul> <p>
+ *
+ * <a name="entry_desc">
+ * <h3>Entry description files</h3>
+ * </a>
+ *
+ * Checking of the source can be controlled by specifying one or more entry
+ * description files, each listing the names and types of entries that are
+ * allowed to appear in the source. Each entry description file is treated as a
+ * {@link Properties} source file, where each key is the fully qualified name
+ * of an entry (<code><i>component</i>.<i>name</i></code>) and each value
+ * specifies the expected type for that entry. Types should be specified in
+ * normal source code format, except that whitespace is not permitted between
+ * tokens. Types in the <code>java.lang</code> package may be unqualified, but
+ * fully qualified names must be used for other types (<code>import</code>
+ * statements are not supported).  If any entry description files are supplied,
+ * then any public entry that appears in the source being checked, whose fully
+ * qualified name does not appear in any entry description file, or whose
+ * actual type is not assignable to the expected type, is treated as an
+ * error. <p>
+ *
+ * Entry description files for all of the Apache River release services and utilities
+ * are provided in the <code>configentry</code> subdirectory beneath the
+ * top-level directory of the Apache River release installation. <p>
+ *
+ * Here is a sample entry description file:
+ *
+ * <blockquote>
+ * <pre>
+ * comp.foo Integer[]
+ * comp.bar net.jini.core.constraint.MethodConstraints
+ * comp.baz long
+ * </pre>
+ * </blockquote>
+ *
+ * Here is an associated sample configuration file:
+ *
+ * <blockquote>
+ * <pre>
+ * import net.jini.constraint.*;
+ * import net.jini.core.constraint.*;
+ * comp {
+ *     foo = new Integer[] { new Integer(3) };
+ *     bar = new BasicMethodConstraints(
+ *               new InvocationConstraints(Integrity.YES, null));
+ *     baz = 33L;
+ * }
+ * </pre>
+ * </blockquote> <p>
+ *
+ * <a name="examples">
+ * <h3>Examples for running CheckConfigurationFile</h3>
+ * </a>
+ *
+ * This utility can be run from the {@linkplain #main command line}, or by
+ * calling the {@link #check(String, ClassLoader, String[], String,
+ * PrintStream)} or {@link #check(ConfigurationFile, Properties, ClassLoader,
+ * PrintStream)} methods. <p>
+ *
+ * An example command line usage is:
+ *
+ * <blockquote>
+ * <pre>
+ * java -jar <var><b>install_dir</b></var>/lib/checkconfigurationfile.jar \
+ *      -cp <var><b>install_dir</b></var>/lib/norm.jar:<var><b>install_dir</b></var>/lib/jsk-platform.jar \
+ *      -entries <var><b>install_dir</b></var>/configentry/norm-transient \
+ *      <var><b>your-norm.config</b></var>
+ * </pre>
+ * </blockquote>
+ *
+ * where <var><b>install_dir</b></var> is the directory where the Apache River release
+ * is installed, and <var><b>your-norm.config</b></var> is a configuration
+ * source file intended for use with the transient {@linkplain
+ * com.sun.jini.norm Norm} service implementation. This command will print out
+ * any problems that it detects in the configuration file, including entries
+ * that are not recognized or have the wrong type for the Norm service.
+ *
+ * @author Sun Microsystems, Inc.
+ * @see ConfigurationFile
+ * @since 2.0
+ */
+public class CheckConfigurationFile
+{
+
+    /**
+     * The primitive types
+     */
+    private static final Class[] primitives = {
+        Boolean.TYPE, Byte.TYPE, Character.TYPE, Short.TYPE, Integer.TYPE,
+        Long.TYPE, Float.TYPE, Double.TYPE
+    };
+
+    private static final String RESOURCE =
+        "META-INF/services/" + Configuration.class.getName();
+
+    private static ResourceBundle resources;
+    private static boolean resinit = false;
+
+    /* This class is not instantiable */
+    private CheckConfigurationFile()
+    {
+    }
+
+    /**
+     * Command line interface for checking the format of source and override
+     * options for a {@link ConfigurationFile}, printing messages to
+     * <code>System.err</code> for any errors found. If errors are found,
+     * continues to check the rest of the source and overrides, and then calls
+     * <code>System.exit</code> with a non-<code>zero</code> argument. <p>
+     *
+     * The command line arguments are:
+     *
+     * <pre>
+     * [ -cp <var><b>classpath</b></var> ] [ -entries <var><b>entrydescs</b></var> ] <var><b>location</b></var> [ <var><b>option</b></var>... ]
+     * </pre>
+     * or
+     * <pre>
+     * [ -cp <var><b>classpath</b></var> ] [ -entries <var><b>entrydescs</b></var> ] -stdin [ <var><b>location</b></var> [ <var><b>option</b></var>... ] ]
+     * </pre>
+     * or
+     * <pre>
+     * -help
+     * </pre>
+     *
+     * If the only argument is <code>-help</code>, a usage message is
+     * printed. <p>
+     *
+     * The <var><b>classpath</b></var> value for the <code>-cp</code> option
+     * specifies one or more directories and zip/JAR files, separated by the
+     * {@linkplain File#pathSeparatorChar path separator character}, where the
+     * application classes are located.  A class loader that loads classes from
+     * this path will be created, with the extension class loader as its
+     * parent. If this option is not specified, the system class loader is used
+     * instead. <p>
+     *
+     * The <var><b>entrydescs</b></var> value for the <code>-entries</code>
+     * option specifies one or more entry description files, separated by the
+     * path separator character. <p>
+     *
+     * The <var><b>location</b></var> argument specifies the source file to be
+     * checked. If the <code>-stdin</code> option is used, then the actual
+     * source data will be read from standard input, and any
+     * <var><b>location</b></var> argument is simply used for identification
+     * purposes in error messages. <p>
+     *
+     * The remaining arguments specify any entry override values that should be
+     * passed to the <code>ConfigurationFile</code> constructor. <p>
+     *
+     * The class loader obtained above is used to resolve all expected types
+     * specified in the entry description files, and to obtain the
+     * configuration provider. The configuration provider class is found from
+     * the class loader in the same manner as specified by {@link
+     * ConfigurationProvider}.  The resulting class must be {@link
+     * ConfigurationFile} or a subclass; if it is a subclass, it must have a
+     * public constructor with three parameters of type: {@link Reader},
+     * <code>String[]</code>, and {@link ClassLoader}. An instance of the
+     * provider is created by passing that constructor a <code>Reader</code>
+     * for the source file to be checked, the location and entry override
+     * values, and the class loader.
+     */
+    public static void main( String[] args )
+    {
+        if( args.length == 0 )
+        {
+            usage();
+        }
+        else if( args.length == 1 && "-help".equals( args[ 0 ] ) )
+        {
+            print( System.err, "checkconfig.usage", File.pathSeparator );
+            return;
+        }
+        String classPath = null;
+        String entriesPath = null;
+        boolean stdin = false;
+        int i = 0;
+        while( i < args.length )
+        {
+            if( "-cp".equals( args[ i ] ) )
+            {
+                if( args.length < i + 2 )
+                {
+                    usage();
+                }
+                classPath = args[ i + 1 ];
+                i += 2;
+            }
+            else if( "-entries".equals( args[ i ] ) )
+            {
+                if( args.length < i + 2 )
+                {
+                    usage();
+                }
+                entriesPath = args[ i + 1 ];
+                i += 2;
+            }
+            else if( "-stdin".equals( args[ i ] ) )
+            {
+                stdin = true;
+                i++;
+            }
+            else
+            {
+                break;
+            }
+        }
+        if( !stdin && i == args.length )
+        {
+            usage();
+        }
+        ClassLoader loader = ClassLoader.getSystemClassLoader();
+        if( classPath != null )
+        {
+            loader = loader.getParent();
+        }
+        String[] configOptions = new String[args.length - i];
+        System.arraycopy( args, i, configOptions, 0, configOptions.length );
+        boolean ok = check( classPath, loader, stdin, configOptions,
+                            entriesPath, System.err );
+        if( !ok )
+        {
+            System.exit( 1 );
+        }
+    }
+
+    private static void usage()
+    {
+        print( System.err, "checkconfig.usage", File.pathSeparator );
+        System.exit( 1 );
+    }
+
+    /**
+     * Returns information about the specified permitted entries, returning
+     * null if there is a problem loading properties from the files.
+     */
+    private static Properties getEntries( String files, PrintStream err )
+    {
+        Properties entries = new Properties();
+        StringTokenizer tokens =
+            new StringTokenizer( files, File.pathSeparator );
+        while( tokens.hasMoreTokens() )
+        {
+            String file = tokens.nextToken();
+            InputStream in = null;
+            try
+            {
+                in = new BufferedInputStream( new FileInputStream( file ) );
+                entries.load( in );
+            }
+            catch( FileNotFoundException e )
+            {
+                print( err, "checkconfig.notfound", file );
+                return null;
+            }
+            catch( Throwable t )
+            {
+                print( err, "checkconfig.read.err",
+                       new String[]{ file, t.getClass().getName(),
+                                     t.getLocalizedMessage() } );
+                t.printStackTrace( err );
+                return null;
+            }
+            finally
+            {
+                if( in != null )
+                {
+                    try
+                    {
+                        in.close();
+                    }
+                    catch( IOException e )
+                    {
+                    }
+                }
+            }
+        }
+        return entries;
+    }
+
+    /**
+     * Checks the format of a configuration source file. Returns
+     * <code>true</code> if there are no errors, and <code>false</code>
+     * otherwise. <p>
+     *
+     * The <code>classPath</code> argument specifies one or more directories
+     * and zip/JAR files, separated by the {@linkplain File#pathSeparatorChar
+     * path separator character}, where the application classes are located.  A
+     * class loader that loads classes from this path will be created, with
+     * <code>loader</code> as its parent. The <code>ConfigurationFile</code> is
+     * created with this class loader, and all expected types specified in
+     * entry description files are resolved in this class loader. If
+     * <code>classPath</code> is <code>null</code>, then <code>loader</code> is
+     * used instead. <p>
+     *
+     * The class loader is used to resolve all expected types specified in the
+     * entry description files, and to obtain the configuration provider. The
+     * configuration provider class is found from the class loader in the same
+     * manner as specified by {@link ConfigurationProvider}.  The resulting
+     * class must be {@link ConfigurationFile} or a subclass; if it is a
+     * subclass, it must have a public constructor with three parameters of
+     * type: {@link Reader}, <code>String[]</code>, and {@link
+     * ClassLoader}. An instance of the provider is created by passing that
+     * constructor a <code>Reader</code> for the source file to be checked,
+     * the location and entry override values, and the class loader.
+     *
+     * @param classPath     the search path for application classes, or
+     *                      <code>null</code> to use the specified class loader
+     * @param loader        the parent class loader to use for application classes if
+     *                      <code>classPath</code> is not <code>null</code>, otherwise the class
+     *                      loader to use for resolving application classes
+     * @param configOptions the configuration source file to check, plus any
+     *                      entry overrides
+     * @param entriesPath   one or more entry description files, separated by the
+     *                      path separator character, or <code>null</code>
+     * @param err           the stream to use for printing errors
+     * @return <code>true</code> if there are no errors, <code>false</code>
+     *         otherwise
+     * @throws NullPointerException if <code>loader</code>,
+     *                              <code>configOptions</code>, or <code>err</code> is <code>null</code>
+     * @see #check(ConfigurationFile, Properties, ClassLoader, PrintStream)
+     */
+    public static boolean check( String classPath,
+                                 ClassLoader loader,
+                                 String[] configOptions,
+                                 String entriesPath,
+                                 PrintStream err )
+    {
+        if( loader == null || configOptions == null || err == null )
+        {
+            throw new NullPointerException();
+        }
+        return check( classPath, loader, false, configOptions, entriesPath,
+                      err );
+    }
+
+    /**
+     * Checks the format of a configuration source file, using classes loaded
+     * from classPath and loader, requiring entries to match the names and
+     * values from entriesPath (unless entriesPath is null).  If stdin is
+     * true, reads the configuration source from standard input.
+     */
+    private static boolean check( String classPath,
+                                  ClassLoader loader,
+                                  boolean stdin,
+                                  String[] configOptions,
+                                  String entriesPath,
+                                  PrintStream err )
+    {
+        if( classPath != null )
+        {
+            StringTokenizer st = new StringTokenizer( classPath,
+                                                      File.pathSeparator );
+            URL[] urls = new URL[st.countTokens()];
+            for( int i = 0; st.hasMoreTokens(); i++ )
+            {
+                String elt = st.nextToken();
+                try
+                {
+                    urls[ i ] = new File( elt ).toURI().toURL();
+                }
+                catch( MalformedURLException e )
+                {
+                    print( err, "checkconfig.classpath", elt );
+                    return false;
+                }
+            }
+            loader = URLClassLoader.newInstance( urls, loader );
+        }
+        Properties entries = null;
+        if( entriesPath != null )
+        {
+            entries = getEntries( entriesPath, err );
+            if( entries == null )
+            {
+                return false;
+            }
+        }
+        String location;
+        if( configOptions.length == 0 )
+        {
+            location = "(stdin)";
+        }
+        else
+        {
+            configOptions = (String[]) configOptions.clone();
+            location = configOptions[ 0 ];
+            configOptions[ 0 ] = "-";
+        }
+        Constructor configCons = getProviderConstructor( loader, err );
+        if( configCons == null )
+        {
+            return false;
+        }
+        try
+        {
+            InputStream in;
+            if( stdin )
+            {
+                in = System.in;
+            }
+            else if( "-".equals( location ) )
+            {
+                in = new ByteArrayInputStream( new byte[0] );
+            }
+            else
+            {
+                try
+                {
+                    URL url = new URL( location );
+                    in = url.openStream();
+                }
+                catch( MalformedURLException e )
+                {
+                    in = new FileInputStream( location );
+                }
+            }
+            Object config;
+            try
+            {
+                config = configCons.newInstance(
+                    new Object[]{ new InputStreamReader( in ),
+                                  configOptions,
+                                  loader } );
+            }
+            finally
+            {
+                if( !stdin )
+                {
+                    try
+                    {
+                        in.close();
+                    }
+                    catch( IOException e )
+                    {
+                    }
+                }
+            }
+            return check( config, entries, loader, err );
+        }
+        catch( FileNotFoundException e )
+        {
+            print( err, "checkconfig.notfound", location );
+        }
+        catch( Throwable t )
+        {
+            print( err, "checkconfig.read", location, t );
+        }
+        return false;
+    }
+
+    /**
+     * Returns the (Reader, String[], ClassLoader) constructor for the
+     * resource-specified configuration provider in loader.
+     */
+    private static Constructor getProviderConstructor( ClassLoader loader,
+                                                       PrintStream err )
+    {
+        URL resource = null;
+        try
+        {
+            for( Enumeration providers = loader.getResources( RESOURCE );
+                 providers.hasMoreElements(); )
+            {
+                resource = (URL) providers.nextElement();
+            }
+        }
+        catch( IOException e )
+        {
+            print( err, "checkconfig.resources", "", e );
+        }
+        String classname = ( resource == null ?
+                             ConfigurationFile.class.getName() :
+                             getProviderName( resource, err ) );
+        if( classname == null )
+        {
+            return null;
+        }
+        try
+        {
+            Class provider = Class.forName( classname, false, loader );
+            try
+            {
+                if( !Class.forName( ConfigurationFile.class.getName(),
+                                    false, loader ).isAssignableFrom( provider ) )
+                {
+                    print( err, "checkconfig.notsubclass", classname );
+                    return null;
+                }
+                return provider.getConstructor( new Class[]{ Reader.class,
+                                                             String[].class,
+                                                             ClassLoader.class } );
+            }
+            catch( ClassNotFoundException e )
+            {
+                print( err, "checkconfig.notsubclass", classname );
+            }
+            catch( NoSuchMethodException e )
+            {
+                print( err, "checkconfig.noconstructor", classname );
+            }
+        }
+        catch( ClassNotFoundException e )
+        {
+            print( err, "checkconfig.noprovider", classname );
+        }
+        catch( Throwable t )
+        {
+            print( err, "checkconfig.provider", classname, t );
+        }
+        return null;
+    }
+
+    /**
+     * Returns the configuration provider class name specified in the contents
+     * of the URL.
+     */
+    private static String getProviderName( URL url, PrintStream err )
+    {
+        InputStream in = null;
+        try
+        {
+            in = url.openStream();
+            BufferedReader reader =
+                new BufferedReader( new InputStreamReader( in, "utf-8" ) );
+            String result = null;
+            while( true )
+            {
+                String line = reader.readLine();
+                if( line == null )
+                {
+                    break;
+                }
+                int commentPos = line.indexOf( '#' );
+                if( commentPos >= 0 )
+                {
+                    line = line.substring( 0, commentPos );
+                }
+                line = line.trim();
+                int len = line.length();
+                if( len != 0 )
+                {
+                    if( result != null )
+                    {
+                        print( err, "checkconfig.multiproviders",
+                               url.toString() );
+                        return null;
+                    }
+                    result = line;
+                }
+            }
+            if( result == null )
+            {
+                print( err, "checkconfig.missingprovider", url.toString() );
+                return null;
+            }
+            return result;
+        }
+        catch( IOException e )
+        {
+            print( err, "configconfig.read", url.toString(), e );
+            return null;
+        }
+        finally
+        {
+            if( in != null )
+            {
+                try
+                {
+                    in.close();
+                }
+                catch( IOException e )
+                {
+                }
+            }
+        }
+    }
+
+    /**
+     * Checks the format of a <code>ConfigurationFile</code>. Returns
+     * <code>true</code> if there are no errors, and <code>false</code>
+     * otherwise.
+     *
+     * @param config  the <code>ConfigurationFile</code> to check
+     * @param entries the entry descriptions to use (where each key is a fully
+     *                qualified entry name and each value is the expected type), or
+     *                <code>null</code>
+     * @param loader  the class loader to use for resolving type names used in
+     *                the entry descriptions
+     * @param err     the stream to use for printing errors
+     * @return <code>true</code> if there are no errors, <code>false</code>
+     *         otherwise
+     * @throws NullPointerException if <code>config</code>,
+     *                              <code>loader</code>, or <code>err</code> is <code>null</code>
+     * @see #check(String, ClassLoader, String[], String, PrintStream)
+     */
+    public static boolean check( ConfigurationFile config,
+                                 Properties entries,
+                                 ClassLoader loader,
+                                 PrintStream err )
+    {
+        if( config == null || loader == null || err == null )
+        {
+            throw new NullPointerException();
+        }
+        return check( (Object) config, entries, loader, err );
+    }
+
+    /**
+     * Checks the entries in config against the descriptions in entries,
+     * resolving expected types in loader.
+     */
+    private static boolean check( Object config,
+                                  Properties entries,
+                                  ClassLoader loader,
+                                  PrintStream err )
+    {
+        Method getType;
+        String[] entryNames;
+        try
+        {
+            getType = config.getClass().getMethod( "getEntryType",
+                                                   new Class[]{ String.class,
+                                                                String.class } );
+            Method getNames = config.getClass().getMethod( "getEntryNames",
+                                                           null );
+            Set entrySet = (Set) getNames.invoke( config, new Object[0] );
+            entryNames =
+                (String[]) entrySet.toArray( new String[entrySet.size()] );
+        }
+        catch( Throwable t )
+        {
+            print( err, "checkconfig.unexpected", "", t );
+            return false;
+        }
+        Arrays.sort( entryNames );
+        boolean ok = true;
+        for( int i = 0; i < entryNames.length; i++ )
+        {
+            String entryName = entryNames[ i ];
+            String expectedTypeName = entries != null
+                                      ? entries.getProperty( entryName ) : null;
+            if( entries != null && expectedTypeName == null )
+            {
+                print( err, "checkconfig.unknown", entryName );
+                ok = false;
+            }
+            try
+            {
+                int dot = entryName.lastIndexOf( '.' );
+                String component = entryName.substring( 0, dot );
+                String name = entryName.substring( dot + 1 );
+                Class type = (Class) getType.invoke( config,
+                                                     new Object[]{ component,
+                                                                   name } );
+                if( expectedTypeName != null )
+                {
+                    try
+                    {
+                        Class expectedType =
+                            findClass( expectedTypeName, loader );
+                        if( !isAssignableFrom( expectedType, type ) )
+                        {
+                            print( err, "checkconfig.mismatch",
+                                   new String[]{ entryName, typeName( type ),
+                                                 typeName( expectedType ) } );
+                            ok = false;
+                        }
+                    }
+                    catch( ClassNotFoundException e )
+                    {
+                        print( err, "checkconfig.expect.fail",
+                               new String[]{ entryName, e.getMessage() } );
+                        ok = false;
+                    }
+                    catch( Throwable t )
+                    {
+                        print( err, "checkconfig.expect.err",
+                               new String[]{ entryName, expectedTypeName,
+                                             t.getClass().getName(),
+                                             t.getLocalizedMessage() } );
+                        t.printStackTrace( err );
+                        ok = false;
+                    }
+                }
+            }
+            catch( Throwable t )
+            {
+                print( err, "checkconfig.actual", entryName, t );
+                ok = false;
+            }
+        }
+        return ok;
+    }
+
+    /**
+     * Returns the type with the specified name, including primitives and
+     * arrays, and checking the java.lang package for unqualified names.  This
+     * method supports both internal names ('[I', '[Ljava.lang.Integer;',
+     * 'java.util.Map$Entry') and source level name ('int[]', 'Integer[]',
+     * 'java.util.Map.Entry').
+     */
+    private static Class findClass( String name, ClassLoader loader )
+        throws ClassNotFoundException
+    {
+        if( name.indexOf( '.' ) < 0 )
+        {
+            for( int i = primitives.length; --i >= 0; )
+            {
+                if( name.equals( primitives[ i ].getName() ) )
+                {
+                    return primitives[ i ];
+                }
+            }
+        }
+        try
+        {
+            return Class.forName( name, false, loader );
+        }
+        catch( ClassNotFoundException notFound )
+        {
+            int bracket = name.indexOf( '[' );
+            if( bracket > 0 )
+            {
+                /* Array */
+                int dims = 0;
+                int len = name.length();
+                for( int i = bracket; i < len; i += 2, dims++ )
+                {
+                    if( name.charAt( i ) != '['
+                        || i + 1 >= len
+                        || name.charAt( i + 1 ) != ']' )
+                    {
+                        /* Invalid array class name */
+                        throw notFound;
+                    }
+                }
+                try
+                {
+                    Class base = findClass( name.substring( 0, bracket ), loader );
+                    return Array.newInstance( base, new int[dims] ).getClass();
+                }
+                catch( ClassNotFoundException e )
+                {
+                }
+            }
+            else if( name.indexOf( '.' ) < 0 )
+            {
+                /* Try java.lang package */
+                try
+                {
+                    return findClass( "java.lang." + name, loader );
+                }
+                catch( ClassNotFoundException e )
+                {
+                }
+            }
+            else
+            {
+                /* Try substituting '$' for '.' to look for nested classes */
+                int dot;
+                while( ( dot = name.lastIndexOf( '.' ) ) >= 0 )
+                {
+                    name = name.substring( 0, dot ) + '$' +
+                           name.substring( dot + 1 );
+                    try
+                    {
+                        return Class.forName( name, false, loader );
+                    }
+                    catch( ClassNotFoundException e )
+                    {
+                    }
+                }
+            }
+            throw notFound;
+        }
+    }
+
+    /**
+     * Returns the name of a type, in source code format.
+     */
+    private static String typeName( Class type )
+    {
+        if( type == null )
+        {
+            return "null";
+        }
+        StringBuffer buf = new StringBuffer();
+        if( type.isArray() )
+        {
+            Class component;
+            while( ( component = type.getComponentType() ) != null )
+            {
+                buf.append( "[]" );
+                type = component;
+            }
+        }
+        return type.getName().replace( '$', '.' ) + buf;
+    }
+
+    /**
+     * Checks if an object of type source can be assigned to a variable of type
+     * dest, where source is null for a null object.
+     */
+    private static boolean isAssignableFrom( Class dest, Class source )
+    {
+        if( dest.isPrimitive() )
+        {
+            return source == dest;
+        }
+        else
+        {
+            return source == null || dest.isAssignableFrom( source );
+        }
+    }
+
+    /**
+     * Returns a message from the resource bundle.
+     */
+    private static synchronized String getString( String key, PrintStream err )
+    {
+        if( !resinit )
+        {
+            try
+            {
+                resinit = true;
+                resources = ResourceBundle.getBundle(
+                    "com.sun.jini.tool.resources.checkconfig" );
+            }
+            catch( MissingResourceException e )
+            {
+                e.printStackTrace( err );
+            }
+        }
+        try
+        {
+            return resources != null ? resources.getString( key ) : null;
+        }
+        catch( MissingResourceException e )
+        {
+            return null;
+        }
+    }
+
+    /**
+     * If t is a ConfigurationException, uses the key keyPrefix+".fail",
+     * with source as the value for {0} and the localized message of t
+     * as the value for {1}. Otherwise, uses the key keyPrefix+".err",
+     * with source as the value for {0}, the exception class name as the
+     * value for {1}, and the localized message of t as the value for {2}.
+     */
+    private static void print( PrintStream err,
+                               String keyPrefix,
+                               String source,
+                               Throwable t )
+    {
+        if( t instanceof InvocationTargetException )
+        {
+            t = t.getCause();
+        }
+        if( t.getClass().getName().equals(
+            ConfigurationException.class.getName() ) )
+        {
+            if( t.getCause() == null )
+            {
+                print( err, keyPrefix + ".fail",
+                       new String[]{ source, t.getLocalizedMessage() } );
+                return;
+            }
+            else
+            {
+                t = t.getCause();
+            }
+        }
+        print( err, keyPrefix + ".err",
+               new String[]{ source, t.getClass().getName(),
+                             t.getLocalizedMessage() } );
+        t.printStackTrace( err );
+    }
+
+    private static void print( PrintStream err, String key, String val )
+    {
+        print( err, key, new String[]{ val } );
+    }
+
+    private static void print( PrintStream err, String key, String[] vals )
+    {
+        String fmt = getString( key, err );
+        if( fmt == null )
+        {
+            fmt = "no text found: \"" + key + "\" {0}";
+        }
+        err.println( MessageFormat.format( fmt, vals ) );
+    }
+}

Added: incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/CheckSer.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/CheckSer.java?rev=724973&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/CheckSer.java (added)
+++ incubator/river/jtsk/skunk/niclas1/tools/src/main/java/com/sun/jini/tool/CheckSer.java Tue Dec  9 21:09:41 2008
@@ -0,0 +1,180 @@
+/*
+ * 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;
+
+import java.io.File;
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+
+/**
+ * Tool to check for serializable classes that do not have explicit
+ * <code>serialVersionUID</code> fields.
+ *
+ * @author Sun Microsystems, Inc.
+ */
+public class CheckSer
+{
+
+    private static final int MASK = Modifier.STATIC | Modifier.FINAL;
+
+    /**
+     * Checks class file directory hierarchies for serializable classes
+     * that do not have explicit <code>serialVersionUID</code> fields,
+     * and prints the names of such classes to the standard output stream.
+     * The only options are zero or more filenames that specify the roots
+     * of directory hierarchies; if no filenames are specified, the single
+     * root <code>/vob/jive/classes</code> is used. In those hierarchies,
+     * each file with a name ending in the suffix <code>.class</code> is
+     * treated as a class file; the corresponding class name is obtained
+     * from the filename by stripping off both the original prefix root
+     * filename and the <code>.class</code> suffix, and replacing each file
+     * separator character with a period (<code>.</code>). Each such class
+     * is loaded from the class loader of this tool. If the class is not an
+     * interface, directly or indirectly implements {@link Serializable},
+     * and does not have a declared <code>static</code> <code>final</code>
+     * field named <code>serialVersionUID</code>, then the name of the class
+     * is printed to the standard output stream.
+     *
+     * @param args the roots of directory hierarchies
+     */
+    public static void main( String[] args )
+    {
+        if( args.length == 0 )
+        {
+            args = new String[]{ "/vob/jive/classes" };
+        }
+        for( int i = 0; i < args.length; i++ )
+        {
+            check( args[ i ], args[ i ].length() + 1 );
+        }
+    }
+
+    /**
+     * Checks the class file directory hierarchy starting from the specified
+     * directory. In the hierarchy, each file with a name ending in the
+     * suffix <code>.class</code> is treated as a class file; the
+     * corresponding class name is obtained from the filename by stripping
+     * off the first <code>strip</code> characters of prefix and the
+     * <code>.class</code> suffix, and replacing each file separator
+     * character with a period (<code>.</code>). Each such class is loaded
+     * from the class loader of this tool. If the class is not an interface,
+     * directly or indirectly implements {@link Serializable}, and does not
+     * have a declared <code>static</code> <code>final</code> field named
+     * <code>serialVersionUID</code>, then the name of the class is printed
+     * to the standard output stream.
+     *
+     * @param dir   directory hierarchy root
+     * @param strip number of characters of prefix to strip from each
+     *              class file name
+     */
+    public static void check( String dir, int strip )
+    {
+        String[] files = new File( dir ).list();
+        if( files == null )
+        {
+            print( "checkser.nodir", dir );
+            return;
+        }
+        for( int i = 0; i < files.length; i++ )
+        {
+            String file = dir + File.separatorChar + files[ i ];
+            if( file.endsWith( ".class" ) )
+            {
+                checkClass( file, strip );
+            }
+            else if( new File( file ).isDirectory() )
+            {
+                check( file, strip );
+            }
+        }
+    }
+
+    private static void checkClass( String file, int strip )
+    {
+        file = file.substring( strip, file.length() - 6 );
+        file = file.replace( File.separatorChar, '.' );
+        try
+        {
+            Class c = Class.forName( file );
+            if( c.isInterface() || !Serializable.class.isAssignableFrom( c ) )
+            {
+                return;
+            }
+            Field f = c.getDeclaredField( "serialVersionUID" );
+            if( ( f.getModifiers() & MASK ) != MASK )
+            {
+                System.out.println( file );
+            }
+        }
+        catch( ClassNotFoundException e )
+        {
+            print( "checkser.failed", file );
+        }
+        catch( NoClassDefFoundError e )
+        {
+            print( "checkser.failed", file );
+        }
+        catch( NoSuchFieldException e )
+        {
+            System.out.println( file );
+        }
+    }
+
+    private static ResourceBundle resources;
+    private static boolean resinit = false;
+
+    private static synchronized String getString( String key )
+    {
+        if( !resinit )
+        {
+            try
+            {
+                resources = ResourceBundle.getBundle(
+                    "com.sun.jini.tool.resources.checkser" );
+                resinit = true;
+            }
+            catch( MissingResourceException e )
+            {
+                e.printStackTrace();
+            }
+        }
+        try
+        {
+            return resources.getString( key );
+        }
+        catch( MissingResourceException e )
+        {
+            return null;
+        }
+    }
+
+    private static void print( String key, String val )
+    {
+        String fmt = getString( key );
+        if( fmt == null )
+        {
+            fmt = "no text found: \"" + key + "\" {0}";
+        }
+        System.out.println( MessageFormat.format( fmt, new String[]{ val } ) );
+    }
+}