1 package com.soapuser.soap.server.util;
    2 
    3 import java.lang.reflect.*;
    4 import java.util.*;
    5 import java.io.*;
    6 
    7 /**
    8  * This class generates a DeploymentDescriptor xml file for SOAP 2.0
    9  * It takes a rather crude option to generate bean mapping entries
   10  * for all classes that are NOT in the java.lang package. This may be
   11  * refined later
   12  */
   13 public class DDGenerator {
   14 
   15   private static StringBuffer replace( StringBuffer original, String toBeReplaced, String by )
   16   throws Exception
   17   {
   18     String s = original.toString();
   19     int start = s.indexOf( toBeReplaced );
   20     if ( start == -1 )
   21       throw new Exception( "Could not find string " + toBeReplaced + " in " + s );
   22     return original.replace( start, start+toBeReplaced.length(), by );
   23   }
   24 
   25   private static StringBuffer readTemplate( String fileName )
   26   throws Exception
   27   {
   28     File file = new File( fileName );
   29     InputStream is = new BufferedInputStream( new FileInputStream( file ) );
   30     byte[] buffer = new byte[ (int)file.length() ];
   31     is.read( buffer );
   32     is.close();
   33     return new StringBuffer( new String( buffer ) );
   34   }
   35 
   36   private static void writeDD( String fileName, String content )
   37   throws Exception
   38   {
   39     File file = new File( fileName );
   40     OutputStream os = new BufferedOutputStream( new FileOutputStream( file ) );
   41     os.write( content.getBytes() );
   42     os.close();
   43   }
   44 
   45   private static String getLastNamePart( String className ) {
   46     int dot = className.lastIndexOf( '.' );
   47     if ( dot == -1 )
   48       return className;
   49     return className.substring( dot+1 );
   50   }
   51 
   52   /**
   53    * utility:
   54    * - if clazz is an array, loops to find the base type
   55    * - if clazz is 'a proper bean to be serialized', returns it
   56    * - otherwise return null
   57    */
   58   private static Class getGenuineClass( Class clazz ) {
   59     while ( clazz.isArray() )
   60       clazz = clazz.getComponentType();
   61     if ( clazz.isPrimitive() || clazz.getName().startsWith( "java.lang." ) )
   62       return null;
   63     return clazz;
   64   }
   65 
   66   /**
   67    * returns a String corresponding to the mapping of a particular bean
   68    */
   69   private static String generateMapping(
   70     String template, Class service, Class beanClass, Set beansDone )
   71   throws Exception
   72   {
   73     if ( beanClass == null || beansDone.contains( beanClass ) )
   74       return "";
   75     StringBuffer work = new StringBuffer( template );  // clone
   76     replace( work, "%serviceName%", getLastNamePart( service.getName() ) );
   77     replace( work, "%fullyQualifiedBeanClassName%", beanClass.getName() );
   78     replace( work, "%fullyQualifiedBeanClassName%", beanClass.getName() ); // x2!
   79     beansDone.add( beanClass );
   80     return work.toString();
   81   }
   82 
   83   /**
   84    * returns a String corresponding to the mapping of all the bean's subtypes
   85    */
   86   private static String generateSubtypeMappings(
   87             String template, Class service, Class beanClass, Set beansDone )
   88   throws Exception
   89   {
   90     if ( beanClass == null )
   91         return "";
   92     Field[] fields = beanClass.getDeclaredFields();
   93     StringBuffer b = new StringBuffer();
   94     Class subBeanClass;
   95 
   96     //For each field in the bean
   97     for ( int i=0; i<fields.length; i++ )
   98     {
   99         //take note of the field type,
  100         subBeanClass = getGenuineClass( fields[i].getType() );
  101 
  102         //generate mapping for it
  103         b.append( generateMapping( template, service, subBeanClass, beansDone ) );
  104 
  105         //and (recursively) for its subtypes
  106         b.append( generateSubtypeMappings( template, service, subBeanClass, beansDone ) );
  107     }
  108     return b.toString();
  109   }
  110 
  111   /**
  112    * returns a String corresponding to the mapping of all the service's beans
  113    */
  114   private static String generateMappings( String template, Class service )
  115   throws Exception
  116   {
  117     Method[] methods = service.getMethods();
  118     Set beansDone = new HashSet();
  119     StringBuffer b = new StringBuffer();
  120     Class beanClass;
  121 
  122     //For each method
  123     for ( int i=0; i<methods.length; i++ )
  124     {
  125         //take note of the return type,
  126         beanClass = getGenuineClass( methods[i].getReturnType() );
  127 
  128         //generate mapping for it,
  129         b.append( generateMapping( template, service, beanClass, beansDone ) );
  130 
  131         //and (recursively) for its subtypes.
  132         b.append( generateSubtypeMappings( template, service, beanClass, beansDone ) );
  133 
  134         //For each parameter of the method
  135         for ( int j=0; j<methods[i].getParameterTypes().length; j++ )
  136         {
  137             //take note of the parameter type
  138             beanClass = getGenuineClass( methods[i].getParameterTypes()[j] );
  139 
  140             //generate a mapping for it
  141             b.append( generateMapping( template, service, beanClass, beansDone ) );
  142 
  143             //and (recursively for its subtypes
  144             b.append( generateSubtypeMappings( template, service, beanClass, beansDone ) );
  145         }
  146     }
  147     return b.toString();
  148   }
  149 
  150   /**
  151    * uses DD xml templates where variables to be expanded are surrounded by %
  152    * - by definition, all public methods of the claa passed are exported
  153    * - by definition, all Objects passed to or returned from these methods are exported
  154    */
  155   public static void generateDD(
  156     String serviceName,
  157     String implementationName,
  158     String ddFileName )
  159     throws Exception
  160   {
  161     String ddTemplateFileName = "DeploymentDescriptorTemplate.xml";
  162     String ddMappingEntryTemplateFileName = "DDMappingEntryTemplate.xml";
  163     Class service = Class.forName( serviceName );
  164     Class implementation = Class.forName( implementationName );
  165     // find out methods
  166     Method[] methods = service.getMethods();
  167     StringBuffer spaceDelimitedMethodNameList = new StringBuffer();
  168     for ( int i=0; i<methods.length; i++ )
  169       spaceDelimitedMethodNameList.append( methods[i].getName() ).append( ' ' );
  170 
  171     // produce the header
  172     StringBuffer dd = readTemplate( ddTemplateFileName );
  173     replace( dd, "%serviceName%", getLastNamePart( service.getName() ) );
  174     replace( dd, "%spaceDelimitedMethodNameList%", spaceDelimitedMethodNameList.toString() );
  175     replace( dd, "%fullyQualifiedImplementationClassName%", implementation.getName() );
  176 
  177     // find out exchanged beans: we have as many beans as distinct returned or passed classes
  178     StringBuffer dm = readTemplate( ddMappingEntryTemplateFileName );
  179     String dmOut = generateMappings( dm.toString(), service );
  180 
  181     // produce the big string
  182     replace( dd, "%mappingEntryList%", dmOut.toString() );
  183 
  184     // write the DeploymentDescriptor
  185     writeDD( ddFileName, dd.toString() );
  186 
  187     // echo the string for convenience
  188     System.out.println( dd.toString() );
  189     System.out.println( "Wrote " + ddFileName );
  190   }
  191 
  192   public static void main( String[] args )
  193   throws Exception
  194   {
  195     if ( args.length < 3 )
  196       System.out.println( "Pass <intf. class name> <impl. class name> <output_file_name>" );
  197     else {
  198       generateDD( args[0], args[1], args[2] );
  199     if ( args.length >= 4 ) {
  200       org.apache.soap.server.ServiceManagerClient.main(
  201         new String[] {
  202           "http://localhost:8080/soap/servlet/rpcrouter",
  203           "deploy",
  204           args[2]
  205         }
  206       );
  207       System.out.println( "Deployed " + args[2] );
  208     }
  209   }
  210   }
  211 }
HTML generated by Java2Html, 2000 Think Tank Ltd, Douglas, Isle Of Man. All rights reserved