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.executor;
016    
017    import com.liferay.portal.kernel.concurrent.ThreadPoolExecutor;
018    import com.liferay.portal.kernel.executor.PortalExecutorFactory;
019    import com.liferay.portal.kernel.executor.PortalExecutorManager;
020    import com.liferay.portal.kernel.log.Log;
021    import com.liferay.portal.kernel.log.LogFactoryUtil;
022    import com.liferay.portal.kernel.security.pacl.PACLConstants;
023    import com.liferay.portal.kernel.security.pacl.permission.PortalRuntimePermission;
024    
025    import java.security.Permission;
026    
027    import java.util.Map;
028    import java.util.concurrent.Callable;
029    import java.util.concurrent.ConcurrentHashMap;
030    import java.util.concurrent.ExecutionException;
031    import java.util.concurrent.Future;
032    import java.util.concurrent.TimeUnit;
033    import java.util.concurrent.TimeoutException;
034    
035    /**
036     * @author Shuyang Zhou
037     */
038    public class PortalExecutorManagerImpl implements PortalExecutorManager {
039    
040            public void afterPropertiesSet() {
041                    if (_portalExecutorFactory == null) {
042                            throw new IllegalArgumentException(
043                                    "Portal executor factory is null");
044                    }
045            }
046    
047            public <T> Future<T> execute(String name, Callable<T> callable) {
048                    ThreadPoolExecutor threadPoolExecutor = getPortalExecutor(name);
049    
050                    return threadPoolExecutor.submit(callable);
051            }
052    
053            public <T> T execute(
054                            String name, Callable<T> callable, long timeout, TimeUnit timeUnit)
055                    throws ExecutionException, InterruptedException, TimeoutException {
056    
057                    ThreadPoolExecutor threadPoolExecutor = getPortalExecutor(name);
058    
059                    Future<T> future = threadPoolExecutor.submit(callable);
060    
061                    return future.get(timeout, timeUnit);
062            }
063    
064            public ThreadPoolExecutor getPortalExecutor(String name) {
065                    return getPortalExecutor(name, true);
066            }
067    
068            public ThreadPoolExecutor getPortalExecutor(
069                    String name, boolean createIfAbsent) {
070    
071                    SecurityManager securityManager = System.getSecurityManager();
072    
073                    if (securityManager != null) {
074                            Permission permission = new PortalRuntimePermission(
075                                    PACLConstants.PORTAL_RUNTIME_PERMISSION_THREAD_POOL_EXECUTOR,
076                                    name);
077    
078                            securityManager.checkPermission(permission);
079                    }
080    
081                    ThreadPoolExecutor threadPoolExecutor = _threadPoolExecutors.get(name);
082    
083                    if ((threadPoolExecutor == null) && createIfAbsent) {
084                            synchronized (_threadPoolExecutors) {
085                                    threadPoolExecutor = _threadPoolExecutors.get(name);
086    
087                                    if (threadPoolExecutor == null) {
088                                            threadPoolExecutor =
089                                                    _portalExecutorFactory.createPortalExecutor(name);
090    
091                                            _threadPoolExecutors.put(name, threadPoolExecutor);
092                                    }
093                            }
094                    }
095    
096                    return threadPoolExecutor;
097            }
098    
099            public ThreadPoolExecutor registerPortalExecutor(
100                    String name, ThreadPoolExecutor threadPoolExecutor) {
101    
102                    SecurityManager securityManager = System.getSecurityManager();
103    
104                    if (securityManager != null) {
105                            Permission permission = new PortalRuntimePermission(
106                                    PACLConstants.PORTAL_RUNTIME_PERMISSION_THREAD_POOL_EXECUTOR,
107                                    name);
108    
109                            securityManager.checkPermission(permission);
110                    }
111    
112                    ThreadPoolExecutor oldThreadPoolExecutor = _threadPoolExecutors.get(
113                            name);
114    
115                    if (oldThreadPoolExecutor == null) {
116                            synchronized (_threadPoolExecutors) {
117                                    oldThreadPoolExecutor = _threadPoolExecutors.get(name);
118    
119                                    if (oldThreadPoolExecutor == null) {
120                                            oldThreadPoolExecutor = _threadPoolExecutors.put(
121                                                    name, threadPoolExecutor);
122                                    }
123                            }
124                    }
125    
126                    return oldThreadPoolExecutor;
127            }
128    
129            public void setPortalExecutorFactory(
130                    PortalExecutorFactory portalExecutorFactory) {
131    
132                    _portalExecutorFactory = portalExecutorFactory;
133            }
134    
135            public void setPortalExecutors(
136                    Map<String, ThreadPoolExecutor> threadPoolExecutors) {
137    
138                    if (threadPoolExecutors != null) {
139                            _threadPoolExecutors =
140                                    new ConcurrentHashMap<String, ThreadPoolExecutor>(
141                                            threadPoolExecutors);
142                    }
143            }
144    
145            public void shutdown() {
146                    shutdown(false);
147            }
148    
149            public void shutdown(boolean interrupt) {
150                    for (Map.Entry<String, ThreadPoolExecutor> entry :
151                                    _threadPoolExecutors.entrySet()) {
152    
153                            try {
154                                    SecurityManager securityManager = System.getSecurityManager();
155    
156                                    if (securityManager != null) {
157                                            String name = entry.getKey();
158    
159                                            Permission permission = new PortalRuntimePermission(
160                                                    PACLConstants.
161                                                            PORTAL_RUNTIME_PERMISSION_THREAD_POOL_EXECUTOR,
162                                                    name);
163    
164                                            securityManager.checkPermission(permission);
165                                    }
166                            }
167                            catch (SecurityException se) {
168                                    _log.error(se, se);
169    
170                                    continue;
171                            }
172    
173                            ThreadPoolExecutor threadPoolExecutor = entry.getValue();
174    
175                            if (interrupt) {
176                                    threadPoolExecutor.shutdownNow();
177                            }
178                            else {
179                                    threadPoolExecutor.shutdown();
180                            }
181                    }
182    
183                    _threadPoolExecutors.clear();
184            }
185    
186            public void shutdown(String name) {
187                    shutdown(name, false);
188            }
189    
190            public void shutdown(String name, boolean interrupt) {
191                    SecurityManager securityManager = System.getSecurityManager();
192    
193                    if (securityManager != null) {
194                            Permission permission = new PortalRuntimePermission(
195                                    PACLConstants.PORTAL_RUNTIME_PERMISSION_THREAD_POOL_EXECUTOR,
196                                    name);
197    
198                            securityManager.checkPermission(permission);
199                    }
200    
201                    ThreadPoolExecutor threadPoolExecutor = _threadPoolExecutors.remove(
202                            name);
203    
204                    if (threadPoolExecutor == null) {
205                            if (_log.isDebugEnabled()) {
206                                    _log.debug("No portal executor found for name " + name);
207                            }
208    
209                            return;
210                    }
211    
212                    if (interrupt) {
213                            threadPoolExecutor.shutdownNow();
214                    }
215                    else {
216                            threadPoolExecutor.shutdown();
217                    }
218            }
219    
220            private static Log _log = LogFactoryUtil.getLog(
221                    PortalExecutorManagerImpl.class);
222    
223            private PortalExecutorFactory _portalExecutorFactory;
224            private Map<String, ThreadPoolExecutor> _threadPoolExecutors =
225                    new ConcurrentHashMap<String, ThreadPoolExecutor>();
226    
227    }