Clover Coverage Report
Coverage timestamp: Fri May 24 2013 13:47:27 UTC
../../../../../img/srcFileCovDistChart10.png 0% of files have more coverage
100   373   45   4.76
32   198   0.45   21
21     2.14  
1    
 
  DefaultModuleAddress       Line # 38 100 45 93.5% 0.9346405
 
No Tests
 
1    /* This file is part of the project "Hilbert II" - http://www.qedeq.org
2    *
3    * Copyright 2000-2013, Michael Meyling <mime@qedeq.org>.
4    *
5    * "Hilbert II" is free software; you can redistribute
6    * it and/or modify it under the terms of the GNU General Public
7    * License as published by the Free Software Foundation; either
8    * version 2 of the License, or (at your option) any later version.
9    *
10    * This program is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13    * GNU General Public License for more details.
14    */
15   
16    package org.qedeq.kernel.se.common;
17   
18    import java.io.File;
19    import java.io.IOException;
20    import java.net.MalformedURLException;
21    import java.net.URL;
22    import java.util.ArrayList;
23    import java.util.List;
24   
25    import org.qedeq.base.io.Path;
26    import org.qedeq.base.io.UrlUtility;
27    import org.qedeq.base.trace.Trace;
28    import org.qedeq.base.utility.StringUtility;
29    import org.qedeq.kernel.se.base.module.LocationList;
30    import org.qedeq.kernel.se.base.module.Specification;
31   
32   
33    /**
34    * An object of this class represents an address for a QEDEQ module.
35    *
36    * @author Michael Meyling
37    */
 
