001package co.codewizards.cloudstore.core.appid;
002
003import static co.codewizards.cloudstore.core.io.StreamUtil.*;
004import static java.util.Objects.*;
005
006import java.io.FileNotFoundException;
007import java.io.IOException;
008import java.io.InputStream;
009import java.io.InputStreamReader;
010import java.io.OutputStream;
011import java.io.OutputStreamWriter;
012import java.io.Reader;
013import java.io.Writer;
014import java.util.HashMap;
015import java.util.Map;
016import java.util.ServiceLoader;
017
018import co.codewizards.cloudstore.core.oio.File;
019import co.codewizards.cloudstore.core.util.IOUtil;
020
021public class AppIdRegistry {
022
023        private static final class Holder {
024                public static final AppIdRegistry instance = new AppIdRegistry();
025        }
026
027        public static AppIdRegistry getInstance() {
028                return Holder.instance;
029        }
030
031        private volatile AppId appId;
032
033        protected AppIdRegistry() {
034        }
035
036        public AppId getAppIdOrFail() {
037                AppId appId = this.appId;
038                if (appId == null) {
039                        for (final AppId ai : ServiceLoader.load(AppId.class)) {
040                                if (appId == null || appId.getPriority() < ai.getPriority())
041                                        appId = ai;
042                        }
043
044                        if (appId == null)
045                                throw new IllegalStateException("No AppId implementation found!");
046
047                        this.appId = appId;
048                }
049                return appId;
050        }
051
052        public void copyResourceResolvingAppId(final Reader reader, final Writer writer) throws IOException {
053                requireNonNull(writer, "writer");
054                requireNonNull(reader, "reader");
055
056                final AppId appId = getAppIdOrFail();
057                Map<String, Object> variables = new HashMap<>();
058                variables.put("appId.simpleId", appId.getSimpleId());
059                variables.put("appId.qualifiedId", appId.getQualifiedId());
060                variables.put("appId.name", appId.getName());
061                variables.put("appId.webSiteBaseUrl", appId.getWebSiteBaseUrl());
062                IOUtil.replaceTemplateVariables(writer, reader, variables);
063        }
064
065        public void copyResourceResolvingAppId(final Class<?> sourceResClass, final String sourceResName, final File destinationFile) throws IOException {
066                InputStream source = null;
067                OutputStream destination = null;
068                try{
069                        source = sourceResClass.getResourceAsStream(sourceResName);
070                        if (source == null)
071                                throw new FileNotFoundException("Class " + sourceResClass.getName() + " could not find resource " + sourceResName);
072
073                        if (destinationFile.exists()) {
074                                if (destinationFile.isFile()) {
075                                        if (!destinationFile.canWrite())
076                                                throw new IOException("destination file is unwriteable: " + destinationFile.getCanonicalPath());
077                                } else
078                                        throw new IOException("destination is not a file: " +   destinationFile.getCanonicalPath());
079                        } else {
080                                final File parentdir = destinationFile.getAbsoluteFile().getParentFile();
081                                if (parentdir == null || !parentdir.exists())
082                                        throw new IOException("destination's parent directory doesn't exist: " + destinationFile.getCanonicalPath());
083                                if (!parentdir.canWrite())
084                                        throw new IOException("destination's parent directory is unwriteable: " + destinationFile.getCanonicalPath());
085                        }
086                        destination = castStream(destinationFile.createOutputStream());
087
088                        try (Reader r = new InputStreamReader(source)) {
089                                try (Writer w = new OutputStreamWriter(destination)) {
090                                        copyResourceResolvingAppId(r, w);
091                                }
092                        }
093
094                } finally {
095                        if (source != null)
096                                try { source.close(); } catch (final IOException e) { ; }
097
098                        if (destination != null)
099                                try { destination.close(); } catch (final IOException e) { ; }
100                }
101        }
102}