aboutsummaryrefslogblamecommitdiffstats
path: root/infrastructure/com.etherpad.openofficeservice/importexport.scala
blob: f5150ad4e7bad43db58cd38f9b8eca6db0d69993 (plain) (tree)




























































































































































































                                                                                                                                      
/**
 * Copyright 2009 Google Inc.
 * 
 * Licensed 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.etherpad.openofficeservice;

import net.appjet.common.sars.{SarsServer,SarsMessageHandler};

import java.io.{DataInputStream,DataOutputStream};
import java.io.{File,FileOutputStream,ByteArrayInputStream,ByteArrayOutputStream};

class OOSException(m: String) extends RuntimeException(m);
class UnsupportedFormatException(format: String) extends OOSException("Unsupported format: "+format);
object TemporaryFailure extends OOSException("Temporary failure");

// stub object here. Please replace if you'd like to use openoffice!
object OpenOfficeServerUtility {
  def checkServerAvailability(host: String, port: Int): Boolean = {
    return false;
  }
  def runOpenOfficeServer(path: String, host: String, port: Int, timeout: Int, wait: Boolean) {
    // nothing
  }
}

class OpenOfficeFileConverter {
  def setOpenOfficeServerDetails(host: String, port: Int) {
    // nothing
  }
  
  def convertFile(src: File, dst: File, converter: String, extension: String): Boolean = {
    return false;
  }
}

object OpenOfficeService {
  val formats = Map(
    "pdf" -> "writer_pdf_Export",
    "doc" -> "MS Word 97",
    "html" -> "HTML (StarWriter)",
    "odt" -> "writer8",
    //"html" -> "XHTML Writer File",
    "txt" -> "Text"
  );

  def createTempFile(bytes: Array[byte], suffix: String) = {
    var f = File.createTempFile("ooconvert-", if (suffix == null) { null } else if (suffix == "") { "" } else { "."+suffix });
  	if (bytes != null) {
  		val fos = new FileOutputStream(f);
  		fos.write(bytes);		
  	}
  	f;
  }

  var soffice = "soffice";
  def setExecutable(exec: String) {
    soffice = exec;
  }

  def convertFile(from: String, to: String, bytes: Array[byte]): Array[byte] = {
    if (from == to) {
      return bytes;
    }

  	val tempFile = createTempFile(bytes, from);
  	val outFile = createTempFile(null, to);

  	val openOfficeServerHost = "localhost";
  	val openOfficeServerPort = 8100;
  	if (! OpenOfficeServerUtility.checkServerAvailability(openOfficeServerHost, openOfficeServerPort)) {
  		try {
  			OpenOfficeServerUtility.runOpenOfficeServer(soffice, openOfficeServerHost, openOfficeServerPort, 20000, true);
  		} catch {
  		  case e: java.io.IOException => {
  		    e.printStackTrace();
  		    throw TemporaryFailure;
    		}
  		}
  	}
  	var converter = new OpenOfficeFileConverter();
  	converter.setOpenOfficeServerDetails(openOfficeServerHost, openOfficeServerPort);
  	var status = false;
  	try {
  		status = converter.convertFile(tempFile, outFile, formats(to), to);
  	} catch {
  	  case e => {
  	    e.printStackTrace();
  		  throw new OOSException("Unknown exception occurred: "+e.getMessage());
		  }
  	}
  	if (status == false) {
  	  throw new UnsupportedFormatException(from);
  	}
  	net.appjet.common.util.BetterFile.getFileBytes(outFile);
  }

  def main(args: Array[String]) {
    if (args.length > 0) {
      soffice = args(0);
      if (soffice.length == 0) {
        exit(1);
      }
    }
    
    // Query format:
    // from: String, to: String, count: Int, bytes: Array[byte]
    // Response format:
    // status: Int, <data>
    //   status 0 (success) - <data>: count: Int, bytes: Array[byte]
    //   status 1 (temporary failure) - <data>: <none>
    //   status 2 (permanent failure) - <data>: type: Int
    //               type - 0: unknown failure.
    //                    - 1: unsupported format
    val handler = new SarsMessageHandler {
      override def handle(b: Array[byte]): Option[Array[byte]] = {
        val is = new DataInputStream(new ByteArrayInputStream(b));
        val from = is.readUTF;
        val to = is.readUTF;
        val len = is.readInt;
        val bytes = new Array[byte](len);
        is.readFully(bytes);
        var status = 0;
        var permfailuretype = 0;
        
        println("Converting "+from+" -> "+to+" ("+len+" bytes)");
        
        val output = try {
          convertFile(from, to, bytes);
        } catch {
          case TemporaryFailure => {
            status = 1;
            null;
          }
          case e: UnsupportedFormatException => {
            status = 2;
            permfailuretype = 1;
            null;
          }
          case e => {
            status = 2;
            permfailuretype = 0;
            e.printStackTrace();
            null;
          }
        }
        
        val retBytes = new ByteArrayOutputStream();
        val ret = new DataOutputStream(retBytes);
        if (status != 0) {
          ret.writeInt(status); // error
          status match {
            case 2 => {
              ret.writeInt(permfailuretype);
            }
            case _ => { }
          }
        } else {
          ret.writeInt(0); // success
          ret.writeInt(output.length);
          ret.write(output, 0, output.length);
        }
        Some(retBytes.toByteArray());
      }
    }
    
    val server = new SarsServer("ooffice-password", handler, None, 8101);
    server.start();
    println("Server running...");
    server.join();
    println("Server quitting...");
  }
}