View Javadoc

1   /*
2    * Copyright 2013 smartics, Kronseder & Reiner GmbH
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package de.smartics.properties.resource.filesystem.heap;
17  
18  import java.io.File;
19  import java.io.IOException;
20  import java.net.MalformedURLException;
21  import java.net.URL;
22  import java.util.ArrayList;
23  import java.util.Iterator;
24  import java.util.List;
25  
26  import org.apache.commons.io.FileUtils;
27  import org.slf4j.Logger;
28  import org.slf4j.LoggerFactory;
29  
30  import de.smartics.properties.resource.domain.ArtifactId;
31  import de.smartics.properties.resource.domain.ArtifactRef;
32  import de.smartics.properties.resource.domain.ClassPathEnvironment;
33  import de.smartics.properties.resource.heap.HeapException;
34  import de.smartics.properties.resource.heap.ResourceHeap;
35  import de.smartics.util.lang.Arg;
36  
37  /**
38   * Provides an implementation of {@link ResourceHeap} based on a file system.
39   */
40  public final class FileSystemResourceHeap implements ResourceHeap
41  {
42    // ********************************* Fields *********************************
43  
44    // --- constants ------------------------------------------------------------
45  
46    /**
47     * Reference to the logger for this class.
48     */
49    private static final Logger LOG = LoggerFactory
50        .getLogger(FileSystemResourceHeap.class);
51  
52    // --- members --------------------------------------------------------------
53  
54    /**
55     * The list of root folders to traverse.
56     */
57    private final List<File> rootFolders = new ArrayList<File>();
58  
59    /**
60     * The artifact identifier to use for properties files encountered.
61     */
62    private ArtifactId defaultArtifactId = new ArtifactId.Builder()
63        .withGroupId("unknown-group").withName("unknown")
64        .withVersion("unknown-version").withArchiveType("properties").build();
65  
66    // ****************************** Initializer *******************************
67  
68    // ****************************** Constructors ******************************
69  
70    // ****************************** Inner Classes *****************************
71  
72    // ********************************* Methods ********************************
73  
74    // --- init -----------------------------------------------------------------
75  
76    // --- get&set --------------------------------------------------------------
77  
78    /**
79     * Returns the artifact identifier to use for properties files encountered.
80     *
81     * @return the artifact identifier to use for properties files encountered.
82     */
83    public ArtifactId getDefaultArtifactId()
84    {
85      return defaultArtifactId;
86    }
87  
88    /**
89     * Sets the artifact identifier to use for properties files encountered.
90     *
91     * @param defaultArtifactId the artifact identifier to use for properties
92     *          files encountered.
93     */
94    public void setDefaultArtifactId(final ArtifactId defaultArtifactId)
95    {
96      this.defaultArtifactId = defaultArtifactId;
97    }
98  
99    // --- business -------------------------------------------------------------
100 
101   /**
102    * Adds a root folder to check for property resources.
103    *
104    * @param rootFolder the folder to add as a root to check for property
105    *          resources.
106    * @throws NullPointerException if {@code rootFolder} is <code>null</code>.
107    * @throws IllegalArgumentException if {@code rootFolder} is not a directory.
108    */
109   public void addRootFolder(final File rootFolder) throws NullPointerException,
110     IllegalArgumentException
111   {
112     Arg.checkNotNull("rootFolder", rootFolder);
113 
114     if (!rootFolder.isDirectory())
115     {
116       throw new IllegalArgumentException(String.format("'%s' is not a folder.",
117           rootFolder.getAbsolutePath()));
118     }
119 
120     rootFolders.add(rootFolder);
121   }
122 
123   @Override
124   @SuppressWarnings("unchecked")
125   public ClassPathEnvironment resolve() throws HeapException
126   {
127     final ClassPathEnvironment env = new ClassPathEnvironment();
128     final String[] extensions =
129         new String[] { "jar", "ear", "war", "sar", "properties" };
130 
131     for (final File rootFolder : rootFolders)
132     {
133       boolean containsPropertiesFile = false;
134       for (final Iterator<File> files =
135           FileUtils.iterateFiles(rootFolder, extensions, true); files.hasNext();)
136       {
137         final File file = files.next();
138 
139         if (!isPropertiesFile(file))
140         {
141           final ArtifactRef archiveArtifactRef = createArchiveArtifactRef(file);
142           if (archiveArtifactRef != null)
143           {
144             env.addArchiveArtifactRef(archiveArtifactRef);
145           }
146         }
147         else if (!containsPropertiesFile)
148         {
149           containsPropertiesFile = true;
150           final ArtifactRef rootRef = createFolderRef(rootFolder);
151           env.addAnyArtifactRef(rootRef);
152         }
153       }
154     }
155 
156     return env;
157   }
158 
159   private ArtifactRef createFolderRef(final File file)
160   {
161     try
162     {
163       return new ArtifactRef(defaultArtifactId, file.toURI().toURL());
164     }
165     catch (final MalformedURLException e)
166     {
167       LOG.debug("Cannot transform file '{}' to an URL: "
168                 + e.getLocalizedMessage());
169       return null;
170     }
171   }
172 
173   private boolean isPropertiesFile(final File file)
174   {
175     final String name = file.getName();
176     final boolean isPropertiesFile = name.endsWith(".properties");
177     return isPropertiesFile;
178   }
179 
180   private static ArtifactRef createArchiveArtifactRef(final File archiveFile)
181     throws HeapException
182   {
183     try
184     {
185       final ArtifactId id = readArtifactId(archiveFile);
186       final URL url = archiveFile.toURI().toURL();
187       if (id != null)
188       {
189         final ArtifactRef ref = new ArtifactRef(id, url);
190         return ref;
191       }
192     }
193     catch (final MalformedURLException e)
194     {
195       LOG.debug("Cannot transform file '{}' to an URL: "
196                 + e.getLocalizedMessage());
197     }
198     catch (final IOException e)
199     {
200       throw new HeapException(new FileMessageBean(
201           FileSystemResourceCode.FAILED_TO_READ_ARCHIVE_FILE, e, archiveFile));
202     }
203     return null;
204   }
205 
206   private static ArtifactId readArtifactId(final File archiveFile)
207     throws NullPointerException, IOException
208   {
209     final ArtifactIdGrabber grabber = ArtifactIdGrabber.createLazy(archiveFile);
210     if (grabber.isDefinitionArchive())
211     {
212       final ArtifactId id = grabber.getArtifactId();
213       return id;
214     }
215     return null;
216   }
217 
218   // --- object basics --------------------------------------------------------
219 
220 }