diff options
Diffstat (limited to 'JLanguageTool/src/java/de/danielnaber/languagetool/databroker/DefaultResourceDataBroker.java')
-rw-r--r-- | JLanguageTool/src/java/de/danielnaber/languagetool/databroker/DefaultResourceDataBroker.java | 360 |
1 files changed, 360 insertions, 0 deletions
diff --git a/JLanguageTool/src/java/de/danielnaber/languagetool/databroker/DefaultResourceDataBroker.java b/JLanguageTool/src/java/de/danielnaber/languagetool/databroker/DefaultResourceDataBroker.java new file mode 100644 index 0000000..d365ea5 --- /dev/null +++ b/JLanguageTool/src/java/de/danielnaber/languagetool/databroker/DefaultResourceDataBroker.java @@ -0,0 +1,360 @@ +/* LanguageTool, a natural language style checker + * Copyright (C) 2006 Daniel Naber (http://www.danielnaber.de) + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA + */ +package de.danielnaber.languagetool.databroker; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.security.Permission; + +import de.danielnaber.languagetool.JLanguageTool; + +/** + * Responsible for getting any items from the grammar checker's resource + * directories. This default data broker assumes that they are accessible + * directly via class-path and the directory names are like specified in: + * + * <ul style="list-type: circle"> + * <li>{@link ResourceDataBroker#RESOURCE_DIR}</li> + * <li>{@link ResourceDataBroker#RULES_DIR}</li> + * </ul> + * <p> + * + * If you'd like to determine another resource directory location this default + * data broker provides proper methods. + * Assuming your {@code /rules} and {@code /resource} directories are accessible + * via class-path with following path information: + * + * <ul style="list-type: circle"> + * <li>{@code /res/grammarchecker/rulesdirname}</li> + * <li>{@code /res/grammarchecker/resourcedirname}</li> + * </ul> + * + * In this case you have to invoke the methods + * {@link ResourceDataBroker#setRulesDir(String)} and + * {@link ResourceDataBroker#setResourceDir(String)} with following arguments: + * + * <ul style="list-type: circle"> + * <li>{@code /res/grammarchecker/rulesdirname}</li> + * <li>{@code /res/grammarchecker/resourcedirname}</li> + * </ul> + * <p> + * + * Make sure that you never obtain any grammar checker resources by calling + * {@code Object.class.getResource(String)} or {@code + * Object.class.getResourceAsStream(String)} directly. If you would like to + * obtain something from these directories do always use + * {@link JLanguageTool#getDataBroker()} which provides proper methods for + * reading the directories above. + * <p> + * + * For example, if you want to get the {@link URL} of {@code + * /rules/de/grammar.xml} just invoke + * {@link ResourceDataBroker#getFromRulesDirAsUrl(String)} and pass {@code + * /de/grammar.xml} as a string. Note: The {@code /rules} directory's name isn't + * passed, because its name might have changed. The same usage does apply for the + * {@code /resource} directory. + * + * @see ResourceDataBroker + * @author PAX + * @since 1.0.1 + */ +public class DefaultResourceDataBroker implements ResourceDataBroker { + + /** + * The directory's name of the grammar checker's resource directory. The + * default value equals {@link ResourceDataBroker#RESOURCE_DIR}. + */ + protected String resourceDir; + + /** + * The directory's name of the grammar checker's rules directory. The + * default value equals {@link ResourceDataBroker#RULES_DIR}. + */ + protected String rulesDir; + + /** + * Instantiates this data broker with the default resource directory names + * as specified in: + * + * <ul> + * <li>{@link ResourceDataBroker#RESOURCE_DIR}</li> + * <li>{@link ResourceDataBroker#RULES_DIR}</li> + * </ul> + */ + public DefaultResourceDataBroker() { + this(ResourceDataBroker.RESOURCE_DIR, ResourceDataBroker.RULES_DIR); + } + + /** + * Instantiates this data broker with the passed resource directory names. + * + * @param resourceDir + * The directory's name of the grammar checker's resource + * directory. The default value equals + * {@link ResourceDataBroker#RESOURCE_DIR}. + * @param rulesDir + * The directory's name of the grammar checker's rules directory. + * The default value equals + * {@link ResourceDataBroker#RULES_DIR}. + */ + public DefaultResourceDataBroker(final String resourceDir, final String rulesDir) { + this.setResourceDir(resourceDir); + this.setRulesDir(rulesDir); + } + + /** + * See: + * {@link ResourceDataBroker#getFromResourceDirAsStream(java.lang.String)} + * + * @param path + * The relative path to the item inside of the {@code /resource} + * directory. Please start your path information with {@code /} + * because it will be concatenated with the directory's name: + * /resource<b>/yourpath</b>. + * @return An {@link InputStream} object to the requested item or {@code + * null} if it wasn't found. + */ + @Override + public InputStream getFromResourceDirAsStream(final String path) { + final String completePath = this.getCompleteResourceUrl(path); + return ResourceDataBroker.class.getResourceAsStream(completePath); + } + + /** + * See: + * {@link ResourceDataBroker#getFromResourceDirAsUrl(java.lang.String)} + * + * @param path + * The relative path to the item inside of the {@code /resource} + * directory. Please start your path information with {@code /} + * because it will be concatenated with the directory's name: + * /resource<b>/yourpath</b>. + * @return An {@link URL} object to the requested item or {@code null} if it + * wasn't found. + */ + @Override + public URL getFromResourceDirAsUrl(final String path) { + final String completePath = this.getCompleteResourceUrl(path); + return getFixedJarURL(ResourceDataBroker.class.getResource(completePath)); + } + + /** + * Concatenates the passed resource path with the currently set {@code + * resource} directory path. + * + * @param path + * The relative path to a resource item inside of the {@code + * resource} directory. + * @return The full relative path to the resource including the path to the + * {@code resource} directory. + */ + private String getCompleteResourceUrl(final String path) { + final StringBuffer completePath = new StringBuffer(this.getResourceDir()); + + if (!this.getResourceDir().endsWith("/") && !(path.charAt(0)=='/')) { + completePath.append('/'); + } + + if (this.getResourceDir().endsWith("/") && (path.charAt(0)=='/') + && path.length() > 1) { + completePath.append(path.substring(1)); + } else { + completePath.append(path); + } + + return completePath.toString(); + } + + /** + * See: + * {@link ResourceDataBroker#getFromRulesDirAsStream(java.lang.String)} + * + * @param path + * The relative path to the item inside of the {@code /rules} + * directory. Please start your path information with {@code /} + * because it will be concatenated with the directory's name: + * /rules<b>/yourpath</b>. + * @return An {@link InputStream} object to the requested item or {@code + * null} if it wasn't found. + */ + @Override + public InputStream getFromRulesDirAsStream(final String path) { + final StringBuffer completePath = this.getCompleteRulesUrl(path); + return ResourceDataBroker.class.getResourceAsStream(completePath.toString()); + } + + /** + * See: {@link ResourceDataBroker#getFromRulesDirAsUrl(java.lang.String)} + * + * @param path + * The relative path to the item inside of the {@code /rules} + * directory. Please start your path information with {@code /} + * because it will be concatenated with the directory's name: + * /rules<b>/yourpath</b>. + * @return An {@link URL} object to the requested item or {@code null} if it + * wasn't found. + */ + @Override + public URL getFromRulesDirAsUrl(final String path) { + final StringBuffer completePath = this.getCompleteRulesUrl(path); + return getFixedJarURL(ResourceDataBroker.class.getResource(completePath.toString())); + } + + /** + * Concatenates the passed resource path with the currently set {@code + * rules} directory path. + * + * @param path + * The relative path to a resource item inside of the {@code + * rules} directory. + * @return The full relative path to the resource including the path to the + * {@code rules} directory. + */ + private StringBuffer getCompleteRulesUrl(final String path) { + final StringBuffer completePath = new StringBuffer(this.getRulesDir()); + + if (!this.getRulesDir().endsWith("/") && !(path.charAt(0)=='/')) { + completePath.append('/'); + } + + if (this.getRulesDir().endsWith("/") && (path.charAt(0)=='/') && path.length() > 1) { + completePath.append(path.substring(1)); + } else { + completePath.append(path); + } + + return completePath; + } + + /** + * @return The directory's name of the grammar checker's resource directory. + * The default value equals + * {@link ResourceDataBroker#RESOURCE_DIR}. + */ + @Override + public String getResourceDir() { + return this.resourceDir; + } + + /** + * @param resourceDir + * The directory's name of the grammar checker's resource + * directory. The default value was + * {@link ResourceDataBroker#RESOURCE_DIR}. Please let this + * string start with {@code '/'} and use this character as path + * separator. Don't set this character to the string's end. Valid + * example value: {@code /subdir/furtherdir/resourcedir}. + */ + @Override + public void setResourceDir(final String resourceDir) { + this.resourceDir = (resourceDir == null) ? "" : resourceDir; + } + + /** + * @return The directory's name of the grammar checker's rules directory. + * The default value equals {@link ResourceDataBroker#RULES_DIR}. + */ + @Override + public String getRulesDir() { + return this.rulesDir; + } + + /** + * @param rulesDir + * The directory's name of the grammar checker's rules directory. + * The default value was {@link ResourceDataBroker#RULES_DIR}. + * Please let this string start with {@code '/'} and use this + * character as path separator. Don't set this character to the + * string's end. Valid example value: {@code + * /subdir/furtherdir/rulesdir}. + */ + @Override + public void setRulesDir(final String rulesDir) { + this.rulesDir = (rulesDir == null) ? "" : rulesDir; + } + + /** + * Fixes the getResource bug if you want to obtain any resource from a JAR file under Java + * 1.5.0_16 Webstart. (Workaround by {@code mevanclark} from http://forums.sun.com) + * + * @param url The {@link URL} to be fixed. + * @return The fixed version if necessary. + */ + private static URL getFixedJarURL(URL url) { + if (url == null) { + return url; + } + + final String originalURLProtocol = url.getProtocol(); + if (!"jar".equalsIgnoreCase(originalURLProtocol)) { + return url; + } + + final String originalURLString = url.toString(); + final int bangSlashIndex = originalURLString.indexOf("!/"); + if (bangSlashIndex > -1) { + return url; + } + + final String originalURLPath = url.getPath(); + final URLConnection urlConnection; + try { + urlConnection = url.openConnection(); + if (urlConnection == null) { + throw new IOException("urlConnection is null"); + } + } catch (IOException e) { + return url; + } + + final Permission urlConnectionPermission; + try { + urlConnectionPermission = urlConnection.getPermission(); + if (urlConnectionPermission == null) { + throw new IOException("urlConnectionPermission is null"); + } + } catch (IOException e) { + return url; + } + + final String urlConnectionPermissionName = urlConnectionPermission.getName(); + if (urlConnectionPermissionName == null) { + return url; + } + + final File file = new File(urlConnectionPermissionName); + if (!file.exists()) { + return url; + } + + try { + final String newURLStr = "jar:" + file.toURI().toURL().toExternalForm() + "!/" + originalURLPath; + url = new URL(newURLStr); + } catch (MalformedURLException e) { + return url; + } + + return url; + } + +} |