/**
 * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 */

package com.liferay.portal.service.http;

import com.liferay.portal.kernel.io.ProtectedObjectInputStream;
import com.liferay.portal.kernel.servlet.HttpHeaders;
import com.liferay.portal.kernel.util.Base64;
import com.liferay.portal.kernel.util.MethodHandler;
import com.liferay.portal.kernel.util.MethodWrapper;
import com.liferay.portal.kernel.util.ObjectValuePair;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.security.auth.HttpPrincipal;
import com.liferay.portal.security.auth.PrincipalException;

import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import java.net.HttpURLConnection;
import java.net.URL;

import javax.servlet.http.HttpServletRequest;

/**
 * @author Brian Wing Shun Chan
 */
@SuppressWarnings("deprecation")
public class TunnelUtil {

	public static Object invoke(
			HttpPrincipal httpPrincipal, MethodHandler methodHandler)
		throws Exception {

		HttpURLConnection urlc = _getConnection(httpPrincipal);

		ObjectOutputStream oos = new ObjectOutputStream(urlc.getOutputStream());

		oos.writeObject(
			new ObjectValuePair<HttpPrincipal, MethodHandler>(
				httpPrincipal, methodHandler));

		oos.flush();
		oos.close();

		Object returnObj = null;

		try {
			ObjectInputStream ois = new ProtectedObjectInputStream(
				urlc.getInputStream());

			returnObj = ois.readObject();

			ois.close();
		}
		catch (EOFException eofe) {
		}
		catch (IOException ioe) {
			String ioeMessage = ioe.getMessage();

			if ((ioeMessage != null) &&
					(ioeMessage.indexOf("HTTP response code: 401") != -1)) {

				throw new PrincipalException(ioeMessage);
			}
			else {
				throw ioe;
			}
		}

		if ((returnObj != null) && returnObj instanceof Exception) {
			throw (Exception)returnObj;
		}

		return returnObj;
	}

	/**
	 * @deprecated
	 */
	public static Object invoke(
			HttpPrincipal httpPrincipal, MethodWrapper methodWrapper)
		throws Exception {

		HttpURLConnection urlc = _getConnection(httpPrincipal);

		ObjectOutputStream oos = new ObjectOutputStream(urlc.getOutputStream());

		oos.writeObject(
			new ObjectValuePair<HttpPrincipal, MethodWrapper>(
				httpPrincipal, methodWrapper));

		oos.flush();
		oos.close();

		Object returnObj = null;

		try {
			ObjectInputStream ois = new ProtectedObjectInputStream(
				urlc.getInputStream());

			returnObj = ois.readObject();

			ois.close();
		}
		catch (EOFException eofe) {
		}
		catch (IOException ioe) {
			String ioeMessage = ioe.getMessage();

			if ((ioeMessage != null) &&
					(ioeMessage.indexOf("HTTP response code: 401") != -1)) {

				throw new PrincipalException(ioeMessage);
			}
			else {
				throw ioe;
			}
		}

		if ((returnObj != null) && returnObj instanceof Exception) {
			throw (Exception)returnObj;
		}

		return returnObj;
	}

	private static HttpURLConnection _getConnection(HttpPrincipal httpPrincipal)
		throws IOException {

		if (httpPrincipal == null || httpPrincipal.getUrl() == null) {
			return null;
		}

		URL url = null;

		if (Validator.isNull(httpPrincipal.getLogin()) ||
			Validator.isNull(httpPrincipal.getPassword())) {

			url = new URL(httpPrincipal.getUrl() + "/tunnel-web/liferay/do");
		}
		else {
			url = new URL(
				httpPrincipal.getUrl() + "/tunnel-web/secure/liferay/do");
		}

		HttpURLConnection urlc = (HttpURLConnection)url.openConnection();

		urlc.setDoInput(true);
		urlc.setDoOutput(true);
		urlc.setUseCaches(false);

		urlc.setRequestMethod("POST");

		if (Validator.isNotNull(httpPrincipal.getLogin()) &&
			Validator.isNotNull(httpPrincipal.getPassword())) {

			String userNameAndPassword =
				httpPrincipal.getLogin() + StringPool.COLON +
					httpPrincipal.getPassword();

			urlc.setRequestProperty(
				HttpHeaders.AUTHORIZATION,
				HttpServletRequest.BASIC_AUTH + StringPool.SPACE +
					Base64.encode(userNameAndPassword.getBytes()));
		}

		return urlc;
	}

}