/
ScriptHookWrapper.java
141 lines (120 loc) · 4.87 KB
/
ScriptHookWrapper.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/* Copyright (c) 2018 Boundless and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/org/documents/edl-v10.html
*
* Contributors:
* Gabriel Roldan - initial implementation
*/
package org.locationtech.geogig.scripting;
import java.io.File;
import java.net.URI;
import java.util.List;
import java.util.Optional;
import org.eclipse.jdt.annotation.Nullable;
import org.locationtech.geogig.hooks.CommandHook;
import org.locationtech.geogig.hooks.Hookable;
import org.locationtech.geogig.repository.AbstractGeoGigOp;
import org.locationtech.geogig.repository.Context;
import com.google.common.collect.Lists;
import lombok.NonNull;
public class ScriptHookWrapper implements CommandHook {
public @Override boolean appliesTo(Class<? extends AbstractGeoGigOp<?>> clazz) {
return clazz.isAnnotationPresent(Hookable.class);
}
public @Override @NonNull List<CommandHook> unwrap(@NonNull AbstractGeoGigOp<?> command) {
return findScriptHooksFor(command);
}
public @Override <C extends AbstractGeoGigOp<?>> C pre(C command) {
throw new UnsupportedOperationException();
}
public @Override <T> T post(AbstractGeoGigOp<T> command, @Nullable Object retVal,
@Nullable RuntimeException exception) throws Exception {
throw new UnsupportedOperationException();
}
/**
* Returns the filename to be used for a script corresponding to the hook for a given GeoGig
* operation. Returns {@link Optional.absent} if the specified operation does not allows hooks
*
* @param class the operation
* @return the string to be used as filename for storing the script files for the corresponding
* hook
*/
static Optional<String> getFilename(Class<? extends AbstractGeoGigOp<?>> clazz) {
Hookable annotation = clazz.getAnnotation(Hookable.class);
if (annotation != null) {
return Optional.of(annotation.name());
} else {
return Optional.empty();
}
}
public static List<CommandHook> findScriptHooksFor(AbstractGeoGigOp<?> operation) {
@SuppressWarnings("unchecked")
final Class<? extends AbstractGeoGigOp<?>> clazz = (Class<? extends AbstractGeoGigOp<?>>) operation
.getClass();
List<CommandHook> hooks = Lists.newLinkedList();
/*
* add any script hook that's configured for the operation iif it's @Hookable
*/
final Optional<String> name = getFilename(clazz);
if (!name.isPresent()) {
return hooks;
}
final File hooksDir = findHooksDirectory(operation);
if (hooksDir == null) {
return hooks;
}
if (name.isPresent()) {
String preHookName = "pre_" + name.get().toLowerCase();
String postHookName = "post_" + name.get().toLowerCase();
File[] files = hooksDir.listFiles();
for (File file : files) {
String filename = file.getName();
if (isHook(filename, preHookName)) {
hooks.add(Scripting.createScriptHook(file, true));
}
if (isHook(filename, postHookName)) {
hooks.add(Scripting.createScriptHook(file, false));
}
}
}
return hooks;
}
/**
* Looks up for the hooks directory in the repository {@code operation} works on.
* <p>
* Implementation note: this method must not create any command through
* {@link Context#command(Class)} either directly or indirectly or a stack overflow exception
* would be thrown
*
* @return {@code null} if the {@code operation} is not running on a repository, or the
* repository has no {@code hooks} directory at all.
*/
@Nullable
private static File findHooksDirectory(AbstractGeoGigOp<?> operation) {
if (operation.context().repository() == null
|| operation.context().repository().getLocation() == null) {
return null;
}
URI url = operation.context().repository().getLocation();
if (!"file".equals(url.getScheme())) {
// Hooks not in a filesystem are not supported
return null;
}
File repoDir = new File(url);
File hooksDir = new File(repoDir, "hooks");
if (!hooksDir.exists()) {
return null;
}
return hooksDir;
}
private static boolean isHook(final String filename, final String hookNamePrefix) {
if (hookNamePrefix.equals(filename) || filename.startsWith(hookNamePrefix + ".")) {
if (!filename.endsWith("sample")) {
return true;
}
}
return false;
}
}