001
014
015 package com.liferay.util.resiliency.spi.provider;
016
017 import com.liferay.portal.kernel.log.Log;
018 import com.liferay.portal.kernel.log.LogFactoryUtil;
019 import com.liferay.portal.kernel.process.ClassPathUtil;
020 import com.liferay.portal.kernel.resiliency.mpi.MPIHelperUtil;
021 import com.liferay.portal.kernel.resiliency.spi.provider.SPIProvider;
022 import com.liferay.portal.kernel.util.ReflectionUtil;
023 import com.liferay.portal.kernel.util.StringBundler;
024 import com.liferay.portal.kernel.util.StringPool;
025
026 import java.io.File;
027
028 import java.lang.reflect.Method;
029
030 import java.util.ArrayList;
031 import java.util.List;
032 import java.util.concurrent.atomic.AtomicReference;
033
034 import javax.servlet.ServletContext;
035 import javax.servlet.ServletContextEvent;
036 import javax.servlet.ServletContextListener;
037
038
041 public class SPIClassPathContextListener implements ServletContextListener {
042
043 public static volatile String SPI_CLASS_PATH = StringPool.BLANK;
044
045 @Override
046 public void contextDestroyed(ServletContextEvent servletContextEvent) {
047 SPIProvider spiProvider = spiProviderReference.getAndSet(null);
048
049 if (spiProvider != null) {
050 MPIHelperUtil.unregisterSPIProvider(spiProvider);
051 }
052 }
053
054 @Override
055 public void contextInitialized(ServletContextEvent servletContextEvent) {
056 ServletContext servletContext = servletContextEvent.getServletContext();
057
058 String contextPath = servletContext.getRealPath(StringPool.BLANK);
059 String spiEmbeddedLibDirName = servletContext.getInitParameter(
060 "spiEmbeddedLibDir");
061
062 File spiEmbeddedLibDir = new File(contextPath, spiEmbeddedLibDirName);
063
064 if (!spiEmbeddedLibDir.exists() || !spiEmbeddedLibDir.isDirectory()) {
065 _log.error(
066 "Unable to find SPI embedded lib directory " +
067 spiEmbeddedLibDir.getAbsolutePath());
068
069 return;
070 }
071
072 List<File> jarFiles = new ArrayList<File>();
073
074 for (File file : spiEmbeddedLibDir.listFiles()) {
075 String fileName = file.getName();
076
077 if (fileName.endsWith(".jar")) {
078 jarFiles.add(file);
079 }
080 }
081
082 StringBundler sb = new StringBundler(jarFiles.size() * 2 + 4);
083
084 for (File file : jarFiles) {
085 sb.append(file.getAbsolutePath());
086 sb.append(File.pathSeparator);
087 }
088
089 if (_log.isDebugEnabled()) {
090 _log.debug("SPI embedded lib class path " + sb.toString());
091 }
092
093 sb.append(contextPath);
094 sb.append("/WEB-INF/classes");
095 sb.append(File.pathSeparator);
096
097 sb.append(ClassPathUtil.getGlobalClassPath());
098
099 SPI_CLASS_PATH = sb.toString();
100
101 if (_log.isDebugEnabled()) {
102 _log.debug("SPI class path " + SPI_CLASS_PATH);
103 }
104
105 String spiProviderClassName = servletContext.getInitParameter(
106 "spiProviderClassName");
107
108 Thread currentThread = Thread.currentThread();
109
110 ClassLoader contextClassLoader = currentThread.getContextClassLoader();
111
112 try {
113 Class<SPIProvider> spiProviderClass =
114 (Class<SPIProvider>)loadClassDirectly(
115 contextClassLoader, spiProviderClassName);
116
117 SPIProvider spiProvider = spiProviderClass.newInstance();
118
119 boolean result = spiProviderReference.compareAndSet(
120 null, spiProvider);
121
122 if (!result) {
123 _log.error(
124 "Duplicate SPI provider " + spiProvider +
125 " is already registered in servlet context " +
126 servletContext.getContextPath());
127 }
128 else {
129 MPIHelperUtil.registerSPIProvider(spiProvider);
130 }
131 }
132 catch (Exception e) {
133 _log.error(
134 "Unable to create SPI provider with name " +
135 spiProviderClassName,
136 e);
137 }
138 }
139
140 protected static Class<?> loadClassDirectly(
141 ClassLoader classLoader, String className)
142 throws Exception {
143
144 synchronized (classLoader) {
145 Method findLoadedClassMethod = ReflectionUtil.getDeclaredMethod(
146 ClassLoader.class, "findLoadedClass", String.class);
147
148 Class<?> clazz = (Class<?>)findLoadedClassMethod.invoke(
149 classLoader, className);
150
151 if (clazz == null) {
152 Method findClassMethod = ReflectionUtil.getDeclaredMethod(
153 ClassLoader.class, "findClass", String.class);
154
155 clazz = (Class<?>)findClassMethod.invoke(
156 classLoader, className);
157 }
158
159 Method resolveClassMethod = ReflectionUtil.getDeclaredMethod(
160 ClassLoader.class, "resolveClass", Class.class);
161
162 resolveClassMethod.invoke(classLoader, clazz);
163
164 return clazz;
165 }
166 }
167
168 protected static final AtomicReference<SPIProvider> spiProviderReference =
169 new AtomicReference<SPIProvider>();
170
171 private static Log _log = LogFactoryUtil.getLog(
172 SPIClassPathContextListener.class);
173
174 }