001
014
015 package com.liferay.portlet.documentlibrary.util;
016
017 import com.liferay.portal.kernel.configuration.Filter;
018 import com.liferay.portal.kernel.io.DummyOutputStream;
019 import com.liferay.portal.kernel.log.Log;
020 import com.liferay.portal.kernel.log.LogFactoryUtil;
021 import com.liferay.portal.kernel.process.ClassPathUtil;
022 import com.liferay.portal.kernel.process.ProcessException;
023 import com.liferay.portal.kernel.util.OSDetector;
024 import com.liferay.portal.kernel.util.PortalClassLoaderUtil;
025 import com.liferay.portal.kernel.util.PropsKeys;
026 import com.liferay.portal.kernel.util.ReflectionUtil;
027 import com.liferay.portal.kernel.util.SetUtil;
028 import com.liferay.portal.kernel.util.Validator;
029 import com.liferay.portal.kernel.xuggler.Xuggler;
030 import com.liferay.portal.kernel.xuggler.XugglerInstallException;
031 import com.liferay.portal.util.PropsUtil;
032 import com.liferay.portal.xuggler.XugglerImpl;
033
034 import com.xuggle.ferry.JNILibrary;
035
036 import java.io.File;
037 import java.io.PrintStream;
038
039 import java.lang.reflect.Field;
040
041 import java.net.URL;
042 import java.net.URLClassLoader;
043
044 import java.util.Iterator;
045 import java.util.Properties;
046 import java.util.Set;
047 import java.util.concurrent.Callable;
048 import java.util.logging.Level;
049 import java.util.logging.Logger;
050 import java.util.regex.Matcher;
051 import java.util.regex.Pattern;
052
053
056 public class XugglerAutoInstallHelper {
057
058 public static void installNativeLibraries() throws ProcessException {
059 if (isNativeLibraryInstalled()) {
060 if (_log.isDebugEnabled()) {
061 _log.debug("Xuggler is already installed");
062 }
063
064 return;
065 }
066
067 String xugglerJarFile = getXugglerJarFileName();
068
069 if (xugglerJarFile == null) {
070 _log.error(
071 "Xuggler auto install is not supported on system: " +
072 System.getProperty("os.name") + "/" +
073 System.getProperty("os.arch"));
074
075 return;
076 }
077
078 ClassLoader classLoader = PortalClassLoaderUtil.getClassLoader();
079
080 PortalClassLoaderUtil.setClassLoader(
081 ClassLoader.getSystemClassLoader());
082
083 try {
084 Xuggler xuggler = new XugglerImpl();
085
086 try {
087 xuggler.installNativeLibraries(xugglerJarFile);
088 }
089 catch (XugglerInstallException.MustBeURLClassLoader xie) {
090 if (_log.isDebugEnabled()) {
091 _log.debug(xie, xie);
092 }
093 }
094 catch (Exception e) {
095 throw new ProcessException(e);
096 }
097
098 if (xuggler.isNativeLibraryInstalled()) {
099 if (_log.isInfoEnabled()) {
100 _log.info("Xuggler installed successfully");
101 }
102 }
103 else {
104 _log.error("Xuggler auto install failed");
105 }
106 }
107 finally {
108 PortalClassLoaderUtil.setClassLoader(classLoader);
109 }
110 }
111
112 public static class IsNativeLibraryInstalledCallable
113 implements Callable<Boolean> {
114
115 @Override
116 public Boolean call() throws Exception {
117 PrintStream printStream = System.out;
118
119 System.setOut(new PrintStream(new DummyOutputStream()));
120
121 Package pkg = JNILibrary.class.getPackage();
122
123 Logger logger = Logger.getLogger(pkg.getName());
124
125 Level level = logger.getLevel();
126
127 logger.setLevel(Level.OFF);
128
129 String property = System.getProperty(
130 "java.util.logging.config.file");
131
132 System.setProperty("java.util.logging.config.file", "configFile");
133
134 Xuggler xuggler = new XugglerImpl();
135
136 Field informAdministratorField = ReflectionUtil.getDeclaredField(
137 XugglerImpl.class, "_informAdministrator");
138
139 informAdministratorField.setBoolean(xuggler, false);
140
141 try {
142 return xuggler.isNativeLibraryInstalled();
143 }
144 finally {
145 if (property == null) {
146 System.clearProperty("java.util.logging.config.file");
147 }
148 else {
149 System.setProperty(
150 "java.util.logging.config.file", property);
151 }
152
153 logger.setLevel(level);
154
155 System.setOut(printStream);
156 }
157 }
158
159 }
160
161 private static String getXugglerJarFileName() {
162 String bitmode = OSDetector.getBitmode();
163
164 if (Validator.isNull(bitmode) ||
165 (!bitmode.equals("32") && !bitmode.equals("64"))) {
166
167 return null;
168 }
169
170 if (OSDetector.isApple()) {
171 return PropsUtil.get(
172 PropsKeys.XUGGLER_JAR_FILE, new Filter(bitmode + "-mac"));
173 }
174
175 if (OSDetector.isLinux()) {
176 return PropsUtil.get(
177 PropsKeys.XUGGLER_JAR_FILE, new Filter(bitmode + "-linux"));
178 }
179
180 if (OSDetector.isWindows()) {
181 return PropsUtil.get(
182 PropsKeys.XUGGLER_JAR_FILE, new Filter(bitmode + "-win"));
183 }
184
185 return null;
186 }
187
188 private static boolean isNativeLibraryInstalled() {
189 Properties properties = PropsUtil.getProperties(
190 PropsKeys.XUGGLER_JAR_FILE, false);
191
192 Set<Object> jarFiles = SetUtil.fromCollection(properties.values());
193
194 jarFiles.remove(getXugglerJarFileName());
195
196 Thread currentThread = Thread.currentThread();
197
198 ClassLoader contextClassLoader = currentThread.getContextClassLoader();
199
200 Set<URL> urls = ClassPathUtil.getClassPathURLs(contextClassLoader);
201
202 Iterator<URL> iterator = urls.iterator();
203
204 while (iterator.hasNext()) {
205 URL url = iterator.next();
206
207 String protocol = url.getProtocol();
208
209 if (protocol.equals("file")) {
210 File file = new File(url.getPath());
211
212 Matcher matcher = _pattern.matcher(file.getName());
213
214 if (matcher.matches()) {
215 if (jarFiles.contains(matcher.replaceAll("$1$2"))) {
216 file.delete();
217
218 iterator.remove();
219 }
220 }
221 }
222 }
223
224 URLClassLoader urlClassLoader = new URLClassLoader(
225 urls.toArray(new URL[urls.size()]), null);
226
227 currentThread.setContextClassLoader(urlClassLoader);
228
229 try {
230 Class<Callable<Boolean>> clazz =
231 (Class<Callable<Boolean>>)urlClassLoader.loadClass(
232 IsNativeLibraryInstalledCallable.class.getName());
233
234 Callable<Boolean> callable = clazz.newInstance();
235
236 return callable.call();
237 }
238 catch (Exception e) {
239 return false;
240 }
241 finally {
242 currentThread.setContextClassLoader(contextClassLoader);
243 }
244 }
245
246 private static final Log _log = LogFactoryUtil.getLog(
247 XugglerAutoInstallHelper.class);
248
249 private static final Pattern _pattern = Pattern.compile(
250 "(.*)-\\d+-\\d+(\\.jar)");
251
252 }