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