001    package com.github.sarxos.webcam.ds.civil;
002    
003    import java.io.File;
004    import java.io.FileNotFoundException;
005    import java.io.FileOutputStream;
006    import java.io.IOException;
007    import java.io.InputStream;
008    import java.io.OutputStream;
009    
010    import org.slf4j.Logger;
011    import org.slf4j.LoggerFactory;
012    
013    
014    public class LtiCivilLoader {
015    
016            private static final Logger LOG = LoggerFactory.getLogger(LtiCivilLoader.class);
017    
018            /**
019             * Will be called until JVM shutdown.
020             * 
021             * @author Bartosz Firyn (SarXos)
022             */
023            private static class Deleter extends Thread {
024    
025                    private File file = null;
026    
027                    public Deleter(File file) {
028                            super();
029                            this.file = file;
030                    }
031    
032                    @Override
033                    public void run() {
034                            super.run();
035                            boolean removed = file.delete();
036                            if (!removed) {
037                                    file.deleteOnExit();
038                            }
039                    }
040            }
041    
042            /**
043             * Copy bytes from a large (over 2GB) InputStream to an OutputStream.
044             * 
045             * @param input the InputStream to read from
046             * @param output the OutputStream to write to
047             * @return the number of bytes copied
048             * @throws NullPointerException if the input or output is null
049             * @throws IOException if an I/O error occurs
050             */
051            public static long copy(InputStream input, OutputStream output) throws IOException {
052                    byte[] buffer = new byte[1024 * 4];
053                    long count = 0;
054                    int n = 0;
055                    while (-1 != (n = input.read(buffer))) {
056                            output.write(buffer, 0, n);
057                            count += n;
058                    }
059                    return count;
060            }
061    
062            public static void load(String lib) {
063                    LOG.info("Loading native library: " + lib);
064                    try {
065                            System.loadLibrary(lib);
066                            LOG.info("DLL has been loaded from memory: " + lib);
067                    } catch (UnsatisfiedLinkError e) {
068                            try {
069                                    load("webcam-capture-lib-" + System.currentTimeMillis(), lib);
070                            } catch (Exception e2) {
071                                    LOG.error("Exception when loading DLL library", e2);
072                                    throw new RuntimeException(e2);
073                            }
074                    }
075            }
076    
077            public static void load(String path, String name) {
078    
079                    String libroot = "/META-INF/lib";
080                    String libpath = null;
081                    String libfile = null;
082    
083                    boolean arch64 = System.getProperty("os.arch").indexOf("64") != -1;
084                    boolean linux = System.getProperty("os.name").toLowerCase().indexOf("linux") != -1;
085    
086                    if (linux) {
087                            if (arch64) {
088                                    libpath = libroot + "/linux64/";
089                                    libfile = "lib" + name + ".so";
090                            } else {
091                                    libpath = libroot + "/linux32/";
092                                    libfile = "lib" + name + ".so";
093                            }
094                    } else {
095                            libpath = libroot + "/win32/";
096                            libfile = name + ".dll";
097                    }
098    
099                    File parent = new File(System.getProperty("java.io.tmpdir") + "/" + path);
100                    if (!parent.exists()) {
101                            if (!parent.mkdirs()) {
102                                    throw new RuntimeException("Cannot create directory: " + parent.getAbsolutePath());
103                            }
104                    }
105    
106                    File file = new File(parent, libfile);
107                    if (!file.exists()) {
108    
109                            boolean created = false;
110                            try {
111                                    created = file.createNewFile();
112                            } catch (IOException e) {
113                                    throw new RuntimeException("Not able to create file: " + file, e);
114                            }
115                            if (!created) {
116                                    throw new RuntimeException("File cannot be created: " + file);
117                            }
118    
119                            Runtime.getRuntime().addShutdownHook(new Deleter(file));
120                    }
121    
122                    String resource = libpath + libfile;
123    
124                    InputStream in = LtiCivilDriver.class.getResourceAsStream(resource);
125                    if (in == null) {
126                            throw new RuntimeException("Resource not found: " + resource);
127                    }
128    
129                    FileOutputStream fos = null;
130    
131                    try {
132                            fos = new FileOutputStream(file);
133                            copy(in, fos);
134                    } catch (FileNotFoundException e) {
135                            throw new RuntimeException("File not found " + file, e);
136                    } catch (IOException e) {
137                            throw new RuntimeException("IO exception", e);
138                    } finally {
139                            if (in != null) {
140                                    try {
141                                            in.close();
142                                    } catch (IOException e) {
143                                            throw new RuntimeException("Cannot close input stream", e);
144                                    }
145                            }
146                            if (fos != null) {
147                                    try {
148                                            fos.close();
149                                    } catch (IOException e) {
150                                            throw new RuntimeException("Cannot close file output stream", e);
151                                    }
152                            }
153                    }
154    
155                    try {
156                            System.load(file.getAbsolutePath());
157                    } catch (UnsatisfiedLinkError e) {
158                            throw new RuntimeException("Library file cannot be loaded: " + file, e);
159                    }
160            }
161    }