38    public class DefaultModuleAddress implements ModuleAddress {
39   
40    /** Default memory module address with identifier "default". */
41    public static final DefaultModuleAddress MEMORY = new DefaultModuleAddress();
42   
43    /** This class. */
44    private static final Class CLASS = DefaultModuleAddress.class;
45   
46    /** URL form of this address. */
47    private final String url;
48   
49    /** Header (including protocol, host, port, user) but without file path. */
50    private final String header;
51   
52    /** Path (without protocol, host, port and file name). */
53    private final String path;
54   
55    /** File name of QEDEQ module including <code>.xml</code>. */
56    private final String fileName;
57   
58    /** Is module address relative? */
59    private final boolean relativeAddress;
60   
61    /** Is module address a file? */
62    private final boolean fileAddress;
63   
64    /** Module name. That is file name without <code>.xml</code> */
65    private final String name;
66   
67    /**
68    * Constructor.
69    *
70    * @param u Address of module. Must not be <code>null</code>.
71    * Must be a URL with protocol "file" or "http" and address a file
72    * with extension ".xml".
73    * @throws MalformedURLException Address is formally incorrect.
74    */
 
75  242 toggle public DefaultModuleAddress(final String u) throws MalformedURLException {
76  242 this(u, (DefaultModuleAddress) null);
77    }
78   
79    /**
80    * Constructor.
81    *
82    * @param u Address of module. Must not be <code>null</code>.
83    * Must be a URL with protocol "file" or "http" and address a file
84    * with extension ".xml".
85    * @throws MalformedURLException Address is formally incorrect.
86    */
 
87  454 toggle public DefaultModuleAddress(final URL u) throws MalformedURLException {
88  454 this(u.toExternalForm(), (ModuleAddress) null);
89    }
90   
91    /**
92    * Constructor.
93    *
94    * @param file File path of module. Must address a file
95    * with extension ".xml".
96    * @throws IOException Problem with file location.
97    */
 
98  58 toggle public DefaultModuleAddress(final File file) throws IOException {
99  58 this(UrlUtility.toUrl(file.getCanonicalFile()));
100    }
101   
102    /**
103    * Default constructor for memory modules.
104    */
 
105  511 toggle public DefaultModuleAddress() {
106  511 this(true, "default");
107    }
108   
109    /**
110    * Constructor mainly used for memory modules.
111    * TODO 20110227 m31: this is no object oriented design: a parameter must be true???
112    * refactor code and create extra memory module address class!
113    *
114    * @param memory Must be true. If not a runtime exception occurs.
115    * @param identifier Identifies the module in memory. Must not be <code>null</code>.
116    */
 
117  586 toggle public DefaultModuleAddress(final boolean memory, final String identifier) {
118  586 if (!memory) {
119  1 throw new IllegalArgumentException("memory must be true");
120    }
121  585 if (identifier == null) {
122  1 throw new NullPointerException();
123    }
124  584 url = "memory://" + identifier;
125  584 name = identifier;
126  584 fileAddress = false;
127  584 fileName = identifier;
128  584 header = "memory:";
129  584 path = "";
130  584 relativeAddress = false;
131    }
132   
133    /**
134    * Constructor.
135    *
136    * @param address Address of module. Must not be <code>null</code>.
137    * Must be a URL with protocol "file" or "http" (if <code>parent</code> is
138    * <code>null</code>) and address a file
139    * with extension ".xml".
140    * @param parent Address of parent module. Can be <code>null</code>.
141    * @throws MalformedURLException Address is formally incorrect.
142    */
 
143  1134 toggle public DefaultModuleAddress(final String address, final ModuleAddress parent)
144    throws MalformedURLException {
145  1134 final String method = "ModuleAddress(String, ModuleAddress)";
146  1134 if (address == null) {
147  2 throw new NullPointerException();
148    }
149  1132 URL urmel;
150  1132 try {
151  1132 if (parent != null) {
152  435 urmel = new URL(new URL(StringUtility.replace(parent.getUrl(), "file://", "file:")), address);
153    } else {
154  697 urmel = new URL(address);
155    }
156    } catch (MalformedURLException e) {
157  12 Trace.trace(CLASS, this, method, "address=" + address);
158  12 Trace.trace(CLASS, this, method, "parent=" + parent);
159  12 Trace.trace(CLASS, this, method, e);
160  12 try {
161  12 final String newAddress = "file:" + address;
162  12 if (parent != null) {
163  0 urmel = new URL(new URL(parent.getUrl()), newAddress);
164    } else {
165  12 urmel = new URL(newAddress);
166    }
167    } catch (MalformedURLException ex) {
168  0 throw e; // throw original exception
169    }
170    }
171  1132 final Path p = new Path(urmel.getPath());
172  1132 this.path = p.getDirectory();
173  1132 this.fileName = p.getFileName();
174  1132 Trace.trace(CLASS, this, method, "path=" + this.path);
175  1132 Trace.trace(CLASS, this, method, "fileName=" + this.fileName);
176  1132 this.relativeAddress = p.isRelative();
177  1132 if (!this.fileName.endsWith(".xml")) {
178  1 throw new MalformedURLException("file name doesn't end with \".xml\": "
179    + this.fileName);
180    }
181  1131 Trace.trace(CLASS, this, method, "protocol=" + urmel.getProtocol());
182  1131 fileAddress = urmel.getProtocol().equalsIgnoreCase("file");
183  1131 String urm = urmel.toString();
184  1131 Trace.trace(CLASS, this, method, "replacing " + urmel.getPath() + " by " + p.toString());
185  1131 urm = StringUtility.replace(urm, urmel.getPath(), p.toString());
186  1131 if (fileAddress) {
187  704 if (urm.startsWith("file:") && !urm.startsWith("file://")) {
188  704 urm = "file://" + urm.substring("file:".length());
189    }
190    }
191  1131 url = urm;
192  1131 final int positionBefore = this.fileName.lastIndexOf(".");
193  1131 final String mname = this.fileName.substring(0, positionBefore);
194  1131 this.name = mname;
195  1131 final int positionPath = url.lastIndexOf(p.toString());
196  1131 if (positionPath < 0) {
197  0 throw new IllegalArgumentException(
198    "couldn't determine begin of file path: "
199    + url + "\nsearching for: " + p);
200    }
201  1131 this.header = url.substring(0, positionPath);
202    }
203   
204    /**
205    * Get module address as {@link ModuleContext}. Creates a new object.
206    *
207    * @return Module address as {@link ModuleContext}.
208    */
 
209  69553 toggle public ModuleContext createModuleContext() {
210  69553 return new ModuleContext(this);
211    }
212   
213    /**
214    * Get address header (including protocol, host, port, user)
215    * but without file path.
216    *
217    * @return address header
218    */
 
219  11 toggle public String getHeader() {
220  11 return header;
221    }
222   
223    /**
224    * Get address path (without protocol, host, port and file name).
225    *
226    * @return module path
227    */
 
228  11 toggle public String getPath() {
229  11 return path;
230    }
231   
232    /**
233    * Get module file name.
234    *
235    * @return Module file name.
236    */
 
237  74 toggle public String getFileName() {
238  74 return fileName;
239    }
240   
241    /**
242    * Get name of module (file name without <code>.xml</code>).
243    *
244    * @return Module name.
245    */
 
246  74 toggle public String getName() {
247  74 return this.name;
248    }
249   
250    /**
251    * Get fully qualified URL of module.
252    *
253    * @return URL for QEDEQ module.
254    */
 
255  64429 toggle public String getUrl() {
256  64429 return this.url;
257    }
258   
259    /**
260    * Was this module address created relatively?
261    *
262    * @return Relatively created?
263    */
 
264  12 toggle public boolean isRelativeAddress() {
265  12 return this.relativeAddress;
266    }
267   
268    /**
269    * Is this a local QEDEQ file. That means the address starts with <code>file:</code>.
270    *
271    * @return Is the QEDEQ module a local file?
272    */
 
273  60231 toggle public boolean isFileAddress() {
274  60231 return fileAddress;
275    }
276   
 
277  649 toggle public final String toString() {
278  649 return url;
279    }
280   
 
281  107120 toggle public final int hashCode() {
282  107120 return url.hashCode();
283    }
284   
 
285  5211 toggle public final boolean equals(final Object object) {
286  5211 if (!(object instanceof DefaultModuleAddress)) {
287  1 return false;
288    }
289  5210 return url.equals(((DefaultModuleAddress) object).url);
290    }
291   
292    /**
293    * Get the file name of the specified module.
294    *
295    * @param spec Here are the (perhaps relative) addresses to
296    * another module.
297    * @return File name of specified module.
298    */
 
299  260 toggle private static final String getModuleFileName(final Specification spec) {
300   
301  260 return spec.getName() + ".xml";
302    }
303   
 
304  260 toggle public final ModuleAddress[] getModulePaths(final Specification spec) throws IOException {
305   
306  260 final String fileNameEnd = getModuleFileName(spec);
307  260 final LocationList locations = spec.getLocationList();
308  260 final List result = new ArrayList();
309  695 for (int i = 0; locations != null && i < locations.size(); i++) {
310  435 if (locations.get(i) == null) {
311  0 continue;
312    }
313  435 String file = locations.get(i).getLocation();
314  435 if (file.equals(".")) {
315  219 file = "";
316  216 } else if (!file.endsWith("/")) {
317  216 file += "/";
318    }
319  435 file += fileNameEnd;
320  435 result.add(new DefaultModuleAddress(file, this));
321    }
322  260 return (ModuleAddress[]) result.toArray(new ModuleAddress[] {});
323    }
324   
325    /**
326    * Create relative address from <code>origin</code> to <code>next</code>.
327    * If both addresses point to the same file we return "".
328    *
329    * @param origin This is the original location (URL!).
330    * @param next This should be the next location (URL!).
331    * @return Relative (or if necessary absolute) address.
332    */
 
333  12 toggle public static final String createRelativeAddress(final String origin,
334    final String next) {
335  12 if (origin.equals(next)) {
336  1 return "";
337    }
338  11 final URL urlOrgin;
339  11 try {
340  11 urlOrgin = new URL(origin);
341    } catch (MalformedURLException e) {
342  7 return createRelative(origin, next);
343    }
344  4 try {
345  4 final URL urlNext = new URL(next);
346  4 if (urlOrgin.getProtocol().equals(urlNext.getProtocol())
347    && urlOrgin.getHost().equals(urlNext.getHost())
348    && urlOrgin.getPort() == urlNext.getPort()) {
349  3 final String org = urlOrgin.getFile();
350  3 final String nex = urlNext.getFile();
351  3 return createRelative(org, nex);
352    }
353    // no relative address possible
354  1 return urlNext.toString();
355    } catch (MalformedURLException e) {
356  0 return next;
357    }
358    }
359   
360    /**
361    * Create relative address. Assume only file paths.
362    *
363    * @param org This is the original location.
364    * @param nex This should be the next location.
365    * @return Relative path (if possible).
366    */
 
367  10 toggle public static String createRelative(final String org, final String nex) {
368  10 final Path from = new Path(org);
369  10 return from.createRelative(nex).toString();
370    }
371   
372    }
373