Package recommender.impl.webservice

Source Code of recommender.impl.webservice.WebserviceRecommender

package recommender.impl.webservice;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.util.Collection;
import java.util.SortedSet;
import java.util.TreeSet;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
import org.apache.commons.httpclient.util.IdleConnectionTimeoutThread;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.DisposableBean;

import recommender.core.interfaces.RecommenderConnector;
import recommender.core.interfaces.model.RecommendationResult;
import recommender.core.interfaces.renderer.RecommendationRenderer;
import recommender.core.util.RecommendationResultComparator;
import recommender.impl.database.IdleClosingConnectionManager;

/**
* Class for encapsulating webservice queries to recommenders
*
* @author fei
*
* @param <E> the recommendation entity
* @param <R> the recommendation
*/
public class WebserviceRecommender<E, R extends RecommendationResult> implements RecommenderConnector<E, R>, DisposableBean {
  private static final Log log = LogFactory.getLog(WebserviceRecommender.class);
 
  private static final int SOCKET_TIMEOUT_MS = 10000;
  private static final int HTTP_CONNECTION_TIMEOUT_MS = 1000;
  private static final long IDLE_TIMEOUT_MS = 3000;
 
  private boolean trusted;
  private final HttpClient client;
  // service's address
  private URL address;
  // serializes entity
  private RecommendationRenderer<E, R> renderer;
 
  // ConnectionManager
  private final IdleClosingConnectionManager connectionManager;
  private final IdleConnectionTimeoutThread idleConnectionHandler;
 
  /**
   * default constructor
   */
  public WebserviceRecommender() {
    // Create an instance of HttpClient.
    connectionManager = new IdleClosingConnectionManager();
    client = new HttpClient(connectionManager);
   
    // set default timeouts
    final HttpConnectionManagerParams connectionParams = connectionManager.getParams();
    connectionParams.setSoTimeout(SOCKET_TIMEOUT_MS);
    connectionParams.setConnectionTimeout(HTTP_CONNECTION_TIMEOUT_MS);
    connectionManager.setParams(connectionParams);
    log.debug("MAXCONNECTIONS: "+connectionParams.getMaxTotalConnections());
    log.debug("MAXCONNECTIONSPERHOST: "+connectionParams.getDefaultMaxConnectionsPerHost());
   
    // handle idle connections
    connectionManager.closeIdleConnections(IDLE_TIMEOUT_MS);
    idleConnectionHandler = new IdleConnectionTimeoutThread();
    idleConnectionHandler.addConnectionManager(connectionManager);
    idleConnectionHandler.start();
  }
  /**
   * Constructor
   * @param renderer
   * @param address
   */
  public WebserviceRecommender(final RecommendationRenderer<E, R> renderer, final URL address) {
    this(renderer);
    this.setAddress(address);
  }
 
  /**
   * inits the recommender
   * @param renderer
   */
  public WebserviceRecommender(final RecommendationRenderer<E, R> renderer) {
    this();
    this.renderer = renderer;
  }
 
  /**
   * @return the address
   */
  public URL getAddress() {
    return this.address;
  }

  /**
   * @param address the address to set
   */
  public void setAddress(URL address) {
    this.address = address;
  }
 
  /**
   * @param renderer the renderer to serialize recommendation entities and recommendation results
   */
  @Override
  public void setRecommendationRenderer(RecommendationRenderer<E, R> renderer) {
    this.renderer = renderer;
  }
 
  @Override
  public void addRecommendation(final Collection<R> recommendationResults, final E entity) {
    // render entity
    // FIXME: choose buffer size
    final StringWriter sw = new StringWriter(100);
    renderEntity(entity, sw);
   
    // Create a method instance.
    final NameValuePair[] data = { new NameValuePair(ID_RECQUERY, sw.toString()) };
    // Create a method instance and send request
    final PostMethod cnct = new PostMethod(getAddress().toString() + "/" + METHOD_GETRECOMMENDEDTAGS);
    cnct.setRequestBody(data);
    final InputStreamReader input = sendRequest(cnct);
   
    // Deal with the response.
    SortedSet<R> result = null;
    if (input != null) {
      try {
        result = renderer.parseRecommendationResultList(input);
      } catch (final Exception e) {
        log.error("Error parsing recommender response (" + getAddress().toString() + ").", e);
        result = null;
      } finally {
        try {
          input.close();
        } catch (IOException e) {
          log.error("error while closing input stream", e);
        }
      }
    }
    if (result != null) {
      recommendationResults.addAll(result);
    }
    cnct.releaseConnection();
  }
 
