embulk 0.6.2 → 0.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/bin/embulk +2 -2
- data/build.gradle +11 -2
- data/embulk-cli/src/main/java/org/embulk/cli/Main.java +0 -2
- data/embulk-core/build.gradle +1 -1
- data/embulk-core/src/main/java/org/embulk/command/Runner.java +10 -0
- data/embulk-core/src/main/java/org/embulk/exec/GuessExecutor.java +3 -2
- data/embulk-core/src/main/java/org/embulk/exec/PreviewExecutor.java +1 -1
- data/embulk-core/src/main/java/org/embulk/jruby/JRubyScriptingModule.java +18 -6
- data/embulk-core/src/main/java/org/embulk/plugin/PluginManager.java +14 -11
- data/embulk-core/src/main/java/org/embulk/spi/Column.java +5 -5
- data/embulk-core/src/main/java/org/embulk/spi/ColumnConfig.java +4 -4
- data/embulk-core/src/main/java/org/embulk/spi/Exec.java +6 -0
- data/embulk-core/src/main/java/org/embulk/spi/FileInputRunner.java +1 -1
- data/embulk-core/src/main/java/org/embulk/spi/Schema.java +2 -2
- data/embulk-core/src/main/java/org/embulk/spi/SchemaConfig.java +2 -2
- data/embulk-core/src/main/java/org/embulk/spi/unit/ByteSize.java +148 -0
- data/embulk-core/src/test/java/org/embulk/spi/unit/TestByteSize.java +79 -0
- data/embulk-docs/build.gradle +5 -1
- data/embulk-docs/src/customization.rst +184 -0
- data/embulk-docs/src/index.rst +10 -1
- data/embulk-docs/src/release.rst +1 -0
- data/embulk-docs/src/release/release-0.6.3.rst +23 -0
- data/lib/embulk/command/embulk_run.rb +41 -3
- data/lib/embulk/data/new/gitignore.erb +1 -0
- data/lib/embulk/data/new/java/build.gradle.erb +20 -4
- data/lib/embulk/java/bootstrap.rb +2 -2
- data/lib/embulk/plugin.rb +1 -1
- data/lib/embulk/version.rb +1 -1
- data/test/helper.rb +7 -0
- metadata +8 -6
- data/embulk-docs/plugins/index.html.erb +0 -73
- data/embulk-docs/plugins/plugins.css +0 -148
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b37c9dd1d3a700e0057040d27f0a29e917e21b13
|
4
|
+
data.tar.gz: 3372de3c3f382dc6f83bea6936d84af3b815194c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7d0c416b6c063508b95d23941c5cf97149bcf6fd11134392f79d0d7540f106df019e502fc7296ba47a94a945a64c8b34a4d4aaf682227d390300592d598c0f1a
|
7
|
+
data.tar.gz: b370deb8322442973cc3109ca2a0b8eb3931d11840f55e7d230f56c10de45c93a71d39cb892dad491ef67870c9e77932fabee4d82cf99ea601ba3417ea3e7cc8
|
data/.travis.yml
CHANGED
data/bin/embulk
CHANGED
@@ -69,9 +69,9 @@ unless jruby_complete
|
|
69
69
|
end
|
70
70
|
|
71
71
|
if overwrite_optimize == true || (default_optimize == true && overwrite_optimize != false)
|
72
|
-
|
72
|
+
java_args = %w[-XX:+AggressiveOpts -XX:+UseConcMarkSweepGC] + java_args
|
73
73
|
else
|
74
|
-
|
74
|
+
java_args = %w[-XX:+AggressiveOpts -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -Xverify:none] + java_args
|
75
75
|
end
|
76
76
|
|
77
77
|
# java ... -jar ruby-complete.jar $EMBULK_HOME/lib/embulk/command/embulk.rb "$@"
|
data/build.gradle
CHANGED
@@ -5,14 +5,17 @@ plugins {
|
|
5
5
|
id 'com.github.jruby-gradle.base' version '0.1.5'
|
6
6
|
id 'com.github.johnrengelman.shadow' version '1.2.0'
|
7
7
|
}
|
8
|
-
import com.github.jrubygradle.JRubyExec
|
9
8
|
|
10
9
|
def java_projects = [project(":embulk-core"), project(":embulk-standards"), project(":embulk-cli")]
|
11
10
|
def release_projects = [project(":embulk-core"), project(":embulk-standards")]
|
12
11
|
|
13
12
|
allprojects {
|
14
13
|
group = 'org.embulk'
|
15
|
-
version = '0.6.
|
14
|
+
version = '0.6.3'
|
15
|
+
|
16
|
+
ext {
|
17
|
+
jrubyVersion = '1.7.19'
|
18
|
+
}
|
16
19
|
|
17
20
|
apply plugin: 'java'
|
18
21
|
apply plugin: 'maven-publish'
|
@@ -137,6 +140,11 @@ subprojects {
|
|
137
140
|
}
|
138
141
|
}
|
139
142
|
|
143
|
+
import com.github.jrubygradle.JRubyExec
|
144
|
+
jruby {
|
145
|
+
execVersion = project.jrubyVersion
|
146
|
+
}
|
147
|
+
|
140
148
|
dependencies {
|
141
149
|
jrubyExec 'rubygems:test-unit:3.0.+'
|
142
150
|
}
|
@@ -187,6 +195,7 @@ task rubyTest(type: JRubyExec) {
|
|
187
195
|
jrubyArgs '-Ilib', '-Itest', '-rtest/unit', '-eTest::Unit::AutoRunner.run(true, *ARGV)'
|
188
196
|
script 'test'
|
189
197
|
}
|
198
|
+
rubyTest.dependsOn('classpath')
|
190
199
|
|
191
200
|
//
|
192
201
|
// gem task
|
@@ -4,8 +4,6 @@ public class Main
|
|
4
4
|
{
|
5
5
|
public static void main(String[] args)
|
6
6
|
{
|
7
|
-
// TODO set GEM_HOME to point the internal gem repository created by gem-maven-plugin?
|
8
|
-
|
9
7
|
// $ java -jar jruby-complete.jar classpath:embulk/command/embulk.rb "$@"
|
10
8
|
String[] jrubyArgs = new String[args.length + 1];
|
11
9
|
jrubyArgs[0] = "classpath:embulk/command/embulk.rb";
|
data/embulk-core/build.gradle
CHANGED
@@ -27,7 +27,7 @@ dependencies {
|
|
27
27
|
compile 'log4j:log4j:1.2.17'
|
28
28
|
compile 'org.slf4j:slf4j-api:1.7.10'
|
29
29
|
compile 'org.slf4j:slf4j-log4j12:1.7.10'
|
30
|
-
compile 'org.jruby:jruby-complete:
|
30
|
+
compile 'org.jruby:jruby-complete:' + project.jrubyVersion
|
31
31
|
compile 'com.google.code.findbugs:annotations:3.0.0'
|
32
32
|
compile 'org.yaml:snakeyaml:1.14'
|
33
33
|
compile 'javax.validation:validation-api:1.1.0.Final'
|
@@ -50,6 +50,9 @@ public class Runner
|
|
50
50
|
|
51
51
|
private List<PluginType> guessPlugins;
|
52
52
|
public List<PluginType> getGuessPlugins() { return guessPlugins; }
|
53
|
+
|
54
|
+
private boolean useGlobalRubyRuntime;
|
55
|
+
public boolean getUseGlobalRubyRuntime() { return useGlobalRubyRuntime; }
|
53
56
|
}
|
54
57
|
|
55
58
|
private final Options options;
|
@@ -72,16 +75,23 @@ public class Runner
|
|
72
75
|
{
|
73
76
|
String logLevel = options.getLogLevel();
|
74
77
|
if (logLevel != null) {
|
78
|
+
// used by LoggerProvider
|
75
79
|
systemConfig.set("log_level", logLevel);
|
76
80
|
}
|
77
81
|
|
78
82
|
List<PluginType> guessPlugins = options.getGuessPlugins();
|
79
83
|
if (guessPlugins != null && !guessPlugins.isEmpty()) {
|
84
|
+
// used by GuessExecutor
|
80
85
|
List<PluginType> list = new ArrayList<PluginType>() { };
|
81
86
|
list = systemConfig.get((Class<List<PluginType>>) list.getClass(), "guess_plugins", list);
|
82
87
|
list.addAll(guessPlugins);
|
83
88
|
systemConfig.set("guess_plugins", list);
|
84
89
|
}
|
90
|
+
|
91
|
+
if (options.getUseGlobalRubyRuntime()) {
|
92
|
+
// used by JRubyScriptingModule
|
93
|
+
systemConfig.set("use_global_ruby_runtime", true);
|
94
|
+
}
|
85
95
|
}
|
86
96
|
|
87
97
|
public void main(String command, String[] args)
|
@@ -3,6 +3,7 @@ package org.embulk.exec;
|
|
3
3
|
import java.util.List;
|
4
4
|
import java.util.Set;
|
5
5
|
import java.util.ArrayList;
|
6
|
+
import java.util.concurrent.ExecutionException;
|
6
7
|
import com.google.common.collect.ImmutableList;
|
7
8
|
import com.google.common.base.Throwables;
|
8
9
|
import com.google.inject.Inject;
|
@@ -87,8 +88,8 @@ public class GuessExecutor
|
|
87
88
|
}
|
88
89
|
}
|
89
90
|
});
|
90
|
-
} catch (
|
91
|
-
throw Throwables.propagate(ex);
|
91
|
+
} catch (ExecutionException ex) {
|
92
|
+
throw Throwables.propagate(ex.getCause());
|
92
93
|
}
|
93
94
|
}
|
94
95
|
|
@@ -16,10 +16,12 @@ import com.google.inject.Key;
|
|
16
16
|
import com.google.inject.spi.Dependency;
|
17
17
|
import com.google.inject.spi.ProviderWithDependencies;
|
18
18
|
import org.jruby.CompatVersion;
|
19
|
+
import org.jruby.embed.LocalContextScope;
|
19
20
|
import org.jruby.embed.ScriptingContainer;
|
20
21
|
import org.embulk.plugin.PluginSource;
|
21
22
|
import org.embulk.config.ConfigSource;
|
22
23
|
import org.embulk.config.ModelManager;
|
24
|
+
import org.embulk.exec.ForSystemConfig;
|
23
25
|
import org.embulk.spi.BufferAllocator;
|
24
26
|
|
25
27
|
public class JRubyScriptingModule
|
@@ -27,15 +29,12 @@ public class JRubyScriptingModule
|
|
27
29
|
{
|
28
30
|
public JRubyScriptingModule(ConfigSource systemConfig)
|
29
31
|
{
|
30
|
-
// TODO get jruby-home from systemConfig to call jruby.container.setHomeDirectory
|
31
|
-
// TODO get jruby-load-paths from systemConfig to call jruby.container.setLoadPaths
|
32
32
|
}
|
33
33
|
|
34
34
|
@Override
|
35
35
|
public void configure(Binder binder)
|
36
36
|
{
|
37
37
|
binder.bind(ScriptingContainer.class).toProvider(ScriptingContainerProvider.class).in(Scopes.SINGLETON);
|
38
|
-
//binder.bind(JRubyModule.class).in(Scopes.SINGLETON);
|
39
38
|
|
40
39
|
Multibinder<PluginSource> multibinder = Multibinder.newSetBinder(binder, PluginSource.class);
|
41
40
|
multibinder.addBinding().to(JRubyPluginSource.class);
|
@@ -45,16 +44,25 @@ public class JRubyScriptingModule
|
|
45
44
|
implements ProviderWithDependencies<ScriptingContainer>
|
46
45
|
{
|
47
46
|
private final Injector injector;
|
47
|
+
private final boolean useGlobalRubyRuntime;
|
48
48
|
|
49
49
|
@Inject
|
50
|
-
public ScriptingContainerProvider(Injector injector)
|
50
|
+
public ScriptingContainerProvider(Injector injector, @ForSystemConfig ConfigSource systemConfig)
|
51
51
|
{
|
52
52
|
this.injector = injector;
|
53
|
+
|
54
|
+
// use_global_ruby_runtime is valid only when it's guaranteed that just one Injector is
|
55
|
+
// instantiated in this JVM.
|
56
|
+
this.useGlobalRubyRuntime = systemConfig.get(boolean.class, "use_global_ruby_runtime", false);
|
57
|
+
|
58
|
+
// TODO get jruby-home from systemConfig to call jruby.container.setHomeDirectory
|
59
|
+
// TODO get jruby-load-paths from systemConfig to call jruby.container.setLoadPaths
|
53
60
|
}
|
54
61
|
|
55
62
|
public ScriptingContainer get()
|
56
63
|
{
|
57
|
-
|
64
|
+
LocalContextScope scope = (useGlobalRubyRuntime ? LocalContextScope.SINGLETON : LocalContextScope.SINGLETHREAD);
|
65
|
+
ScriptingContainer jruby = new ScriptingContainer(scope);
|
58
66
|
jruby.setCompatVersion(CompatVersion.RUBY1_9);
|
59
67
|
|
60
68
|
// Search embulk/java/bootstrap.rb from a $LOAD_PATH.
|
@@ -72,9 +80,13 @@ public class JRubyScriptingModule
|
|
72
80
|
// jruby searches embulk/java/bootstrap.rb from the beginning of $LOAD_PATH.
|
73
81
|
jruby.runScriptlet("require 'embulk/java/bootstrap'");
|
74
82
|
|
83
|
+
// TODO validate Embulk::Java::Injected::Injector doesn't exist? If it already exists,
|
84
|
+
// Injector is created more than once in this JVM although use_global_ruby_runtime
|
85
|
+
// is set to true.
|
86
|
+
|
75
87
|
// set some constants
|
76
88
|
jruby.callMethod(
|
77
|
-
jruby.runScriptlet("Embulk::Java"),
|
89
|
+
jruby.runScriptlet("Embulk::Java::Injected"),
|
78
90
|
"const_set", "Injector", injector);
|
79
91
|
jruby.callMethod(
|
80
92
|
jruby.runScriptlet("Embulk::Java::Injected"),
|
@@ -13,7 +13,7 @@ public class PluginManager
|
|
13
13
|
private final List<PluginSource> sources;
|
14
14
|
private final Injector injector;
|
15
15
|
|
16
|
-
// Set<PluginSource> is injected BuiltinPluginSourceModule or extensions
|
16
|
+
// Set<PluginSource> is injected by BuiltinPluginSourceModule or extensions
|
17
17
|
// using Multibinder<PluginSource>.
|
18
18
|
@Inject
|
19
19
|
public PluginManager(Set<PluginSource> pluginSources, Injector injector)
|
@@ -32,31 +32,34 @@ public class PluginManager
|
|
32
32
|
throw new ConfigException(String.format("%s type is not set (if you intend to use NullOutputPlugin, you should enclose null in quotes such as {type: \"null\"}.", iface.getSimpleName()));
|
33
33
|
}
|
34
34
|
|
35
|
-
List<
|
35
|
+
List<PluginSourceNotMatchException> exceptions = new ArrayList<>();
|
36
36
|
for (PluginSource source : sources) {
|
37
37
|
try {
|
38
38
|
return source.newPlugin(iface, type);
|
39
39
|
} catch (PluginSourceNotMatchException e) {
|
40
|
-
|
41
|
-
causes.add(e.getCause());
|
42
|
-
} else {
|
43
|
-
causes.add(e);
|
44
|
-
}
|
40
|
+
exceptions.add(e);
|
45
41
|
}
|
46
42
|
}
|
47
43
|
|
44
|
+
throw buildPluginNotFoundException(iface, type, exceptions);
|
45
|
+
}
|
46
|
+
|
47
|
+
private static ConfigException buildPluginNotFoundException(Class<?> iface, PluginType type,
|
48
|
+
List<PluginSourceNotMatchException> exceptions)
|
49
|
+
{
|
48
50
|
StringBuilder message = new StringBuilder();
|
49
51
|
message.append(String.format("%s '%s' is not found.", iface.getSimpleName(), type.getName()));
|
50
|
-
for (
|
52
|
+
for (PluginSourceNotMatchException exception : exceptions) {
|
53
|
+
Throwable cause = (exception.getCause() == null ? exception : exception.getCause());
|
51
54
|
if (cause.getMessage() != null) {
|
52
55
|
message.append(String.format("%n"));
|
53
56
|
message.append(cause.getMessage());
|
54
57
|
}
|
55
58
|
}
|
56
59
|
ConfigException e = new ConfigException(message.toString());
|
57
|
-
for (
|
58
|
-
e.addSuppressed(
|
60
|
+
for (PluginSourceNotMatchException exception : exceptions) {
|
61
|
+
e.addSuppressed(exception);
|
59
62
|
}
|
60
|
-
|
63
|
+
return e;
|
61
64
|
}
|
62
65
|
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
package org.embulk.spi;
|
2
2
|
|
3
|
-
import
|
3
|
+
import java.util.Objects;
|
4
4
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
5
5
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
6
6
|
import org.embulk.spi.type.Type;
|
@@ -72,15 +72,15 @@ public class Column
|
|
72
72
|
return false;
|
73
73
|
}
|
74
74
|
Column other = (Column) obj;
|
75
|
-
return Objects.
|
76
|
-
Objects.
|
77
|
-
Objects.
|
75
|
+
return Objects.equals(index, other.index) &&
|
76
|
+
Objects.equals(name, other.name) &&
|
77
|
+
Objects.equals(type, other.type);
|
78
78
|
}
|
79
79
|
|
80
80
|
@Override
|
81
81
|
public int hashCode()
|
82
82
|
{
|
83
|
-
return Objects.
|
83
|
+
return Objects.hash(index, name, type);
|
84
84
|
}
|
85
85
|
|
86
86
|
@Override
|
@@ -1,6 +1,6 @@
|
|
1
1
|
package org.embulk.spi;
|
2
2
|
|
3
|
-
import
|
3
|
+
import java.util.Objects;
|
4
4
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
5
5
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
6
6
|
import org.embulk.spi.type.Type;
|
@@ -60,14 +60,14 @@ public class ColumnConfig
|
|
60
60
|
return false;
|
61
61
|
}
|
62
62
|
ColumnConfig other = (ColumnConfig) obj;
|
63
|
-
return Objects.
|
64
|
-
Objects.
|
63
|
+
return Objects.equals(this.name, other.name) &&
|
64
|
+
Objects.equals(type, other.type);
|
65
65
|
}
|
66
66
|
|
67
67
|
@Override
|
68
68
|
public int hashCode()
|
69
69
|
{
|
70
|
-
return Objects.
|
70
|
+
return Objects.hash(name, type);
|
71
71
|
}
|
72
72
|
|
73
73
|
@Override
|
@@ -2,6 +2,7 @@ package org.embulk.spi;
|
|
2
2
|
|
3
3
|
import java.util.concurrent.ExecutionException;
|
4
4
|
import org.slf4j.Logger;
|
5
|
+
import com.google.inject.Injector;
|
5
6
|
import org.embulk.config.Task;
|
6
7
|
import org.embulk.config.ModelManager;
|
7
8
|
import org.embulk.config.CommitReport;
|
@@ -38,6 +39,11 @@ public class Exec
|
|
38
39
|
return session;
|
39
40
|
}
|
40
41
|
|
42
|
+
public static Injector getInjector()
|
43
|
+
{
|
44
|
+
return session().getInjector();
|
45
|
+
}
|
46
|
+
|
41
47
|
public static Logger getLogger(String name)
|
42
48
|
{
|
43
49
|
return session().getLogger(name);
|
@@ -80,7 +80,7 @@ public class FileInputRunner
|
|
80
80
|
throw new NoSampleException("Can't get sample data because the first input file is empty");
|
81
81
|
}
|
82
82
|
|
83
|
-
GuessExecutor guessExecutor = Exec.
|
83
|
+
GuessExecutor guessExecutor = Exec.getInjector().getInstance(GuessExecutor.class);
|
84
84
|
return guessExecutor.guessParserConfig(sample, config, Exec.session().getExecConfig());
|
85
85
|
}
|
86
86
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
package org.embulk.spi;
|
2
2
|
|
3
3
|
import java.util.List;
|
4
|
-
import
|
4
|
+
import java.util.Objects;
|
5
5
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
6
6
|
import com.fasterxml.jackson.annotation.JsonValue;
|
7
7
|
import org.embulk.spi.type.Type;
|
@@ -78,7 +78,7 @@ public class Schema
|
|
78
78
|
return false;
|
79
79
|
}
|
80
80
|
Schema other = (Schema) obj;
|
81
|
-
return Objects.
|
81
|
+
return Objects.equals(columns, other.columns);
|
82
82
|
}
|
83
83
|
|
84
84
|
@Override
|
@@ -1,7 +1,7 @@
|
|
1
1
|
package org.embulk.spi;
|
2
2
|
|
3
3
|
import java.util.List;
|
4
|
-
import
|
4
|
+
import java.util.Objects;
|
5
5
|
import com.google.common.collect.ImmutableList;
|
6
6
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
7
7
|
import com.fasterxml.jackson.annotation.JsonValue;
|
@@ -41,7 +41,7 @@ public class SchemaConfig
|
|
41
41
|
return false;
|
42
42
|
}
|
43
43
|
SchemaConfig other = (SchemaConfig) obj;
|
44
|
-
return Objects.
|
44
|
+
return Objects.equals(columns, other.columns);
|
45
45
|
}
|
46
46
|
|
47
47
|
@Override
|
@@ -0,0 +1,148 @@
|
|
1
|
+
package org.embulk.spi.unit;
|
2
|
+
|
3
|
+
import java.util.Objects;
|
4
|
+
import java.util.Locale;
|
5
|
+
import java.util.regex.Matcher;
|
6
|
+
import java.util.regex.Pattern;
|
7
|
+
import com.google.common.base.Preconditions;
|
8
|
+
import com.fasterxml.jackson.annotation.JsonCreator;
|
9
|
+
import com.fasterxml.jackson.annotation.JsonValue;
|
10
|
+
|
11
|
+
public class ByteSize
|
12
|
+
implements Comparable<ByteSize>
|
13
|
+
{
|
14
|
+
private static final Pattern PATTERN = Pattern.compile("\\A(\\d+(?:\\.\\d+)?)\\s?([a-zA-Z]*)\\z");
|
15
|
+
|
16
|
+
private final long bytes;
|
17
|
+
private final Unit displayUnit;
|
18
|
+
|
19
|
+
public ByteSize(double size, Unit unit)
|
20
|
+
{
|
21
|
+
Preconditions.checkArgument(!Double.isInfinite(size), "size is infinite");
|
22
|
+
Preconditions.checkArgument(!Double.isNaN(size), "size is not a number");
|
23
|
+
Preconditions.checkArgument(size >= 0, "size is negative");
|
24
|
+
Preconditions.checkNotNull(unit, "unit is null");
|
25
|
+
Preconditions.checkArgument(size * unit.getFactor() <= (double) Long.MAX_VALUE, "size is large than (2^63)-1 in bytes");
|
26
|
+
this.bytes = (long) (size * unit.getFactor());
|
27
|
+
this.displayUnit = unit;
|
28
|
+
}
|
29
|
+
|
30
|
+
@JsonCreator
|
31
|
+
public ByteSize(long bytes)
|
32
|
+
{
|
33
|
+
Preconditions.checkArgument(bytes >= 0, "size is negative");
|
34
|
+
this.bytes = bytes;
|
35
|
+
this.displayUnit = Unit.BYTES;
|
36
|
+
}
|
37
|
+
|
38
|
+
public long getBytes()
|
39
|
+
{
|
40
|
+
return bytes;
|
41
|
+
}
|
42
|
+
|
43
|
+
public long roundTo(Unit unit)
|
44
|
+
{
|
45
|
+
return (long) Math.floor(getValue(unit) + 0.5);
|
46
|
+
}
|
47
|
+
|
48
|
+
public double getValue(Unit unit)
|
49
|
+
{
|
50
|
+
return bytes / (double) unit.getFactor();
|
51
|
+
}
|
52
|
+
|
53
|
+
@JsonCreator
|
54
|
+
public static ByteSize parseByteSize(String size)
|
55
|
+
{
|
56
|
+
Preconditions.checkNotNull(size, "size is null");
|
57
|
+
Preconditions.checkArgument(!size.isEmpty(), "size is empty");
|
58
|
+
|
59
|
+
Matcher matcher = PATTERN.matcher(size);
|
60
|
+
if (!matcher.matches()) {
|
61
|
+
throw new IllegalArgumentException("Invalid byte size string '" + size + "'");
|
62
|
+
}
|
63
|
+
|
64
|
+
double value = Double.parseDouble(matcher.group(1)); // NumberFormatException extends IllegalArgumentException.
|
65
|
+
|
66
|
+
String unitString = matcher.group(2);
|
67
|
+
if (unitString.isEmpty()) {
|
68
|
+
return new ByteSize(value, Unit.BYTES);
|
69
|
+
} else {
|
70
|
+
String upperUnitString = unitString.toUpperCase(Locale.ENGLISH);
|
71
|
+
for (Unit unit : Unit.values()) {
|
72
|
+
if (unit.getUnitString().toUpperCase(Locale.ENGLISH).equals(upperUnitString)) {
|
73
|
+
return new ByteSize(value, unit);
|
74
|
+
}
|
75
|
+
}
|
76
|
+
}
|
77
|
+
|
78
|
+
throw new IllegalArgumentException("Unknown unit '" + unitString + "'");
|
79
|
+
}
|
80
|
+
|
81
|
+
@JsonValue
|
82
|
+
@Override
|
83
|
+
public String toString()
|
84
|
+
{
|
85
|
+
double value = getValue(displayUnit);
|
86
|
+
String integer = String.format(Locale.ENGLISH, "%d", (long) value);
|
87
|
+
String decimal = String.format(Locale.ENGLISH, "%.2f", value);
|
88
|
+
if (decimal.equals(integer + ".00")) {
|
89
|
+
return integer + displayUnit.getUnitString();
|
90
|
+
} else {
|
91
|
+
return decimal + displayUnit.getUnitString();
|
92
|
+
}
|
93
|
+
}
|
94
|
+
|
95
|
+
@Override
|
96
|
+
public int compareTo(ByteSize o)
|
97
|
+
{
|
98
|
+
return Long.compare(bytes, o.bytes);
|
99
|
+
}
|
100
|
+
|
101
|
+
@Override
|
102
|
+
public boolean equals(Object obj)
|
103
|
+
{
|
104
|
+
if (this == obj) {
|
105
|
+
return true;
|
106
|
+
}
|
107
|
+
if (!(obj instanceof ByteSize)) {
|
108
|
+
return false;
|
109
|
+
}
|
110
|
+
ByteSize o = (ByteSize) obj;
|
111
|
+
return this.bytes == o.bytes;
|
112
|
+
}
|
113
|
+
|
114
|
+
@Override
|
115
|
+
public int hashCode()
|
116
|
+
{
|
117
|
+
return Objects.hashCode(bytes);
|
118
|
+
}
|
119
|
+
|
120
|
+
public enum Unit
|
121
|
+
{
|
122
|
+
BYTES(1L, "B"),
|
123
|
+
KB(1L << 10, "KB"),
|
124
|
+
MB(1L << 20, "MB"),
|
125
|
+
GB(1L << 30, "GB"),
|
126
|
+
TB(1L << 40, "TB"),
|
127
|
+
PT(1L << 50, "PB");
|
128
|
+
|
129
|
+
private final long factor;
|
130
|
+
private final String unitString;
|
131
|
+
|
132
|
+
Unit(long factor, String unitString)
|
133
|
+
{
|
134
|
+
this.factor = factor;
|
135
|
+
this.unitString = unitString;
|
136
|
+
}
|
137
|
+
|
138
|
+
long getFactor()
|
139
|
+
{
|
140
|
+
return factor;
|
141
|
+
}
|
142
|
+
|
143
|
+
String getUnitString()
|
144
|
+
{
|
145
|
+
return unitString;
|
146
|
+
}
|
147
|
+
}
|
148
|
+
}
|