001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.util;
016    
017    import com.liferay.portal.kernel.cluster.ClusterExecutorUtil;
018    import com.liferay.portal.kernel.cluster.ClusterRequest;
019    import com.liferay.portal.kernel.cluster.FutureClusterResponses;
020    import com.liferay.portal.kernel.log.Log;
021    import com.liferay.portal.kernel.log.LogFactoryUtil;
022    import com.liferay.portal.kernel.util.FileUtil;
023    import com.liferay.portal.kernel.util.HttpUtil;
024    import com.liferay.portal.kernel.util.MethodHandler;
025    import com.liferay.portal.kernel.util.MethodKey;
026    import com.liferay.portal.kernel.util.ProgressStatusConstants;
027    import com.liferay.portal.kernel.util.ProgressTracker;
028    import com.liferay.portal.kernel.util.StringPool;
029    import com.liferay.portal.model.CompanyConstants;
030    import com.liferay.portlet.documentlibrary.store.DLStoreUtil;
031    
032    import java.io.File;
033    import java.io.InputStream;
034    
035    import java.lang.reflect.Method;
036    
037    import java.net.URI;
038    import java.net.URL;
039    import java.net.URLClassLoader;
040    
041    import java.util.concurrent.TimeUnit;
042    
043    /**
044     * @author Alexander Chow
045     */
046    public class JarUtil {
047    
048            public static void downloadAndInstallJar(
049                            boolean globalClassPath, String url, String name,
050                            ProgressTracker progressTracker)
051                    throws Exception {
052    
053                    setProgressStatus(progressTracker, ProgressStatusConstants.DOWNLOADING);
054    
055                    if (_log.isInfoEnabled()) {
056                            _log.info("Downloading " + url);
057                    }
058    
059                    byte[] bytes = HttpUtil.URLtoByteArray(url);
060    
061                    setProgressStatus(progressTracker, ProgressStatusConstants.COPYING);
062    
063                    if (PropsValues.CLUSTER_LINK_ENABLED) {
064                            try {
065                                    DLStoreUtil.deleteFile(
066                                            _REPOSITORY, _REPOSITORY, _FILE_PATH + name);
067                            }
068                            catch (Exception e) {
069                            }
070    
071                            DLStoreUtil.addFile(
072                                    _REPOSITORY, _REPOSITORY, _FILE_PATH + name, bytes);
073    
074                            try {
075                                    ClusterRequest clusterRequest =
076                                            ClusterRequest.createMulticastRequest(
077                                                    new MethodHandler(
078                                                            _installJarKey, globalClassPath, name));
079    
080                                    FutureClusterResponses futureClusterResponses =
081                                            ClusterExecutorUtil.execute(clusterRequest);
082    
083                                    futureClusterResponses.get(30, TimeUnit.SECONDS);
084                            }
085                            finally {
086                                    try {
087                                            DLStoreUtil.deleteFile(
088                                                    _REPOSITORY, _REPOSITORY, _FILE_PATH + name);
089                                    }
090                                    catch (Exception e) {
091                                    }
092                            }
093                    }
094                    else {
095                            setProgressStatus(progressTracker, ProgressStatusConstants.COPYING);
096    
097                            installJar(bytes, globalClassPath, name);
098                    }
099            }
100    
101            public static void installJar(boolean globalClassPath, String name)
102                    throws Exception {
103    
104                    installJar(null, globalClassPath, name);
105            }
106    
107            protected static void addJarFileToClassLoader(File file) throws Exception {
108                    Class<?> clazz = URLClassLoader.class;
109    
110                    Method method = clazz.getDeclaredMethod(
111                            "addURL", new Class[] {URL.class});
112    
113                    method.setAccessible(true);
114    
115                    URI uri = file.toURI();
116    
117                    method.invoke(
118                            ClassLoader.getSystemClassLoader(), new Object[] {uri.toURL()});
119            }
120    
121            protected static void installJar(
122                            byte[] bytes, boolean globalClassPath, String name)
123                    throws Exception {
124    
125                    String libPath = PropsValues.LIFERAY_LIB_PORTAL_DIR;
126    
127                    if (globalClassPath) {
128                            libPath = PropsValues.LIFERAY_LIB_GLOBAL_DIR;
129                    }
130    
131                    File file = new File(libPath + StringPool.SLASH + name);
132    
133                    InputStream is = null;
134    
135                    try {
136                            if (_log.isInfoEnabled()) {
137                                    _log.info("Writing " + file);
138                            }
139    
140                            if (bytes != null) {
141                                    FileUtil.write(file, bytes);
142                            }
143                            else {
144                                    is = DLStoreUtil.getFileAsStream(
145                                            _REPOSITORY, _REPOSITORY, _FILE_PATH + name);
146    
147                                    FileUtil.write(file, is);
148                            }
149                    }
150                    finally {
151                            if (is != null) {
152                                    is.close();
153                            }
154                    }
155    
156                    addJarFileToClassLoader(file);
157            }
158    
159            protected static void setProgressStatus(
160                    ProgressTracker progressTracker, int status) {
161    
162                    if (progressTracker == null) {
163                            return;
164                    }
165    
166                    progressTracker.setStatus(status);
167            }
168    
169            private static final String _FILE_PATH = "jar_temp/";
170    
171            private static final long _REPOSITORY = CompanyConstants.SYSTEM;
172    
173            private static Log _log = LogFactoryUtil.getLog(JarUtil.class);
174    
175            private static MethodKey _installJarKey = new MethodKey(
176                    JarUtil.class, "installJar", boolean.class, String.class);
177    
178    }