1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package org.modeshape.example.repository;
25
26 import java.io.IOException;
27 import java.util.ArrayList;
28 import java.util.Collections;
29 import java.util.HashSet;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Set;
33 import java.util.concurrent.TimeUnit;
34 import javax.jcr.Credentials;
35 import javax.jcr.Node;
36 import javax.jcr.NodeIterator;
37 import javax.jcr.PropertyIterator;
38 import javax.jcr.Session;
39 import javax.jcr.Value;
40 import javax.security.auth.login.LoginContext;
41 import javax.security.auth.login.LoginException;
42 import net.jcip.annotations.Immutable;
43 import org.jboss.security.config.IDTrustConfiguration;
44 import org.modeshape.common.collection.Problem;
45 import org.modeshape.common.text.NoOpEncoder;
46 import org.modeshape.common.util.CheckArg;
47 import org.modeshape.graph.ExecutionContext;
48 import org.modeshape.graph.Graph;
49 import org.modeshape.graph.JaasSecurityContext;
50 import org.modeshape.graph.Location;
51 import org.modeshape.graph.property.Path;
52 import org.modeshape.graph.property.PathFactory;
53 import org.modeshape.graph.property.PathNotFoundException;
54 import org.modeshape.graph.property.Property;
55 import org.modeshape.jcr.JcrConfiguration;
56 import org.modeshape.jcr.JcrEngine;
57 import org.modeshape.jcr.JcrRepository;
58 import org.xml.sax.SAXException;
59
60
61
62
63 public class RepositoryClient {
64
65 public static final String INMEMORY_REPOSITORY_SOURCE_CLASSNAME = "org.modeshape.connector.inmemory.InMemoryRepositorySource";
66 public static final String JAAS_LOGIN_CONTEXT_NAME = "modeshape-jcr";
67
68
69
70
71 public static void main( String[] args ) {
72
73 IDTrustConfiguration idtrustConfig = new IDTrustConfiguration();
74 try {
75 idtrustConfig.config("security/jaas.conf.xml");
76 } catch (Exception ex) {
77 throw new IllegalStateException(ex);
78 }
79
80
81 RepositoryClient client = new RepositoryClient();
82 for (String arg : args) {
83 arg = arg.trim();
84 if (arg.equals("--api=jcr")) client.setApi(Api.JCR);
85 if (arg.equals("--api=dna")) client.setApi(Api.ModeShape);
86 if (arg.equals("--jaas")) client.setJaasContextName(JAAS_LOGIN_CONTEXT_NAME);
87 if (arg.startsWith("--jaas=") && arg.length() > 7) client.setJaasContextName(arg.substring(7).trim());
88 }
89
90
91 client.setUserInterface(new ConsoleInput(client, args));
92 }
93
94 public enum Api {
95 JCR,
96 ModeShape;
97 }
98
99 private Api api = Api.JCR;
100 private String jaasContextName = JAAS_LOGIN_CONTEXT_NAME;
101 private UserInterface userInterface;
102 private LoginContext loginContext;
103 private JcrEngine engine;
104
105
106
107
108 public void setUserInterface( UserInterface userInterface ) {
109 this.userInterface = userInterface;
110 }
111
112
113
114
115
116
117 public void setApi( Api api ) {
118 this.api = api != null ? api : Api.ModeShape;
119 }
120
121
122
123
124
125
126 public void setJaasContextName( String jaasContextName ) {
127 this.jaasContextName = jaasContextName;
128 }
129
130
131
132
133
134
135
136 public void startRepositories() throws IOException, SAXException {
137 if (engine != null) return;
138
139
140 JcrConfiguration configuration = new JcrConfiguration();
141 configuration.loadFrom(userInterface.getRepositoryConfiguration());
142
143
144 engine = configuration.build();
145 engine.start();
146
147 if (engine.getProblems().hasProblems()) {
148 for (Problem problem : engine.getProblems()) {
149 System.err.println(problem.getMessageString());
150 }
151 throw new RuntimeException("Could not start due to problems");
152 }
153
154
155
156
157 String location = this.userInterface.getLocationOfRepositoryFiles();
158
159
160 engine.getGraph("Cars").importXmlFrom(location + "/cars.xml").into("/");
161 engine.getGraph("Aircraft").importXmlFrom(location + "/aircraft.xml").into("/");
162 }
163
164
165
166
167
168
169 public List<String> getNamesOfRepositories() {
170 List<String> names = new ArrayList<String>(engine.getRepositoryNames());
171 Collections.sort(names);
172 return Collections.unmodifiableList(names);
173 }
174
175
176
177
178
179
180
181 public void shutdown() throws InterruptedException, LoginException {
182 logout();
183 if (engine == null) return;
184 try {
185
186 engine.shutdown();
187 engine.awaitTermination(5, TimeUnit.SECONDS);
188 } finally {
189 engine = null;
190 }
191 }
192
193
194
195
196
197
198
199 protected LoginContext getLoginContext() throws LoginException {
200 if (loginContext == null) {
201 if (jaasContextName != null) {
202 loginContext = new LoginContext(jaasContextName, this.userInterface.getCallbackHandler());
203 loginContext.login();
204 }
205 }
206 return loginContext;
207 }
208
209
210
211
212
213
214 public void logout() throws LoginException {
215 if (loginContext != null) {
216 try {
217 loginContext.logout();
218 } finally {
219 loginContext = null;
220 }
221 }
222 }
223
224
225
226
227
228
229
230
231
232
233
234
235
236 public boolean getNodeInfo( String sourceName,
237 String pathToNode,
238 Map<String, Object[]> properties,
239 List<String> children ) throws Throwable {
240 LoginContext loginContext = getLoginContext();
241 switch (api) {
242 case JCR: {
243 JcrRepository jcrRepository = engine.getRepository(sourceName);
244 Session session = null;
245 if (loginContext != null) {
246
247 Credentials credentials = new JaasCredentials(loginContext);
248 session = jcrRepository.login(credentials);
249 } else {
250 session = jcrRepository.login();
251 }
252 try {
253
254 pathToNode = pathToNode.replaceAll("^/+", "");
255
256 Node root = session.getRootNode();
257 Node node = root;
258 if (pathToNode.length() != 0) {
259 if (!pathToNode.endsWith("]")) pathToNode = pathToNode + "[1]";
260 node = pathToNode.equals("") ? root : root.getNode(pathToNode);
261 }
262
263
264 if (properties != null) {
265 for (PropertyIterator iter = node.getProperties(); iter.hasNext();) {
266 javax.jcr.Property property = iter.nextProperty();
267 Object[] values = null;
268
269 if (property.getDefinition().isMultiple()) {
270 Value[] jcrValues = property.getValues();
271 values = new String[jcrValues.length];
272 for (int i = 0; i < jcrValues.length; i++) {
273 values[i] = jcrValues[i].getString();
274 }
275 } else {
276 values = new Object[] {property.getValue().getString()};
277 }
278 properties.put(property.getName(), values);
279 }
280 }
281 if (children != null) {
282
283 Set<String> sameNameSiblings = new HashSet<String>();
284 for (NodeIterator iter = node.getNodes(); iter.hasNext();) {
285 javax.jcr.Node child = iter.nextNode();
286 if (child.getIndex() > 1) sameNameSiblings.add(child.getName());
287 }
288 for (NodeIterator iter = node.getNodes(); iter.hasNext();) {
289 javax.jcr.Node child = iter.nextNode();
290 String name = child.getName();
291 if (sameNameSiblings.contains(name)) name = name + "[" + child.getIndex() + "]";
292 children.add(name);
293 }
294 }
295 } catch (javax.jcr.ItemNotFoundException e) {
296 return false;
297 } catch (javax.jcr.PathNotFoundException e) {
298 return false;
299 } finally {
300 if (session != null) session.logout();
301 }
302 break;
303 }
304 case ModeShape: {
305 try {
306
307 ExecutionContext context = this.engine.getExecutionContext();
308 if (loginContext != null) {
309 JaasSecurityContext security = new JaasSecurityContext(loginContext);
310 context = context.with(security);
311 }
312 Graph graph = engine.getGraph(context, sourceName);
313 org.modeshape.graph.Node node = graph.getNodeAt(pathToNode);
314
315 if (properties != null) {
316
317 for (Property property : node.getProperties()) {
318 String name = property.getName().getString(context.getNamespaceRegistry());
319 properties.put(name, property.getValuesAsArray());
320 }
321 }
322 if (children != null) {
323
324 for (Location child : node.getChildren()) {
325 String name = child.getPath().getLastSegment().getString(context.getNamespaceRegistry());
326 children.add(name);
327 }
328 }
329 } catch (PathNotFoundException e) {
330 return false;
331 }
332 break;
333 }
334 }
335 return true;
336 }
337
338
339
340
341
342
343
344
345
346 public String buildPath( String current,
347 String input ) {
348 if (current == null) current = "/";
349 if (input == null || input.length() == 0) return current;
350 ExecutionContext context = this.engine.getExecutionContext();
351 PathFactory factory = context.getValueFactories().getPathFactory();
352 Path inputPath = factory.create(input);
353 if (inputPath.isAbsolute()) {
354 return inputPath.getNormalizedPath().getString(context.getNamespaceRegistry(), NoOpEncoder.getInstance());
355 }
356 Path currentPath = factory.create(current);
357 currentPath = factory.create(currentPath, inputPath);
358 currentPath = currentPath.getNormalizedPath();
359 return currentPath.getString(context.getNamespaceRegistry(), NoOpEncoder.getInstance());
360 }
361
362
363
364
365
366
367 @Immutable
368 protected static class JaasCredentials implements Credentials {
369 private static final long serialVersionUID = 1L;
370 private final LoginContext context;
371
372 public JaasCredentials( LoginContext context ) {
373 CheckArg.isNotNull(context, "context");
374 this.context = context;
375 }
376
377
378
379
380
381
382 public LoginContext getLoginContext() {
383 return context;
384 }
385
386 }
387 }