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}