001    /**
002     * Copyright (c) 2000-2013 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.kernel.deploy.auto;
016    
017    import com.liferay.portal.kernel.deploy.auto.context.AutoDeploymentContext;
018    import com.liferay.portal.kernel.log.Log;
019    import com.liferay.portal.kernel.log.LogFactoryUtil;
020    
021    import java.io.File;
022    
023    import java.util.HashMap;
024    import java.util.Iterator;
025    import java.util.List;
026    import java.util.Map;
027    import java.util.Set;
028    import java.util.concurrent.CopyOnWriteArrayList;
029    
030    /**
031     * @author Ivica Cardic
032     * @author Brian Wing Shun Chan
033     */
034    public class AutoDeployDir {
035    
036            public static final String DEFAULT_NAME = "defaultAutoDeployDir";
037    
038            public AutoDeployDir(
039                    String name, File deployDir, File destDir, long interval,
040                    List<AutoDeployListener> autoDeployListeners) {
041    
042                    _name = name;
043                    _deployDir = deployDir;
044                    _destDir = destDir;
045                    _interval = interval;
046                    _autoDeployListeners = new CopyOnWriteArrayList<AutoDeployListener>(
047                            autoDeployListeners);
048                    _blacklistFileTimestamps = new HashMap<String, Long>();
049            }
050    
051            public File getDeployDir() {
052                    return _deployDir;
053            }
054    
055            public File getDestDir() {
056                    return _destDir;
057            }
058    
059            public long getInterval() {
060                    return _interval;
061            }
062    
063            public List<AutoDeployListener> getListeners() {
064                    return _autoDeployListeners;
065            }
066    
067            public String getName() {
068                    return _name;
069            }
070    
071            public void registerListener(AutoDeployListener listener) {
072                    _autoDeployListeners.add(listener);
073            }
074    
075            public void start() {
076                    if (!_deployDir.exists()) {
077                            if (_log.isInfoEnabled()) {
078                                    _log.info("Creating missing directory " + _deployDir);
079                            }
080    
081                            boolean created = _deployDir.mkdirs();
082    
083                            if (!created) {
084                                    _log.error("Directory " + _deployDir + " could not be created");
085                            }
086                    }
087    
088                    if (_interval > 0) {
089                            try {
090                                    Thread currentThread = Thread.currentThread();
091    
092                                    _autoDeployScanner = new AutoDeployScanner(
093                                            currentThread.getThreadGroup(),
094                                            AutoDeployScanner.class.getName(), this);
095    
096                                    _autoDeployScanner.start();
097    
098                                    if (_log.isInfoEnabled()) {
099                                            _log.info("Auto deploy scanner started for " + _deployDir);
100                                    }
101                            }
102                            catch (Exception e) {
103                                    _log.error(e, e);
104    
105                                    stop();
106    
107                                    return;
108                            }
109                    }
110                    else {
111                            if (_log.isInfoEnabled()) {
112                                    _log.info("Auto deploy scanning is disabled for " + _deployDir);
113                            }
114                    }
115            }
116    
117            public void stop() {
118                    if (_autoDeployScanner != null) {
119                            _autoDeployScanner.pause();
120                    }
121            }
122    
123            public void unregisterListener(AutoDeployListener autoDeployListener) {
124                    _autoDeployListeners.remove(autoDeployListener);
125            }
126    
127            protected AutoDeploymentContext buildAutoDeploymentContext(File file) {
128                    AutoDeploymentContext autoDeploymentContext =
129                            new AutoDeploymentContext();
130    
131                    autoDeploymentContext.setFile(file);
132    
133                    return autoDeploymentContext;
134            }
135    
136            protected void processFile(File file) {
137                    String fileName = file.getName();
138    
139                    if (!file.canRead()) {
140                            _log.error("Unable to read " + fileName);
141    
142                            return;
143                    }
144    
145                    if (!file.canWrite()) {
146                            _log.error("Unable to write " + fileName);
147    
148                            return;
149                    }
150    
151                    if (_blacklistFileTimestamps.containsKey(fileName) &&
152                            (_blacklistFileTimestamps.get(fileName) == file.lastModified())) {
153    
154                            if (_log.isDebugEnabled()) {
155                                    _log.debug(
156                                            "Skip processing of " + fileName + " because it is " +
157                                                    "blacklisted");
158                            }
159    
160                            return;
161                    }
162    
163                    if (_log.isInfoEnabled()) {
164                            _log.info("Processing " + fileName);
165                    }
166    
167                    try {
168                            AutoDeploymentContext autoDeploymentContext =
169                                    buildAutoDeploymentContext(file);
170    
171                            for (AutoDeployListener autoDeployListener : _autoDeployListeners) {
172                                    autoDeployListener.deploy(autoDeploymentContext);
173                            }
174    
175                            if (file.delete()) {
176                                    return;
177                            }
178    
179                            _log.error("Auto deploy failed to remove " + fileName);
180                    }
181                    catch (Exception e) {
182                            _log.error(e, e);
183                    }
184    
185                    if (_log.isInfoEnabled()) {
186                            _log.info("Add " + fileName + " to the blacklist");
187                    }
188    
189                    _blacklistFileTimestamps.put(fileName, file.lastModified());
190            }
191    
192            protected void scanDirectory() {
193                    File[] files = _deployDir.listFiles();
194    
195                    Set<String> blacklistedFileNames = _blacklistFileTimestamps.keySet();
196    
197                    Iterator<String> iterator = blacklistedFileNames.iterator();
198    
199                    while (iterator.hasNext()) {
200                            String blacklistedFileName = iterator.next();
201    
202                            boolean blacklistedFileExists = false;
203    
204                            for (File file : files) {
205                                    if (blacklistedFileName.equalsIgnoreCase(file.getName())) {
206                                            blacklistedFileExists = true;
207                                    }
208                            }
209    
210                            if (!blacklistedFileExists) {
211                                    if (_log.isDebugEnabled()) {
212                                            _log.debug(
213                                                    "Remove blacklisted file " + blacklistedFileName +
214                                                            " because it was deleted");
215                                    }
216    
217                                    iterator.remove();
218                            }
219                    }
220    
221                    for (File file : files) {
222                            String fileName = file.getName();
223    
224                            fileName = fileName.toLowerCase();
225    
226                            if (file.isFile() &&
227                                    (fileName.endsWith(".jar") || fileName.endsWith(".lpkg") ||
228                                     fileName.endsWith(".war") || fileName.endsWith(".xml") ||
229                                     fileName.endsWith(".zip"))) {
230    
231                                    processFile(file);
232                            }
233                    }
234            }
235    
236            private static Log _log = LogFactoryUtil.getLog(AutoDeployDir.class);
237    
238            private List<AutoDeployListener> _autoDeployListeners;
239            private AutoDeployScanner _autoDeployScanner;
240            private Map<String, Long> _blacklistFileTimestamps;
241            private File _deployDir;
242            private File _destDir;
243            private long _interval;
244            private String _name;
245    
246    }