1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    *
5    *
6    *
7    * The contents of this file are subject to the terms of the Liferay Enterprise
8    * Subscription License ("License"). You may not use this file except in
9    * compliance with the License. You can obtain a copy of the License by
10   * contacting Liferay, Inc. See the License for the specific language governing
11   * permissions and limitations under the License, including but not limited to
12   * distribution rights of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.kernel.deploy.auto;
24  
25  import com.liferay.portal.kernel.log.Log;
26  import com.liferay.portal.kernel.log.LogFactoryUtil;
27  import com.liferay.portal.kernel.util.IntegerWrapper;
28  
29  import java.io.File;
30  
31  import java.util.HashMap;
32  import java.util.HashSet;
33  import java.util.List;
34  import java.util.Map;
35  import java.util.Set;
36  import java.util.concurrent.CopyOnWriteArrayList;
37  
38  /**
39   * <a href="AutoDeployDir.java.html"><b><i>View Source</i></b></a>
40   *
41   * @author Ivica Cardic
42   * @author Brian Wing Shun Chan
43   */
44  public class AutoDeployDir {
45  
46      public static final String DEFAULT_NAME = "defaultAutoDeployDir";
47  
48      public AutoDeployDir(
49          String name, File deployDir, File destDir, long interval,
50          int blacklistThreshold, List<AutoDeployListener> listeners) {
51  
52          _name = name;
53          _deployDir = deployDir;
54          _destDir = destDir;
55          _interval = interval;
56          _blacklistThreshold = blacklistThreshold;
57          _listeners = new CopyOnWriteArrayList<AutoDeployListener>(listeners);
58          _inProcessFiles = new HashMap<String, IntegerWrapper>();
59          _blacklistFiles = new HashSet<String>();
60      }
61  
62      public int getBlacklistThreshold() {
63          return _blacklistThreshold;
64      }
65  
66      public File getDeployDir() {
67          return _deployDir;
68      }
69  
70      public File getDestDir() {
71          return _destDir;
72      }
73  
74      public long getInterval() {
75          return _interval;
76      }
77  
78      public List<AutoDeployListener> getListeners() {
79          return _listeners;
80      }
81  
82      public String getName() {
83          return _name;
84      }
85  
86      public void registerListener(AutoDeployListener listener) {
87          _listeners.add(listener);
88      }
89  
90      public void start() {
91          if (!_deployDir.exists()) {
92              if (_log.isInfoEnabled()) {
93                  _log.info("Creating missing directory " + _deployDir);
94              }
95  
96              boolean created = _deployDir.mkdirs();
97  
98              if (!created) {
99                  _log.error("Directory " + _deployDir + " could not be created");
100             }
101         }
102 
103         if (_interval > 0) {
104             try {
105                 Thread currentThread = Thread.currentThread();
106 
107                 _scanner = new AutoDeployScanner(
108                     currentThread.getThreadGroup(),
109                     AutoDeployScanner.class.getName(), this);
110 
111                 _scanner.start();
112 
113                 if (_log.isInfoEnabled()) {
114                     _log.info("Auto deploy scanner started for " + _deployDir);
115                 }
116             }
117             catch (Exception e) {
118                 _log.error(e, e);
119 
120                 stop();
121 
122                 return;
123             }
124         }
125         else {
126             if (_log.isInfoEnabled()) {
127                 _log.info("Auto deploy scanning is disabled for " + _deployDir);
128             }
129         }
130     }
131 
132     public void stop() {
133         if (_scanner != null) {
134             _scanner.pause();
135         }
136     }
137 
138     public void unregisterListener(AutoDeployListener listener) {
139         _listeners.remove(listener);
140     }
141 
142     protected void processFile(File file) {
143         String fileName = file.getName();
144 
145         if (!file.canRead()) {
146             _log.error("Unable to read " + fileName);
147 
148             return;
149         }
150 
151         if (!file.canWrite()) {
152             _log.error("Unable to write " + fileName);
153 
154             return;
155         }
156 
157         if (_blacklistFiles.contains(fileName)) {
158             if (_log.isDebugEnabled()) {
159                 _log.debug(
160                     "Skip processing of " + fileName + " because it is " +
161                         "blacklisted. You must restart the server to remove " +
162                             "the file from the blacklist.");
163             }
164 
165             return;
166         }
167 
168         IntegerWrapper attempt = _inProcessFiles.get(fileName);
169 
170         if (attempt == null) {
171             attempt = new IntegerWrapper(1);
172 
173             _inProcessFiles.put(fileName, attempt);
174 
175             if (_log.isInfoEnabled()) {
176                 _log.info("Processing " + fileName);
177             }
178         }
179         else {
180             if (_log.isInfoEnabled()) {
181                 _log.info(
182                     "Processing " + fileName + ". This is attempt " +
183                         attempt.getValue() + ".");
184             }
185         }
186 
187         try {
188             for (AutoDeployListener listener : _listeners) {
189                 listener.deploy(file);
190             }
191 
192             if (file.delete()) {
193                 _inProcessFiles.remove(fileName);
194             }
195             else {
196                 _log.error("Auto deploy failed to remove " + fileName);
197 
198                 if (_log.isInfoEnabled()) {
199                     _log.info("Add " + fileName + " to the blacklist");
200                 }
201 
202                 _blacklistFiles.add(fileName);
203             }
204         }
205         catch (Exception e) {
206             _log.error(e, e);
207 
208             attempt.increment();
209 
210             if (attempt.getValue() >= _blacklistThreshold) {
211                 if (_log.isInfoEnabled()) {
212                     _log.info("Add " + fileName + " to the blacklist");
213                 }
214 
215                 _blacklistFiles.add(fileName);
216             }
217         }
218     }
219 
220     protected void scanDirectory() {
221         File[] files = _deployDir.listFiles();
222 
223         for (int i = 0; i < files.length; i++) {
224             File file = files[i];
225 
226             String fileName = file.getName().toLowerCase();
227 
228             if ((file.isFile()) &&
229                 (fileName.endsWith(".war") || fileName.endsWith(".zip") ||
230                  fileName.endsWith(".xml"))) {
231 
232                 processFile(file);
233             }
234         }
235     }
236 
237     private static Log _log = LogFactoryUtil.getLog(AutoDeployDir.class);
238 
239     private Set<String> _blacklistFiles;
240     private int _blacklistThreshold;
241     private File _deployDir;
242     private File _destDir;
243     private Map<String, IntegerWrapper> _inProcessFiles;
244     private long _interval;
245     private List<AutoDeployListener> _listeners;
246     private String _name;
247     private AutoDeployScanner _scanner;
248 
249 }