1   /* Copyright 2002-2022 CS GROUP
2    * Licensed to CS GROUP (CS) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * CS licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.orekit.data;
18  
19  
20  import java.io.File;
21  import java.io.InputStream;
22  import java.net.URISyntaxException;
23  import java.util.IdentityHashMap;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.regex.Matcher;
27  import java.util.regex.Pattern;
28  
29  import org.hipparchus.exception.DummyLocalizable;
30  import org.junit.After;
31  import org.junit.Assert;
32  import org.junit.Test;
33  import org.orekit.Utils;
34  import org.orekit.errors.OrekitException;
35  
36  public class DataProvidersManagerTest {
37  
38      @After
39      public void tearDown() {
40          // clear the filters so they don't change other tests
41          DataContext.getDefault().getDataProvidersManager().resetFiltersToDefault();
42      }
43  
44      @Test
45      public void testDefaultConfiguration() {
46          System.setProperty(DataProvidersManager.OREKIT_DATA_PATH, getPath("regular-data"));
47          CountingLoader crawler = new CountingLoader(false);
48          DataContext.getDefault().getDataProvidersManager().clearProviders();
49          Assert.assertFalse(DataContext.getDefault().getDataProvidersManager().isSupported(new DirectoryCrawler(new File(getPath("regular-data")))));
50          Assert.assertTrue(DataContext.getDefault().getDataProvidersManager().feed(".*", crawler));
51          Assert.assertEquals(18, crawler.getCount());
52      }
53  
54      @Test
55      public void testLoadMonitoring() {
56          System.setProperty(DataProvidersManager.OREKIT_DATA_PATH, getPath("regular-data"));
57          DataProvidersManager manager = DataContext.getDefault().getDataProvidersManager();
58          manager.clearProviders();
59          manager.clearLoadedDataNames();
60          Assert.assertFalse(manager.isSupported(new DirectoryCrawler(new File(getPath("regular-data")))));
61          Assert.assertEquals(0, manager.getLoadedDataNames().size());
62          CountingLoader tleCounter = new CountingLoader(false);
63          Assert.assertFalse(manager.feed(".*\\.tle$", tleCounter));
64          Assert.assertEquals(0, tleCounter.getCount());
65          Assert.assertEquals(0, manager.getLoadedDataNames().size());
66          CountingLoader txtCounter = new CountingLoader(false);
67          Assert.assertTrue(manager.feed(".*\\.txt$", txtCounter));
68          Assert.assertEquals(5, txtCounter.getCount());
69          Assert.assertEquals(5, manager.getLoadedDataNames().size());
70          CountingLoader de405Counter = new CountingLoader(false);
71          Assert.assertTrue(manager.feed(".*\\.405$", de405Counter));
72          Assert.assertEquals(4, de405Counter.getCount());
73          Assert.assertEquals(9, manager.getLoadedDataNames().size());
74          manager.clearLoadedDataNames();
75          Assert.assertEquals(0, manager.getLoadedDataNames().size());
76      }
77  
78      @Test
79      public void testLoadFailure() {
80          System.setProperty(DataProvidersManager.OREKIT_DATA_PATH, getPath("regular-data"));
81          DataContext.getDefault().getDataProvidersManager().clearProviders();
82          CountingLoader crawler = new CountingLoader(true);
83          try {
84              DataContext.getDefault().getDataProvidersManager().feed(".*", crawler);
85              Assert.fail("an exception should have been thrown");
86          } catch (OrekitException oe) {
87              // expected
88          }
89          Assert.assertEquals(18, crawler.getCount());
90      }
91  
92      @Test
93      public void testEmptyProperty() {
94          System.setProperty(DataProvidersManager.OREKIT_DATA_PATH, "");
95          CountingLoader crawler = new CountingLoader(false);
96          DataContext.getDefault().getDataProvidersManager().clearProviders();
97          DataContext.getDefault().getDataProvidersManager().feed(".*", crawler);
98          Assert.assertEquals(0, crawler.getCount());
99      }
100 
101     @Test(expected=OrekitException.class)
102     public void testInexistentDirectory() {
103         File inexistent = new File(getPath("regular-data"), "inexistent");
104         System.setProperty(DataProvidersManager.OREKIT_DATA_PATH, inexistent.getAbsolutePath());
105         CountingLoader crawler = new CountingLoader(false);
106         DataContext.getDefault().getDataProvidersManager().clearProviders();
107         DataContext.getDefault().getDataProvidersManager().feed(".*", crawler);
108     }
109 
110     @Test(expected=OrekitException.class)
111     public void testInexistentZipArchive() {
112         File inexistent = new File(getPath("regular-data"), "inexistent.zip");
113         System.setProperty(DataProvidersManager.OREKIT_DATA_PATH, inexistent.getAbsolutePath());
114         CountingLoader crawler = new CountingLoader(false);
115         DataContext.getDefault().getDataProvidersManager().clearProviders();
116         DataContext.getDefault().getDataProvidersManager().feed(".*", crawler);
117     }
118 
119     @Test(expected=OrekitException.class)
120     public void testNeitherDirectoryNorZip() {
121         System.setProperty(DataProvidersManager.OREKIT_DATA_PATH, getPath("regular-data/UTC-TAI.history"));
122         CountingLoader crawler = new CountingLoader(false);
123         DataContext.getDefault().getDataProvidersManager().clearProviders();
124         DataContext.getDefault().getDataProvidersManager().feed(".*", crawler);
125     }
126 
127     @Test
128     public void testListModification() {
129         System.setProperty(DataProvidersManager.OREKIT_DATA_PATH, getPath("regular-data"));
130         CountingLoader crawler = new CountingLoader(false);
131         DataProvidersManager manager = DataContext.getDefault().getDataProvidersManager();
132         manager.clearProviders();
133         Assert.assertFalse(manager.isSupported(new DirectoryCrawler(new File(getPath("regular-data")))));
134         Assert.assertTrue(manager.feed(".*", crawler));
135         Assert.assertTrue(crawler.getCount() > 0);
136         List<DataProvider> providers = manager.getProviders();
137         Assert.assertEquals(1, providers.size());
138         for (DataProvider provider : providers) {
139             Assert.assertTrue(manager.isSupported(provider));
140         }
141         Assert.assertNotNull(manager.removeProvider(providers.get(0)));
142         Assert.assertEquals(0, manager.getProviders().size());
143         DataProvider provider = new DataProvider() {
144             public boolean feed(Pattern supported, DataLoader visitor, DataProvidersManager manager) {
145                 return true;
146             }
147         };
148         manager.addProvider(provider);
149         Assert.assertEquals(1, manager.getProviders().size());
150         manager.addProvider(provider);
151         Assert.assertEquals(2, manager.getProviders().size());
152         Assert.assertNotNull(manager.removeProvider(provider));
153         Assert.assertEquals(1, manager.getProviders().size());
154         Assert.assertNull(manager.removeProvider(new DataProvider() {
155             @Deprecated
156             public boolean feed(Pattern supported, DataLoader visitor, DataProvidersManager manager) {
157                 throw new OrekitException(new DummyLocalizable("oops!"));
158             }
159         }));
160         Assert.assertEquals(1, manager.getProviders().size());
161         Assert.assertNotNull(manager.removeProvider(manager.getProviders().get(0)));
162         Assert.assertEquals(0, manager.getProviders().size());
163     }
164 
165     @Test
166     public void testComplexPropertySetting() {
167         String sep = System.getProperty("path.separator");
168         File top = new File(getPath("regular-data"));
169         File dir1 = new File(top, "de405-ephemerides");
170         File dir2 = new File(new File(top, "Earth-orientation-parameters"), "monthly");
171         System.setProperty(DataProvidersManager.OREKIT_DATA_PATH,
172                            dir1 + sep + sep + sep + sep + dir2);
173         DataContext.getDefault().getDataProvidersManager().clearProviders();
174 
175         CountingLoader crawler = new CountingLoader(false);
176         Assert.assertTrue(DataContext.getDefault().getDataProvidersManager().feed(".*\\.405$", crawler));
177         Assert.assertEquals(4, crawler.getCount());
178 
179         crawler = new CountingLoader(false);
180         Assert.assertTrue(DataContext.getDefault().getDataProvidersManager().feed(".*\\.txt$", crawler));
181         Assert.assertEquals(1, crawler.getCount());
182 
183         crawler = new CountingLoader(false);
184         Assert.assertTrue(DataContext.getDefault().getDataProvidersManager().feed("bulletinb_.*\\.txt$", crawler));
185         Assert.assertEquals(2, crawler.getCount());
186 
187     }
188 
189     @Test
190     public void testMultiZip() {
191         System.setProperty(DataProvidersManager.OREKIT_DATA_PATH, getPath("zipped-data/multizip.zip"));
192         CountingLoader crawler = new CountingLoader(false);
193         DataContext.getDefault().getDataProvidersManager().clearProviders();
194         Assert.assertTrue(DataContext.getDefault().getDataProvidersManager().feed(".*\\.txt$", crawler));
195         Assert.assertEquals(6, crawler.getCount());
196     }
197 
198     @Test
199     public void testSimpleFilter() {
200         Utils.setDataRoot("regular-data");
201         CountingFilter filter = new CountingFilter();
202         DataContext.getDefault().getDataProvidersManager().getFiltersManager().addFilter(filter);
203         CountingLoader crawler = new CountingLoader(false);
204         Assert.assertTrue(DataContext.getDefault().getDataProvidersManager().feed(".*", crawler));
205         Assert.assertEquals(18, crawler.getCount());
206         Assert.assertEquals(18, filter.getFilteredCount());
207         Assert.assertEquals(18, filter.getOpenedCount());
208     }
209 
210     @Test
211     public void testMultiLayerFilter() {
212         Utils.setDataRoot("regular-data");
213         final int layers = 10;
214         MultiLayerFilter filter = new MultiLayerFilter(layers);
215         DataContext.getDefault().getDataProvidersManager().getFiltersManager().addFilter(filter);
216         CountingLoader crawler = new CountingLoader(false);
217         Assert.assertTrue(DataContext.getDefault().getDataProvidersManager().feed(".*", crawler));
218         Assert.assertEquals(18, crawler.getCount());
219         Assert.assertEquals(18 * layers, filter.getOpenedCount());
220     }
221 
222     private static class CountingLoader implements DataLoader {
223         private boolean shouldFail;
224         private int count;
225         public CountingLoader(boolean shouldFail) {
226             this.shouldFail = shouldFail;
227             count = 0;
228         }
229         public boolean stillAcceptsData() {
230             return true;
231         }
232         public void loadData(InputStream input, String name)
233             {
234             ++count;
235             if (shouldFail) {
236                 throw new OrekitException(new DummyLocalizable("intentional failure"));
237             }
238         }
239         public int getCount() {
240             return count;
241         }
242     }
243 
244     private static class CountingFilter implements DataFilter {
245         private Map<DataSource, DataSource> filtered;
246         private int opened;
247         public CountingFilter() {
248             filtered = new IdentityHashMap<>();
249             opened   = 0;
250         }
251         public DataSource filter(DataSource original) {
252             if (filtered.containsKey(original)) {
253                 return original;
254             } else {
255                 DataSource f = new DataSource(original.getName(),
256                                             () -> {
257                                                 ++opened;
258                                                 return original.getOpener().openStreamOnce();
259                                             });
260                 filtered.put(f, f);
261                 return f;
262             }
263         }
264         public int getFilteredCount() {
265             return filtered.size();
266         }
267         public int getOpenedCount() {
268             return opened;
269         }
270     }
271 
272     private static class MultiLayerFilter implements DataFilter {
273         private static final String  PREFIX  = "multilayer-";
274         private static final Pattern PATTERN = Pattern.compile(PREFIX + "(\\d+)-(.*)");
275         private final int layers;
276         private int opened;
277         public MultiLayerFilter(final int layers) {
278             this.layers = layers;
279             this.opened = 0;
280         }
281         public DataSource filter(final DataSource original) {
282             Matcher matcher = PATTERN.matcher(original.getName());
283             int level = 0;
284             String baseName = original.getName();
285             if (matcher.matches()) {
286                 level = Integer.parseInt(matcher.group(1));
287                 baseName = matcher.group(2);
288             }
289             if (level++ < layers) {
290                 // add one filtering layer
291                 return new DataSource(PREFIX + level + "-" + baseName,
292                                      () -> {
293                                          ++opened;
294                                          return original.getOpener().openStreamOnce();
295                                      });
296             } else {
297                 // final layer, don't filter anymore
298                 return original;
299             }
300         }
301         public int getOpenedCount() {
302             return opened;
303         }
304     }
305 
306     private String getPath(String resourceName) {
307         try {
308             ClassLoader loader = DirectoryCrawlerTest.class.getClassLoader();
309             return loader.getResource(resourceName).toURI().getPath();
310         } catch (URISyntaxException e) {
311             Assert.fail(e.getLocalizedMessage());
312             return null;
313         }
314     }
315 
316 }