  @Override
  public SortedSet<R> getRecommendation(final E entity) {
    final SortedSet<R> retVal = new TreeSet<R>(new RecommendationResultComparator<R>());
    addRecommendation(retVal, entity);
    return retVal;
  }
 
  @Override
  public void setFeedback(final E entity, final R result) {
    // render entity
    final StringWriter sw = new StringWriter(100);
    renderEntity(entity, sw);
   
    // create a method instance.
    final NameValuePair[] data = { new NameValuePair(ID_FEEDBACK, sw.toString()) };

    // send request
    final PostMethod cnct = new PostMethod(getAddress().toString() + "/" + METHOD_SETFEEDBACK);
    cnct.setRequestBody(data);
    final InputStreamReader input = sendRequest(cnct);

    // Deal with the response.
    if (input != null) {
      // TODO: check for response code before parsing the state
      final String status = renderer.parseStat(input);
      log.info("Feedback status: " + status);
     
      try {
        input.close();
      } catch (IOException e) {
        log.error("error while closing connection ", e);
      }
    }
   
    cnct.releaseConnection();
  }

  @Override
  public String getInfo() {
    return "Webservice";
  }

  @Override
  public String getId() {
    return getAddress().toString();
  }
 
  @Override
  public void setNumberOfResultsToRecommend(int numberOfResultsToRecommend) {
    // nothing to do
  }
 
  /* (non-Javadoc)
   * @see recommender.core.interfaces.RecommenderConnector#getRecommendationRenderer()
   */
  @Override
  public RecommendationRenderer<E, R> getRecommendationRenderer() {
    return this.renderer;
  }

  private void renderEntity(final E entity, final StringWriter sw) {
    renderer.serializeRecommendationEntity(sw, entity);
  }

  private InputStreamReader sendRequest(final PostMethod cnct) {
    InputStreamReader input = null;
   
    try {
      // Execute the method.
      final int statusCode = client.executeMethod(cnct);
     
      if (statusCode != HttpStatus.SC_OK) {
        log.error("Method at " + getAddress().toString() + " failed: " + cnct.getStatusLine());
      } else {
        // Read the response body.
        // responseBody = cnct.getResponseBody();
        input = new InputStreamReader(cnct.getResponseBodyAsStream(), "UTF-8");
      }
    } catch (final HttpException e) {
      log.fatal("Fatal protocol violation("+getAddress()+"): " + e.getMessage(), e);
    } catch (final UnsupportedEncodingException ex) {
      // returns InputStream with default encoding if a exception
      // is thrown with utf-8 support
      log.fatal("Encoding error("+getAddress()+"): " + ex.getMessage(), ex);
    } catch (final IOException e) {
      log.fatal("Fatal transport error("+getAddress()+"): " + e.getMessage(), e);
    } catch (final Exception e) {
      log.fatal("Unknown error ("+getAddress()+")", e);
    }
   
    // all done.
    return input;
  }

  @Override
  public void destroy() throws Exception {
    // needed to prevent a failing spring-context to start more and more threads
    if (idleConnectionHandler != null) {
      idleConnectionHandler.shutdown();
    }
  }

  /**
   * @return the trusted
   */
  @Override
  public boolean isTrusted() {
    return this.trusted;
  }

  /**
   * @param trusted the trusted to set
   */
  public void setTrusted(boolean trusted) {
    this.trusted = trusted;
  }
}
TOP

Related Classes of recommender.impl.webservice.WebserviceRecommender

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.