Home | History | Annotate | Download | only in bridge
      1 /*
      2  * Copyright (C) 2014 Google Inc.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.google.caliper.bridge;
     18 
     19 import static com.google.common.base.Preconditions.checkState;
     20 
     21 import com.google.common.io.BaseEncoding;
     22 
     23 import java.io.ByteArrayInputStream;
     24 import java.io.ByteArrayOutputStream;
     25 import java.io.IOException;
     26 import java.io.ObjectInputStream;
     27 import java.io.ObjectOutputStream;
     28 
     29 /**
     30  * Serializes and deserializes WorkerSpecs as base64 encoded strings so they can be passed on the
     31  * command line to the worker.
     32  *
     33  * <p>Java serialization is a appropriate in this usecase because there are no compatibility
     34  * concerns.  The messages encoded/decoded by this class are only used to communicate with another
     35  * JVM that is running with the same version of the java classes.  Also, it should be lighter weight
     36  * and faster than other common serialization solutions.
     37  */
     38 public final class CommandLineSerializer {
     39   private CommandLineSerializer() {}
     40 
     41   /** Returns the given serializable object as a base64 encoded String. */
     42   public static String render(WorkerSpec message) {
     43     ByteArrayOutputStream bytes = new ByteArrayOutputStream();
     44     try {
     45       ObjectOutputStream out = new ObjectOutputStream(bytes);
     46       out.writeObject(message);
     47       out.close();
     48       return BaseEncoding.base64().encode(bytes.toByteArray());
     49     } catch (IOException e) {
     50       throw new RuntimeException(e);
     51     }
     52   }
     53 
     54   /** Parses the given base64 encoded string as an object of the given type. */
     55   public static WorkerSpec parse(String arg) {
     56     try {
     57       ByteArrayInputStream bais = new ByteArrayInputStream(BaseEncoding.base64().decode(arg));
     58       ObjectInputStream in = new ObjectInputStream(bais);
     59       WorkerSpec instance = (WorkerSpec) in.readObject();
     60       in.close();
     61       checkState(bais.read() == -1,
     62           "Message %s contains more than one object.", arg);
     63       return instance;
     64     } catch (IOException e) {
     65       throw new RuntimeException(e);  // assertion error?
     66     } catch (ClassNotFoundException e) {
     67       throw new RuntimeException("cannot decode message", e);
     68     }
     69   }
     70 }
     71