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 package org.objectledge.external;
30
31 import java.io.File;
32 import java.io.IOException;
33 import java.util.Set;
34 import java.util.regex.Pattern;
35
36 import org.jcontainer.dna.Configuration;
37 import org.jcontainer.dna.ConfigurationException;
38 import org.objectledge.ComponentInitializationError;
39 import org.objectledge.filesystem.FileSystem;
40 import org.objectledge.filesystem.LocalFileSystemProvider;
41 import org.objectledge.utils.StringUtils;
42
43 /***
44 * A helper object for manangin a directory containing executable scripts in the local filesystem.
45 * <p>
46 * The helper has two functions:
47 * <ul>
48 * <li>Ensuring that the scripts in the local filesystem have apropriate privileges. This is useful
49 * after the scripts get extracted from war/jar files using the
50 * {@link org.objectledge.filesystem.ContentExtractor}</li>
51 * <li>Providing absolute paths to the script files in the server filesystem. This is necessary to
52 * execute the scritpts.</li>
53 * </ul>
54 *
55 * @author <a href="rafal@caltha.pl">RafaĆ Krzewski</a>
56 * @version $Id: ScriptDirectory.java,v 1.2 2006/03/28 18:02:38 zwierzem Exp $
57 */
58 public class ScriptDirectory
59 {
60 public static final String DEFAULT_PROVIDER = "local";
61
62 public static final String DEFAULT_DIRECTORY = null;
63
64 public static final String DEFAULT_PATH_PATTERN = ".*//.(sh|pl|py)$";
65
66 public static final String DEFAULT_COMMAND = "chmod a+x";
67
68 private static String fs = System.getProperty("file.separator");
69
70 private final LocalFileSystemProvider provider;
71
72 private final String directory;
73
74 private final File baseDir;
75
76 /***
77 * Creates a new ScriptDirectory instance.
78 *
79 * @param fileSystem the FileSystem component.
80 * @param providerName the name of the provider to use ("local" in normal circumstances).
81 * @param directory the directory to scan for scripts in order to ensure executability (null to
82 * disable).
83 * @param pathPattern pattern to match file name against in order to decide if they should be
84 * made executable.
85 * @param command the command string to execute to make a script executable - path is appended
86 * as additional argument argument.
87 */
88 public ScriptDirectory(FileSystem fileSystem, String providerName, String directory,
89 String pathPattern, String command)
90 {
91 this.directory = directory;
92 this.provider = (LocalFileSystemProvider)fileSystem.getProvider(providerName);
93 this.baseDir = null;
94 ensureExecutable(pathPattern, command);
95 }
96
97 /***
98 * Creates a new ScriptDirectory instance.
99 *
100 * @param baseDir the script directory in the host filesystem.
101 * @param pathPattern pattern to match file name against in order to decide if they should be
102 * made executable.
103 * @param command the command string to execute to make a script executable - path is appended
104 * as additional argument argument.
105 */
106 public ScriptDirectory(File baseDir, String pathPattern, String command)
107 {
108 this.directory = null;
109 this.provider = null;
110 this.baseDir = baseDir;
111 ensureExecutable(pathPattern, command);
112 }
113
114 /***
115 * Creates a new ScriptDirectory instance.
116 *
117 * @param fileSystem the FileSystem component.
118 * @param configuration component configuration.
119 * @throws ConfigurationException
120 */
121 public ScriptDirectory(FileSystem fileSystem, Configuration configuration)
122 throws ConfigurationException
123 {
124 if(configuration.getChild("ledge-fs", false) != null)
125 {
126 String providerName = configuration.getChild("ledge-fs").getChild("provider").getValue(
127 DEFAULT_PROVIDER);
128 this.provider = (LocalFileSystemProvider)fileSystem.getProvider(providerName);
129 this.directory = configuration.getChild("ledge-fs").getChild("directory").getValue();
130 this.baseDir = null;
131 }
132 else
133 {
134 this.provider = null;
135 this.directory = null;
136 this.baseDir = new File(configuration.getChild("host-fs").getChild("directory")
137 .getValue());
138 }
139 String pathPattern = configuration.getChild("ensure-executable").getChild("pattern")
140 .getValue(DEFAULT_PATH_PATTERN);
141 String command = configuration.getChild("ensure-executable").getChild("command").getValue(
142 DEFAULT_COMMAND);
143 ensureExecutable(pathPattern, command);
144 }
145
146 /***
147 * Returns the canonical script path in the server's filesystem.
148 *
149 * @param script the path inside Ledge virtual filesystem.
150 * @return the canonical script path in the server's filesystem.
151 * @throws IOException if the path cannot be determined.
152 */
153 public String getPath(String script)
154 throws IOException
155 {
156 if(provider != null)
157 {
158 return provider.getFile(directory + "/" + script).getCanonicalPath();
159 }
160 else
161 {
162 return new File(baseDir, script.replace("/", fs)).getCanonicalPath();
163 }
164 }
165
166
167
168 private void ensureExecutable(String pathPattern, String command)
169 {
170 if(pathPattern != null && pathPattern.length() > 0)
171 {
172 try
173 {
174 if(provider != null)
175 {
176 ensureExecutable(provider, directory, Pattern.compile(pathPattern), command
177 .split(" "));
178 }
179 else
180 {
181 ensureExecutable(baseDir, Pattern.compile(pathPattern), command.split(" "));
182 }
183 }
184 catch(Exception e)
185 {
186 throw new ComponentInitializationError(
187 "failed to ensure script execution permissions", e);
188 }
189 }
190 }
191
192 private static void ensureExecutable(LocalFileSystemProvider provider, String directory,
193 Pattern namePattern, String[] commandTokens)
194 throws IOException, InterruptedException
195 {
196 Set<String> items = provider.list(directory);
197 for(String item : items)
198 {
199 String path = directory + "/" + item;
200 if(provider.isDirectory(path))
201 {
202 ensureExecutable(provider, path, namePattern, commandTokens);
203 }
204 else if(namePattern.matcher(path).matches())
205 {
206 Runtime.getRuntime().exec(
207 StringUtils.push(commandTokens, provider.getFile(path).getCanonicalPath()))
208 .waitFor();
209 }
210 }
211 }
212
213 private static void ensureExecutable(File dir, Pattern namePattern, String[] commandTokens)
214 throws InterruptedException, IOException
215 {
216 File[] items = dir.listFiles();
217 for(File item : items)
218 {
219 if(item.isDirectory())
220 {
221 ensureExecutable(item, namePattern, commandTokens);
222 }
223 else if(namePattern.matcher(item.getPath()).matches())
224 {
225 Runtime.getRuntime().exec(StringUtils.push(commandTokens, item.getCanonicalPath()))
226 .waitFor();
227 }
228 }
229 }
230 }