com.app.server.SARDeployer.java Source code

Java tutorial

Introduction

Here is the source code for com.app.server.SARDeployer.java

Source

package com.app.server;

/*Copyright 2013 - 2015, Arun_Soundararajan (arun_srajan_2007@yahoo.com).and/or its affiliates.
    
All files in this repository or distribution are licensed under the
Apache License, Version 2.0 (the "License");
you may not use any files in this repository or distribution 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.*/

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.management.ManagementFactory;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;

import javax.management.Attribute;
import javax.management.AttributeNotFoundException;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.InvalidAttributeValueException;
import javax.management.MBeanException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.ReflectionException;

import org.apache.commons.digester3.Digester;
import org.apache.commons.digester3.binder.DigesterLoader;
import org.apache.commons.digester3.xmlrules.FromXmlRulesModule;
import org.apache.commons.vfs2.AllFileSelector;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSelectInfo;
import org.apache.commons.vfs2.FileSelector;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.impl.StandardFileSystemManager;
import org.apache.log4j.Logger;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import com.app.messaging.MessagingClassConstruct;
import com.app.server.util.ClassLoaderUtil;
import com.app.services.ExecutorServicesConstruct;

/**
 * This class is the implementation of the SAR archive deployer which frequently listens
 * in the deploy directory and configures the sar and start the service. 
 * @author arun
 *
 */
public class SARDeployer implements SARDeployerMBean {
    /*private String deployDirectory; 
    private Logger logger=Logger.getLogger(SARDeployer.class);
    int numberOfSarDeployed=0;
    private CopyOnWriteArrayList sarsDeployed=new CopyOnWriteArrayList();
    Digester sardigester;
    private static SARDeployer sarDeployer=null;
    private SARDeployer(String deployDirectory){
       this.deployDirectory=deployDirectory;
    }
    public static SARDeployer newInstance(String deployDirectory){
       if(sarDeployer==null){
     sarDeployer=new SARDeployer(deployDirectory);
       }
       return sarDeployer;
    }
    ConcurrentHashMap sarsMap=new ConcurrentHashMap();   */
    Vector serviceList, deployerList;
    ConcurrentHashMap<String, ObjectName> serviceListObjName = new ConcurrentHashMap<String, ObjectName>();
    Digester sardigester;
    ServerConfig serverConfig;
    int numberOfSarDeployed = 0;
    private Logger log = Logger.getLogger(SARDeployer.class);
    MBeanServer mbeanServer;
    HashMap sarsMap = new HashMap();
    CopyOnWriteArrayList<String> sarsDeployed = new CopyOnWriteArrayList<String>();
    public static final String OBJECT_NAME = "com.app.server:type=deployer,service=SARDeployer";

    /**
     * This method is the implementation of the SAR deployer
     */
    public void init(Vector deployerlist) {
        // TODO Auto-generated method stub
        this.deployerList = deployerlist;

    }

