/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 * 
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_ucbhelper.hxx"
#include <ucbhelper/configureucb.hxx>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/ucb/XContentProvider.hpp>
#include <com/sun/star/ucb/XContentProviderManager.hpp>
#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/uno/RuntimeException.hpp>
#include <rtl/ustrbuf.hxx>

#include "osl/diagnose.h"

#ifndef _UCBHELPER_PROVCONF_HXX_
#include <provconf.hxx>
#endif
#include <registerucb.hxx>

using namespace com::sun::star;

namespace {

bool fillPlaceholders(rtl::OUString const & rInput,
					  uno::Sequence< uno::Any > const & rReplacements,
					  rtl::OUString * pOutput)
{
	sal_Unicode const * p = rInput.getStr();
	sal_Unicode const * pEnd = p + rInput.getLength();
	sal_Unicode const * pCopy = p;
	rtl::OUStringBuffer aBuffer;
	while (p != pEnd)
		switch (*p++)
		{
			case '&':
				if (pEnd - p >= 4
					&& p[0] == 'a' && p[1] == 'm' && p[2] == 'p'
					&& p[3] == ';')
				{
					aBuffer.append(pCopy, p - 1 - pCopy);
					aBuffer.append(sal_Unicode('&'));
					p += 4;
					pCopy = p;
				}
				else if (pEnd - p >= 3
						 && p[0] == 'l' && p[1] == 't' && p[2] == ';')
				{
					aBuffer.append(pCopy, p - 1 - pCopy);
					aBuffer.append(sal_Unicode('<'));
					p += 3;
					pCopy = p;
				}
				else if (pEnd - p >= 3
						 && p[0] == 'g' && p[1] == 't' && p[2] == ';')
				{
					aBuffer.append(pCopy, p - 1 - pCopy);
					aBuffer.append(sal_Unicode('>'));
					p += 3;
					pCopy = p;
				}
				break;

			case '<':
				sal_Unicode const * q = p;
				while (q != pEnd && *q != '>')
					++q;
				if (q == pEnd)
					break;
				rtl::OUString aKey(p, q - p);
				rtl::OUString aValue;
				bool bFound = false;
				for (sal_Int32 i = 2; i + 1 < rReplacements.getLength();
					 i += 2)
				{
					rtl::OUString aReplaceKey;
					if ((rReplacements[i] >>= aReplaceKey)
						&& aReplaceKey == aKey
						&& (rReplacements[i + 1] >>= aValue))
					{
						bFound = true;
						break;
					}
				}
				if (!bFound)
					return false;
				aBuffer.append(pCopy, p - 1 - pCopy);
				aBuffer.append(aValue);
				p = q + 1;
				pCopy = p;
				break;
		}
	aBuffer.append(pCopy, pEnd - pCopy);
	*pOutput = aBuffer.makeStringAndClear();
	return true;
}

}

namespace ucbhelper {

//============================================================================
//
//  configureUcb
//
//============================================================================

bool
configureUcb(
	uno::Reference< ucb::XContentProviderManager > const & rManager,
	uno::Reference< lang::XMultiServiceFactory > const & rServiceFactory,
    ContentProviderDataList const & rData,
    ContentProviderRegistrationInfoList * pInfos)
	throw (uno::RuntimeException)
{
    ContentProviderDataList::const_iterator aEnd(rData.end());
    for (ContentProviderDataList::const_iterator aIt(rData.begin());
		 aIt != aEnd; ++aIt)
	{
        ContentProviderRegistrationInfo aInfo;
        bool bSuccess = registerAtUcb(rManager,
                                      rServiceFactory,
                                      aIt->ServiceName,
                                      aIt->Arguments,
                                      aIt->URLTemplate,
                                      &aInfo);

        if (bSuccess && pInfos)
            pInfos->push_back(aInfo);
	}

	return true;
}

//============================================================================
//
//  configureUcb
//
//============================================================================

bool
configureUcb(
	uno::Reference< ucb::XContentProviderManager > const & rManager,
	uno::Reference< lang::XMultiServiceFactory > const & rServiceFactory,
	uno::Sequence< uno::Any > const & rArguments,
	std::vector< ContentProviderRegistrationInfo > * pInfos)
	throw (uno::RuntimeException)
{
	rtl::OUString aKey1;
	rtl::OUString aKey2;
	if (rArguments.getLength() < 2
		|| !(rArguments[0] >>= aKey1) || !(rArguments[1] >>= aKey2))
	{
		OSL_ENSURE(false, "ucb::configureUcb(): Bad arguments");
		return false;
	}

	ContentProviderDataList aData;
	if (!getContentProviderData(rServiceFactory, aKey1, aKey2, aData))
	{
		OSL_ENSURE(false, "ucb::configureUcb(): No configuration");
		return false;
	}

	ContentProviderDataList::const_iterator aEnd(aData.end());
	for (ContentProviderDataList::const_iterator aIt(aData.begin());
		 aIt != aEnd; ++aIt)
	{
		rtl::OUString aProviderArguments;
		if (fillPlaceholders(aIt->Arguments,
							 rArguments,
							 &aProviderArguments))
		{
			ContentProviderRegistrationInfo aInfo;
			bool bSuccess = registerAtUcb(rManager,
										  rServiceFactory,
										  aIt->ServiceName,
										  aProviderArguments,
										  aIt->URLTemplate,
										  &aInfo);
			OSL_ENSURE(bSuccess, "ucb::configureUcb(): Bad content provider");

			if (bSuccess && pInfos)
				pInfos->push_back(aInfo);
		}
		else
			OSL_ENSURE(false,
					   "ucb::configureUcb(): Bad argument placeholders");
	}

	return true;
}

}

//============================================================================
//
//  unconfigureUcb
//
//============================================================================

namespace ucbhelper {

void
unconfigureUcb(
	uno::Reference< ucb::XContentProviderManager > const & rManager,
	std::vector< ContentProviderRegistrationInfo > const & rInfos)
	throw (uno::RuntimeException)
{
	std::vector< ContentProviderRegistrationInfo >::const_iterator
		aEnd(rInfos.end());
	for (std::vector< ContentProviderRegistrationInfo >::const_iterator
			 aIt(rInfos.begin());
		 aIt != aEnd; ++aIt)
		deregisterFromUcb(rManager, *aIt);
}

}
