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.config.transfer.filesystem;
17  
18  import java.io.BufferedOutputStream;
19  import java.io.File;
20  import java.io.FileOutputStream;
21  import java.io.IOException;
22  import java.io.OutputStream;
23  import java.util.Properties;
24  
25  import org.apache.commons.io.FileUtils;
26  import org.apache.commons.io.IOUtils;
27  
28  import de.smartics.properties.api.config.domain.Property;
29  import de.smartics.properties.api.config.domain.PropertyLocation;
30  import de.smartics.properties.api.config.domain.PropertyProvider;
31  import de.smartics.properties.api.config.domain.key.ConfigurationKey;
32  import de.smartics.properties.api.config.transfer.PropertySink;
33  import de.smartics.properties.api.config.transfer.TransferException;
34  import de.smartics.properties.spi.config.domain.key.ConfigurationKeyContextManager;
35  import de.smartics.util.io.FileFunction;
36  import de.smartics.util.lang.Arg;
37  
38  /**
39   * Writes properties to a folder.
40   */
41  public final class FileSystemPropertySink implements PropertySink
42  {
43    // ********************************* Fields *********************************
44  
45    // --- constants ------------------------------------------------------------
46  
47    // --- members --------------------------------------------------------------
48  
49    /**
50     * The name of the folder the properties definitions are written to.
51     */
52    private final File targetFolder;
53  
54    /**
55     * The format the property definition files will be written to.
56     */
57    private final PropertiesFormat outputFormat;
58  
59    // ****************************** Initializer *******************************
60  
61    // ****************************** Constructors ******************************
62  
63    /**
64     * Convenience constructor to create native properties files.
65     *
66     * @param targetFolder the name of the folder the properties definitions are
67     *          written to.
68     */
69    public FileSystemPropertySink(final File targetFolder)
70    {
71      this(targetFolder, PropertiesFormat.NATIVE);
72    }
73  
74    /**
75     * Default constructor.
76     *
77     * @param targetFolder the name of the folder the properties definitions are
78     *          written to.
79     * @param outputFormat the format the property definition files will be
80     *          written to.
81     * @throws NullPointerException if {@code targetFolder} or
82     *           {@code outputFormat} is <code>null</code>.
83     */
84    public FileSystemPropertySink(final File targetFolder,
85        final PropertiesFormat outputFormat) throws NullPointerException
86    {
87      this.targetFolder = Arg.checkNotNull("targetFolder", targetFolder);
88      this.outputFormat = Arg.checkNotNull("outputFormat", outputFormat);
89    }
90  
91    // ****************************** Inner Classes *****************************
92  
93    // ********************************* Methods ********************************
94  
95    // --- init -----------------------------------------------------------------
96  
97    // --- get&set --------------------------------------------------------------
98  
99    // --- business -------------------------------------------------------------
100 
101   @Override
102   public void clear() throws TransferException
103   {
104     try
105     {
106       FileUtils.cleanDirectory(targetFolder);
107     }
108     catch (final IOException e)
109     {
110       final ConfigurationKey<?> key =
111           ConfigurationKeyContextManager.INSTANCE.context()
112               .configurationKeyFactory().createDefaultKey();
113       throw new TransferException(new TransferMessageBean(
114           TransferFileCode.FAILED_TO_CLEAN, e, key, targetFolder));
115     }
116   }
117 
118   // TODO: Not yet transactional ...
119   @Override
120   public void write(final PropertyProvider provider) throws TransferException
121   {
122     final PropertyLocation location = provider.getSourceId();
123     final ConfigurationKey<?> key = provider.getConfigurationKey();
124 
125     final Properties properties = createProperties(provider);
126 
127     writeProperties(key, location, properties);
128   }
129 
130   private Properties createProperties(final PropertyProvider provider)
131   {
132     final Properties properties = new Properties();
133     for (final Property property : provider.getProperties())
134     {
135       final String name = property.getName();
136       final String value = property.getValue();
137       properties.setProperty(name, value);
138     }
139     return properties;
140   }
141 
142   private void writeProperties(final ConfigurationKey<?> key,
143       final PropertyLocation location, final Properties properties)
144   {
145     // FIXME: translate location to a valid filename path
146     final String path = location.getPath();
147     final File propertiesFile = createFile(path);
148     OutputStream out = null;
149     try
150     {
151       final File parentDir = propertiesFile.getParentFile();
152       FileFunction.provideDirectory(parentDir);
153 
154       out = new BufferedOutputStream(new FileOutputStream(propertiesFile));
155 
156       final String comments = key.toString();
157       if (outputFormat == PropertiesFormat.XML)
158       {
159         properties.storeToXML(out, comments);
160       }
161       else
162       {
163         properties.store(out, comments);
164       }
165     }
166     catch (final IOException e)
167     {
168       throw new TransferException(new TransferMessageBean(
169           TransferFileCode.FAILED_TO_TRANSFER, e, key, targetFolder));
170     }
171     finally
172     {
173       IOUtils.closeQuietly(out);
174     }
175   }
176 
177   private File createFile(final String path)
178   {
179     final String adjustedPath = outputFormat.adjustPath(path);
180     return new File(targetFolder, adjustedPath);
181   }
182 
183   // TODO: Not yet transactional ...
184   @Override
185   public void write(final Iterable<PropertyProvider> providers)
186     throws TransferException
187   {
188     for (final PropertyProvider provider : providers)
189     {
190       write(provider);
191     }
192   }
193 
194   /**
195    * {@inheritDoc}
196    * <p>
197    * This is a no-op.
198    * </p>
199    */
200   @Override
201   public void close() throws TransferException
202   {
203   }
204 
205   // --- object basics --------------------------------------------------------
206 
207 }