001/*
002 * (C) Copyright 2011 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     matic
018 */
019package org.nuxeo.runtime.tomcat.dev;
020
021import java.io.File;
022import java.lang.reflect.Method;
023
024/**
025 * Invokes the ReloadService by reflection as this module does not have access to the runtime context.
026 *
027 * @author matic
028 * @since 5.5
029 */
030public class ReloadServiceInvoker {
031
032    protected Object reloadService;
033
034    protected Method deployBundle;
035
036    protected Method undeployBundle;
037
038    /**
039     * Method to run the deployment preprocessor, previously handled by the deployBundle method
040     *
041     * @since 5.6
042     */
043    protected Method runDeploymentPreprocessor;
044
045    /**
046     * Method to install local web resources, as the deployment preprocessor won't see dev bundles as defined by Nuxeo
047     * IDE
048     *
049     * @since 5.6
050     */
051    protected Method installWebResources;
052
053    protected Method flush;
054
055    protected Method reload;
056
057    protected Method flushSeam;
058
059    protected Method reloadSeam;
060
061    public ReloadServiceInvoker(ClassLoader cl) throws ReflectiveOperationException {
062        Class<?> frameworkClass = cl.loadClass("org.nuxeo.runtime.api.Framework");
063        Class<?> reloadServiceClass = cl.loadClass("org.nuxeo.runtime.reload.ReloadService");
064        Method getLocalService = frameworkClass.getDeclaredMethod("getLocalService", new Class<?>[] { Class.class });
065        reloadService = getLocalService.invoke(null, new Object[] { reloadServiceClass });
066        deployBundle = reloadServiceClass.getDeclaredMethod("deployBundle", new Class<?>[] { File.class });
067        undeployBundle = reloadServiceClass.getDeclaredMethod("undeployBundle", new Class<?>[] { String.class });
068        runDeploymentPreprocessor = reloadServiceClass.getDeclaredMethod("runDeploymentPreprocessor", new Class<?>[0]);
069        installWebResources = reloadServiceClass.getDeclaredMethod("installWebResources", new Class<?>[] { File.class });
070        flush = reloadServiceClass.getDeclaredMethod("flush", new Class<?>[0]);
071        reload = reloadServiceClass.getDeclaredMethod("reload", new Class<?>[0]);
072        flushSeam = reloadServiceClass.getDeclaredMethod("flushSeamComponents", new Class<?>[0]);
073        reloadSeam = reloadServiceClass.getDeclaredMethod("reloadSeamComponents", new Class<?>[0]);
074    }
075
076    public void hotDeployBundles(DevBundle[] bundles) throws ReflectiveOperationException {
077        ClassLoader cl = Thread.currentThread().getContextClassLoader();
078        try {
079            Thread.currentThread().setContextClassLoader(reloadService.getClass().getClassLoader());
080            flush();
081            boolean hasSeam = false;
082            // rebuild existing war, this will remove previously copied web
083            // resources
084            // commented out for now, see NXP-9642
085            // runDeploymentPreprocessor();
086            for (DevBundle bundle : bundles) {
087                if (bundle.devBundleType == DevBundleType.Bundle) {
088                    bundle.name = (String) deployBundle.invoke(reloadService, new Object[] { bundle.file() });
089                    // install its web resources
090                    installWebResources.invoke(reloadService, new Object[] { bundle.file() });
091                } else if (bundle.devBundleType.equals(DevBundleType.Seam)) {
092                    hasSeam = true;
093                }
094            }
095            if (hasSeam) {
096                reloadSeam();
097            }
098            reload();
099        } finally {
100            Thread.currentThread().setContextClassLoader(cl);
101        }
102    }
103
104    public void hotUndeployBundles(DevBundle[] bundles) throws ReflectiveOperationException {
105        ClassLoader cl = Thread.currentThread().getContextClassLoader();
106        try {
107            Thread.currentThread().setContextClassLoader(reloadService.getClass().getClassLoader());
108            boolean hasSeam = false;
109            for (DevBundle bundle : bundles) {
110                if (bundle.devBundleType.equals(DevBundleType.Bundle) && bundle.name != null) {
111                    undeployBundle.invoke(reloadService, new Object[] { bundle.name });
112                } else if (bundle.devBundleType.equals(DevBundleType.Seam)) {
113                    hasSeam = true;
114                }
115            }
116            // run deployment preprocessor again: this will remove potential
117            // resources that were copied in the war at deploy
118            // commented out for now, see NXP-9642
119            // runDeploymentPreprocessor();
120            if (hasSeam) {
121                flushSeam.invoke(reloadService);
122            }
123        } finally {
124            Thread.currentThread().setContextClassLoader(cl);
125        }
126    }
127
128    protected void flush() throws ReflectiveOperationException {
129        flush.invoke(reloadService);
130    }
131
132    protected void reload() throws ReflectiveOperationException {
133        reload.invoke(reloadService);
134    }
135
136    protected void reloadSeam() throws ReflectiveOperationException {
137        reloadSeam.invoke(reloadService);
138    }
139
140    protected void runDeploymentPreprocessor() throws ReflectiveOperationException {
141        runDeploymentPreprocessor.invoke(reloadService);
142    }
143
144}