View Javadoc
1   /*
2    * Copyright (c) 2008 Sonatype, Inc. All rights reserved.
3    *
4    * This program is licensed to you under the Apache License Version 2.0,
5    * and you may not use this file except in compliance with the Apache License Version 2.0.
6    * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
7    *
8    * Unless required by applicable law or agreed to in writing,
9    * software distributed under the Apache License Version 2.0 is distributed on an
10   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11   * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
12   */
13  
14  package org.codehaus.plexus.components.secdispatcher.internal;
15  
16  import javax.xml.stream.XMLStreamException;
17  
18  import java.io.IOException;
19  import java.io.InputStream;
20  import java.io.OutputStream;
21  import java.nio.charset.StandardCharsets;
22  import java.nio.file.Files;
23  import java.nio.file.NoSuchFileException;
24  import java.nio.file.Path;
25  import java.nio.file.StandardCopyOption;
26  import java.util.HashMap;
27  import java.util.List;
28  import java.util.Map;
29  import java.util.concurrent.ThreadLocalRandom;
30  
31  import org.codehaus.plexus.components.secdispatcher.SecDispatcher;
32  import org.codehaus.plexus.components.secdispatcher.model.Config;
33  import org.codehaus.plexus.components.secdispatcher.model.ConfigProperty;
34  import org.codehaus.plexus.components.secdispatcher.model.SettingsSecurity;
35  import org.codehaus.plexus.components.secdispatcher.model.io.stax.SecurityConfigurationStaxReader;
36  import org.codehaus.plexus.components.secdispatcher.model.io.stax.SecurityConfigurationStaxWriter;
37  
38  import static java.util.Objects.requireNonNull;
39  
40  /**
41   *
42   *
43   * @author Oleg Gusakov
44   * @version $Id$
45   *
46   */
47  public final class SecUtil {
48      private SecUtil() {}
49  
50      /**
51       * Reads the configuration model up, if exists, otherwise returns {@code null}.
52       */
53      public static SettingsSecurity read(Path configurationFile) throws IOException {
54          requireNonNull(configurationFile, "configurationFile must not be null");
55          SettingsSecurity sec;
56          try {
57              try (InputStream in = Files.newInputStream(configurationFile)) {
58                  sec = new SecurityConfigurationStaxReader().read(in);
59              }
60              return sec;
61          } catch (NoSuchFileException e) {
62              return null;
63          } catch (XMLStreamException e) {
64              throw new IOException("Parsing error", e);
65          }
66      }
67  
68      /**
69       * Returns config with given name, or {@code null} if not exist.
70       */
71      public static Map<String, String> getConfig(SettingsSecurity sec, String name) {
72          if (sec != null && name != null) {
73              List<Config> cl = sec.getConfigurations();
74              if (!cl.isEmpty()) {
75                  for (Config cf : cl) {
76                      if (!name.equals(cf.getName())) {
77                          continue;
78                      }
79                      List<ConfigProperty> pl = cf.getProperties();
80                      if (pl.isEmpty()) {
81                          break;
82                      }
83                      Map<String, String> res = new HashMap<>(pl.size());
84                      for (ConfigProperty p : pl) {
85                          res.put(p.getName(), p.getValue());
86                      }
87                      return res;
88                  }
89              }
90          }
91          return null;
92      }
93  
94      public static String specVersion() {
95          String specVer = SecDispatcher.class.getPackage().getSpecificationVersion();
96          if (specVer == null) {
97              specVer = "test"; // in UT
98          }
99          return specVer;
100     }
101 
102     private static final boolean IS_WINDOWS =
103             System.getProperty("os.name", "unknown").startsWith("Windows");
104 
105     public static void write(Path target, SettingsSecurity configuration, boolean doBackup) throws IOException {
106         requireNonNull(target, "file must not be null");
107         requireNonNull(configuration, "configuration must not be null");
108         Path parent = requireNonNull(target.getParent(), "target must have parent");
109         Files.createDirectories(parent);
110         Path tempFile = parent.resolve(target.getFileName() + "."
111                 + Long.toUnsignedString(ThreadLocalRandom.current().nextLong()) + ".tmp");
112 
113         configuration.setModelVersion(specVersion());
114         configuration.setModelEncoding(StandardCharsets.UTF_8.name());
115 
116         try {
117             try (OutputStream tempOut = Files.newOutputStream(tempFile)) {
118                 new SecurityConfigurationStaxWriter().write(tempOut, configuration);
119             }
120 
121             if (doBackup && Files.isRegularFile(target)) {
122                 Files.copy(target, parent.resolve(target.getFileName() + ".bak"), StandardCopyOption.REPLACE_EXISTING);
123             }
124             if (IS_WINDOWS) {
125                 try (InputStream is = Files.newInputStream(tempFile);
126                         OutputStream os = Files.newOutputStream(target)) {
127                     is.transferTo(os);
128                 }
129             } else {
130                 Files.move(tempFile, target, StandardCopyOption.REPLACE_EXISTING);
131             }
132         } catch (XMLStreamException e) {
133             throw new IOException("XML Processing error", e);
134         } finally {
135             Files.deleteIfExists(tempFile);
136         }
137     }
138 }