001    /**
002     * Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
003     *
004     * All rights reserved. Licensed under the OSI BSD License.
005     *
006     * http://www.opensource.org/licenses/bsd-license.php
007     */
008    package com.barchart.udt.lib;
009    
010    import java.io.InputStream;
011    import java.util.ArrayList;
012    import java.util.List;
013    import java.util.Properties;
014    
015    import org.slf4j.Logger;
016    import org.slf4j.LoggerFactory;
017    
018    /**
019     * maven-nar-plugin build-time properties which determine library name and path
020     * conventions; AOL stands for "arch/os/linker"
021     */
022    public class PluginPropsUDT {
023    
024            /**
025             * suffix for c++ compiler configured for platform in
026             * {@link #NAR_AOL_PROPERTIES} file
027             */
028            protected static final String AOL_CPP_COMPILER = "cpp.compiler";
029    
030            /**
031             * suffix for JNI library file extension as defined in
032             * {@link #NAR_AOL_PROPERTIES} file
033             */
034            protected static final String AOL_JNI_EXTENSION = "jni.extension";
035    
036            /**
037             * suffix for dependency libraries as defined in {@link #NAR_AOL_PROPERTIES}
038             * file
039             */
040            protected static final String AOL_LINKER_DEPENDENCY = "linker.dependency";
041    
042            /**
043             * suffix for shared library file prefix as defined in
044             * {@link #NAR_AOL_PROPERTIES} file
045             */
046            protected static final String AOL_SHARED_PREFIX = "shared.prefix";
047    
048            /**
049             * missing / invalid property value representation
050             */
051            protected static final String EMPTY_VALUE = "";
052    
053            protected static final Logger log = LoggerFactory
054                            .getLogger(PluginPropsUDT.class);
055    
056            /**
057             * NAR properties file; should be present in project root folder during
058             * build time for plug-in configuration and as a class path resource during
059             * run time for properties lookup.
060             */
061            protected static final String NAR_AOL_PROPERTIES = "aol.properties";
062    
063            /**
064             * current architecture reported by JVM
065             */
066            protected static final String OS_ARCH = System.getProperty("os.arch");
067    
068            /**
069             * current operating system reported by JVM
070             */
071            protected static final String OS_NAME = System.getProperty("os.name");
072    
073            /**
074             * properties from {@link #NAR_AOL_PROPERTIES} file
075             */
076            protected static final Properties props = new Properties();
077    
078            static {
079    
080                    try {
081    
082                            log.info("ARCH/OS/LINK = {}/{}/{}", narARCH(), narOS(), narLINK());
083    
084                            log.debug("Loading aol.properties.");
085    
086                            final InputStream input = PluginPropsUDT.class.getClassLoader()
087                                            .getResourceAsStream(NAR_AOL_PROPERTIES);
088    
089                            props.load(input);
090    
091                    } catch (final Throwable e) {
092    
093                            log.error("Failed to load aol.properties.", e);
094    
095                    }
096    
097            }
098    
099            /**
100             * dependency libraries specified in {@link #NAR_AOL_PROPERTIES} file
101             */
102            protected static List<String> currentDependencyLibraries() {
103    
104                    final List<String> list = new ArrayList<String>();
105    
106                    final String entryText = property(currentNarKeyLinkerDependency());
107    
108                    if (entryText == null || entryText.length() == 0) {
109                            return list;
110                    }
111    
112                    final String[] entryArray = entryText.split("\\s");
113    
114                    for (final String entry : entryArray) {
115                            list.add(entry.trim());
116                    }
117    
118                    return list;
119    
120            }
121    
122            /**
123             * nar key prefix for current arch/os/link
124             */
125            protected static String currentNarKey() {
126                    return formatNarKey(narARCH(), narOS(), narLINK());
127            }
128    
129            /**
130             * full nar key built from arch/os/link prefix and the key suffix
131             */
132            protected static String currentNarKey(final String suffix) {
133                    return currentNarKey() + "." + suffix;
134            }
135    
136            /**
137             * CPP compiler for the platform
138             */
139            protected static String currentNarKeyCppCompiler() {
140                    return currentNarKey(AOL_CPP_COMPILER);
141            }
142    
143            /**
144             * JNI extension for the platform
145             */
146            protected static String currentNarKeyJniExtension() {
147                    return currentNarKey(AOL_JNI_EXTENSION);
148            }
149    
150            /**
151             * list of dependencies for the platform
152             */
153            protected static String currentNarKeyLinkerDependency() {
154                    return currentNarKey(AOL_LINKER_DEPENDENCY);
155            }
156    
157            /**
158             * library name prefix for the platform
159             */
160            protected static String currentNarKeySharedPrefix() {
161                    return currentNarKey(AOL_SHARED_PREFIX);
162            }
163    
164            /**
165             * nar aol path entry for current arch/os/link
166             */
167            protected static String currentNarPath() {
168                    return formatNarPath(narARCH(), narOS(), narLINK());
169            }
170    
171            /**
172             * list of release library paths expected to be resent for current platform;
173             * must be packaged in the jar; used during release delivery
174             */
175            protected static List<String> currentReleaseLibraries(final String coreName) {
176    
177                    final List<String> list = new ArrayList<String>();
178    
179                    /** dependency */
180                    for (final String name : currentDependencyLibraries()) {
181                            final String path = formatMainReleasePath(name);
182                            list.add(path);
183                    }
184    
185                    /** main */
186                    {
187                            final String name = formatMainLibraryName(coreName);
188                            final String path = formatMainReleasePath(name);
189                            list.add(path);
190                    }
191    
192                    return list;
193    
194            }
195    
196            /**
197             * list of staging library paths expected to be resent for current platform;
198             * must be located on test class path; used during NAR build
199             */
200            protected static List<String> currentStagingLibraries(final String coreName) {
201    
202                    final List<String> list = new ArrayList<String>();
203    
204                    /** dependency */
205                    for (final String name : currentDependencyLibraries()) {
206                            final String path = formatTestingDependencyPath(name);
207                            list.add(path);
208                    }
209    
210                    /** main */
211                    {
212                            final String path = formatMainStagingPath(coreName);
213                            list.add(path);
214                    }
215    
216                    return list;
217    
218            }
219    
220            /**
221             * list of testing library paths expected to be resent for current platform;
222             * must be located on test class path; used during CDT build
223             */
224            protected static List<String> currentTestingLibraries(final String coreName) {
225    
226                    final List<String> list = new ArrayList<String>();
227    
228                    /** dependency */
229                    for (final String name : currentDependencyLibraries()) {
230                            final String path = formatTestingDependencyPath(name);
231                            list.add(path);
232                    }
233    
234                    /** main */
235                    {
236                            final String path = formatMainTestingPath(coreName);
237                            list.add(path);
238                    }
239    
240                    return list;
241    
242            }
243    
244            /**
245             * make main library name with {@link #AOL_SHARED_PREFIX} and
246             * {@link #AOL_JNI_EXTENSION} convention
247             */
248            protected static String formatMainLibraryName(final String coreName) {
249                    final String prefix = property(currentNarKeySharedPrefix());
250                    final String extension = property(currentNarKeyJniExtension());
251                    return String.format("%s%s.%s", prefix, coreName, extension);
252            }
253    
254            /**
255             * location of release main library and dependency libraries in release jar
256             */
257            protected static String formatMainReleasePath(final String name) {
258                    final String aol = currentNarPath();
259                    return String.format("/lib/%s/jni/%s", aol, name);
260            }
261    
262            /**
263             * location of staging main library on the test class path
264             */
265            protected static String formatMainStagingPath(final String coreName) {
266                    final String aol = currentNarPath();
267                    final String mainName = formatMainLibraryName(coreName);
268                    return String.format("/%s-%s-jni/lib/%s/jni/%s", //
269                                    coreName, aol, aol, mainName);
270            }
271    
272            /**
273             * location of testing main library on the test class path
274             */
275            protected static String formatMainTestingPath(final String coreName) {
276                    final String mainName = formatMainLibraryName(coreName);
277                    return String.format("/%s", //
278                                    mainName);
279            }
280    
281            /**
282             * {@link #NAR_AOL_PROPERTIES} property key prefix
283             */
284            protected static String formatNarKey(final String arch, final String os,
285                            final String link) {
286                    return String.format("%s.%s.%s", arch, os, link);
287            }
288    
289            /**
290             * {@link #NAR_AOL_PROPERTIES} aol path element
291             */
292            protected static String formatNarPath(final String arch, final String os,
293                            final String link) {
294                    return String.format("%s-%s-%s", arch, os, link);
295            }
296    
297            /**
298             * location of dependency libraries on test class path
299             */
300            protected static String formatTestingDependencyPath(final String name) {
301                    final String aol = currentNarPath();
302                    return String.format("/aol/%s/lib/%s", aol, name);
303            }
304    
305            /**
306             * is current platform defined in {@link #NAR_AOL_PROPERTIES} file?
307             */
308            protected static boolean isSupportedPlatform() {
309                    return !EMPTY_VALUE.equals(property(currentNarKeyCppCompiler()));
310            }
311    
312            /**
313             * map JVM arch name to NAR arch name
314             */
315            protected static String narARCH() {
316                    return OS_ARCH;
317            }
318    
319            /**
320             * map JVM arch/os name to NAR tool chain name
321             */
322            protected static String narLINK() {
323                    return "gpp";
324            }
325    
326            /**
327             * map JVM os name to NAR os name
328             */
329            protected static String narOS() {
330                    if (OS_NAME.contains("Mac OS X")) {
331                            return "MacOSX";
332                    }
333                    if (OS_NAME.contains("Windows")) {
334                            return "Windows";
335                    }
336                    return OS_NAME;
337            }
338    
339            /**
340             * find property entry in the {@link #NAR_AOL_PROPERTIES} file
341             */
342            protected static String property(final String key) {
343                    final String value = props.getProperty(key);
344                    if (value instanceof String) {
345                            return value;
346                    } else {
347                            return EMPTY_VALUE;
348                    }
349            }
350    
351    }