    @Override
    public void init(Vector serviceList, ServerConfig serverConfig, MBeanServer server) {
        // TODO Auto-generated method stub
        this.serviceList = serviceList;
        this.serverConfig = serverConfig;
        this.mbeanServer = server;
        DigesterLoader serverdigesterLoader = DigesterLoader.newLoader(new FromXmlRulesModule() {

            protected void loadRules() {
                // TODO Auto-generated method stub
                try {
                    loadXMLRules(new InputSource(new FileInputStream("./config/sar-config.xml")));
                } catch (Exception e) {
                    log.error("Could not able to load the rules file sar-config.xml", e);
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }
        });
        sardigester = serverdigesterLoader.newDigester();
        log.info("initialized");
    }

    public void deploy(URL url) {
        // TODO Auto-generated method stub
        //while(true){         

        try {
            //log.info(url);
            File sarFile = new File(url.toURI());
            if (sarFile.getName().toLowerCase().endsWith(".sar")) {
                extractSarDeploy(null, new File(url.toURI()));
            } else if (sarFile.getName().toLowerCase().endsWith("-service.xml")) {
                deployService(sarFile);
            }
            numberOfSarDeployed++;
            sarsDeployed.add(url.toURI().toString());
            log.info(url.toURI() + " Deployed");
        } catch (Exception e) {
            log.error("Could not able to deploy sar package " + url, e);
            // TODO Auto-generated catch block
            //e.printStackTrace();
        }

        //log.info("War Deployed Successfully in path: "+fileCurrLastModified.getFile().getAbsolutePath());

        //}
    }

    public void deploy(FileObject fobj, StandardFileSystemManager fsManager, ClassLoader cL) {
        // TODO Auto-generated method stub
        //while(true){         

        try {
            //log.info(url);
            extractSarDeploy(cL, fobj, fsManager);
            numberOfSarDeployed++;
            sarsDeployed.add(fobj.getURL().toURI().toString());
            log.info(fobj.getURL().toURI() + " Deployed");
        } catch (Exception e) {
            try {
                log.error("Could not able to deploy sar package " + fobj.getURL().toURI(), e);
            } catch (Exception e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
            // TODO Auto-generated catch block
            //e.printStackTrace();
        }

        //log.info("War Deployed Successfully in path: "+fileCurrLastModified.getFile().getAbsolutePath());

        //}
    }

    /**
     * This method adds the url to the classloader.
     * @param warDirectory
     * @param classLoader
     */
    /*private void AddUrlToClassLoader(File warDirectory,WebClassLoader classLoader){
       File webInfDirectory=new File(warDirectory.getAbsolutePath()+"/WEB-INF/lib/");
       //logger.info(webInfDirectory.getAbsolutePath());
       if(webInfDirectory.exists()){
     File[] jarfiles=webInfDirectory.listFiles();
     for(int jarcount=0;jarcount<jarfiles.length;jarcount++){
        //logger.info(jarfiles[jarcount]);
        if(jarfiles[jarcount].getName().endsWith(".jar")){
           try {
           //   //log.info("Adding absolute path "+jarfiles[jarcount].getAbsolutePath());
              new WebServer().addURL(new URL("file:"+jarfiles[jarcount].getAbsolutePath()),classLoader);
           } catch (IOException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
           }
        }
     }
       }
    }*/

    public void deployService(File sarFile) {
        try {
            Sar sar = (Sar) sardigester.parse(new InputSource(new FileInputStream(sarFile)));
            CopyOnWriteArrayList mbeans = sar.getMbean();
            //log.info(mbeanServer);
            ObjectName objName;
            for (int index = 0; index < mbeans.size(); index++) {
                Mbean mbean = (Mbean) mbeans.get(index);
                //log.info(mbean.getObjectname());
                //log.info(mbean.getCls());
                objName = new ObjectName(mbean.getObjectname());
                Class service = Thread.currentThread().getContextClassLoader().loadClass(mbean.getCls());
                Object obj = service.newInstance();
                if (mbeanServer.isRegistered(objName)) {
                    //mbs.invoke(objName, "stopService", null, null);
                    //mbs.invoke(objName, "destroy", null, null);
                    mbeanServer.unregisterMBean(objName);
                }
                mbeanServer.createMBean(service.getName(), objName);
                //mbs.registerMBean(obj, objName);
                CopyOnWriteArrayList attrlist = mbean.getMbeanAttribute();
                if (attrlist != null) {
                    for (int count = 0; count < attrlist.size(); count++) {
                        MBeanAttribute attr = (MBeanAttribute) attrlist.get(count);
                        Attribute mbeanattribute = new Attribute(attr.getName(), attr.getValue());
                        mbeanServer.setAttribute(objName, mbeanattribute);
                    }
                }
                Attribute mbeanattribute = new Attribute("ObjectName", objName);
                mbeanServer.setAttribute(objName, mbeanattribute);
                if (((String) mbeanServer.getAttribute(objName, "Deployer")).equals("true")) {
                    mbeanServer.invoke(objName, "init", new Object[] { deployerList },
                            new String[] { Vector.class.getName() });
                    //this.deployerList.add(objName.getCanonicalName());

                }
                mbeanServer.invoke(objName, "init", new Object[] { serviceList, serverConfig, mbeanServer },
                        new String[] { Vector.class.getName(), ServerConfig.class.getName(),
                                MBeanServer.class.getName() });
                mbeanServer.invoke(objName, "start", null, null);
            }
        } catch (Exception ex) {
            log.error("Could not able to deploy the SAR package " + sarFile.toURI(), ex);
            //ex.printStackTrace();
        }
    }

    public CopyOnWriteArrayList<String> unpack(final FileObject unpackFileObject, final File outputDir,
            StandardFileSystemManager fileSystemManager) throws IOException {
        outputDir.mkdirs();
        URLClassLoader webClassLoader;
        CopyOnWriteArrayList<String> classPath = new CopyOnWriteArrayList<String>();
        final FileObject packFileObject = fileSystemManager
                .resolveFile("jar:" + unpackFileObject.toString() + "!/");
        try {
            FileObject outputDirFileObject = fileSystemManager.toFileObject(outputDir);
            outputDirFileObject.copyFrom(packFileObject, new AllFileSelector());
            FileObject[] libs = outputDirFileObject.findFiles(new FileSelector() {

                public boolean includeFile(FileSelectInfo arg0) throws Exception {
                    return arg0.getFile().getName().getBaseName().toLowerCase().endsWith(".jar");
                }

                public boolean traverseDescendents(FileSelectInfo arg0) throws Exception {
                    // TODO Auto-generated method stub
                    return true;
                }

            });
            /*String replaceString="file:///"+outputDir.getAbsolutePath().replace("\\","/");
            replaceString=replaceString.endsWith("/")?replaceString:replaceString+"/";*/
            // System.out.println(replaceString);
            for (FileObject lib : libs) {
                // System.out.println(outputDir.getAbsolutePath());
                // System.out.println(jsp.getName().getFriendlyURI());
                classPath.add(lib.getName().getFriendlyURI());
                // System.out.println(relJspName);
            }
        } finally {
            packFileObject.close();
        }
        return classPath;
    }

    /**
     * This method extracts the SAR archive and configures for the SAR and starts the services
     * @param file
     * @param warDirectoryPath
     * @throws IOException
     */
    public void extractSarDeploy(ClassLoader cL, Object... args) throws IOException {
        CopyOnWriteArrayList classPath = null;
        File file = null;
        String fileName = "";
        String fileWithPath = "";
        if (args[0] instanceof File) {
            classPath = new CopyOnWriteArrayList();
            file = (File) args[0];
            fileWithPath = file.getAbsolutePath();
            ZipFile zip = new ZipFile(file);
            ZipEntry ze = null;
            fileName = file.getName();
            fileName = fileName.substring(0, fileName.indexOf('.'));
            fileName += "sar";
            String fileDirectory;
            Enumeration<? extends ZipEntry> entries = zip.entries();
            int numBytes;
            while (entries.hasMoreElements()) {
                ze = entries.nextElement();
                // //log.info("Unzipping " + ze.getName());
                String filePath = serverConfig.getDeploydirectory() + "/" + fileName + "/" + ze.getName();
                if (!ze.isDirectory()) {
                    fileDirectory = filePath.substring(0, filePath.lastIndexOf('/'));
                } else {
                    fileDirectory = filePath;
                }
                // //log.info(fileDirectory);
                createDirectory(fileDirectory);
                if (!ze.isDirectory()) {
                    FileOutputStream fout = new FileOutputStream(filePath);
                    byte[] inputbyt = new byte[8192];
                    InputStream istream = zip.getInputStream(ze);
                    while ((numBytes = istream.read(inputbyt, 0, inputbyt.length)) >= 0) {
                        fout.write(inputbyt, 0, numBytes);
                    }
                    fout.close();
                    istream.close();
                    if (ze.getName().endsWith(".jar")) {
                        classPath.add(filePath);
                    }
                }
            }
            zip.close();
        } else if (args[0] instanceof FileObject) {
            FileObject fileObj = (FileObject) args[0];
            fileName = fileObj.getName().getBaseName();
            try {
                fileWithPath = fileObj.getURL().toURI().toString();
            } catch (URISyntaxException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            fileName = fileName.substring(0, fileName.indexOf('.'));
            fileName += "sar";
            classPath = unpack(fileObj, new File(serverConfig.getDeploydirectory() + "/" + fileName + "/"),
                    (StandardFileSystemManager) args[1]);
        }
        URLClassLoader loader = (URLClassLoader) ClassLoader.getSystemClassLoader();
        URL[] urls = loader.getURLs();
        WebClassLoader sarClassLoader;
        if (cL != null) {
            sarClassLoader = new WebClassLoader(urls, cL);
        } else {
            sarClassLoader = new WebClassLoader(urls);
        }
        for (int index = 0; index < classPath.size(); index++) {
            // log.info("file:"+classPath.get(index));
            sarClassLoader.addURL(new URL("file:" + classPath.get(index)));
        }
        sarClassLoader.addURL(new URL("file:" + serverConfig.getDeploydirectory() + "/" + fileName + "/"));
        //log.info(sarClassLoader.geturlS());
        sarsMap.put(fileWithPath, sarClassLoader);
        try {
            Sar sar = (Sar) sardigester.parse(new InputSource(new FileInputStream(
                    serverConfig.getDeploydirectory() + "/" + fileName + "/META-INF/" + "mbean-service.xml")));
            CopyOnWriteArrayList mbeans = sar.getMbean();
            //log.info(mbeanServer);
            ObjectName objName, classLoaderObjectName = new ObjectName("com.app.server:classLoader=" + fileName);
            if (!mbeanServer.isRegistered(classLoaderObjectName)) {
                mbeanServer.registerMBean(sarClassLoader, classLoaderObjectName);
            } else {
                mbeanServer.unregisterMBean(classLoaderObjectName);
                mbeanServer.registerMBean(sarClassLoader, classLoaderObjectName);
                ;
            }
            for (int index = 0; index < mbeans.size(); index++) {
                Mbean mbean = (Mbean) mbeans.get(index);
                //log.info(mbean.getObjectname());
                //log.info(mbean.getCls());
                objName = new ObjectName(mbean.getObjectname());
                Class service = sarClassLoader.loadClass(mbean.getCls());
                if (mbeanServer.isRegistered(objName)) {
                    //mbs.invoke(objName, "stopService", null, null);
                    //mbs.invoke(objName, "destroy", null, null);
                    mbeanServer.unregisterMBean(objName);
                }
                mbeanServer.createMBean(service.getName(), objName, classLoaderObjectName);
                //mbs.registerMBean(obj, objName);
                CopyOnWriteArrayList attrlist = mbean.getMbeanAttribute();
                if (attrlist != null) {
                    for (int count = 0; count < attrlist.size(); count++) {
                        MBeanAttribute attr = (MBeanAttribute) attrlist.get(count);
                        Attribute mbeanattribute = new Attribute(attr.getName(), attr.getValue());
                        mbeanServer.setAttribute(objName, mbeanattribute);
                    }
                }
                Attribute mbeanattribute = new Attribute("ObjectName", objName);
                mbeanServer.setAttribute(objName, mbeanattribute);
                if (((String) mbeanServer.getAttribute(objName, "Deployer")).equals("true")) {
                    mbeanServer.invoke(objName, "init", new Object[] { deployerList },
                            new String[] { Vector.class.getName() });

                }
                mbeanServer.invoke(objName, "init", new Object[] { serviceList, serverConfig, mbeanServer },
                        new String[] { Vector.class.getName(), ServerConfig.class.getName(),
                                MBeanServer.class.getName() });
                mbeanServer.invoke(objName, "start", null, null);
                serviceListObjName.put(fileWithPath, objName);
            }
        } catch (Exception e) {
            log.error("Could not able to deploy sar archive " + fileWithPath, e);
            // TODO Auto-generated catch block
            //e.printStackTrace();
        }
    }

    /**
     * This method creates the directory for SAR
     * @param dir
     */
    public void createDirectory(String dir) {
        String[] dirs = dir.split("/");
        String tmpDirPath = dirs[0];
        for (int i = 1; i < dirs.length; i++) {
            tmpDirPath += "/" + dirs[i];
            File file = new File(tmpDirPath);
            if (!file.exists()) {
                file.mkdir();
            }
        }
    }

    /**
     * This method undeployed the SAR
     * @param dir
     * @return
     */
    public boolean deleteDir(File dir) {
        String fileName = dir.getName();
        //log.info("Dirname to be deleted"+fileName);
        Sar sar = null;
        fileName = fileName.substring(0, fileName.indexOf('.'));
        fileName += "sar";
        try {
            sar = (Sar) sardigester.parse(new InputSource(new FileInputStream(
                    serverConfig.getDeploydirectory() + "/" + fileName + "/META-INF/" + "mbean-service.xml")));
        } catch (Exception e) {
            log.error("Could not able to parse sar " + serverConfig.getDeploydirectory() + "/" + fileName
                    + "/META-INF/" + "mbean-service.xml", e);
            // TODO Auto-generated catch block
            //e.printStackTrace();
        }
        URLClassLoader sarClassLoader = (URLClassLoader) sarsMap.get(fileName);
        if (sarClassLoader != null) {
            ClassLoaderUtil.closeClassLoader(sarClassLoader);
            CopyOnWriteArrayList mbeans = sar.getMbean();
            //log.info(mbeanServer);
            ObjectName objName;
            try {
                for (int index = 0; index < mbeans.size(); index++) {
                    Mbean mbean = (Mbean) mbeans.get(index);
                    //log.info(mbean.getObjectname());
                    //log.info(mbean.getCls());
                    objName = new ObjectName(mbean.getObjectname());
                    if (mbeanServer.isRegistered(objName)) {
                        if (((String) mbeanServer.getAttribute(objName, "Deployer")).equals("true")) {
                            mbeanServer.invoke(objName, "undeploy", null, null);
                        }
                        mbeanServer.invoke(objName, "stop", null, null);
                        mbeanServer.invoke(objName, "destroy", null, null);
                        //mbs.invoke(objName, "stopService", null, null);
                        //mbs.invoke(objName, "destroy", null, null);
                        mbeanServer.unregisterMBean(objName);
                    }
                }
            } catch (Exception e) {
                log.error("Could not able to undeploy stop and destroy sar in " + dir.getName(), e);
                // TODO Auto-generated catch block
                //e.printStackTrace();
            }
        }
        return recursiveDelete(new File(serverConfig.getDeploydirectory() + "/" + fileName + "/"));

    }

    /**
     * This method recursively deletes the SAR directory
     * @param dir
     * @return
     */
    public boolean recursiveDelete(File dir) {
        if (dir.isDirectory()) {
            String[] children = dir.list();
            for (int i = 0; i < children.length; i++) {
                boolean success = recursiveDelete(new File(dir, children[i]));
                if (!success) {
                    return false;
                }
            }
        }
        // The directory is now empty so delete it
        return dir.delete();
    }

    public int numDeployer() {
        return numberOfSarDeployed;
    }

    public List deployerList() {
        // TODO Auto-generated method stub
        return null;
    }

    public void start() {
        this.deployerList.add(OBJECT_NAME);
        log.info("started");
    }

    public void stop() {
        try {
            for (int serviceCount = 0; serviceCount < serviceList.size(); serviceCount++) {
                mbeanServer.invoke(new ObjectName((String) serviceList.get(serviceCount)), "stop", null, null);
            }
        } catch (Exception ex) {
            log.error("could not stop service", ex);
        }
        try {
            this.deployerList.remove(OBJECT_NAME);
            for (int deployerCount = 0; deployerCount < deployerList.size(); deployerCount++) {
                mbeanServer.invoke(new ObjectName((String) deployerList.get(deployerCount)), "stop", null, null);
            }
        } catch (Exception ex) {
            log.error("could not stop deployer", ex);
        }
        log.info("stopped");
    }

    public void destroy() {
        try {
            while (serviceList.size() != 0) {
                mbeanServer.invoke(new ObjectName((String) serviceList.get(0)), "destroy", null, null);
            }
        } catch (Exception ex) {
            log.error("could not stop service", ex);
        }
        try {
            while (deployerList.size() != 0) {
                mbeanServer.invoke(new ObjectName((String) deployerList.get(0)), "destroy", null, null);
            }
        } catch (Exception ex) {
            log.error("could not stop deployer", ex);
        }
        log.info("destroyed");
    }

    public boolean accept(URL url) {
        File file;
        boolean acceptSar = false;
        try {
            file = new File(url.toURI());
            if (file.getName().endsWith(".sar")) {
                acceptSar = true;
            } else if (file.getName().endsWith("-service.xml")) {
                acceptSar = true;
            }
        } catch (Exception e) {
            log.error("Syntax of the url is not correct" + url, e);
            // TODO Auto-generated catch block
            //e.printStackTrace();
        }
        return acceptSar;

    }

    public void undeploy(URL url) {
        try {
            String filewithpath = url.toURI().toString().replace("file:/", "").replace("/", "\\");
            mbeanServer.invoke((ObjectName) serviceListObjName.get(filewithpath), "undeploy", new Object[] { url },
                    new String[] { URL.class.getName() });
            mbeanServer.invoke((ObjectName) serviceListObjName.get(filewithpath), "stop", null, null);
            mbeanServer.invoke((ObjectName) serviceListObjName.get(filewithpath), "destroy", null, null);
            File file = new File(url.toURI());
            deleteDir(file);
            file.delete();
            serviceListObjName.remove(filewithpath);
            sarsDeployed.remove(url.toURI().toString());
            log.info(url.toURI() + " undeployed");
        } catch (Exception e) {
            log.error("Syntax of the url is not correct" + url, e);
            // TODO Auto-generated catch block
            //e.printStackTrace();
        }

    }

    @Override
    public String getDeployer() {
        // TODO Auto-generated method stub
        return "true";
    }

    public void setDeployer(String isdeployer) {
        // TODO Auto-generated method stub

    }

    @Override
    public void setObjectName(ObjectName objName) {
    }

    @Override
    public ObjectName getObjectName() {
        // TODO Auto-generated method stub
        try {
            return new ObjectName(OBJECT_NAME);
        } catch (Exception e) {
            log.error("Could not able to create object name " + OBJECT_NAME, e);
            // TODO Auto-generated catch block
            //e.printStackTrace();
        }
        return null;
    }

    @Override
    public CopyOnWriteArrayList<String> getSarsDeployed() {
        // TODO Auto-generated method stub
        return sarsDeployed;
    }

}