/*
 * JBoss, Home of Professional Open Source
 * Copyright 2005, JBoss Inc., and individual contributors as indicated
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This 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 software 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 software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.jboss.deployment;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import javax.management.ObjectName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Source;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;

import org.jboss.mx.util.MBeanProxy;
import org.jboss.util.xml.DOMWriter;

import org.w3c.dom.Document;
import org.xml.sax.SAXException;

/**
 * XSLSubDeployer.java
 *
 *
 * Created: Fri Jul 12 09:54:51 2002
 *
 * @author <a href="mailto:juha@jboss.org">Juha Lindfors</a>
 * @author <a href="mailto:d_jencks@users.sourceforge.net">David Jencks</a>
 * @jmx.mbean name="jboss.system:service=XSLDeployer"
 * extends="org.jboss.deployment.SubDeployerMBean"
 */

public class XSLSubDeployer
      extends SubDeployerSupport
      implements XSLSubDeployerMBean
{

   protected String xslUrl;

   protected String packageSuffix;

   protected String ddSuffix;

   protected DocumentBuilderFactory dbf;

   private Templates templates;

   protected ObjectName delegateName = SARDeployerMBean.OBJECT_NAME;

   protected SubDeployer delegate;

   public XSLSubDeployer()
   {

   }

   /**
    * Describe <code>setXslUrl</code> method here.
    *
    * @param xslUrl a <code>String</code> value
    *
    * @jmx.managed-attribute
    */
   public void setXslUrl(final String xslUrl)
   {
      this.xslUrl = xslUrl;
   }

   /**
    * Describe <code>getXslUrl</code> method here.
    *
    * @return a <code>String</code> value
    *
    * @jmx.managed-attribute
    */
   public String getXslUrl()
   {
      return xslUrl;
   }

   /**
    * Describe <code>setPackageSuffix</code> method here.
    *
    * @param packageSuffix a <code>String</code> value
    *
    * @jmx.managed-attribute
    */
   public void setPackageSuffix(final String packageSuffix)
   {
      this.packageSuffix = packageSuffix;
   }

   /**
    * Describe <code>getPackageSuffix</code> method here.
    *
    * @return a <code>String</code> value
    *
    * @jmx.managed-attribute
    */
   public String getPackageSuffix()
   {
      return packageSuffix;
   }

   /**
    * Describe <code>setDdSuffix</code> method here.
    *
    * @param ddSuffix a <code>String</code> value
    *
    * @jmx.managed-attribute
    */
   public void setDdSuffix(final String ddSuffix)
   {
      this.ddSuffix = ddSuffix;
   }

   /**
    * Describe <code>getDdSuffix</code> method here.
    *
    * @return a <code>String</code> value
    *
    * @jmx.managed-attribute
    */
   public String getDdSuffix()
   {
      return ddSuffix;
   }

   /**
    * Describe <code>setDelegateName</code> method here.
    *
    * @param delegateName an <code>ObjectName</code> value
    *
    * @jmx.managed-attribute
    */
   public void setDelegateName(final ObjectName delegateName)
   {
      this.delegateName = delegateName;
   }

   /**
    * Describe <code>getDelegateName</code> method here.
    *
    * @jmx.managed-attribute
    */
   public ObjectName getDelegateName()
   {
      return delegateName;
   }

   protected void createService() throws Exception
   {
      super.createService();
      delegate = (SubDeployer) MBeanProxy.get(SubDeployer.class, delegateName, server);
      TransformerFactory tf = TransformerFactory.newInstance();

      dbf = DocumentBuilderFactory.newInstance();
      dbf.setNamespaceAware(true);
      InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(xslUrl);
      StreamSource ss = new StreamSource(is);
      templates = tf.newTemplates(ss);
      log.debug("Created templates: " + templates);
   }

   protected void destroyService() throws Exception
   {
      templates = null;
      super.destroyService();
   }

   public boolean accepts(DeploymentInfo di)
   {
      String urlStr = di.url.toString();
      return
           (packageSuffix != null &&  (urlStr.endsWith(packageSuffix) || urlStr.endsWith(packageSuffix + "/")))
        || (ddSuffix != null && urlStr.endsWith(ddSuffix));
   }

   public void init(DeploymentInfo di) throws DeploymentException
   {
      if (di.document == null)
      {
         findDd(di);
      }
      try
      {
         Transformer trans = templates.newTransformer();
         Source s = new DOMSource(di.document);
         DOMResult r = new DOMResult();
         setParameters(trans);
         trans.transform(s, r);
         di.document = (Document) r.getNode();
         if (log.isDebugEnabled())
         {
            StringWriter sw = new StringWriter();
            DOMWriter w = new DOMWriter(sw, false);
            w.print(di.document, true);
            log.debug("transformed into doc: " + sw.getBuffer().toString());
         }
      }
      catch (TransformerException ce)
      {
         throw new DeploymentException("Problem with xsl transformation", ce);
      }
      //super.init(di);
      delegate.init(di);
   }

   public void create(DeploymentInfo di) throws DeploymentException
   {
      delegate.create(di);
   }

   public void start(DeploymentInfo di) throws DeploymentException
   {
      delegate.start(di);
   }

   public void stop(DeploymentInfo di) throws DeploymentException
   {
      delegate.stop(di);
   }

   public void destroy(DeploymentInfo di) throws DeploymentException
   {
      delegate.destroy(di);
   }

   protected void setParameters(Transformer trans) throws TransformerException
   {
      //override to set document names etc.
      String dataDir = System.getProperty("jboss.server.data.dir");
      trans.setParameter("jboss.server.data.dir", dataDir);
   }

   protected void findDd(DeploymentInfo di) throws DeploymentException
   {

      try
      {
         DocumentBuilder db = dbf.newDocumentBuilder();
         String urlStr = di.url.toString();

         if (packageSuffix != null)
         {
            if (urlStr.endsWith(packageSuffix))
            {
            }
            else if (urlStr.endsWith(packageSuffix + "/"))
            {
            }
         }
         if (ddSuffix != null
             && urlStr.endsWith(ddSuffix))
         {
            di.document = (Document) db.parse(di.url.openStream());
         }
      }
      catch (SAXException se)
      {
         throw new DeploymentException("Could not parse dd", se);
      }
      catch (IOException ioe)
      {
         throw new DeploymentException("Could not read dd", ioe);
      }
      catch (ParserConfigurationException pce)
      {
         throw new DeploymentException("Could not create document builder for dd", pce);
      }
   }
}
