/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.ode.axis2.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.axis2.deployment.ServiceBuilder;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.description.AxisModule;
import org.apache.axis2.description.PolicyInclude;
import org.apache.axis2.description.AxisDescription;
import org.apache.axis2.AxisFault;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;
import org.apache.neethi.PolicyEngine;
import org.apache.neethi.Policy;
import org.apache.rampart.RampartMessageData;

import javax.xml.stream.XMLStreamException;
import java.io.IOException;
import java.io.InputStream;
import java.io.File;
import java.net.URL;
import java.net.URI;

/**
 *
 */
public class AxisUtils {

    private static final Logger log = LoggerFactory.getLogger(AxisUtils.class);

    public static void configureService(AxisService axisService, URL service_file) throws IOException, XMLStreamException, AxisFault {
        configureService(new ConfigurationContext(axisService.getAxisConfiguration()), axisService, service_file);
    }

    /**
     * Configure a service instance woth the specified service.xml document.
     * If modules are mentioned in the document, <code>this</code> method will make sure they are properly engaged and engage them if necessary.
     * The modules have to be available in the module repository otherwise an AxisFault will be thrown.
     *
     * @param axisService  the service to configure
     * @param service_file the service.xm document to configure the service with
     * @throws IOException
     * @throws XMLStreamException
     * @throws org.apache.axis2.AxisFault if a module listed in the service.xml is not available in the module repository
     */
    public static void configureService(ConfigurationContext configCtx, AxisService axisService, URL service_file) throws IOException, XMLStreamException, AxisFault {
        InputStream ais = service_file.openStream();
        if (log.isDebugEnabled()) {
            log.debug("Looking for Axis2 service configuration file: " + service_file);
        }
        if (ais != null) {
            if (log.isDebugEnabled()) {
                log.debug("Configuring service " + axisService.getName() + " using: " + service_file);
            }
            try {
                if (configCtx == null)
                    configCtx = new ConfigurationContext(axisService.getAxisConfiguration());
                ServiceBuilder builder = new ServiceBuilder(ais, configCtx, axisService);
                builder.populateService(builder.buildOM());
            } finally {
                ais.close();
            }
            // the service builder only updates the module list but do not engage them
            // modules have to be engaged manually,
            for (int i = 0; i < axisService.getModules().size(); i++) {
                String moduleRef = (String) axisService.getModules().get(i);
                AxisModule module = axisService.getAxisConfiguration().getModule(moduleRef);
                if (module != null) {
                    axisService.engageModule(module);
                } else {
                    throw new AxisFault("Unable to engage module: " + moduleRef);
                }
            }
        }
    }

    public static void applySecurityPolicy(AxisService service, String policy_file) throws IllegalArgumentException {
        URI policyUri = new File(policy_file).toURI();
        if (log.isDebugEnabled()) log.debug("Applying security policy: " + policyUri);
        try {
            InputStream policyStream = policyUri.toURL().openStream();
            try {
                Policy policyDoc = PolicyEngine.getPolicy(policyStream);
                // Neethi parser is really dumb.
                // In case of parsing error, the exception is printed out and swallowed. Null is returned.
                if(policyDoc == null){
                    String msg = "Failed to parse policy: "+policy_file+". Due to Neethi limitations the reason can't be provided. See stacktraces in standard output (not logs)";
                    log.error(msg);
                    throw new IllegalArgumentException(msg);
                }
                service.getPolicyInclude().addPolicyElement(PolicyInclude.AXIS_SERVICE_POLICY, policyDoc);
                // make sure the proper modules are engaged, if they are available
                engageModules(service, "rampart", "rahas");
            } finally {
                policyStream.close();
            }
        } catch (IOException e) {
            throw new IllegalArgumentException("Exception while parsing policy: " + policyUri, e);
        }
    }

    public static void engageModules(AxisDescription description, String... modules) throws AxisFault {
        for (String m : modules) {
            if (description.getAxisConfiguration().getModule(m) != null) {
                if (!description.getAxisConfiguration().isEngaged(m) && !description.isEngaged(m)) {
                    description.engageModule(description.getAxisConfiguration().getModule(m));
                }
            } else {
                if (log.isDebugEnabled()) log.debug("Module " + m + " is not available.");
            }
        }
    }
}
