/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 2007 Bull S.A.S.
 * Contact: jonas-team@ow2.org
 *
 * 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.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 *
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 */

package org.ow2.jonas.ear.internal.mbean;

import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.RuntimeOperationsException;
import javax.management.modelmbean.InvalidTargetObjectTypeException;

import org.ow2.jonas.ear.internal.EARModule;
import org.ow2.jonas.lib.management.javaee.J2EEDeployedObjectMBean;
import org.ow2.jonas.lib.management.javaee.J2eeObjectName;
import org.ow2.util.url.URLUtils;

/**
 * This class is managing the object for JSR77 J2EEApplication.
 * @author Florent BENOIT
 */
public class EARModuleMBean extends J2EEDeployedObjectMBean<EARModule> {

    /**
     * Modules of this application.
     */
    private String[] modules = null;

    /**
     * Public default constructor.
     * @throws MBeanException if this Object can't be created
     */
    public EARModuleMBean() throws MBeanException {
        super();
    }

    /**
     * @return Returns the XML Deployment Descriptors of the J2EEApplication Module.
     */
    @Override
    public String getDeploymentDescriptor() {
        String dd = null;
        try {
            dd = ((EARModule) getManagedResource()).getDeploymentDescriptor();
        } catch (InstanceNotFoundException e) {
            throw new IllegalStateException("Cannot get the managed resource of the EARModuleMBean", e);
        } catch (RuntimeOperationsException e) {
            throw new IllegalStateException("Cannot get the managed resource of the EARModuleMBean", e);
        } catch (MBeanException e) {
            throw new IllegalStateException("Cannot get the managed resource of the EARModuleMBean", e);
        } catch (InvalidTargetObjectTypeException e) {
            throw new IllegalStateException("Cannot get the managed resource of the EARModuleMBean", e);
        }
        return dd;
    }

    /**
     * Build the Modules of this EAR.
     */
    private void initModules() {
        // List of ObjectNames corresponding to J2EEModules
        List<String> modulesList = new ArrayList<String>();

        // Get EAR ObjectName
        ObjectName objectName = null;
        try {
            objectName = ObjectName.getInstance(getObjectName());
        } catch (MalformedObjectNameException e) {
            throw new IllegalStateException("Cannot get ObjectName on '" + getObjectName() + "'", e);
        } catch (NullPointerException e) {
            throw new IllegalStateException("Cannot get ObjectName on '" + getObjectName() + "'", e);
        }

        // Parse Name
        String domain = objectName.getDomain();
        String serverName = objectName.getKeyProperty(J2EESERVER_KEY);

        String appName = objectName.getKeyProperty("name");
        ObjectName modulesOn = null;

        // Add EJBModules
        modulesOn = J2eeObjectName.getEJBModules(domain, serverName, appName);
        addModuleObjectNames(modulesList, modulesOn);

        // Add WebModules
        modulesOn = J2eeObjectName.getWebModules(domain, serverName, appName);
        addModuleObjectNames(modulesList, modulesOn);

        // Add ResourceAdapterModules
        modulesOn = J2eeObjectName.getResourceAdapterModules(domain, serverName, appName);
        addModuleObjectNames(modulesList, modulesOn);

        // Add AppClientModules
        modulesOn = J2eeObjectName.getAppClientModules(domain, serverName, appName);
        addModuleObjectNames(modulesList, modulesOn);

        // set modules
        this.modules = modulesList.toArray(new String[modulesList.size()]);
    }

    /**
     * Add to a destination list ObjectNames corresponding to J2EEModules
     * ObjectName patterns found in the local MBeanServer.
     * @param modulesList destination list
     * @param objectName J2EEModules ObjectName patterns
     */
    @SuppressWarnings("unchecked")
    private void addModuleObjectNames(final List<String> modulesList, final ObjectName objectName) {
        Iterator<ObjectName> itNames = getRegistry().getMBeanServer().queryNames(objectName, null).iterator();
        while (itNames.hasNext()) {
            modulesList.add(itNames.next().toString());
        }
    }

    /**
     * @return the Application Name.
     */
    public String getName() {
        return getManagedComponent().getEARDeployable().getModuleName();
    }

    /**
     * @return the URL of this Application
     */
    public URL getEarUrl() {
        try {
            URL earURL = getManagedComponent().getEARDeployable().getOriginalDeployable().getArchive().getURL();
            if ("file".equals(earURL.getProtocol())) {
                // If file, make sure it is escaped correctly
                File file = URLUtils.urlToFile(earURL);
                earURL = file.toURL();
            }
            return earURL;
        } catch (Exception e) {
            throw new IllegalArgumentException("Cannot get URL from deployable '" + getManagedComponent().getEARDeployable()
                    + "'.", e);
        }
    }

    /**
     * Return the J2EEModules used by this J2EEApplication (jar, war, rar).
     * @return A array of OBJECT_NAMEs corresponding to these modules.
     */
    public String[] getModules() {
        if (modules == null) {
            initModules();
        }
        return modules;
    }
}
