// AdminWriter.java 
// $Id: AdminWriter.java,v 1.8 1998/01/23 10:08:05 bmahe Exp $
// (c) COPYRIGHT MIT and INRIA, 1997.
// Please first read the full copyright statement in file COPYRIGHT.html

package org.w3c.jigsaw.admin;

import java.io.*;
import java.util.*;

import org.w3c.www.mime.*;
import org.w3c.jigsaw.daemon.*;
import org.w3c.tools.resources.*;
import org.w3c.jigsaw.frames.*;

class AdminWriter implements AdminProtocol {

    private int writeRawResource(DataOutputStream out, Resource resource) 
	throws IOException
    {
	int    wrote      = 4;
	Vector classes    = new Vector(8);
	Vector interfaces = new Vector(8);
	// Inspect the class for interfaces and super-classes:
	for (Class c = resource.getClass(); c != null; c = c.getSuperclass()) {
	    Class intfs[] = c.getInterfaces();
	    classes.addElement(c.getName());
	    if ( intfs != null ) {
		for (int i = 0 ; i < intfs.length ; i++) 
		    interfaces.addElement(intfs[i].getName());
	    }
	}
	// Dump the class hierarchy:
	out.writeInt(classes.size()+interfaces.size());
	for (int i = 0 ; i < classes.size() ; i++) {
	    String s = (String) classes.elementAt(i);
	    wrote += getUTFLength(s);
	    out.writeUTF(s);
	}
	// Dump the interfaces:
	for (int i = 0 ; i < interfaces.size() ; i++) {
	    String s = (String) interfaces.elementAt(i);
	    wrote += getUTFLength(s);
	    out.writeUTF(s);
	}
	String id = resource.getIdentifier();
	out.writeUTF((id != null) ? id : "");
	wrote += getUTFLength("");
	return wrote;
    }

    /**
     * Get the number of bytes when encoding String in UTF7.
     * @param str The String that is to be written.
     * @return The number of bytes.
     */

    protected final int getUTFLength(String str) {
	int    strlen = str.length() ;
	int    utflen = 0 ;

	for (int i = 0 ; i < strlen ; i++) {
	    int c = str.charAt(i);
	    if ((c >= 0x0001) && (c <= 0x007F)) {
		utflen++;
	    } else if (c > 0x07FF) {
		utflen += 3;
	    } else {
		utflen += 2;
	    }
	}
	return utflen + 2 ;
    }

    /**
     * Write the given resource to the given output stream.
     * @param out The object output stream to write to.
     * @param resource The resource to write
     * @return The number of bytes wriiten out to the wire.
     * @exception IOException If something went wrong.
     */

    protected final int writeResource(DataOutputStream out
				      , Resource resource) 
	throws IOException
    {
	int wrote = 1;
	
	if (resource instanceof FramedResource) {
	  ResourceFrame[] frames = resource.getFrames();
	  out.write(WIRED_FRAMED);
	  if ((frames != null) && (frames.length > 0)) {
	    out.writeInt(frames.length);
	    for (int i=0 ; i < frames.length ; i++) {
	      String frid = frames[i].getIdentifier();
	      wrote += getUTFLength(frid);
	      out.writeUTF(frid);
	      wrote += writeResource(out, frames[i]);
	    }
	  } else {
	    out.writeInt(0);
	  }
	  wrote += writeRawResource(out, resource);
	} else {
	  out.write(WIRED_PLAIN);
	  wrote += writeRawResource(out, resource);
	}
	// Return the total number of emitted bytes:
	return wrote;
    }

    /**
     * Write that set of attributes to the given output stream.
     * @param out The object output stream to write to.
     * @param attrs The attributes to write.
     * @exception IOException If some IO error occurs.
     */

    protected int writeAttributes(DataOutputStream out
				  , Attribute attrs[]) 
	throws IOException
    {
	ByteArrayOutputStream bytes = new ByteArrayOutputStream();
	ObjectOutputStream    oout  = new ObjectOutputStream(bytes);

	Attribute ca[] = new Attribute[attrs.length];
	for (int i = 0; i < ca.length ; i++) {
	    if ( attrs[i].checkFlag(Attribute.DONTSAVE) )
		continue;
	    ca[i] = attrs[i];
	}
	oout.writeObject(ca);
	oout.close();
	byte bits[] = bytes.toByteArray(); 
	out.write(bits);
	return bits.length;
    }

    AdminWriter(ServerHandler server) {
    }

}
