Clover coverage report - QedeqKernelSe Coverage Report
Coverage timestamp: Do Mai 10 2007 03:16:40 CEST
file stats: LOC: 443   Methods: 23
NCLOC: 236   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
DefaultModuleAddress.java 19,4% 32,5% 47,8% 31,8%
coverage coverage
 1    /* $Id: DefaultModuleAddress.java,v 1.1 2007/05/10 00:37:51 m31 Exp $
 2    *
 3    * This file is part of the project "Hilbert II" - http://www.qedeq.org
 4    *
 5    * Copyright 2000-2007, Michael Meyling <mime@qedeq.org>.
 6    *
 7    * "Hilbert II" is free software; you can redistribute
 8    * it and/or modify it under the terms of the GNU General Public
 9    * License as published by the Free Software Foundation; either
 10    * version 2 of the License, or (at your option) any later version.
 11    *
 12    * This program is distributed in the hope that it will be useful,
 13    * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 15    * GNU General Public License for more details.
 16    */
 17   
 18    package org.qedeq.kernel.bo.load;
 19   
 20    import java.io.File;
 21    import java.io.IOException;
 22    import java.io.UnsupportedEncodingException;
 23    import java.net.MalformedURLException;
 24    import java.net.URL;
 25    import java.net.URLEncoder;
 26   
 27    import org.qedeq.kernel.base.module.LocationList;
 28    import org.qedeq.kernel.base.module.Specification;
 29    import org.qedeq.kernel.bo.module.ModuleAddress;
 30    import org.qedeq.kernel.bo.module.ModuleContext;
 31    import org.qedeq.kernel.bo.module.QedeqBo;
 32    import org.qedeq.kernel.trace.Trace;
 33    import org.qedeq.kernel.utility.IoUtility;
 34    import org.qedeq.kernel.utility.ReplaceUtility;
 35   
 36   
 37    /**
 38    * An object of this class represents an address for a QEDEQ module.
 39    *
 40    * @version $Revision: 1.1 $
 41    * @author Michael Meyling
 42    */
 43    public class DefaultModuleAddress implements ModuleAddress {
 44   
 45    /** Address. */
 46    private final String address;
 47   
 48    /** URL form of this address. */
 49    private final URL url;
 50   
 51    /** Header (including protocol, host, port, user) but without file path. */
 52    private final String header;
 53   
 54    /** Path (without protocol, host, port and file name). */
 55    private final String path;
 56   
 57    /** File name of QEDEQ module including <code>.xml</code>. */
 58    private final String fileName;
 59   
 60    /** Is module address relative? */
 61    private final boolean relativeAddress;
 62   
 63    /** Module name. That is file name without <code>.xml</code> */
 64    private final String name;
 65   
 66    /**
 67    * Constructor.
 68    *
 69    * @param u Address of module.
 70    * @param parent Address of parent module
 71    * @throws IOException if address is formally incorrect
 72    */
 73  0 public DefaultModuleAddress(final URL u, final DefaultModuleAddress parent)
 74    throws IOException {
 75   
 76  0 this(u.toExternalForm(), parent);
 77    }
 78   
 79    /**
 80    * Constructor.
 81    *
 82    * @param u Address of module.
 83    * @throws IOException if address is formally incorrect
 84    */
 85  8 public DefaultModuleAddress(final URL u) throws IOException {
 86  8 this(u.toExternalForm(), (DefaultModuleAddress) null);
 87    }
 88   
 89    /**
 90    * Constructor.
 91    *
 92    * @param file File path of module.
 93    * @throws IOException Address is formally incorrect
 94    */
 95  0 public DefaultModuleAddress(final File file)
 96    throws IOException {
 97  0 this(IoUtility.toUrl(file), (DefaultModuleAddress) null);
 98    }
 99   
 100    /**
 101    * Constructor.
 102    *
 103    * @param address Address of module.
 104    * @throws IOException Address is formally incorrect
 105    */
 106  30 public DefaultModuleAddress(final String address)
 107    throws IOException {
 108  30 this(address, (DefaultModuleAddress) null);
 109    }
 110   
 111    /**
 112    * Constructor.
 113    *
 114    * @param address address of module
 115    * @param parent address of parent module
 116    * @throws IOException if address is formally incorrect
 117    */
 118  38 public DefaultModuleAddress(final String address, final DefaultModuleAddress parent)
 119    throws IOException {
 120   
 121  38 final String method = "ModuleAddress(String, ModuleAddress)";
 122  38 if (address == null) {
 123  0 throw new NullPointerException();
 124    }
 125  38 URL urmel;
 126  38 try {
 127  38 if (parent != null) {
 128  0 urmel = new URL(parent.url, address);
 129    } else {
 130  38 urmel = new URL(address);
 131    }
 132    } catch (MalformedURLException e) {
 133  0 Trace.trace(this, method, "address=" + address);
 134  0 Trace.trace(this, method, "parent=" + parent);
 135  0 Trace.trace(this, method, e);
 136  0 try {
 137  0 final String newAddress = "file:" + address;
 138  0 if (parent != null) {
 139  0 urmel = new URL(parent.url, newAddress);
 140    } else {
 141  0 urmel = new URL(newAddress);
 142    }
 143    } catch (MalformedURLException ex) {
 144  0 throw e; // throw original exception
 145    }
 146    }
 147  38 Trace.trace(this, method, "protocol=" + urmel.getProtocol());
 148  38 url = urmel;
 149  38 this.address = urmel.toExternalForm();
 150  38 Trace.trace(this, method, "address=" + this.address);
 151    /*
 152    Trace.trace(this, METHOD, "url.getFile=" + this.url.getFile());
 153    Trace.trace(this, METHOD, "url.getPath=" + this.url.getPath());
 154    try {
 155    Trace.trace(this, METHOD, "URI File=" +
 156    new File(new URI(this.address)).getAbsoluteFile());
 157    } catch (URISyntaxException e1) {
 158    e1.printStackTrace();
 159    }
 160    */
 161  38 final String p = urmel.getFile();
 162  38 final int position = p.lastIndexOf("/");
 163  38 if (position >= 0 && position + 1 < p.length()) {
 164  38 this.path = p.substring(0, position) + "/";
 165  38 this.fileName = p.substring(position + 1);
 166    } else {
 167  0 this.path = "";
 168  0 this.fileName = p;
 169    }
 170  38 Trace.trace(this, method, "path=" + this.path);
 171  38 Trace.trace(this, method, "fileName=" + this.fileName);
 172  38 this.relativeAddress = !this.path.startsWith("/");
 173  38 if (!this.fileName.endsWith(".xml")) {
 174  0 throw new IOException("file name doesn't end with \".xml\": "
 175    + this.fileName);
 176    }
 177  38 final int positionBefore = this.fileName.lastIndexOf(".");
 178  38 final String mname = this.fileName.substring(0, positionBefore);
 179  38 this.name = mname;
 180  38 final int positionPath
 181    = this.address.lastIndexOf(this.path + this.fileName);
 182  38 if (positionPath < 0) {
 183  0 throw new IllegalArgumentException(
 184    "couldn't determine begin of file path: "
 185    + this.address);
 186    }
 187  38 this.header = this.address.substring(0, positionPath);
 188    }
 189   
 190    /**
 191    * Get module address.
 192    *
 193    * @return module address
 194    */
 195  28 public final String getAddress() {
 196  28 return address;
 197    }
 198   
 199    /**
 200    * Get module address as {@link ModuleContext}. Creates a new object.
 201    *
 202    * @return Module address as {@link ModuleContext}.
 203    */
 204  0 public final ModuleContext createModuleContext() {
 205  0 return new ModuleContext(getAddress());
 206    }
 207   
 208    /**
 209    * Get address header (including protocol, host, port, user)
 210    * but without file path.
 211    *
 212    * @return address header
 213    */
 214  0 public final String getHeader() {
 215  0 return header;
 216    }
 217   
 218    /**
 219    * Get address path (without protocol, host, port and file name).
 220    *
 221    * @return module path
 222    */
 223  18 public final String getPath() {
 224  18 return path;
 225    }
 226   
 227    /**
 228    * Get module file name.
 229    *
 230    * @return Module file name.
 231    */
 232  18 public final String getFileName() {
 233  18 return fileName;
 234    }
 235   
 236    /**
 237    * Get name of module (file name without <code>.xml</code>).
 238    *
 239    * @return Module name.
 240    */
 241  0 public final String getName() {
 242  0 return this.name;
 243    }
 244   
 245    /**
 246    * Get fully qualified URL of module.
 247    *
 248    * @return URL for QEDEQ module.
 249    */
 250  56 public final URL getURL() {
 251  56 return this.url;
 252    }
 253   
 254    /**
 255    * Was this module address created relatively?
 256    *
 257    * @return Relatively created?
 258    */
 259  0 public final boolean isRelativeAddress() {
 260  0 return this.relativeAddress;
 261    }
 262   
 263    /**
 264    * Is this a local QEDEQ file. That means the address starts with <code>file:</code>.
 265    *
 266    * @return Is the QEDEQ module a local file?
 267    */
 268  19 public final boolean isFileAddress() {
 269  19 return getAddress().indexOf("file:") == 0;
 270    }
 271   
 272    /**
 273    * Transform an URL address into a local file path.
 274    *
 275    * @param url transform this URL
 276    * @return result of transformation
 277    */
 278  0 public final String localizeInFileSystem(final String url) {
 279  0 final String encoded;
 280  0 try {
 281  0 encoded = URLEncoder.encode(url, "UTF-8");
 282    } catch (UnsupportedEncodingException e) {
 283  0 Trace.trace(DefaultModuleAddress.class, "localizeInFileSystem(String)", e);
 284  0 throw new RuntimeException(e);
 285    }
 286  0 StringBuffer adr = new StringBuffer(encoded);
 287  0 ReplaceUtility.replace(adr, "://", "/"); // TODO transform these codes into UTF8!!!!
 288  0 ReplaceUtility.replace(adr, ":/", "/");
 289  0 ReplaceUtility.replace(adr, ":", "$");
 290  0 ReplaceUtility.replace(adr, "|", "$$"); // for win32
 291  0 return adr.toString();
 292    }
 293   
 294    /**
 295    * Create relative address from <code>this</code> to <code>reference</code>.
 296    *
 297    * @param reference this should be the next location
 298    * @return relative (or if neccessary absolute) address
 299    */
 300  0 public final String createRelativeAddress(
 301    final ModuleAddress reference) {
 302  0 return createRelativeAddress(getAddress(),
 303    reference.getAddress());
 304    }
 305   
 306  4 public final String toString() {
 307  4 return this.address;
 308    }
 309   
 310  97 public final int hashCode() {
 311  97 return this.address.hashCode();
 312    }
 313   
 314  40 public final boolean equals(final Object object) {
 315  40 if (object == null || !(object instanceof DefaultModuleAddress)) {
 316  2 return false;
 317    }
 318  38 return address.equals(((DefaultModuleAddress) object).address);
 319    }
 320   
 321    /**
 322    * Get the file name of the specified module.
 323    *
 324    * TODO mime 20070326: is this function really neccessary?
 325    *
 326    * @param spec here are the (perhaps relative) addresses to
 327    * another module
 328    * @return file name of specified module
 329    */
 330  0 public static final String getModuleFileName(final Specification spec) {
 331   
 332  0 return spec.getName() + ".xml";
 333    }
 334   
 335    /**
 336    * Get all potential module addresses from a module specification.
 337    *
 338    * TODO mime 20070326: add context information (for error case)
 339    *
 340    * @param module Starting from that module (has an absolute
 341    * address).
 342    * @param spec Here are the (perhaps relative) addresses to
 343    * another module.
 344    * @return Array of absolute address strings.
 345    * @throws IOException One address is not correctly formed.
 346    */
 347  0 public static final ModuleAddress[] getModulePaths(final QedeqBo module,
 348    final Specification spec) throws IOException {
 349   
 350  0 final String fileNameEnd = getModuleFileName(spec);
 351  0 final LocationList locations = spec.getLocationList();
 352  0 final ModuleAddress[] result
 353    = new ModuleAddress[locations.size()];
 354  0 for (int i = 0; i < locations.size(); i++) {
 355  0 String fileName
 356    = locations.get(i).getLocation();
 357  0 if (fileName.equals(".")) {
 358  0 fileName = "";
 359  0 } else if (!fileName.endsWith("/")) {
 360  0 fileName += "/";
 361    }
 362  0 fileName += fileNameEnd;
 363  0 result[i] = new DefaultModuleAddress(fileName,
 364    (DefaultModuleAddress) module.getModuleAddress());
 365    }
 366  0 return result;
 367    }
 368   
 369    /**
 370    * Create relative address from <code>orgin</code> to <code>next</code>.
 371    *
 372    * @param origin This is the original location (URL!).
 373    * @param next This should be the next location (URL!).
 374    * @return Relative (or if necessary absolute) address.
 375    */
 376  0 public static final String createRelativeAddress(final String origin,
 377    final String next) {
 378  0 if (origin.equals(next)) {
 379  0 return "";
 380    }
 381  0 try {
 382  0 final URL urlOrgin = new URL(origin);
 383  0 final URL urlNext = new URL(next);
 384   
 385  0 if (urlOrgin.getProtocol().equals(urlNext.getProtocol())
 386    && urlOrgin.getHost().equals(urlNext.getHost())
 387    && urlOrgin.getPort() == urlNext.getPort()) {
 388  0 final String org = urlOrgin.getFile();
 389  0 final String nex = urlNext.getFile();
 390  0 int i = -1; // position of next '/'
 391  0 int j = 0; // position of last '/'
 392  0 while (0 <= (i = org.indexOf("/", j))) {
 393  0 if (i >= 0 && nex.length() > i
 394    && org.substring(j, i).equals(
 395    nex.substring(j, i))) {
 396  0 j = i + 1;
 397    } else {
 398  0 break;
 399    }
 400    }
 401  0 if (j > 0) {
 402  0 i = j;
 403  0 StringBuffer result = new StringBuffer(nex.length());
 404  0 while (0 <= (i = org.indexOf("/", i))) {
 405  0 i++;
 406  0 result.append("../");
 407    }
 408  0 result.append(nex.substring(j));
 409  0 return result.toString();
 410    } else {
 411  0 return "/" + nex;
 412    }
 413    } else { // no relative address possible
 414  0 return urlNext.toString();
 415    }
 416    } catch (MalformedURLException e) {
 417  0 return next;
 418    }
 419   
 420    }
 421   
 422    /**
 423    * Get module address with new ending. E.g.: ".html" instead of ".qedeq".
 424    *
 425    * @param address The address of something (e.g.: a module).
 426    * @param newEnding This should be the new ending (e.g.: "html").
 427    * @return module address with substituted ending
 428    */
 429  0 public static final String newEnding(final String address,
 430    final String newEnding) {
 431  0 if (address.length() == 0) {
 432  0 return "";
 433    }
 434  0 final int i = address.lastIndexOf(".");
 435  0 if (i > 0) {
 436  0 return address.substring(0, i + 1) + newEnding;
 437    } else {
 438  0 return address + "." + newEnding;
 439    }
 440    }
 441   
 442    }
 443