View Javadoc
1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.commons.crypto;
19  
20  import java.io.IOException;
21  import java.util.HashMap;
22  import java.util.Locale;
23  
24  /**
25   * Provides OS name and architecture name.
26   * Used by the JNI make process to get information from the build environment.
27   */
28  final class OsInfo {
29      private final static HashMap<String, String> archMapping = new HashMap<>();
30  
31      /**
32       * The constant string represents for X86 architecture, the value is:
33       * {@value #X86}.
34       */
35      static final String X86 = "x86";
36  
37      /**
38       * The constant string represents for X86_64 architecture, the value is:
39       * {@value #X86_64}.
40       */
41      static final String X86_64 = "x86_64";
42  
43      /**
44       * The constant string represents for IA64_32 architecture, the value is:
45       * {@value #IA64_32}.
46       */
47      static final String IA64_32 = "ia64_32";
48  
49      /**
50       * The constant string represents for IA64 architecture, the value is:
51       * {@value #IA64}.
52       */
53      static final String IA64 = "ia64";
54  
55      /**
56       * The constant string represents for PPC architecture, the value is:
57       * {@value #PPC}.
58       */
59      static final String PPC = "ppc";
60  
61      /**
62       * The constant string represents for PPC64 architecture, the value is:
63       * {@value #PPC64}.
64       */
65      static final String PPC64 = "ppc64";
66  
67      /**
68       * The private constructor of {@link OsInfo}.
69       */
70      private OsInfo() {
71      }
72  
73      static {
74          // x86 mappings
75          archMapping.put(X86, X86);
76          archMapping.put("i386", X86);
77          archMapping.put("i486", X86);
78          archMapping.put("i586", X86);
79          archMapping.put("i686", X86);
80          archMapping.put("pentium", X86);
81  
82          // x86_64 mappings
83          archMapping.put(X86_64, X86_64);
84          archMapping.put("amd64", X86_64);
85          archMapping.put("em64t", X86_64);
86          archMapping.put("universal", X86_64); // Needed for openjdk7 in Mac
87  
88          // Itenium 64-bit mappings
89          archMapping.put(IA64, IA64);
90          archMapping.put("ia64w", IA64);
91  
92          // Itenium 32-bit mappings, usually an HP-UX construct
93          archMapping.put(IA64_32, IA64_32);
94          archMapping.put("ia64n", IA64_32);
95  
96          // PowerPC mappings
97          archMapping.put(PPC, PPC);
98          archMapping.put("power", PPC);
99          archMapping.put("powerpc", PPC);
100         archMapping.put("power_pc", PPC);
101         archMapping.put("power_rs", PPC);
102 
103         // TODO: PowerPC 64bit mappings
104         archMapping.put(PPC64, PPC64);
105         archMapping.put("power64", PPC64);
106         archMapping.put("powerpc64", PPC64);
107         archMapping.put("power_pc64", PPC64);
108         archMapping.put("power_rs64", PPC64);
109     }
110 
111     /**
112      * The main method.
113      * This is used by the JNI make processing in Makefile.common
114      *
115      * @param args the argv.
116      */
117     public static void main(String[] args) {
118         if (args.length >= 1) {
119             if ("--os".equals(args[0])) {
120                 System.out.print(getOSName());
121                 return;
122             } else if ("--arch".equals(args[0])) {
123                 System.out.print(getArchName());
124                 return;
125             }
126         }
127 
128         System.out.print(getNativeLibFolderPathForCurrentOS());
129     }
130 
131     /**
132      * Gets the native lib folder.
133      *
134      * @return the current OS's native lib folder.
135      */
136     static String getNativeLibFolderPathForCurrentOS() {
137         return getOSName() + "/" + getArchName();
138     }
139 
140     /**
141      * Gets the OS name.
142      *
143      * @return the OS name.
144      */
145     static String getOSName() {
146         return translateOSNameToFolderName(System.getProperty("os.name"));
147     }
148 
149     /**
150      * Gets the architecture name.
151      *
152      * @return the architecture name.
153      */
154     static String getArchName() {
155         // if running Linux on ARM, need to determine ABI of JVM
156         String osArch = System.getProperty("os.arch");
157         if (osArch.startsWith("arm")
158                 && System.getProperty("os.name").contains("Linux")) {
159             String javaHome = System.getProperty("java.home");
160             try {
161                 // determine if first JVM found uses ARM hard-float ABI
162                 String[] cmdarray = {
163                         "/bin/sh",
164                         "-c",
165                         "find '"
166                                 + javaHome
167                                 + "' -name 'libjvm.so' | head -1 | xargs readelf -A | "
168                                 + "grep 'Tag_ABI_VFP_args: VFP registers'" };
169                 int exitCode = Runtime.getRuntime().exec(cmdarray).waitFor();
170                 if (exitCode == 0) {
171                     return "armhf";
172                 }
173             } catch (IOException e) { //NOPMD
174                 // ignored: fall back to "arm" arch (soft-float ABI)
175             } catch (InterruptedException e) { //NOPMD
176                 // ignored: fall back to "arm" arch (soft-float ABI)
177             }
178         } else {
179             String lc = osArch.toLowerCase(Locale.US);
180             if (archMapping.containsKey(lc)) {
181                 return archMapping.get(lc);
182             }
183         }
184         return translateArchNameToFolderName(osArch);
185     }
186 
187     /**
188      * Translates the OS name to folder name.
189      *
190      * @param osName the OS name.
191      * @return the folder name.
192      */
193     private static String translateOSNameToFolderName(String osName) {
194         if (osName.contains("Windows")) {
195             return "Windows";
196         } else if (osName.contains("Mac")) {
197             return "Mac";
198         } else if (osName.contains("Linux")) {
199             return "Linux";
200         } else if (osName.contains("AIX")) {
201             return "AIX";
202         }
203 
204         else {
205             return osName.replaceAll("\\W", "");
206         }
207     }
208 
209     /**
210      * Translates the architecture name to folder name.
211      *
212      * @param archName the architecture name.
213      * @return the folder name.
214      */
215     private static String translateArchNameToFolderName(String archName) {
216         return archName.replaceAll("\\W", "");
217     }
218 }