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.BufferedInputStream;
011    import java.io.BufferedOutputStream;
012    import java.io.File;
013    import java.io.FileOutputStream;
014    import java.io.InputStream;
015    import java.io.OutputStream;
016    import java.net.URL;
017    import java.net.URLConnection;
018    
019    import org.slf4j.Logger;
020    import org.slf4j.LoggerFactory;
021    
022    /**
023     * class path resource extractor and system loader
024     */
025    public class ResourceManagerUDT {
026    
027            protected final static Logger log = LoggerFactory
028                            .getLogger(ResourceManagerUDT.class);
029    
030            protected static boolean isSameResource(final URLConnection conONE,
031                            final URLConnection conTWO) throws Exception {
032    
033                    final long timeONE = conONE.getLastModified();
034                    final long sizeONE = conONE.getContentLength();
035    
036                    final long timeTWO = conTWO.getLastModified();
037                    final long sizeTWO = conTWO.getContentLength();
038    
039                    return sizeONE == sizeTWO && timeONE == timeTWO;
040    
041            }
042    
043            protected static URLConnection fileConnection(final File file)
044                            throws Exception {
045    
046                    final URL url = file.toURI().toURL();
047    
048                    final URLConnection connection = url.openConnection();
049    
050                    return connection;
051    
052            }
053    
054            protected final static int EOF = -1;
055    
056            /** will use time stamp of jar file */
057            protected static long timeStamp(final URLConnection connIN) {
058                    return connIN.getLastModified();
059            }
060    
061            /**
062             * extract resource from class path into local file system
063             */
064            protected static void extractResource(final String sourcePath,
065                            final String targetPath) throws Exception {
066    
067                    final URL sourceUrl = ResourceManagerUDT.class.getResource(sourcePath);
068    
069                    if (sourceUrl == null) {
070                            log.warn("classpath resource not found: {}", sourcePath);
071                            throw new IllegalArgumentException("resource not found");
072                    }
073    
074                    log.debug("sourceURL={} ", sourceUrl);
075    
076                    final URLConnection sourceConn = sourceUrl.openConnection();
077    
078                    if (sourceConn == null) {
079                            log.warn("classpath resource connection not available: {}",
080                                            sourcePath);
081                            throw new IllegalArgumentException("resource not found");
082                    }
083    
084                    final File targetFile = new File(targetPath).getAbsoluteFile();
085                    log.debug("targetFile={} ", targetFile);
086    
087                    final File targetFolder = targetFile.getParentFile().getAbsoluteFile();
088                    log.debug("targetFolder={} ", targetFolder);
089    
090                    ensureTargetFolder(targetFolder);
091    
092                    final URLConnection targetConn = fileConnection(targetFile);
093    
094                    if (isSameResource(sourceConn, targetConn)) {
095                            log.debug("already extracted; sourcePath={} targetPath={}",
096                                            sourcePath, targetPath);
097                            return;
098                    } else {
099                            log.debug("make new extraction destination for targetPath={}",
100                                            targetPath);
101                            targetFile.delete();
102                            targetFile.createNewFile();
103                    }
104    
105                    final long sourceTime = timeStamp(sourceConn);
106    
107                    final InputStream sourceStream = new BufferedInputStream(//
108                                    sourceUrl.openStream());
109    
110                    final OutputStream targetStream = new BufferedOutputStream(//
111                                    new FileOutputStream(targetFile));
112    
113                    final byte[] array = new byte[64 * 1024];
114    
115                    int readCount = 0;
116    
117                    while ((readCount = sourceStream.read(array)) != EOF) {
118                            targetStream.write(array, 0, readCount);
119                    }
120    
121                    targetStream.flush();
122    
123                    sourceStream.close();
124                    targetStream.close();
125    
126                    /** synchronize target time stamp with source to avoid repeated copy */
127                    targetFile.setLastModified(sourceTime);
128    
129                    log.debug("extracted OK; sourcePath={} targetPath={}", sourcePath,
130                                    targetPath);
131    
132            }
133    
134            protected static void ensureTargetFolder(final File folder)
135                            throws Exception {
136                    if (folder.exists()) {
137                            if (folder.isDirectory()) {
138                                    log.debug("found folder={}", folder);
139                            } else {
140                                    log.error("not a directory; folder={}", folder);
141                                    throw new IllegalArgumentException(
142                                                    "extract destination exists, but as a file and not a folder");
143                            }
144                    } else {
145                            final boolean isSuccess = folder.mkdirs();
146                            if (isSuccess) {
147                                    log.debug("mkdirs : folder={}", folder);
148                            } else {
149                                    log.error("mkdirs failure; folder={}", folder);
150                                    throw new IllegalStateException(
151                                                    "failed to make extract destination folder");
152                            }
153                    }
154            }
155    
156            protected static void ensureTargetFolder(final String targetFolder)
157                            throws Exception {
158    
159                    final File folder = new File(targetFolder).getAbsoluteFile();
160    
161                    ensureTargetFolder(folder);
162    
163            }
164    
165            /**
166             * load library using absolute file path
167             */
168            protected static void systemLoad(final String targetPath) throws Exception {
169    
170                    final File loadFile = new File(targetPath);
171    
172                    final String loadPath = loadFile.getAbsolutePath();
173    
174                    System.load(loadPath);
175    
176            }
177    
178            /**
179             * load library using absolute file path
180             */
181            protected static void systemLoad(final String sourcePath,
182                            final String targetPath) throws Exception {
183    
184                    extractResource(sourcePath, targetPath);
185    
186                    systemLoad(targetPath);
187    
188            }
189    
190    }