001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 * 
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 * 
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.log4j.lf5.viewer.configure;
018
019import java.io.BufferedInputStream;
020import java.io.File;
021import java.io.FileInputStream;
022import java.io.FileNotFoundException;
023import java.io.FileOutputStream;
024import java.io.IOException;
025import java.io.InputStream;
026import java.io.ObjectInputStream;
027import java.io.ObjectOutputStream;
028import java.net.URL;
029import java.util.Iterator;
030import java.util.LinkedList;
031
032
033/**
034 * <p>MRUFileManager handles the storage and retrival the most
035 * recently opened log files.
036 *
037 * @author Brad Marlborough
038 * @author Richard Hurst
039 */
040
041// Contributed by ThoughtWorks Inc.
042
043public class MRUFileManager {
044  //--------------------------------------------------------------------------
045  //   Constants:
046  //--------------------------------------------------------------------------
047  private static final String CONFIG_FILE_NAME = "mru_file_manager";
048  private static final int DEFAULT_MAX_SIZE = 3;
049
050  //--------------------------------------------------------------------------
051  //   Protected Variables:
052  //--------------------------------------------------------------------------
053
054  //--------------------------------------------------------------------------
055  //   Private Variables:
056  //--------------------------------------------------------------------------
057  private int _maxSize = 0;
058  private LinkedList _mruFileList;
059
060  //--------------------------------------------------------------------------
061  //   Constructors:
062  //--------------------------------------------------------------------------
063  public MRUFileManager() {
064    load();
065    setMaxSize(DEFAULT_MAX_SIZE);
066  }
067
068  public MRUFileManager(int maxSize) {
069    load();
070    setMaxSize(maxSize);
071  }
072  //--------------------------------------------------------------------------
073  //   Public Methods:
074  //--------------------------------------------------------------------------
075
076  /**
077   * Saves a list of MRU files out to a file.
078   */
079  public void save() {
080    File file = new File(getFilename());
081
082    try {
083      ObjectOutputStream oos = new ObjectOutputStream(new
084          FileOutputStream(file));
085      oos.writeObject(_mruFileList);
086      oos.flush();
087      oos.close();
088    } catch (Exception e) {
089      // do nothing
090      e.printStackTrace();
091    }
092  }
093
094  /**
095   * Gets the size of the MRU file list.
096   */
097  public int size() {
098    return _mruFileList.size();
099  }
100
101  /**
102   * Returns a particular file name stored in a MRU file
103   * list based on an index value.
104   */
105  public Object getFile(int index) {
106    if (index < size()) {
107      return _mruFileList.get(index);
108    }
109
110    return null;
111  }
112
113  /**
114   * Returns a input stream to the resource at the specified index
115   */
116  public InputStream getInputStream(int index) throws IOException,
117      FileNotFoundException {
118    if (index < size()) {
119      Object o = getFile(index);
120      if (o instanceof File) {
121        return getInputStream((File) o);
122      } else {
123        return getInputStream((URL) o);
124      }
125    }
126    return null;
127  }
128
129  /**
130   * Adds a file name to the MRU file list.
131   */
132  public void set(File file) {
133    setMRU(file);
134  }
135
136  /**
137   * Adds a url to the MRU file list.
138   */
139  public void set(URL url) {
140    setMRU(url);
141  }
142
143  /**
144   * Gets the list of files stored in the MRU file list.
145   */
146  public String[] getMRUFileList() {
147    if (size() == 0) {
148      return null;
149    }
150
151    String[] ss = new String[size()];
152
153    for (int i = 0; i < size(); i++) {
154      Object o = getFile(i);
155      if (o instanceof File) {
156        ss[i] = ((File) o).getAbsolutePath();
157      } else // must be a url
158      {
159        ss[i] = o.toString();
160      }
161
162    }
163
164    return ss;
165  }
166
167  /**
168   * Moves the the index to the top of the MRU List
169   *
170   * @param index The index to be first in the mru list
171   */
172  public void moveToTop(int index) {
173    _mruFileList.add(0, _mruFileList.remove(index));
174  }
175
176  /**
177   * Creates the directory where the MRU file list will be written.
178   * The "lf5" directory is created in the Documents and Settings
179   * directory on Windows 2000 machines and where ever the user.home
180   * variable points on all other platforms.
181   */
182  public static void createConfigurationDirectory() {
183    String home = System.getProperty("user.home");
184    String sep = System.getProperty("file.separator");
185    File f = new File(home + sep + "lf5");
186    if (!f.exists()) {
187      try {
188        f.mkdir();
189      } catch (SecurityException e) {
190        e.printStackTrace();
191      }
192    }
193
194  }
195  //--------------------------------------------------------------------------
196  //   Protected Methods:
197  //--------------------------------------------------------------------------
198  /**
199   * Gets an input stream for the corresponding file.
200   *
201   * @param file The file to create the input stream from.
202   * @return InputStream
203   */
204  protected InputStream getInputStream(File file) throws IOException,
205      FileNotFoundException {
206    BufferedInputStream reader =
207        new BufferedInputStream(new FileInputStream(file));
208
209    return reader;
210  }
211
212  /**
213   * Gets an input stream for the corresponding URL.
214   *
215   * @param url The url to create the input stream from.
216   * @return InputStream
217   */
218  protected InputStream getInputStream(URL url) throws IOException {
219    return url.openStream();
220  }
221
222  /**
223   * Adds an object to the mru.
224   */
225  protected void setMRU(Object o) {
226    int index = _mruFileList.indexOf(o);
227
228    if (index == -1) {
229      _mruFileList.add(0, o);
230      setMaxSize(_maxSize);
231    } else {
232      moveToTop(index);
233    }
234  }
235
236  /**
237   * Loads the MRU file list in from a file and stores it in a LinkedList.
238   * If no file exists, a new LinkedList is created.
239   */
240  protected void load() {
241    createConfigurationDirectory();
242    File file = new File(getFilename());
243    if (file.exists()) {
244      try {
245        ObjectInputStream ois = new ObjectInputStream(
246            new FileInputStream(file));
247        _mruFileList = (LinkedList) ois.readObject();
248        ois.close();
249
250        // check that only files and url are in linked list
251        Iterator it = _mruFileList.iterator();
252        while (it.hasNext()) {
253          Object o = it.next();
254          if (!(o instanceof File) && !(o instanceof URL)) {
255            it.remove();
256          }
257        }
258      } catch (Exception e) {
259        _mruFileList = new LinkedList();
260      }
261    } else {
262      _mruFileList = new LinkedList();
263    }
264
265  }
266
267  protected String getFilename() {
268    String home = System.getProperty("user.home");
269    String sep = System.getProperty("file.separator");
270
271    return home + sep + "lf5" + sep + CONFIG_FILE_NAME;
272  }
273
274  /**
275   * Ensures that the MRU list will have a MaxSize.
276   */
277  protected void setMaxSize(int maxSize) {
278    if (maxSize < _mruFileList.size()) {
279      for (int i = 0; i < _mruFileList.size() - maxSize; i++) {
280        _mruFileList.removeLast();
281      }
282    }
283
284    _maxSize = maxSize;
285  }
286  //--------------------------------------------------------------------------
287  //   Private Methods:
288  //--------------------------------------------------------------------------
289
290  //--------------------------------------------------------------------------
291  //   Nested Top-Level Classes or Interfaces
292  //--------------------------------------------------------------------------
293}