Author: desruisseaux
Date: Mon Dec 31 07:38:18 2012
New Revision: 1427049
URL: http://svn.apache.org/viewvc?rev=1427049&view=rev
Log:
Added an About class for providing information on the Apache SIS runtime
environment.
The information provided in this class will be expanded in future version with
things
like SIS data directory and URL to the EPSG database directory.
Added:
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/About.java
(with props)
Modified:
sis/branches/JDK7/pom.xml
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/Supervisor.java
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/SupervisorMBean.java
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/measure/SexagesimalConverter.java
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties
sis/branches/JDK7/sis-utility/src/main/resources/org/apache/sis/internal/util/Descriptions.properties
sis/branches/JDK7/sis-utility/src/main/resources/org/apache/sis/internal/util/Descriptions_fr.properties
sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java
Modified: sis/branches/JDK7/pom.xml
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/pom.xml?rev=1427049&r1=1427048&r2=1427049&view=diff
==============================================================================
--- sis/branches/JDK7/pom.xml (original)
+++ sis/branches/JDK7/pom.xml Mon Dec 31 07:38:18 2012
@@ -330,6 +330,7 @@ Apache SIS is a toolkit for describing l
<index>false</index>
<manifest>
<addClasspath>true</addClasspath>
+ <mainClass>org.apache.sis.util.About</mainClass>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
</manifest>
<manifestEntries>
Modified:
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/Supervisor.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/Supervisor.java?rev=1427049&r1=1427048&r2=1427049&view=diff
==============================================================================
---
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/Supervisor.java
(original)
+++
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/Supervisor.java
Mon Dec 31 07:38:18 2012
@@ -32,9 +32,11 @@ import javax.management.JMException;
import javax.management.NotCompliantMBeanException;
import java.lang.management.ManagementFactory;
+import org.apache.sis.util.About;
import org.apache.sis.util.Localized;
import org.apache.sis.util.logging.Logging;
import org.apache.sis.util.resources.Errors;
+import org.apache.sis.util.collection.TreeTable;
/**
@@ -126,22 +128,6 @@ public final class Supervisor extends St
}
/**
- * If there is something wrong with the current Apache Supervisor status,
- * returns descriptions of the problems. Otherwise returns {@code null}.
- */
- @Override
- public List<String> warnings() {
- final List<String> warnings = Threads.listDeadThreads();
- if (warnings != null) {
- final Errors resources = Errors.getResources(locale);
- for (int i=warnings.size(); --i>=0;) {
- warnings.set(i, resources.getString(Errors.Keys.DeadThread_1,
warnings.get(i)));
- }
- }
- return warnings;
- }
-
- /**
* Returns the operations impact, which is {@code INFO}.
*/
@Override
@@ -196,4 +182,31 @@ public final class Supervisor extends St
return
ResourceBundle.getBundle("org.apache.sis.internal.util.Descriptions",
locale,
Supervisor.class.getClassLoader()).getString(resourceKey);
}
+
+ // -----------------------------------------------------------------------
+ // Implementation of SupervisorMBean interface
+ // -----------------------------------------------------------------------
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public TreeTable configuration() {
+ return About.configuration(locale);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public List<String> warnings() {
+ final List<String> warnings = Threads.listDeadThreads();
+ if (warnings != null) {
+ final Errors resources = Errors.getResources(locale);
+ for (int i=warnings.size(); --i>=0;) {
+ warnings.set(i, resources.getString(Errors.Keys.DeadThread_1,
warnings.get(i)));
+ }
+ }
+ return warnings;
+ }
}
Modified:
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/SupervisorMBean.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/SupervisorMBean.java?rev=1427049&r1=1427048&r2=1427049&view=diff
==============================================================================
---
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/SupervisorMBean.java
(original)
+++
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/SupervisorMBean.java
Mon Dec 31 07:38:18 2012
@@ -17,6 +17,7 @@
package org.apache.sis.internal.util;
import java.util.List;
+import org.apache.sis.util.collection.TreeTable;
/**
@@ -29,6 +30,17 @@ import java.util.List;
*/
public interface SupervisorMBean {
/**
+ * Returns information about the current configuration.
+ * This method tries to focus on the information that are the most
relevant to SIS.
+ * Those information are grouped in sections: a "Versions" section
containing the
+ * Apache SIS version, Java version and operation system version; a
"Classpath"
+ * section containing bootstrap, extension and user classpath, <i>etc</i>.
+ *
+ * @return Configuration information, as a tree for grouping some
configuration by sections.
+ */
+ TreeTable configuration();
+
+ /**
* If there is something wrong with the current Apache SIS status,
* returns descriptions of the problems. Otherwise returns {@code null}.
*
Modified:
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/measure/SexagesimalConverter.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/measure/SexagesimalConverter.java?rev=1427049&r1=1427048&r2=1427049&view=diff
==============================================================================
---
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/measure/SexagesimalConverter.java
(original)
+++
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/measure/SexagesimalConverter.java
Mon Dec 31 07:38:18 2012
@@ -197,7 +197,7 @@ class SexagesimalConverter extends UnitC
if (min >= 0) deg++; else deg--;
min = 0;
} else {
- throw illegalField(angle, min, Vocabulary.Keys.Minutes);
+ throw illegalField(angle, min,
Vocabulary.Keys.AngularMinutes);
}
}
if (sec <= -60 || sec >= 60) { // Do not enter for NaN
@@ -205,7 +205,7 @@ class SexagesimalConverter extends UnitC
if (sec >= 0) min++; else min--;
sec = 0;
} else {
- throw illegalField(angle, sec, Vocabulary.Keys.Seconds);
+ throw illegalField(angle, sec,
Vocabulary.Keys.AngularSeconds);
}
}
return (sec/60 + min)/60 + deg;
Added:
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/About.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/About.java?rev=1427049&view=auto
==============================================================================
--- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/About.java
(added)
+++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/About.java
Mon Dec 31 07:38:18 2012
@@ -0,0 +1,674 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.util;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+import java.util.EnumSet;
+import java.util.Map;
+import java.util.LinkedHashMap;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Date;
+import java.util.TimeZone;
+import java.util.MissingResourceException;
+import java.util.jar.Attributes;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+import java.io.Console;
+import java.io.File;
+import java.io.FileFilter;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.IOException;
+import java.text.Format;
+import java.text.DateFormat;
+import java.text.FieldPosition;
+import java.nio.charset.Charset;
+import org.apache.sis.util.logging.Logging;
+import org.apache.sis.util.resources.Errors;
+import org.apache.sis.util.resources.Vocabulary;
+import org.apache.sis.util.collection.TreeTable;
+import org.apache.sis.util.collection.TreeTables;
+import org.apache.sis.util.collection.DefaultTreeTable;
+
+import static java.lang.System.getProperty;
+import static org.apache.sis.util.collection.TableColumn.NAME;
+import static org.apache.sis.util.collection.TableColumn.VALUE_AS_TEXT;
+
+
+/**
+ * Provides information about the Apache SIS running environment.
+ * This class collects information from various places like {@link
Version#SIS},
+ * {@link System#getProperties()}, {@link Locale#getDefault()} or {@link
TimeZone#getDefault()}.
+ * This class does not collect every possible information. Instead, it tries
to focus on the most
+ * important information for SIS, as determined by experience in
troubleshooting.
+ * Some of those information are:
+ *
+ * <ul>
+ * <li>Version numbers (SIS, Java, Operation system).</li>
+ * <li>Default locale, timezone and character encoding.</li>
+ * <li>Current directory, user home and Java home.</li>
+ * <li>Libraries on the classpath and extension directories.</li>
+ * </ul>
+ *
+ * This class can be invoked from the command line.
+ * See the {@link #main(String[])} method for more information.
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @since 0.3
+ * @version 0.3
+ * @module
+ */
+public enum About {
+ /**
+ * Information about software version numbers.
+ * This section includes:
+ *
+ * <ul>
+ * <li>Apache SIS version</li>
+ * <li>Java runtime version and vendor</li>
+ * <li>Operation system name and version</li>
+ * </ul>
+ */
+ VERSIONS(Vocabulary.Keys.Versions),
+
+ /**
+ * Information about default locale, timezone and character encoding.
+ * This section includes:
+ *
+ * <ul>
+ * <li>Default locale, completed by ISO 3-letter codes</li>
+ * <li>Default timezone, completed by timezone offset</li>
+ * <li>Current date and time in the default timezone</li>
+ * <li>Default character encoding</li>
+ * </ul>
+ */
+ LOCALIZATION(Vocabulary.Keys.Localization),
+
+ /**
+ * Information about user home directory, java installation directory or
other kind of data.
+ * This section includes:
+ *
+ * <ul>
+ * <li>User directory</li>
+ * <li>Default directory</li>
+ * <li>Java home directory</li>
+ * </ul>
+ */
+ PATHS(Vocabulary.Keys.Paths),
+
+ /**
+ * Information about the libraries.
+ * This section includes:
+ *
+ * <ul>
+ * <li>JAR files in the extension directories</li>
+ * <li>JAR files and directories in the application classpath</li>
+ * </ul>
+ */
+ LIBRARIES(Vocabulary.Keys.Libraries);
+
+ /**
+ * The resource key for this section in the {@link Vocabulary} resources
bundle.
+ */
+ private final int resourceKey;
+
+ /**
+ * Creates a new section to be formatted using the given resource.
+ */
+ private About(final int resourceKey) {
+ this.resourceKey = resourceKey;
+ }
+
+ /**
+ * Prints the information to the standard output stream.
+ * This method can be invoked from the command-line as below (the "{@code
sis-utility}" file
+ * can be replaced by any SIS module, and its filename needs to be
completed with the actual
+ * version number):
+ *
+ * {@preformat java
+ * java -jar sis-utility.jar
+ * }
+ *
+ * By default this command prints all information except the {@link
#LIBRARIES} section,
+ * which is verbose. Available options are:
+ *
+ * <ul>
+ * <li>{@code --version}: prints only Apache SIS version number.</li>
+ * <li>{@code --verbose}: prints all information including the
libraries.</li>
+ * </ul>
+ *
+ * @param args Command-line options.
+ */
+ public static void main(final String[] args) {
+ final EnumSet<About> sections = EnumSet.allOf(About.class);
+ String configuration = null;
+ /*
+ * Command-line arguments processing.
+ */
+ if (args.length == 0) {
+ sections.remove(About.LIBRARIES);
+ } else {
+ final String arg = args[0];
+ if (arg.equals("--version")) {
+ configuration = "Apache SIS version " + Version.SIS;
+ } else if (!arg.equals("--verbose")) {
+
System.err.println(Errors.format(Errors.Keys.IllegalArgumentValue_2, 1, arg));
+ return;
+ }
+ if (args.length != 1) { // Checked only after we verified the
first argument.
+
System.err.println(Errors.format(Errors.Keys.IllegalArgumentValue_2, 2,
args[1]));
+ return;
+ }
+ }
+ /*
+ * Format the tree and write result to the console.
+ */
+ if (configuration == null) {
+ configuration = configuration(sections,
Locale.getDefault()).toString();
+ }
+ final Console console = System.console();
+ if (console != null) {
+ final PrintWriter out = console.writer();
+ out.write(configuration);
+ out.write(System.lineSeparator());
+ out.flush();
+ } else {
+ final PrintStream out = System.out;
+ out.println(configuration);
+ out.flush();
+ }
+ }
+
+ /**
+ * Returns all known information about the current Apache SIS running
environment.
+ *
+ * @param locale The locale to use for formatting the texts in the tree.
+ * @return Configuration information, as a tree for grouping some
configuration by sections.
+ */
+ public static TreeTable configuration(final Locale locale) {
+ return configuration(EnumSet.allOf(About.class), locale);
+ }
+
+ /**
+ * Returns a subset of the information about the current Apache SIS
running environment.
+ *
+ * @param sections The section for which information are desired.
+ * @param locale The locale to use for formatting the texts in the tree.
+ * @return Configuration information, as a tree for grouping some
configuration by sections.
+ */
+ public static TreeTable configuration(final Set<About> sections, final
Locale locale) {
+ ArgumentChecks.ensureNonNull("sections", sections);
+ ArgumentChecks.ensureNonNull("locale", locale);
+ String userHome = null;
+ String javaHome = null;
+ final Date now = new Date();
+ final Vocabulary resources = Vocabulary.getResources(locale);
+ final DefaultTreeTable table = new DefaultTreeTable(NAME,
VALUE_AS_TEXT);
+ final TreeTable.Node root = table.getRoot();
+ root.setValue(NAME,
resources.getString(Vocabulary.Keys.LocalConfiguration));
+ table.setRoot(root);
+ /*
+ * Begin with the "Versions" section. The 'newSection' variable will
be updated in the
+ * switch statement when new section will begin, and reset to 'null'
after the 'section'
+ * variable has been updated accordingly.
+ */
+ TreeTable.Node section = null;
+ About newSection = VERSIONS;
+fill: for (int i=0; ; i++) {
+ int nameKey = 0; // The Vocabulary.Key for 'name', used
only if name is null.
+ String name = null; // The value to put in the 'Name' column
of the table.
+ Object value = null; // The value to put in the 'Value'
column of the table.
+ String[] children = null; // Optional children to write below the
node.
+ switch (i) {
+ case 0: {
+ if (sections.contains(VERSIONS)) {
+ name = "Apache SIS";
+ value = Version.SIS;
+ }
+ break;
+ }
+ case 1: {
+ if (sections.contains(VERSIONS)) {
+ name = "Java";
+ value = concatenate(getProperty("java.version"),
getProperty("java.vendor"), true);
+ }
+ break;
+ }
+ case 2: {
+ if (sections.contains(VERSIONS)) {
+ nameKey = Vocabulary.Keys.OperatingSystem;
+ value = concatenate(concatenate(getProperty("os.name"),
+ getProperty("os.version"), false),
getProperty("os.arch"), true);
+ }
+ break;
+ }
+ case 3: {
+ newSection = LOCALIZATION;
+ if (sections.contains(LOCALIZATION)) {
+ final Locale current = Locale.getDefault();
+ if (current != null) {
+ nameKey = Vocabulary.Keys.Locale;
+ value = current.getDisplayName(locale);
+ final CharSequence code =
concatenate(getCode(locale, false), getCode(locale, true), true);
+ if (code != null) {
+ children = new String[]
{resources.getString(Vocabulary.Keys.Code_1, "ISO"), code.toString()};
+ }
+ }
+ }
+ break;
+ }
+ case 4: {
+ if (sections.contains(LOCALIZATION)) {
+ final TimeZone current = TimeZone.getDefault();
+ if (current != null) {
+ nameKey = Vocabulary.Keys.Timezone;
+ final boolean inDaylightTime =
current.inDaylightTime(now);
+ value =
concatenate(current.getDisplayName(inDaylightTime, TimeZone.LONG, locale),
current.getID(), true);
+ final DateFormat df =
DateFormat.getTimeInstance(DateFormat.SHORT, locale);
+ df.setTimeZone(TimeZone.getTimeZone("UTC"));
+ int offset = current.getOffset(now.getTime());
+ StringBuffer buffer = format(df, offset, new
StringBuffer("UTC "));
+ offset -= current.getRawOffset();
+ if (offset != 0) {
+ buffer = format(df, offset, buffer.append(" (")
+
.append(resources.getString(Vocabulary.Keys.DaylightTime)).append('
')).append(')');
+ }
+ children = new String[]
{resources.getString(Vocabulary.Keys.Offset), buffer.toString()};
+ }
+ }
+ break;
+ }
+ case 5: {
+ if (sections.contains(LOCALIZATION)) {
+ nameKey = Vocabulary.Keys.CurrentDateTime;
+ value =
DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG,
locale).format(now);
+ }
+ break;
+ }
+ case 6: {
+ if (sections.contains(LOCALIZATION)) {
+ final Charset current = Charset.defaultCharset();
+ if (current != null) {
+ nameKey = Vocabulary.Keys.CharacterEncoding;
+ value = current.displayName(locale);
+ final Set<String> aliases = current.aliases();
+ if (aliases != null && !aliases.isEmpty()) {
+ final StringBuilder buffer = new
StringBuilder((String) value);
+ String separator = " (";
+ for (final String alias : aliases) {
+ buffer.append(separator).append(alias);
+ separator = ", ";
+ }
+ value = buffer.append(')');
+ }
+ }
+ }
+ break;
+ }
+ case 7: {
+ newSection = PATHS;
+ if (sections.contains(PATHS)) {
+ nameKey = Vocabulary.Keys.UserHome;
+ value = userHome = getProperty("user.home");
+ }
+ break;
+ }
+ case 8: {
+ if (sections.contains(PATHS)) {
+ nameKey = Vocabulary.Keys.CurrentDirectory;
+ value = getProperty("user.dir");
+ }
+ break;
+ }
+ case 9: {
+ if (sections.contains(PATHS)) {
+ nameKey = Vocabulary.Keys.TemporaryFiles;
+ value = getProperty("java.io.tmpdir");
+ }
+ break;
+ }
+ case 10: {
+ if (sections.contains(PATHS)) {
+ nameKey = Vocabulary.Keys.JavaHome;
+ value = javaHome = getProperty("java.home");
+ }
+ break;
+ }
+ case 11: {
+ newSection = LIBRARIES;
+ if (sections.contains(LIBRARIES)) {
+ nameKey = Vocabulary.Keys.JavaExtensions;
+ value = classpath(getProperty("java.ext.dirs"), true);
+ }
+ break;
+ }
+ case 12: {
+ if (sections.contains(LIBRARIES)) {
+ nameKey = Vocabulary.Keys.Classpath;
+ value = classpath(getProperty("java.class.path"),
false);
+ }
+ break;
+ }
+ default: break fill;
+ }
+ /*
+ * At this point, we have the information about one node to create.
+ * If the 'newSection' variable is non-null, then this new node
shall
+ * appear in a new section.
+ */
+ if (value == null) {
+ continue;
+ }
+ if (newSection != null) {
+ section = root.newChild();
+ section.setValue(NAME,
resources.getString(newSection.resourceKey));
+ newSection = null;
+ }
+ if (name == null) {
+ name = resources.getString(nameKey);
+ }
+ final TreeTable.Node node = section.newChild();
+ node.setValue(NAME, name);
+ if (children != null) {
+ for (int j=0; j<children.length; j+=2) {
+ final String c = children[j+1];
+ if (c != null) {
+ final TreeTable.Node child = node.newChild();
+ child.setValue(NAME, children[j]);
+ child.setValue(VALUE_AS_TEXT, c);
+ }
+ }
+ }
+ if (!(value instanceof Map<?,?>)) {
+ node.setValue(VALUE_AS_TEXT, value.toString());
+ continue;
+ }
+ /*
+ * Special case for values of kind Map<File,String>.
+ * They are extension paths or application class paths.
+ */
+ @SuppressWarnings("unchecked")
+ final Map<File,String> paths = (Map<File,String>) value;
+pathTree: for (int j=0; ; j++) {
+ TreeTable.Node directory = null;
+ final String home;
+ final int homeKey;
+ switch (j) {
+ case 0: home = javaHome; homeKey =
Vocabulary.Keys.JavaHome; break;
+ case 1: home = userHome; homeKey =
Vocabulary.Keys.UserHome; break;
+ case 2: home = ""; homeKey = 0; directory = node;
break;
+ default: break pathTree;
+ }
+ if (home == null) {
+ // Should never happen since "user.home" and "java.home"
are
+ // standard properties of the Java platform, but let be
safe.
+ continue;
+ }
+ final File homeDirectory = home.isEmpty() ? null : new
File(home);
+ for (final Iterator<Map.Entry<File,String>>
it=paths.entrySet().iterator(); it.hasNext();) {
+ final Map.Entry<File,String> entry = it.next();
+ File file = entry.getKey();
+ if (homeDirectory != null) {
+ file = relativize(homeDirectory, file);
+ if (file == null) continue;
+ }
+ if (directory == null) {
+ directory = node.newChild();
+ directory.setValue(NAME,
parenthesis(resources.getString(homeKey)));
+ }
+ CharSequence description = entry.getValue();
+ if (description == null) {
+ description =
parenthesis(resources.getString(entry.getKey().isDirectory() ?
+ Vocabulary.Keys.Directory :
Vocabulary.Keys.Untitled).toLowerCase(locale));
+ }
+ TreeTables.nodeForPath(directory, NAME,
file).setValue(VALUE_AS_TEXT, description);
+ it.remove();
+ }
+ if (directory != null) {
+ concatenateSingletons(directory, true);
+ omitMavenRedundancy(directory);
+ }
+ }
+ }
+ TreeTables.valuesAsStrings(table, locale);
+ return table;
+ }
+
+ /**
+ * Returns a map of all JAR files or class directories found in the given
paths,
+ * associated to a description obtained from their {@code
META-INF/MANIFEST.MF}.
+ *
+ * @param paths The paths, separated by {@link File#pathSeparatorChar}.
+ * @param asDirectories {@code true} if the paths shall contain
directories,
+ * or {@code false} if it shall contain JAR files.
+ */
+ private static Map<File,CharSequence> classpath(final String paths, final
boolean asDirectories) {
+ if (paths == null) {
+ return null;
+ }
+ final Map<File,CharSequence> files = new LinkedHashMap<>();
+ for (final CharSequence path : CharSequences.split(paths,
File.pathSeparatorChar)) {
+ final File file = new File(path.toString());
+ if (file.exists()) {
+ if (!asDirectories) {
+ files.put(file, null);
+ } else {
+ // If we are scanning extensions, then the path are
directories
+ // rather than files. So we need to scan the directory
content.
+ final JARFilter filter = new JARFilter();
+ final File[] list = file.listFiles(filter);
+ if (list != null) {
+ Arrays.sort(list);
+ for (final File ext : list) {
+ files.put(ext, null);
+ }
+ }
+ }
+ }
+ }
+ /*
+ * At this point, we have collected all JAR files.
+ * Now set the description from the MANIFEST.MF file.
+ */
+ IOException error = null;
+ for (final Map.Entry<File,CharSequence> entry : files.entrySet()) {
+ final File file = entry.getKey();
+ if (file.isFile()) {
+ CharSequence name = null;
+ try (final JarFile jar = new JarFile(file)) {
+ final Manifest manifest = jar.getManifest();
+ if (manifest != null) {
+ final Attributes attributes =
manifest.getMainAttributes();
+ if (attributes != null) {
+ name =
concatenate(attributes.getValue(Attributes.Name.IMPLEMENTATION_TITLE),
+
attributes.getValue(Attributes.Name.IMPLEMENTATION_VERSION), false);
+ if (name == null) {
+ name =
concatenate(attributes.getValue(Attributes.Name.SPECIFICATION_TITLE),
+
attributes.getValue(Attributes.Name.SPECIFICATION_VERSION), false);
+ }
+ }
+ }
+ } catch (IOException e) {
+ if (error == null) {
+ error = e;
+ } else {
+ error.addSuppressed(e);
+ }
+ continue;
+ }
+ entry.setValue(name);
+ }
+ }
+ if (error != null) {
+ Logging.unexpectedException(About.class, "configuration", error);
+ }
+ return files;
+ }
+
+ /**
+ * If a file path in the given node or any children follow the Maven
pattern, remove the
+ * artefact name and version numbers redundancies in order to make the
name more compact.
+ * For example this method replaces {@code
"org/opengis/geoapi/3.0.0/geoapi-3.0.0.jar"}
+ * by {@code "org/opengis/(â¦)/geoapi-3.0.0.jar"}.
+ */
+ private static void omitMavenRedundancy(final TreeTable.Node node) {
+ for (final TreeTable.Node child : node.getChildren()) {
+ omitMavenRedundancy(child);
+ }
+ final CharSequence name = node.getValue(NAME);
+ final int length = name.length();
+ final int s2 = CharSequences.lastIndexOf(name, File.separatorChar, 0,
length);
+ if (s2 >= 0) {
+ final int s1 = CharSequences.lastIndexOf(name, File.separatorChar,
0, s2);
+ if (s1 >= 0) {
+ final int s0 = CharSequences.lastIndexOf(name,
File.separatorChar, 0, s1) + 1;
+ final StringBuilder buffer = new StringBuilder(s2 -
s0).append(name, s0, s2);
+ buffer.setCharAt(s1-s0, '-');
+ if (CharSequences.regionMatches(name, s2+1, buffer)) {
+ buffer.setLength(0);
+ node.setValue(NAME, buffer.append(name, 0,
s0).append("(â¦)").append(name, s2, length));
+ }
+ }
+ }
+ }
+
+ /**
+ * For every branch containing only one child and no value, merges
in-place that branch and the
+ * node together. This method is used for simplifying depth trees into
something less verbose.
+ * However for any column other than {@code NAME}, this method preserves
the values of the child
+ * node but lost all value of the parent node. For this reason, we perform
the merge only if the
+ * parent has no value.
+ *
+ * <p>See the "<cite>Reduce the depth of a tree</cite>" example in {@link
TreeTables}
+ * for more information.</p>
+ *
+ * @param node The root of the node to simplify.
+ * @param skip {@code true} for disabling concatenation of root node.
+ * @return The root of the simplified tree. May be the given {@code node}
or a child.
+ */
+ private static TreeTable.Node concatenateSingletons(final TreeTable.Node
node, final boolean skip) {
+ final List<TreeTable.Node> children = node.getChildren();
+ final int size = children.size();
+ for (int i=0; i<size; i++) {
+ children.set(i, concatenateSingletons(children.get(i), false));
+ }
+ if (!skip && size == 1) {
+ if (node.getValue(VALUE_AS_TEXT) == null) {
+ final TreeTable.Node child = children.remove(0);
+ final StringBuilder name = new
StringBuilder(node.getValue(NAME));
+ if (!File.separator.contentEquals(name)) {
+ name.append(File.separatorChar);
+ }
+ child.setValue(NAME, name.append(child.getValue(NAME)));
+ return child;
+ }
+ }
+ return node;
+ }
+
+ /**
+ * Concatenates the given strings in the format "main (complement)".
+ * Any of the given strings can be null.
+ *
+ * @param main The main string to show first.
+ * @param complement The string to show after the main one.
+ * @param parenthesis {@code true} for writing the complement between
parenthesis.
+ */
+ private static CharSequence concatenate(final CharSequence main, final
CharSequence complement, final boolean parenthesis) {
+ if (main != null && main.length() != 0) {
+ if (complement != null && complement.length() != 0) {
+ final StringBuilder buffer = (main instanceof StringBuilder)
+ ? (StringBuilder) main : new StringBuilder(main);
+ buffer.append(' ');
+ if (parenthesis) buffer.append('(');
+ buffer.append(complement);
+ if (parenthesis) buffer.append(')');
+ return buffer;
+ }
+ return main;
+ }
+ return complement;
+ }
+
+ /**
+ * Returns the given text between parenthesis.
+ */
+ private static CharSequence parenthesis(final String text) {
+ return new StringBuilder(text.length() +
2).append('(').append(text).append(')');
+ }
+
+ /**
+ * Returns the ISO language or country code for the given locale.
+ */
+ private static String getCode(final Locale locale, final boolean country) {
+ try {
+ return country ? locale.getISO3Country() :
locale.getISO3Language();
+ } catch (MissingResourceException e) {
+ Logging.recoverableException(About.class, "configuration", e);
+ return null;
+ }
+ }
+
+ /**
+ * Formats the given value preceded by a plus or minus sign.
+ * This method is used for formatting timezone offset.
+ *
+ * @param df The {@link DateFormat} to use for formatting the offset.
+ * @param offset The offset to format, as a positive or negative value.
+ * @param buffer The buffer where to format the offset.
+ * @return The given buffer, returned for convenience.
+ */
+ private static StringBuffer format(final Format df, final int offset,
final StringBuffer buffer) {
+ return df.format(Math.abs(offset), buffer.append(offset < 0 ? '-' :
'+').append(' '), new FieldPosition(0));
+ }
+
+ /**
+ * Filters the JAR files in an extension directory.
+ */
+ private static final class JARFilter implements FileFilter {
+ @Override public boolean accept(final File pathname) {
+ return pathname.getName().endsWith(".jar");
+ }
+ }
+
+ /**
+ * Returns the given file relative to the given root, or {@code null} if
the root is not
+ * a parent of that file.
+ *
+ * @param root The root directory (typically Java home or user home
directory).
+ * @param file The file to make relative to the root.
+ * @return The file relative to the given root, or {@code null} if none.
+ */
+ private static File relativize(final File root, final File file) {
+ File parent = file.getParentFile();
+ if (parent == null) {
+ return null;
+ }
+ if (root.equals(parent)) {
+ parent = null;
+ } else {
+ parent = relativize(root, parent);
+ if (parent == null) {
+ return null;
+ }
+ }
+ return new File(parent, file.getName());
+ }
+}
Propchange:
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/About.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/About.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified:
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java?rev=1427049&r1=1427048&r2=1427049&view=diff
==============================================================================
---
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java
(original)
+++
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java
Mon Dec 31 07:38:18 2012
@@ -61,7 +61,82 @@ public final class Vocabulary extends In
/**
* Degrees
*/
- public static final int Degrees = 10;
+ public static final int AngularDegrees = 10;
+
+ /**
+ * Minutes
+ */
+ public static final int AngularMinutes = 11;
+
+ /**
+ * Seconds
+ */
+ public static final int AngularSeconds = 12;
+
+ /**
+ * Character encoding
+ */
+ public static final int CharacterEncoding = 17;
+
+ /**
+ * Classpath
+ */
+ public static final int Classpath = 29;
+
+ /**
+ * {0} code
+ */
+ public static final int Code_1 = 21;
+
+ /**
+ * Current date and time
+ */
+ public static final int CurrentDateTime = 25;
+
+ /**
+ * Current directory
+ */
+ public static final int CurrentDirectory = 33;
+
+ /**
+ * Daylight time
+ */
+ public static final int DaylightTime = 24;
+
+ /**
+ * Directory
+ */
+ public static final int Directory = 36;
+
+ /**
+ * Java extensions
+ */
+ public static final int JavaExtensions = 26;
+
+ /**
+ * Java home directory
+ */
+ public static final int JavaHome = 30;
+
+ /**
+ * Libraries
+ */
+ public static final int Libraries = 35;
+
+ /**
+ * Local configuration
+ */
+ public static final int LocalConfiguration = 14;
+
+ /**
+ * Locale
+ */
+ public static final int Locale = 18;
+
+ /**
+ * Localization
+ */
+ public static final int Localization = 19;
/**
* Maximum value
@@ -79,11 +154,6 @@ public final class Vocabulary extends In
public static final int MinimumValue = 4;
/**
- * Minutes
- */
- public static final int Minutes = 11;
-
- /**
* Name
*/
public static final int Name = 0;
@@ -99,14 +169,39 @@ public final class Vocabulary extends In
public static final int NumberOfValues = 2;
/**
+ * Offset
+ */
+ public static final int Offset = 22;
+
+ /**
+ * Operating system
+ */
+ public static final int OperatingSystem = 16;
+
+ /**
+ * Others
+ */
+ public static final int Others = 34;
+
+ /**
+ * Paths
+ */
+ public static final int Paths = 27;
+
+ /**
+ * Root
+ */
+ public static final int Root = 28;
+
+ /**
* Root Mean Square
*/
public static final int RootMeanSquare = 7;
/**
- * Seconds
+ * Scale
*/
- public static final int Seconds = 12;
+ public static final int Scale = 23;
/**
* Standard deviation
@@ -114,9 +209,39 @@ public final class Vocabulary extends In
public static final int StandardDeviation = 8;
/**
+ * Temporary files
+ */
+ public static final int TemporaryFiles = 31;
+
+ /**
+ * Timezone
+ */
+ public static final int Timezone = 20;
+
+ /**
* Type
*/
public static final int Type = 1;
+
+ /**
+ * Untitled
+ */
+ public static final int Untitled = 37;
+
+ /**
+ * User home directory
+ */
+ public static final int UserHome = 32;
+
+ /**
+ * Value
+ */
+ public static final int Value = 13;
+
+ /**
+ * Versions
+ */
+ public static final int Versions = 15;
}
/**
Modified:
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties?rev=1427049&r1=1427048&r2=1427049&view=diff
==============================================================================
---
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties
(original)
+++
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties
Mon Dec 31 07:38:18 2012
@@ -14,16 +14,41 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
-Angle = Angle
-Degrees = Degrees
-MaximumValue = Maximum value
-MeanValue = Mean value
-MinimumValue = Minimum value
-Minutes = Minutes
-Name = Name
-NumberOfValues = Number of values
-NumberOfNaN = Number of \u2018NaN\u2019
-RootMeanSquare = Root Mean Square
-Seconds = Seconds
-StandardDeviation = Standard deviation
-Type = Type
+Angle = Angle
+AngularDegrees = Degrees
+AngularMinutes = Minutes
+AngularSeconds = Seconds
+CharacterEncoding = Character encoding
+Classpath = Classpath
+Code_1 = {0} code
+CurrentDateTime = Current date and time
+CurrentDirectory = Current directory
+DaylightTime = Daylight time
+Directory = Directory
+JavaExtensions = Java extensions
+JavaHome = Java home directory
+Libraries = Libraries
+LocalConfiguration = Local configuration
+Locale = Locale
+Localization = Localization
+MaximumValue = Maximum value
+MeanValue = Mean value
+MinimumValue = Minimum value
+Name = Name
+NumberOfValues = Number of values
+NumberOfNaN = Number of \u2018NaN\u2019
+Offset = Offset
+OperatingSystem = Operating system
+Others = Others
+Paths = Paths
+Root = Root
+RootMeanSquare = Root Mean Square
+Scale = Scale
+StandardDeviation = Standard deviation
+TemporaryFiles = Temporary files
+Timezone = Timezone
+Type = Type
+Untitled = Untitled
+UserHome = User home directory
+Value = Value
+Versions = Versions
Modified:
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties?rev=1427049&r1=1427048&r2=1427049&view=diff
==============================================================================
---
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties
(original)
+++
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties
Mon Dec 31 07:38:18 2012
@@ -14,16 +14,41 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
-Angle = Angle
-Degrees = Degr\u00e9s
-MaximumValue = Valeur maximale
-MeanValue = Valeur moyenne
-MinimumValue = Valeur minimale
-Minutes = Minutes
-Name = Nom
-NumberOfValues = Nombre de valeurs
-NumberOfNaN = Nombre de \u2018NaN\u2019
-RootMeanSquare = Moyenne quadratique
-Seconds = Secondes
-StandardDeviation = \u00c9cart type
-Type = Type
+Angle = Angle
+AngularDegrees = Degr\u00e9s
+AngularMinutes = Minutes
+AngularSeconds = Secondes
+CharacterEncoding = Encodage des caract\u00e8res
+Classpath = Chemin de classes
+Code_1 = Code {0}
+CurrentDateTime = Date et heure courantes
+CurrentDirectory = R\u00e9pertoire courant
+DaylightTime = Heure normale
+Directory = R\u00e9pertoire
+JavaExtensions = Extensions du Java
+JavaHome = R\u00e9pertoire du Java
+Libraries = Biblioth\u00e8ques
+LocalConfiguration = Configuration locale
+Locale = Locale
+Localization = R\u00e9gionalisation
+MaximumValue = Valeur maximale
+MeanValue = Valeur moyenne
+MinimumValue = Valeur minimale
+Name = Nom
+NumberOfValues = Nombre de valeurs
+NumberOfNaN = Nombre de \u2018NaN\u2019
+Offset = D\u00e9calage
+OperatingSystem = Syst\u00e8me d'exploitation
+Others = Autres
+Paths = Chemins
+Root = Racine
+RootMeanSquare = Moyenne quadratique
+Scale = \u00c9chelle
+StandardDeviation = \u00c9cart type
+TemporaryFiles = Fichiers temporaires
+Timezone = Fuseau horaire
+Type = Type
+Untitled = Sans titre
+UserHome = R\u00e9pertoire de l'utilisateur
+Value = Valeur
+Versions = Versions
Modified:
sis/branches/JDK7/sis-utility/src/main/resources/org/apache/sis/internal/util/Descriptions.properties
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/resources/org/apache/sis/internal/util/Descriptions.properties?rev=1427049&r1=1427048&r2=1427049&view=diff
==============================================================================
---
sis/branches/JDK7/sis-utility/src/main/resources/org/apache/sis/internal/util/Descriptions.properties
(original)
+++
sis/branches/JDK7/sis-utility/src/main/resources/org/apache/sis/internal/util/Descriptions.properties
Mon Dec 31 07:38:18 2012
@@ -1,5 +1,6 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.
-supervisor = Provides information about the state of a running Apache SIS
library.
-org.apache.sis.internal.util.Supervisor = Creates a new supervisor.
-locale = The language of supervisor messages.
-warnings = List of problems detected in the running Apache SIS library. If
this list contains any item, then an application reboot is strongly recommended.
+supervisor=Provides information about the state of a running Apache SIS
library.
+org.apache.sis.internal.util.Supervisor=Creates a new supervisor.
+locale=The language of supervisor messages.
+configuration=Tree of information about the Apache SIS running environment.
+warnings=List of problems detected in the running Apache SIS library. If this
list contains any item, then an application reboot is strongly recommended.
Modified:
sis/branches/JDK7/sis-utility/src/main/resources/org/apache/sis/internal/util/Descriptions_fr.properties
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/resources/org/apache/sis/internal/util/Descriptions_fr.properties?rev=1427049&r1=1427048&r2=1427049&view=diff
==============================================================================
---
sis/branches/JDK7/sis-utility/src/main/resources/org/apache/sis/internal/util/Descriptions_fr.properties
(original)
+++
sis/branches/JDK7/sis-utility/src/main/resources/org/apache/sis/internal/util/Descriptions_fr.properties
Mon Dec 31 07:38:18 2012
@@ -1,5 +1,6 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.
-supervisor = Fournit des informations \u00e0 propos de l\u2019\u00e9tat
d\u2019une biblioth\u00e8que Apache SIS en cours d\u2019ex\u00e9cution.
-org.apache.sis.internal.util.Supervisor = Construit un nouveau superviseur.
-locale = La langue des messages produits par le superviseur.
-warnings = Liste des probl\u00e8mes d\u00e9tect\u00e9s dans la
biblioth\u00e8que Apache SIS en cours d\u2019ex\u00e9cution. Si cette liste
contient des items, alors un red\u00e9marrage de l\u2019application est
fortement recommand\u00e9.
+supervisor=Fournit des informations \u00e0 propos de l\u2019\u00e9tat
d\u2019une biblioth\u00e8que Apache SIS en cours d\u2019ex\u00e9cution.
+org.apache.sis.internal.util.Supervisor=Construit un nouveau superviseur.
+locale=La langue des messages produits par le superviseur.
+configuration=Arborescence d'information concernant l\u2019environnement
d\u2019ex\u00e9cution de Apache SIS.
+warnings=Liste des probl\u00e8mes d\u00e9tect\u00e9s dans la biblioth\u00e8que
Apache SIS en cours d\u2019ex\u00e9cution. Si cette liste contient des items,
alors un red\u00e9marrage de l\u2019application est fortement recommand\u00e9.
Modified:
sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java?rev=1427049&r1=1427048&r2=1427049&view=diff
==============================================================================
---
sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java
(original)
+++
sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java
Mon Dec 31 07:38:18 2012
@@ -57,6 +57,7 @@ import org.junit.runners.Suite;
org.apache.sis.util.collection.DerivedMapTest.class,
org.apache.sis.util.collection.TableColumnTest.class,
org.apache.sis.util.collection.DefaultTreeTableTest.class,
+ org.apache.sis.util.collection.TreeTablesTest.class,
// GeoAPI most basic types.
org.apache.sis.util.iso.TypesTest.class,