embulk 0.6.21 → 0.6.22
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/.gitignore +1 -0
- data/build.gradle +27 -15
- data/embulk-core/build.gradle +17 -1
- data/embulk-core/src/main/java/org/embulk/EmbulkEmbed.java +216 -0
- data/embulk-core/src/main/java/org/embulk/EmbulkService.java +13 -7
- data/embulk-core/src/main/java/org/embulk/command/LiquidTemplate.java +8 -0
- data/embulk-core/src/main/java/org/embulk/command/Runner.java +63 -27
- data/embulk-core/src/main/java/org/embulk/config/ConfigLoader.java +5 -0
- data/embulk-core/src/main/java/org/embulk/config/DataSourceImpl.java +3 -3
- data/embulk-core/src/main/java/org/embulk/exec/ExecModule.java +1 -1
- data/embulk-core/src/main/java/org/embulk/exec/PooledBufferAllocator.java +3 -1
- data/embulk-core/src/main/java/org/embulk/guice/Bootstrap.java +150 -0
- data/embulk-core/src/main/java/org/embulk/guice/CloseableInjector.java +22 -0
- data/embulk-core/src/main/java/org/embulk/guice/CloseableInjectorProxy.java +47 -0
- data/embulk-core/src/main/java/org/embulk/guice/InjectorProxy.java +145 -0
- data/embulk-core/src/main/java/org/embulk/guice/LifeCycleManager.java +187 -0
- data/embulk-core/src/main/java/org/embulk/guice/LifeCycleMethods.java +89 -0
- data/embulk-core/src/main/java/org/embulk/guice/LifeCycleMethodsMap.java +38 -0
- data/embulk-core/src/main/java/org/embulk/guice/LifeCycleModule.java +97 -0
- data/embulk-core/src/main/java/org/embulk/spi/TempFileSpace.java +41 -7
- data/embulk-docs/build.gradle +3 -2
- data/embulk-docs/src/built-in.rst +30 -1
- data/embulk-docs/src/index.rst +1 -1
- data/embulk-docs/src/release.rst +1 -0
- data/embulk-docs/src/release/release-0.6.22.rst +26 -0
- data/gradle/wrapper/gradle-wrapper.jar +0 -0
- data/gradle/wrapper/gradle-wrapper.properties +2 -2
- data/lib/embulk/command/embulk_run.rb +11 -5
- data/lib/embulk/data_source.rb +28 -8
- data/lib/embulk/error.rb +7 -1
- data/lib/embulk/gems.rb +29 -0
- data/lib/embulk/java/bootstrap.rb +4 -0
- data/lib/embulk/java/liquid_helper.rb +17 -0
- data/lib/embulk/version.rb +1 -1
- data/test/helper.rb +11 -2
- metadata +46 -33
@@ -26,6 +26,11 @@ public class ConfigLoader
|
|
26
26
|
this.model = model;
|
27
27
|
}
|
28
28
|
|
29
|
+
public ConfigSource newConfigSource()
|
30
|
+
{
|
31
|
+
return new DataSourceImpl(model);
|
32
|
+
}
|
33
|
+
|
29
34
|
public ConfigSource fromJsonFile(File file) throws IOException
|
30
35
|
{
|
31
36
|
try (FileInputStream is = new FileInputStream(file)) {
|
@@ -123,7 +123,7 @@ public class DataSourceImpl
|
|
123
123
|
if (v == null) {
|
124
124
|
remove(attrName);
|
125
125
|
} else {
|
126
|
-
data.
|
126
|
+
data.set(attrName, model.writeObjectAsJsonNode(v));
|
127
127
|
}
|
128
128
|
return this;
|
129
129
|
}
|
@@ -131,7 +131,7 @@ public class DataSourceImpl
|
|
131
131
|
@Override
|
132
132
|
public DataSourceImpl setNested(String attrName, DataSource v)
|
133
133
|
{
|
134
|
-
data.
|
134
|
+
data.set(attrName, v.getObjectNode());
|
135
135
|
return this;
|
136
136
|
}
|
137
137
|
|
@@ -139,7 +139,7 @@ public class DataSourceImpl
|
|
139
139
|
public DataSourceImpl setAll(DataSource other)
|
140
140
|
{
|
141
141
|
for (Map.Entry<String, JsonNode> field : other.getAttributes()) {
|
142
|
-
data.
|
142
|
+
data.set(field.getKey(), field.getValue());
|
143
143
|
}
|
144
144
|
return this;
|
145
145
|
}
|
@@ -27,7 +27,7 @@ public class ExecModule
|
|
27
27
|
{
|
28
28
|
Preconditions.checkNotNull(binder, "binder is null.");
|
29
29
|
|
30
|
-
binder.bind(ILoggerFactory.class).toProvider(LoggerProvider.class);
|
30
|
+
binder.bind(ILoggerFactory.class).toProvider(LoggerProvider.class).in(Scopes.SINGLETON);
|
31
31
|
binder.bind(ModelManager.class).in(Scopes.SINGLETON);
|
32
32
|
binder.bind(BufferAllocator.class).to(PooledBufferAllocator.class).in(Scopes.SINGLETON);
|
33
33
|
binder.bind(TempFileAllocator.class).in(Scopes.SINGLETON);
|
@@ -3,6 +3,8 @@ package org.embulk.exec;
|
|
3
3
|
import io.netty.buffer.PooledByteBufAllocator;
|
4
4
|
import io.netty.buffer.ByteBuf;
|
5
5
|
import io.netty.util.ResourceLeakDetector;
|
6
|
+
import io.netty.util.internal.logging.InternalLoggerFactory;
|
7
|
+
import io.netty.util.internal.logging.JdkLoggerFactory;
|
6
8
|
import org.embulk.spi.Buffer;
|
7
9
|
import org.embulk.spi.BufferAllocator;
|
8
10
|
import com.google.inject.Inject;
|
@@ -18,7 +20,7 @@ public class PooledBufferAllocator
|
|
18
20
|
private final int pageSize;
|
19
21
|
|
20
22
|
@Inject
|
21
|
-
public PooledBufferAllocator(@ForSystemConfig ConfigSource systemConfig)
|
23
|
+
public PooledBufferAllocator(@ForSystemConfig ConfigSource systemConfig, org.slf4j.ILoggerFactory factory)
|
22
24
|
{
|
23
25
|
this.nettyBuffer = new PooledByteBufAllocator(false);
|
24
26
|
this.pageSize = systemConfig.get(ByteSize.class, "page_size", new ByteSize(DEFAULT_PAGE_SIZE)).getBytesInt();
|
@@ -0,0 +1,150 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright 2015 Sadayuki Furuhashi
|
3
|
+
*
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
* you may not use this file except in compliance with the License.
|
6
|
+
* You may obtain a copy of the License at
|
7
|
+
*
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
*
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
* See the License for the specific language governing permissions and
|
14
|
+
* limitations under the License.
|
15
|
+
*/
|
16
|
+
package org.embulk.guice;
|
17
|
+
|
18
|
+
import com.google.common.base.Function;
|
19
|
+
import com.google.common.collect.ImmutableList;
|
20
|
+
import com.google.common.collect.Iterables;
|
21
|
+
import com.google.common.annotations.Beta;
|
22
|
+
|
23
|
+
import com.google.inject.Binder;
|
24
|
+
import com.google.inject.Guice;
|
25
|
+
import com.google.inject.Module;
|
26
|
+
import com.google.inject.Stage;
|
27
|
+
import com.google.inject.Injector;
|
28
|
+
import java.util.Arrays;
|
29
|
+
import java.util.List;
|
30
|
+
|
31
|
+
@Beta
|
32
|
+
public class Bootstrap
|
33
|
+
{
|
34
|
+
private List<Module> modules;
|
35
|
+
|
36
|
+
private boolean requireExplicitBindings = true;
|
37
|
+
|
38
|
+
private boolean started;
|
39
|
+
|
40
|
+
public Bootstrap(Module... modules)
|
41
|
+
{
|
42
|
+
this(Arrays.asList(modules));
|
43
|
+
}
|
44
|
+
|
45
|
+
public Bootstrap(Iterable<? extends Module> modules)
|
46
|
+
{
|
47
|
+
this.modules = ImmutableList.copyOf(modules);
|
48
|
+
}
|
49
|
+
|
50
|
+
public Bootstrap requireExplicitBindings(boolean requireExplicitBindings)
|
51
|
+
{
|
52
|
+
this.requireExplicitBindings = requireExplicitBindings;
|
53
|
+
return this;
|
54
|
+
}
|
55
|
+
|
56
|
+
public Bootstrap addModules(Module... additionalModules)
|
57
|
+
{
|
58
|
+
return addModules(Arrays.asList(additionalModules));
|
59
|
+
}
|
60
|
+
|
61
|
+
public Bootstrap addModules(Iterable<? extends Module> additionalModules)
|
62
|
+
{
|
63
|
+
modules = ImmutableList.copyOf(Iterables.concat(modules, additionalModules));
|
64
|
+
return this;
|
65
|
+
}
|
66
|
+
|
67
|
+
//public Bootstrap onPreDestroy()
|
68
|
+
//{
|
69
|
+
//}
|
70
|
+
|
71
|
+
//public Bootstrap onPreDestroyException()
|
72
|
+
//{
|
73
|
+
//}
|
74
|
+
|
75
|
+
//public Bootstrap onStop()
|
76
|
+
//{
|
77
|
+
//}
|
78
|
+
|
79
|
+
//public Bootstrap forEachModule(Consumer<? super Module> function)
|
80
|
+
//{
|
81
|
+
// for (Module module : modules) {
|
82
|
+
// function.accept(module);
|
83
|
+
// }
|
84
|
+
// return this;
|
85
|
+
//}
|
86
|
+
|
87
|
+
//public <T> Bootstrap forEachModule(Class<T> ifClass, Consumer<? super T> function)
|
88
|
+
//{
|
89
|
+
// for (Module module : modules) {
|
90
|
+
// if (ifClass.instance(module) {
|
91
|
+
// function.accept(module);
|
92
|
+
// }
|
93
|
+
// }
|
94
|
+
// return this;
|
95
|
+
//}
|
96
|
+
|
97
|
+
public Bootstrap overrideModules(Function<? super List<Module>, ? extends Iterable<? extends Module>> function)
|
98
|
+
{
|
99
|
+
modules = ImmutableList.copyOf(function.apply(modules));
|
100
|
+
return this;
|
101
|
+
}
|
102
|
+
|
103
|
+
public Injector initialize()
|
104
|
+
{
|
105
|
+
Injector injector = start();
|
106
|
+
injector.getInstance(LifeCycleManager.class).destroyOnShutdownHook();
|
107
|
+
return injector;
|
108
|
+
}
|
109
|
+
|
110
|
+
public CloseableInjector initializeCloseable()
|
111
|
+
{
|
112
|
+
Injector injector = start();
|
113
|
+
return new CloseableInjectorProxy(injector, injector.getInstance(LifeCycleManager.class));
|
114
|
+
}
|
115
|
+
|
116
|
+
private Injector start()
|
117
|
+
{
|
118
|
+
if (started) {
|
119
|
+
throw new IllegalStateException("System already initialized");
|
120
|
+
}
|
121
|
+
started = true;
|
122
|
+
|
123
|
+
ImmutableList.Builder<Module> moduleList = ImmutableList.builder();
|
124
|
+
|
125
|
+
moduleList.addAll(modules);
|
126
|
+
|
127
|
+
moduleList.add(new Module()
|
128
|
+
{
|
129
|
+
@Override
|
130
|
+
public void configure(Binder binder)
|
131
|
+
{
|
132
|
+
binder.disableCircularProxies();
|
133
|
+
if (requireExplicitBindings) {
|
134
|
+
binder.requireExplicitBindings();
|
135
|
+
}
|
136
|
+
}
|
137
|
+
});
|
138
|
+
|
139
|
+
moduleList.add(new LifeCycleModule());
|
140
|
+
|
141
|
+
Injector injector = Guice.createInjector(Stage.PRODUCTION, moduleList.build());
|
142
|
+
|
143
|
+
LifeCycleManager lifeCycleManager = injector.getInstance(LifeCycleManager.class);
|
144
|
+
if (lifeCycleManager.size() > 0) {
|
145
|
+
lifeCycleManager.start();
|
146
|
+
}
|
147
|
+
|
148
|
+
return injector;
|
149
|
+
}
|
150
|
+
}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright 2015 Sadayuki Furuhashi
|
3
|
+
*
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
* you may not use this file except in compliance with the License.
|
6
|
+
* You may obtain a copy of the License at
|
7
|
+
*
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
*
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
* See the License for the specific language governing permissions and
|
14
|
+
* limitations under the License.
|
15
|
+
*/
|
16
|
+
package org.embulk.guice;
|
17
|
+
|
18
|
+
import com.google.inject.Injector;
|
19
|
+
|
20
|
+
public interface CloseableInjector
|
21
|
+
extends Injector, AutoCloseable
|
22
|
+
{ }
|
@@ -0,0 +1,47 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright 2015 Sadayuki Furuhashi
|
3
|
+
*
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
* you may not use this file except in compliance with the License.
|
6
|
+
* You may obtain a copy of the License at
|
7
|
+
*
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
*
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
* See the License for the specific language governing permissions and
|
14
|
+
* limitations under the License.
|
15
|
+
*/
|
16
|
+
package org.embulk.guice;
|
17
|
+
|
18
|
+
import com.google.inject.Injector;
|
19
|
+
|
20
|
+
class CloseableInjectorProxy
|
21
|
+
extends InjectorProxy
|
22
|
+
implements CloseableInjector
|
23
|
+
{
|
24
|
+
private final Injector injector;
|
25
|
+
private final LifeCycleManager lifeCycleManager;
|
26
|
+
|
27
|
+
public CloseableInjectorProxy(Injector injector, LifeCycleManager lifeCycleManager)
|
28
|
+
{
|
29
|
+
this.injector = injector;
|
30
|
+
this.lifeCycleManager = lifeCycleManager;
|
31
|
+
}
|
32
|
+
|
33
|
+
@Override
|
34
|
+
protected synchronized Injector injector()
|
35
|
+
{
|
36
|
+
if (lifeCycleManager.isDestroyed()) {
|
37
|
+
throw new IllegalStateException("Injector already closed");
|
38
|
+
}
|
39
|
+
return injector;
|
40
|
+
}
|
41
|
+
|
42
|
+
@Override
|
43
|
+
public synchronized void close() throws Exception
|
44
|
+
{
|
45
|
+
lifeCycleManager.destroy(); // reentrant
|
46
|
+
}
|
47
|
+
}
|
@@ -0,0 +1,145 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright 2015 Sadayuki Furuhashi
|
3
|
+
*
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
* you may not use this file except in compliance with the License.
|
6
|
+
* You may obtain a copy of the License at
|
7
|
+
*
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
*
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
* See the License for the specific language governing permissions and
|
14
|
+
* limitations under the License.
|
15
|
+
*/
|
16
|
+
package org.embulk.guice;
|
17
|
+
|
18
|
+
import com.google.inject.Binding;
|
19
|
+
import com.google.inject.Injector;
|
20
|
+
import com.google.inject.Key;
|
21
|
+
import com.google.inject.MembersInjector;
|
22
|
+
import com.google.inject.Module;
|
23
|
+
import com.google.inject.Provider;
|
24
|
+
import com.google.inject.Scope;
|
25
|
+
import com.google.inject.TypeLiteral;
|
26
|
+
import com.google.inject.spi.TypeConverterBinding;
|
27
|
+
|
28
|
+
import java.lang.annotation.Annotation;
|
29
|
+
import java.util.List;
|
30
|
+
import java.util.Map;
|
31
|
+
import java.util.Set;
|
32
|
+
|
33
|
+
abstract class InjectorProxy
|
34
|
+
implements Injector
|
35
|
+
{
|
36
|
+
protected abstract Injector injector();
|
37
|
+
|
38
|
+
@Override
|
39
|
+
public void injectMembers(Object instance)
|
40
|
+
{
|
41
|
+
injector().injectMembers(instance);
|
42
|
+
}
|
43
|
+
|
44
|
+
@Override
|
45
|
+
public <T> MembersInjector<T> getMembersInjector(TypeLiteral<T> typeLiteral)
|
46
|
+
{
|
47
|
+
return injector().getMembersInjector(typeLiteral);
|
48
|
+
}
|
49
|
+
|
50
|
+
@Override
|
51
|
+
public <T> MembersInjector<T> getMembersInjector(Class<T> type)
|
52
|
+
{
|
53
|
+
return injector().getMembersInjector(type);
|
54
|
+
}
|
55
|
+
|
56
|
+
@Override
|
57
|
+
public Map<Key<?>, Binding<?>> getBindings()
|
58
|
+
{
|
59
|
+
return injector().getBindings();
|
60
|
+
}
|
61
|
+
|
62
|
+
@Override
|
63
|
+
public Map<Key<?>, Binding<?>> getAllBindings()
|
64
|
+
{
|
65
|
+
return injector().getAllBindings();
|
66
|
+
}
|
67
|
+
|
68
|
+
@Override
|
69
|
+
public <T> Binding<T> getBinding(Key<T> key)
|
70
|
+
{
|
71
|
+
return injector().getBinding(key);
|
72
|
+
}
|
73
|
+
|
74
|
+
@Override
|
75
|
+
public <T> Binding<T> getBinding(Class<T> type)
|
76
|
+
{
|
77
|
+
return injector().getBinding(type);
|
78
|
+
}
|
79
|
+
|
80
|
+
@Override
|
81
|
+
public <T> Binding<T> getExistingBinding(Key<T> key)
|
82
|
+
{
|
83
|
+
return injector().getExistingBinding(key);
|
84
|
+
}
|
85
|
+
|
86
|
+
@Override
|
87
|
+
public <T> List<Binding<T>> findBindingsByType(TypeLiteral<T> type)
|
88
|
+
{
|
89
|
+
return injector().findBindingsByType(type);
|
90
|
+
}
|
91
|
+
|
92
|
+
@Override
|
93
|
+
public <T> Provider<T> getProvider(Key<T> key)
|
94
|
+
{
|
95
|
+
return injector().getProvider(key);
|
96
|
+
}
|
97
|
+
|
98
|
+
@Override
|
99
|
+
public <T> Provider<T> getProvider(Class<T> type)
|
100
|
+
{
|
101
|
+
return injector().getProvider(type);
|
102
|
+
}
|
103
|
+
|
104
|
+
@Override
|
105
|
+
public <T> T getInstance(Key<T> key)
|
106
|
+
{
|
107
|
+
return injector().getInstance(key);
|
108
|
+
}
|
109
|
+
|
110
|
+
@Override
|
111
|
+
public <T> T getInstance(Class<T> type)
|
112
|
+
{
|
113
|
+
return injector().getInstance(type);
|
114
|
+
}
|
115
|
+
|
116
|
+
@Override
|
117
|
+
public Injector getParent()
|
118
|
+
{
|
119
|
+
return injector().getParent();
|
120
|
+
}
|
121
|
+
|
122
|
+
@Override
|
123
|
+
public Injector createChildInjector(Iterable<? extends Module> modules)
|
124
|
+
{
|
125
|
+
return injector().createChildInjector(modules);
|
126
|
+
}
|
127
|
+
|
128
|
+
@Override
|
129
|
+
public Injector createChildInjector(Module... modules)
|
130
|
+
{
|
131
|
+
return injector().createChildInjector(modules);
|
132
|
+
}
|
133
|
+
|
134
|
+
@Override
|
135
|
+
public Map<Class<? extends Annotation>, Scope> getScopeBindings()
|
136
|
+
{
|
137
|
+
return injector().getScopeBindings();
|
138
|
+
}
|
139
|
+
|
140
|
+
@Override
|
141
|
+
public Set<TypeConverterBinding> getTypeConverterBindings()
|
142
|
+
{
|
143
|
+
return injector().getTypeConverterBindings();
|
144
|
+
}
|
145
|
+
}
|
@@ -0,0 +1,187 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright 2010 Proofpoint, Inc.
|
3
|
+
*
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
* you may not use this file except in compliance with the License.
|
6
|
+
* You may obtain a copy of the License at
|
7
|
+
*
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
*
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
* See the License for the specific language governing permissions and
|
14
|
+
* limitations under the License.
|
15
|
+
*/
|
16
|
+
/*
|
17
|
+
* Copyright 2015 Sadayuki Furuhashi
|
18
|
+
*/
|
19
|
+
package org.embulk.guice;
|
20
|
+
|
21
|
+
import com.google.common.collect.Lists;
|
22
|
+
|
23
|
+
import javax.annotation.PostConstruct;
|
24
|
+
import javax.annotation.PreDestroy;
|
25
|
+
import java.lang.reflect.InvocationTargetException;
|
26
|
+
import java.lang.reflect.Method;
|
27
|
+
import java.util.Collections;
|
28
|
+
import java.util.List;
|
29
|
+
import java.util.Queue;
|
30
|
+
import java.util.concurrent.ConcurrentLinkedQueue;
|
31
|
+
import java.util.concurrent.atomic.AtomicReference;
|
32
|
+
|
33
|
+
/**
|
34
|
+
* Manages PostConstruct and PreDestroy life cycles
|
35
|
+
*/
|
36
|
+
public final class LifeCycleManager
|
37
|
+
{
|
38
|
+
private final AtomicReference<State> state = new AtomicReference<State>(State.LATENT);
|
39
|
+
private final Queue<Object> managedInstances = new ConcurrentLinkedQueue<Object>();
|
40
|
+
private final LifeCycleMethodsMap methodsMap;
|
41
|
+
|
42
|
+
private enum State
|
43
|
+
{
|
44
|
+
LATENT,
|
45
|
+
STARTING,
|
46
|
+
STARTED,
|
47
|
+
STOPPING,
|
48
|
+
STOPPED
|
49
|
+
}
|
50
|
+
|
51
|
+
/**
|
52
|
+
* @param managedInstances list of objects that have life cycle annotations
|
53
|
+
* @param methodsMap existing or new methods map
|
54
|
+
* @throws Exception exceptions starting instances (depending on mode)
|
55
|
+
*/
|
56
|
+
public LifeCycleManager(List<Object> managedInstances, LifeCycleMethodsMap methodsMap)
|
57
|
+
throws Exception
|
58
|
+
{
|
59
|
+
this.methodsMap = (methodsMap != null) ? methodsMap : new LifeCycleMethodsMap();
|
60
|
+
for (Object instance : managedInstances) {
|
61
|
+
addInstance(instance);
|
62
|
+
}
|
63
|
+
}
|
64
|
+
|
65
|
+
/**
|
66
|
+
* Returns the number of managed instances
|
67
|
+
*
|
68
|
+
* @return qty
|
69
|
+
*/
|
70
|
+
public int size()
|
71
|
+
{
|
72
|
+
return managedInstances.size();
|
73
|
+
}
|
74
|
+
|
75
|
+
/**
|
76
|
+
* Start the life cycle - all instances will have their {@link javax.annotation.PostConstruct} method(s) called
|
77
|
+
*
|
78
|
+
* @throws Exception errors
|
79
|
+
*/
|
80
|
+
public void start()
|
81
|
+
{
|
82
|
+
if (!state.compareAndSet(State.LATENT, State.STARTING)) {
|
83
|
+
throw new IllegalStateException("System already starting");
|
84
|
+
}
|
85
|
+
//log.info("Life cycle starting...");
|
86
|
+
|
87
|
+
for (Object obj : managedInstances) {
|
88
|
+
LifeCycleMethods methods = methodsMap.get(obj.getClass());
|
89
|
+
if (!methods.hasFor(PreDestroy.class)) {
|
90
|
+
managedInstances.remove(obj); // remove reference to instances that aren't needed anymore
|
91
|
+
}
|
92
|
+
}
|
93
|
+
|
94
|
+
state.set(State.STARTED);
|
95
|
+
//log.info("Life cycle startup complete. System ready.");
|
96
|
+
}
|
97
|
+
|
98
|
+
/**
|
99
|
+
* Add a shutdown hook that calls {@link destroy} method
|
100
|
+
*/
|
101
|
+
public void destroyOnShutdownHook()
|
102
|
+
{
|
103
|
+
Runtime.getRuntime().addShutdownHook(new Thread()
|
104
|
+
{
|
105
|
+
@Override
|
106
|
+
public void run()
|
107
|
+
{
|
108
|
+
try {
|
109
|
+
LifeCycleManager.this.destroy();
|
110
|
+
}
|
111
|
+
catch (Exception e) {
|
112
|
+
//log.error(e, "Trying to shut down");
|
113
|
+
}
|
114
|
+
}
|
115
|
+
});
|
116
|
+
}
|
117
|
+
|
118
|
+
/**
|
119
|
+
* Stop the life cycle - all instances will have their {@link javax.annotation.PreDestroy} method(s) called
|
120
|
+
*
|
121
|
+
* @throws Exception errors
|
122
|
+
*/
|
123
|
+
public void destroy()
|
124
|
+
throws Exception
|
125
|
+
{
|
126
|
+
if (!state.compareAndSet(State.STARTED, State.STOPPING)) {
|
127
|
+
return;
|
128
|
+
}
|
129
|
+
|
130
|
+
//log.info("Life cycle stopping...");
|
131
|
+
|
132
|
+
List<Object> reversedInstances = Lists.newArrayList(managedInstances);
|
133
|
+
Collections.reverse(reversedInstances);
|
134
|
+
|
135
|
+
for (Object obj : reversedInstances) {
|
136
|
+
//log.debug("Stopping %s", obj.getClass().getName());
|
137
|
+
LifeCycleMethods methods = methodsMap.get(obj.getClass());
|
138
|
+
for (Method preDestroy : methods.methodsFor(PreDestroy.class)) {
|
139
|
+
//log.debug("\t%s()", preDestroy.getName());
|
140
|
+
preDestroy.invoke(obj);
|
141
|
+
}
|
142
|
+
}
|
143
|
+
|
144
|
+
state.set(State.STOPPED);
|
145
|
+
//log.info("Life cycle stopped.");
|
146
|
+
}
|
147
|
+
|
148
|
+
/**
|
149
|
+
* Return true if state is {@link destroy} is called
|
150
|
+
*/
|
151
|
+
public boolean isDestroyed()
|
152
|
+
{
|
153
|
+
State currentState = state.get();
|
154
|
+
return currentState == State.STOPPING || currentState == State.STOPPED;
|
155
|
+
}
|
156
|
+
|
157
|
+
/**
|
158
|
+
* Add an additional managed instance
|
159
|
+
*
|
160
|
+
* @param instance instance to add
|
161
|
+
* @throws Exception errors
|
162
|
+
*/
|
163
|
+
public void addInstance(Object instance)
|
164
|
+
throws Exception
|
165
|
+
{
|
166
|
+
if (isDestroyed()) {
|
167
|
+
throw new IllegalStateException("System already stopped");
|
168
|
+
}
|
169
|
+
else {
|
170
|
+
startInstance(instance);
|
171
|
+
if (methodsMap.get(instance.getClass()).hasFor(PreDestroy.class)) {
|
172
|
+
managedInstances.add(instance);
|
173
|
+
}
|
174
|
+
}
|
175
|
+
}
|
176
|
+
|
177
|
+
private void startInstance(Object obj)
|
178
|
+
throws IllegalAccessException, InvocationTargetException
|
179
|
+
{
|
180
|
+
//log.debug("Starting %s", obj.getClass().getName());
|
181
|
+
LifeCycleMethods methods = methodsMap.get(obj.getClass());
|
182
|
+
for (Method postConstruct : methods.methodsFor(PostConstruct.class)) {
|
183
|
+
//log.debug("\t%s()", postConstruct.getName());
|
184
|
+
postConstruct.invoke(obj);
|
185
|
+
}
|
186
|
+
}
|
187
|
+
}
|