package org.smartly.packages.cms.impl.cms.endpoint; import org.json.JSONObject; import org.smartly.commons.logging.Level; import org.smartly.commons.logging.Logger; import org.smartly.commons.io.repository.FileRepository; import org.smartly.commons.io.repository.Resource; import org.smartly.commons.io.repository.deploy.FileItem; import org.smartly.commons.util.*; import org.smartly.packages.cms.SmartlyHttpCms; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URLDecoder; import java.util.*; import java.util.jar.JarEntry; import java.util.jar.JarFile; /** * */ public class CMSEndPointRepository { public static final String CHARSET = CMSRouter.CHARSET; private final String _root; private final List<FileItem> _resources; private final Map<String, String> _cache; private boolean _is_jar; private boolean _use_cache; public CMSEndPointRepository(final String root) { _root = root; // PathUtils.toUnixPath((new File(root)).getAbsolutePath()); _resources = new LinkedList<FileItem>(); _cache = Collections.synchronizedMap(new HashMap<String, String>()); _is_jar = false; _use_cache = true; this.loadResources(""); } public boolean isEmpty() { return this.size() == 0; } public int size() { return _resources.size(); } public String getString(final String path) { try { return this.read(path); } catch (Throwable t) { this.getLogger().log(Level.SEVERE, null, t); } return null; } public String getString(final String path, final String defa) { try { return this.read(path); } catch (Throwable t) { this.getLogger().log(Level.SEVERE, null, t); } return null; } public JSONObject getJSONObject(final String path) { try { final String json = this.read(path); return StringUtils.hasText(json) ? new JSONObject(json) : new JSONObject(); } catch (Throwable t) { this.getLogger().log(Level.SEVERE, null, t); } return null; } // ------------------------------------------------------------------------ // p r i v a t e // ------------------------------------------------------------------------ private Logger getLogger() { return SmartlyHttpCms.getCMSLogger(); } private void loadResources(final String startFolder) { _resources.clear(); try { final String folder = PathUtils.join(_root, startFolder); _is_jar = PathUtils.isJar(folder); final String[] resources; if (_is_jar) { resources = this.getResourcesFromJar(folder); } else { resources = this.getResourcesFromRepository(folder); } // add resources to internal list for (final String child : resources) { _resources.add(new FileItem(this, _root, child)); } } catch (Throwable t) { this.getLogger().severe(FormatUtils.format("Unable to Create FileDeployer: {0}", t)); } } private String[] getResourcesFromRepository(final String path) throws IOException { final Set<String> result = new HashSet<String>(); final FileRepository repository = new FileRepository(path); final Resource[] children = repository.getResources(true); for (final Resource child : children) { result.add(child.getPath()); } return result.toArray(new String[result.size()]); } private String[] getResourcesFromJar(final String path) throws IOException { /* A JAR path */ final int jarIdx = path.indexOf("!"); if (jarIdx == -1) { return new String[0]; } // strin out checkpath final String checkpath = path.substring(jarIdx + 2); // strip out only the JAR file final String jarPath = path.substring(5, jarIdx); final File jarFile = new File(URLDecoder.decode( jarPath, CHARSET)); if (!jarFile.exists()) { return new String[0]; } final JarFile jar = new JarFile(jarFile); final Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar final Set<String> resNames = new HashSet<String>(); //avoid duplicates in case it is a subdirectory while (entries.hasMoreElements()) { final String name = entries.nextElement().getName(); if (name.startsWith(checkpath)) { //filter according to the path String entry = name.substring(checkpath.length()); if (StringUtils.hasText(entry)) { int checkSubdir = entry.indexOf("/"); if (checkSubdir >= 0) { // if it is a subdirectory, we just return the directory name //entry = entry.substring(0, checkSubdir); } final String resname = "jar:" + PathUtils.join(path, entry); resNames.add(resname); // debug logging this.getLogger().log(Level.FINER, FormatUtils.format("path='{0}', name='{1}', " + "entry='{2}', resname='{3}'", path, name, entry, resname)); } } } return resNames.toArray(new String[resNames.size()]); } private String getAbsolutePath(final String path) { if (_is_jar) { if (!path.startsWith("jar:")) { return "jar:" + PathUtils.concat(_root, path); } } return PathUtils.concat(_root, path); } private FileItem getFile(final String path) { if (_resources.size() > 0) { final String fullPath = this.getAbsolutePath(path); //_is_jar ? "jar:" + PathUtils.concat(_root, path) : PathUtils.concat(_root, path); // this.getLogger().info("LOOKING FOR: " + fullPath); for (final FileItem item : _resources) { // this.getLogger().info("CHECKING: " + item.getAbsolutePath()); if (fullPath.equalsIgnoreCase(item.getAbsolutePath())) { return item; } } } return null; } private String read(final String path) throws Exception { if (_resources.size() > 0 || _cache.size() > 0) { if (_use_cache && _cache.containsKey(path)) { return _cache.get(path); } return _use_cache ? this.readSync(path) : readNoSync(path); } return null; } private String readNoSync(final String path) throws Exception { final FileItem item = this.getFile(path); if (null != item) { final String result; if (_is_jar) { final InputStream is = ClassLoaderUtils.getResourceAsStream(item.getPackageName()); result = ClassLoaderUtils.getString(is, CHARSET); } else { result = new String(FileUtils.copyToByteArray(new File(item.getAbsolutePath())), CHARSET); } return result; } return null; } private String readSync(final String path) throws Exception { synchronized (_cache) { final String result = this.readNoSync(path); if (StringUtils.hasText(result) && _use_cache) { _cache.put(path, result); } return result; } } }