/* * derived from * CampaignSourceEntry.java * Copyright 2003 (C) David Hibbs <sage_sam@users.sourceforge.net> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package pcgen.persistence.lst; import java.io.File; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import pcgen.base.lang.UnreachableError; import pcgen.core.utils.CoreUtility; import pcgen.system.ConfigurationSettings; import pcgen.system.PCGenSettings; import pcgen.util.Logging; /** * Constructs a URI from a base URI and an offset, where the offset is defined * by the rules available in PCGen. */ public class URIFactory { /** * A static URI to indicate a failure in creating a URI */ public static final URI FAILED_URI; static { try { FAILED_URI = new URI("file:/FAIL"); } catch (URISyntaxException e) { throw new UnreachableError(e); } } /** * Stores the root URI used as the starting point to determine the final URI */ private final URI rootURI; /** * Stores the offset from the root URI */ private final String offset; /** * Constructs a new URIFactory with the given root URI and offset * * @param root * The root URI used as the starting point to determine the final * URI * @param offset * The offset from the root URI */ public URIFactory(URI root, String offset) { if (root == null) { throw new IllegalArgumentException("root URI cannot be null"); } if (offset == null || offset.isEmpty()) { throw new IllegalArgumentException("URI offset cannot be null"); } rootURI = root; this.offset = offset; } /** * Returns the root URI for this URIFactory. * * @return The root URI for this URIFactory */ public URI getRootURI() { return rootURI; } /** * Returns the offset for this URIFactory. * * @return The offset for this URIFactory */ public String getOffset() { return offset; } /** * Returns the normalized URI resulting from the root URI and offset of this * URIFactory. * * @return The normalized URI resulting from the root URI and offset of this * URIFactory */ public URI getURI() { return getNonNormalizedPathURI(rootURI, offset).normalize(); } /** * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return offset.hashCode(); } /** * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object o) { if (o instanceof URIFactory) { URIFactory other = (URIFactory) o; return offset.equals(other.offset) && rootURI.equals(other.rootURI); } return false; } /** * This method converts the provided filePath to either a URL or absolute * path as appropriate. * * @param pccPath * URL where the Campaign that contained the source was at * @param basePath * String path that is to be converted * @return String containing the converted absolute path or URL (as * appropriate) */ private static URI getNonNormalizedPathURI(URI pccPath, String basePath) { if (basePath.length() <= 0) { Logging.errorPrint("Empty Path to LST file in " + pccPath); return FAILED_URI; } /* * Figure out where the PCC file came from that we're processing, so * that we can prepend its path onto any LST file references (or PCC * refs, for that matter) that are relative. If the source line in * question already has path info, then don't bother */ if (basePath.charAt(0) == '@') { String pathNoLeader = trimLeadingFileSeparator(basePath.substring(1)); String path = CoreUtility.fixFilenamePath(pathNoLeader); return new File(ConfigurationSettings.getPccFilesDir(), path) .toURI(); } else if (basePath.charAt(0) == '&') { String pathNoLeader = trimLeadingFileSeparator(basePath.substring(1)); String path = CoreUtility.fixFilenamePath(pathNoLeader); return new File(PCGenSettings.getVendorDataDir(), path).toURI(); } else if (basePath.charAt(0) == '$') { String pathNoLeader = trimLeadingFileSeparator(basePath.substring(1)); String path = CoreUtility.fixFilenamePath(pathNoLeader); return new File(PCGenSettings.getHomebrewDataDir(), path).toURI(); } else if (basePath.charAt(0) == '*') { String pathNoLeader = trimLeadingFileSeparator(basePath.substring(1)); String path = CoreUtility.fixFilenamePath(pathNoLeader); File pccFile = new File(PCGenSettings.getHomebrewDataDir(), path); if (pccFile.exists()) { return pccFile.toURI(); } pccFile = new File(PCGenSettings.getVendorDataDir(), path); if (pccFile.exists()) { return pccFile.toURI(); } return new File(ConfigurationSettings.getPccFilesDir(), path) .toURI(); } else if (basePath.indexOf(':') > 0) { try { // if it's a URL, then we are all done, just return a URI URL url = new URL(basePath); return new URI(url.getProtocol(), url.getHost(), url.getPath(), null); } catch (URISyntaxException | MalformedURLException e) { //Something broke, so wasn't a URL } } /* * At this point, basePath is a relative path */ String pathNoLeader = trimLeadingFileSeparator(basePath); //BUG This captures files that start with "data" :( /* * 1) If the path starts with '/data', assume it means the PCGen data * dir */ if (pathNoLeader.startsWith("data")) { // substring 5 to eliminate the separator after data String path = CoreUtility.fixFilenamePath(pathNoLeader.substring(5)); return new File(ConfigurationSettings.getPccFilesDir(), path) .toURI(); } /* * 2) Otherwise, assume that the path is relative to the current PCC * file URL */ String path = pccPath.getPath(); // URLs always use forward slash; take off the file name try { return new URI(pccPath.getScheme(), null, (path.substring(0, path.lastIndexOf('/') + 1) + basePath.replace('\\', '/')), null); } catch (URISyntaxException e) { Logging.errorPrint("URIFactory failed to convert " + path.substring(0, path.lastIndexOf('/') + 1) + basePath + " to a URI: " + e.getLocalizedMessage()); } return FAILED_URI; } /** * This method trims the leading file separator or URL separator from the * front of a string. * * @param basePath * String containing the base path to trim * @return String containing the trimmed path String */ private static String trimLeadingFileSeparator(String basePath) { String pathNoLeader = basePath; if (pathNoLeader.startsWith("/") || pathNoLeader.startsWith(File.separator)) { pathNoLeader = pathNoLeader.substring(1); } return pathNoLeader; } }