View Javadoc

1   /*
2    * ModeShape (http://www.modeshape.org)
3    * See the COPYRIGHT.txt file distributed with this work for information
4    * regarding copyright ownership.  Some portions may be licensed
5    * to Red Hat, Inc. under one or more contributor license agreements.
6    * See the AUTHORS.txt file in the distribution for a full listing of 
7    * individual contributors. 
8    *
9    * ModeShape is free software. Unless otherwise indicated, all code in ModeShape
10   * is licensed to you under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation; either version 2.1 of
12   * the License, or (at your option) any later version.
13   *
14   * ModeShape is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   * Lesser General Public License for more details.
18   *
19   * You should have received a copy of the GNU Lesser General Public
20   * License along with this software; if not, write to the Free
21   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
23   */
24  package org.modeshape.example.sequencer;
25  
26  import java.net.URL;
27  import java.util.ArrayList;
28  import java.util.Calendar;
29  import java.util.LinkedList;
30  import java.util.List;
31  import java.util.Map;
32  import java.util.Properties;
33  import java.util.TreeMap;
34  import java.util.concurrent.TimeUnit;
35  import javax.jcr.Binary;
36  import javax.jcr.Node;
37  import javax.jcr.NodeIterator;
38  import javax.jcr.PathNotFoundException;
39  import javax.jcr.Property;
40  import javax.jcr.PropertyIterator;
41  import javax.jcr.Repository;
42  import javax.jcr.RepositoryException;
43  import javax.jcr.Session;
44  import javax.jcr.Value;
45  import javax.jcr.ValueFormatException;
46  import org.modeshape.graph.connector.inmemory.InMemoryRepositorySource;
47  import org.modeshape.jcr.JcrConfiguration;
48  import org.modeshape.jcr.JcrEngine;
49  import org.modeshape.jcr.JcrTools;
50  import org.modeshape.jcr.api.SecurityContext;
51  import org.modeshape.jcr.api.SecurityContextCredentials;
52  import org.modeshape.repository.sequencer.SequencingService;
53  import org.modeshape.sequencer.classfile.ClassFileSequencer;
54  import org.modeshape.sequencer.classfile.ClassFileSequencerLexicon;
55  
56  /**
57   * The main application for running the sequencers.
58   */
59  public class SequencingClient {
60  
61      public static final String DEFAULT_REPOSITORY_NAME = "repo";
62      public static final String DEFAULT_WORKSPACE_NAME = "default";
63      public static final String DEFAULT_USERNAME = "jsmith";
64      public static final char[] DEFAULT_PASSWORD = "secret".toCharArray();
65  
66      public static void main( String[] args ) {
67          // Configure the ModeShape configuration. This could be done by loading a configuration from a file, or by
68          // using a (local or remote) configuration repository, or by setting up the configuration programmatically.
69          // This example uses the programmatic approach...
70          String repositoryId = "content";
71          String workspaceName = "default";
72          JcrConfiguration config = new JcrConfiguration();
73          // Set up the in-memory source where we'll upload the content and where the sequenced output will be stored ...
74          config.repositorySource("store")
75                .usingClass(InMemoryRepositorySource.class)
76                .setDescription("The repository for our content")
77                .setProperty("defaultWorkspaceName", workspaceName);
78          // Set up the JCR repository to use the source ...
79          config.repository(repositoryId)
80                .addNodeTypes("sequencing.cnd")
81                .registerNamespace(ClassFileSequencerLexicon.Namespace.PREFIX, ClassFileSequencerLexicon.Namespace.URI)
82                .setSource("store");
83          // Set up the image sequencer ...
84          config.sequencer("Image Sequencer")
85                .usingClass("org.modeshape.sequencer.image.ImageMetadataSequencer")
86                .loadedFromClasspath()
87                .setDescription("Sequences image files to extract the characteristics of the image")
88                .sequencingFrom("//(*.(jpg|jpeg|gif|bmp|pcx|png|iff|ras|pbm|pgm|ppm|psd)[*])/jcr:content[@jcr:data]")
89                .andOutputtingTo("/images/$1");
90          // Set up the MP3 sequencer ...
91          config.sequencer("MP3 Sequencer")
92                .usingClass("org.modeshape.sequencer.mp3.Mp3MetadataSequencer")
93                .loadedFromClasspath()
94                .setDescription("Sequences mp3 files to extract the id3 tags of the audio file")
95                .sequencingFrom("//(*.mp3[*])/jcr:content[@jcr:data]")
96                .andOutputtingTo("/mp3s/$1");
97          // Set up the Java class file sequencer ...
98          config.sequencer("Java Class Sequencer")
99                .usingClass(ClassFileSequencer.class)
100               .setDescription("Sequences Java class files to extract the structure of the classes")
101               .sequencingFrom("//*.class[*]/jcr:content[@jcr:data]")
102               .andOutputtingTo("/classes");
103         // Set up the Java source file sequencer ...
104         config.sequencer("Java Sequencer")
105               .usingClass("org.modeshape.sequencer.java.JavaMetadataSequencer")
106               .loadedFromClasspath()
107               .setDescription("Sequences Java files to extract the AST structure of the Java source code")
108               .sequencingFrom("//(*.java[*])/jcr:content[@jcr:data]")
109               .andOutputtingTo("/java/$1");
110         // Set up the CSV file sequencer ...
111         config.sequencer("CSV Sequencer")
112               .usingClass("org.modeshape.sequencer.text.DelimitedTextSequencer")
113               .loadedFromClasspath()
114               .setDescription("Sequences CSV files to extract the contents")
115               .sequencingFrom("//(*.csv[*])/jcr:content[@jcr:data]")
116               .andOutputtingTo("/csv/$1");
117         // Set up the fixed width file sequencer ...
118         config.sequencer("Fixed Width Sequencer")
119               .usingClass("org.modeshape.sequencer.text.FixedWidthTextSequencer")
120               .loadedFromClasspath()
121               .setDescription("Sequences fixed width files to extract the contents")
122               .setProperty("commentMarker", "#")
123               .setProperty("columnStartPositions", new int[] {10, 20, 30, 40})
124               .sequencingFrom("//(*.txt[*])/jcr:content[@jcr:data]")
125               .andOutputtingTo("/txt/$1");
126 
127         // Now start the client and tell it which repository and workspace to use ...
128         SequencingClient client = new SequencingClient(config, repositoryId, workspaceName);
129         client.setUserInterface(new ConsoleInput(client));
130     }
131 
132     private final String repositoryName;
133     private final String workspaceName;
134     private final JcrConfiguration configuration;
135     private JcrEngine engine;
136     private UserInterface userInterface;
137     private Repository repository;
138 
139     public SequencingClient( JcrConfiguration config,
140                              String repositoryName,
141                              String workspaceName ) {
142         this.configuration = config;
143         this.repositoryName = repositoryName != null ? repositoryName : DEFAULT_REPOSITORY_NAME;
144         this.workspaceName = workspaceName != null ? workspaceName : DEFAULT_WORKSPACE_NAME;
145     }
146 
147     /**
148      * Set the user interface that this client should use.
149      * 
150      * @param userInterface
151      */
152     public void setUserInterface( UserInterface userInterface ) {
153         this.userInterface = userInterface;
154     }
155 
156     /**
157      * Start up the JCR repository, using an implementation-specific API.
158      * 
159      * @throws Exception
160      */
161     public void startRepository() throws Exception {
162         if (this.repository == null) {
163             try {
164                 // Start the ModeShape engine ...
165                 this.engine = this.configuration.build();
166                 this.engine.start();
167 
168                 // Now get the repository instance ...
169                 this.repository = this.engine.getRepository(repositoryName);
170 
171             } catch (Exception e) {
172                 this.repository = null;
173                 throw e;
174             }
175         }
176     }
177 
178     /**
179      * Shutdown the repository. This method only uses the JCR API.
180      * 
181      * @throws Exception
182      */
183     public void shutdownRepository() throws Exception {
184         if (this.repository != null) {
185             try {
186                 this.engine.shutdown();
187                 this.engine.awaitTermination(4, TimeUnit.SECONDS);
188             } finally {
189                 this.repository = null;
190             }
191         }
192     }
193 
194     /**
195      * Get the sequencing statistics.
196      * 
197      * @return the statistics; never null
198      */
199     public SequencingService.Statistics getStatistics() {
200         return this.engine.getSequencingService().getStatistics();
201     }
202 
203     /**
204      * Prompt the user interface for the file to upload into the JCR repository, then upload it using the JCR API.
205      * 
206      * @throws Exception
207      */
208     public void uploadFile() throws Exception {
209         URL url = this.userInterface.getFileToUpload();
210         // Grab the last segment of the URL path, using it as the filename
211         String filename = url.getPath().replaceAll("([^/]*/)*", "");
212         String nodePath = this.userInterface.getRepositoryPath("/a/b/" + filename);
213         String mimeType = getMimeType(url);
214 
215         if (mimeType == null) {
216             System.err.println("Could not determine mime type for file " + url + ".  Cancelling upload.");
217             return;
218         }
219 
220         // Now use the JCR API to upload the file ...
221         Session session = createSession();
222         JcrTools tools = new JcrTools();
223         try {
224             // Create the node at the supplied path ...
225             Node node = tools.findOrCreateNode(session, nodePath, "nt:folder", "nt:file");
226 
227             // Upload the file to that node ...
228             Node contentNode = tools.findOrCreateChild(node, "jcr:content", "nt:resource");
229             contentNode.setProperty("jcr:mimeType", mimeType);
230             contentNode.setProperty("jcr:lastModified", Calendar.getInstance());
231             Binary binaryValue = session.getValueFactory().createBinary(url.openStream());
232             contentNode.setProperty("jcr:data", binaryValue);
233 
234             // Save the session ...
235             session.save();
236         } finally {
237             session.logout();
238         }
239     }
240 
241     /**
242      * Perform a search of the repository for all image metadata automatically created by the image sequencer.
243      * 
244      * @throws Exception
245      */
246     public void search() throws Exception {
247         // Use JCR to search the repository for image metadata ...
248         List<ContentInfo> infos = new ArrayList<ContentInfo>();
249         Session session = createSession();
250         try {
251             // Find the node ...
252             Node root = session.getRootNode();
253 
254             if (root.hasNode("images") || root.hasNode("mp3s")) {
255                 Node mediasNode;
256                 if (root.hasNode("images")) {
257                     mediasNode = root.getNode("images");
258 
259                     for (NodeIterator iter = mediasNode.getNodes(); iter.hasNext();) {
260                         Node mediaNode = iter.nextNode();
261                         if (mediaNode.hasNode("image:metadata")) {
262                             infos.add(extractMediaInfo("image:metadata", "image", mediaNode));
263                         }
264                     }
265                 }
266                 if (root.hasNode("mp3s")) {
267                     mediasNode = root.getNode("mp3s");
268 
269                     for (NodeIterator iter = mediasNode.getNodes(); iter.hasNext();) {
270                         Node mediaNode = iter.nextNode();
271                         if (mediaNode.hasNode("mp3:metadata")) {
272                             infos.add(extractMediaInfo("mp3:metadata", "mp3", mediaNode));
273                         }
274                     }
275                 }
276 
277             }
278             if (root.hasNode("zips")) {
279                 LinkedList<Node> nodesToVisit = new LinkedList<Node>();
280 
281                 for (NodeIterator i = root.getNode("zips").getNodes(); i.hasNext();) {
282                     nodesToVisit.addLast(i.nextNode());
283                 }
284 
285                 while (!nodesToVisit.isEmpty()) {
286                     Node node = nodesToVisit.remove();
287 
288                     String nodeType = "nt:folder".equals(node.getPrimaryNodeType().getName()) ? "folder" : "file";
289                     infos.add(new MediaInfo(node.getPath(), node.getName(), nodeType, new Properties()));
290 
291                     for (NodeIterator i = node.getNodes(); i.hasNext();) {
292                         nodesToVisit.addLast(i.nextNode());
293                     }
294 
295                 }
296             }
297             if (root.hasNode("txt")) {
298                 LinkedList<Node> nodesToVisit = new LinkedList<Node>();
299 
300                 for (NodeIterator i = root.getNode("txt").getNodes(); i.hasNext();) {
301                     nodesToVisit.addLast(i.nextNode());
302                 }
303 
304                 while (!nodesToVisit.isEmpty()) {
305                     Node node = nodesToVisit.remove();
306                     Properties props = new Properties();
307                     int rowCount = 0;
308                     int colCount = 0;
309 
310                     for (NodeIterator rowIter = node.getNodes(); rowIter.hasNext();) {
311                         Node rowNode = rowIter.nextNode();
312 
313                         rowCount++;
314                         colCount = 0;
315 
316                         for (NodeIterator colIter = rowNode.getNodes(); colIter.hasNext();) {
317                             colIter.nextNode();
318                             colCount++;
319                         }
320                     }
321                     props.put("rows", String.valueOf(rowCount));
322                     props.put("columns", String.valueOf(colCount));
323 
324                     infos.add(new ContentInfo(node.getPath(), node.getName(), props));
325                 }
326             }
327             if (root.hasNode("csv")) {
328                 LinkedList<Node> nodesToVisit = new LinkedList<Node>();
329 
330                 for (NodeIterator i = root.getNode("csv").getNodes(); i.hasNext();) {
331                     nodesToVisit.addLast(i.nextNode());
332                 }
333 
334                 while (!nodesToVisit.isEmpty()) {
335                     Node node = nodesToVisit.remove();
336                     Properties props = new Properties();
337                     int rowCount = 0;
338                     int colCount = 0;
339 
340                     for (NodeIterator rowIter = node.getNodes(); rowIter.hasNext();) {
341                         Node rowNode = rowIter.nextNode();
342 
343                         rowCount++;
344                         colCount = 0;
345 
346                         for (NodeIterator colIter = rowNode.getNodes(); colIter.hasNext();) {
347                             colIter.nextNode();
348                             colCount++;
349                         }
350                     }
351                     props.put("rows", String.valueOf(rowCount));
352                     props.put("columns", String.valueOf(colCount));
353 
354                     infos.add(new ContentInfo(node.getPath(), node.getName(), props));
355                 }
356             }
357 
358             if (root.hasNode("classes")) {
359                 LinkedList<Node> nodesToVisit = new LinkedList<Node>();
360 
361                 for (NodeIterator i = root.getNode("classes").getNodes(); i.hasNext();) {
362                     nodesToVisit.addLast(i.nextNode());
363                 }
364 
365                 while (!nodesToVisit.isEmpty()) {
366                     Node node = nodesToVisit.remove();
367 
368                     if ("class:class".equals(node.getPrimaryNodeType().getName())) {
369                         Properties props = new Properties();
370                         props.put("constructors", node.getNode("class:constructors").getNodes().getSize());
371                         props.put("methods", node.getNode("class:methods").getNodes().getSize());
372                         props.put("fields", node.getNode("class:fields").getNodes().getSize());
373 
374                         infos.add(new MediaInfo(node.getPath(), node.getName(), "class", props));
375 
376                     } else {
377                         for (NodeIterator i = node.getNodes(); i.hasNext();) {
378                             nodesToVisit.addLast(i.nextNode());
379                         }
380                     }
381 
382                 }
383             }
384             if (root.hasNode("java")) {
385                 Map<String, List<Properties>> tree = new TreeMap<String, List<Properties>>();
386                 // Find the compilation unit node ...
387                 List<Properties> javaElements;
388                 if (root.hasNode("java")) {
389                     Node javaSourcesNode = root.getNode("java");
390                     for (NodeIterator i = javaSourcesNode.getNodes(); i.hasNext();) {
391 
392                         Node javaSourceNode = i.nextNode();
393 
394                         if (javaSourceNode.hasNodes()) {
395                             Node javaCompilationUnit = javaSourceNode.getNodes().nextNode();
396                             // package informations
397 
398                             javaElements = new ArrayList<Properties>();
399                             try {
400                                 Node javaPackageDeclarationNode = javaCompilationUnit.getNode("java:package/java:packageDeclaration");
401                                 javaElements.add(extractJavaInfo(javaPackageDeclarationNode));
402                                 tree.put("Class package", javaElements);
403                             } catch (PathNotFoundException e) {
404                                 // do nothing
405                             }
406 
407                             // import informations
408                             javaElements = new ArrayList<Properties>();
409                             try {
410                                 for (NodeIterator singleImportIterator = javaCompilationUnit.getNode("java:import/java:importDeclaration/java:singleImport")
411                                                                                             .getNodes(); singleImportIterator.hasNext();) {
412                                     Node javasingleTypeImportDeclarationNode = singleImportIterator.nextNode();
413                                     javaElements.add(extractJavaInfo(javasingleTypeImportDeclarationNode));
414                                 }
415                                 tree.put("Class single Imports", javaElements);
416                             } catch (PathNotFoundException e) {
417                                 // do nothing
418                             }
419 
420                             javaElements = new ArrayList<Properties>();
421                             try {
422                                 for (NodeIterator javaImportOnDemandIterator = javaCompilationUnit.getNode("java:import/java:importDeclaration/java:importOnDemand")
423                                                                                                   .getNodes(); javaImportOnDemandIterator.hasNext();) {
424                                     Node javaImportOnDemandtDeclarationNode = javaImportOnDemandIterator.nextNode();
425                                     javaElements.add(extractJavaInfo(javaImportOnDemandtDeclarationNode));
426                                 }
427                                 tree.put("Class on demand imports", javaElements);
428 
429                             } catch (PathNotFoundException e) {
430                                 // do nothing
431                             }
432                             // class head informations
433                             javaElements = new ArrayList<Properties>();
434                             Node javaNormalDeclarationClassNode = javaCompilationUnit.getNode("java:unitType/java:classDeclaration/java:normalClass/java:normalClassDeclaration");
435                             javaElements.add(extractJavaInfo(javaNormalDeclarationClassNode));
436                             tree.put("Class head information", javaElements);
437 
438                             // field member informations
439                             javaElements = new ArrayList<Properties>();
440                             for (NodeIterator javaFieldTypeIterator = javaCompilationUnit.getNode("java:unitType/java:classDeclaration/java:normalClass/java:normalClassDeclaration/java:field/java:fieldType")
441                                                                                          .getNodes(); javaFieldTypeIterator.hasNext();) {
442                                 Node rootFieldTypeNode = javaFieldTypeIterator.nextNode();
443                                 if (rootFieldTypeNode.hasNode("java:primitiveType")) {
444                                     Node javaPrimitiveTypeNode = rootFieldTypeNode.getNode("java:primitiveType");
445                                     javaElements.add(extractJavaInfo(javaPrimitiveTypeNode));
446                                     // more informations
447                                 }
448 
449                                 if (rootFieldTypeNode.hasNode("java:simpleType")) {
450                                     Node javaSimpleTypeNode = rootFieldTypeNode.getNode("java:simpleType");
451                                     javaElements.add(extractJavaInfo(javaSimpleTypeNode));
452                                 }
453                                 if (rootFieldTypeNode.hasNode("java:parameterizedType")) {
454                                     Node javaParameterizedType = rootFieldTypeNode.getNode("java:parameterizedType");
455                                     javaElements.add(extractJavaInfo(javaParameterizedType));
456                                 }
457                                 if (rootFieldTypeNode.hasNode("java:arrayType")) {
458                                     Node javaArrayType = rootFieldTypeNode.getNode("java:arrayType[2]");
459                                     javaElements.add(extractJavaInfo(javaArrayType));
460                                 }
461                             }
462                             tree.put("Class field members", javaElements);
463 
464                             // constructor informations
465                             javaElements = new ArrayList<Properties>();
466                             for (NodeIterator javaConstructorIterator = javaCompilationUnit.getNode("java:unitType/java:classDeclaration/java:normalClass/java:normalClassDeclaration/java:constructor")
467                                                                                            .getNodes(); javaConstructorIterator.hasNext();) {
468                                 Node javaConstructor = javaConstructorIterator.nextNode();
469                                 javaElements.add(extractJavaInfo(javaConstructor));
470                             }
471                             tree.put("Class constructors", javaElements);
472 
473                             // method informations
474                             javaElements = new ArrayList<Properties>();
475                             for (NodeIterator javaMethodIterator = javaCompilationUnit.getNode("java:unitType/java:classDeclaration/java:normalClass/java:normalClassDeclaration/java:method")
476                                                                                       .getNodes(); javaMethodIterator.hasNext();) {
477                                 Node javaMethod = javaMethodIterator.nextNode();
478                                 javaElements.add(extractJavaInfo(javaMethod));
479                             }
480                             tree.put("Class member functions", javaElements);
481 
482                             JavaInfo javaInfo = new JavaInfo(javaCompilationUnit.getPath(), javaCompilationUnit.getName(),
483                                                              "java source", tree);
484                             infos.add(javaInfo);
485                         }
486                     }
487                 }
488 
489             }
490         } finally {
491             session.logout();
492         }
493 
494         // Display the search results ...
495         this.userInterface.displaySearchResults(infos);
496     }
497 
498     private MediaInfo extractMediaInfo( String metadataNodeName,
499                                         String mediaType,
500                                         Node mediaNode ) throws RepositoryException, PathNotFoundException, ValueFormatException {
501         String nodePath = mediaNode.getPath();
502         String nodeName = mediaNode.getName();
503         mediaNode = mediaNode.getNode(metadataNodeName);
504 
505         // Create a Properties object containing the properties for this node; ignore any children ...
506         Properties props = new Properties();
507         for (PropertyIterator propertyIter = mediaNode.getProperties(); propertyIter.hasNext();) {
508             Property property = propertyIter.nextProperty();
509             String name = property.getName();
510             String stringValue = null;
511             if (property.getDefinition().isMultiple()) {
512                 StringBuilder sb = new StringBuilder();
513                 boolean first = true;
514                 for (Value value : property.getValues()) {
515                     if (!first) {
516                         sb.append(", ");
517                         first = false;
518                     }
519                     sb.append(value.getString());
520                 }
521                 stringValue = sb.toString();
522             } else {
523                 stringValue = property.getValue().getString();
524             }
525             props.put(name, stringValue);
526         }
527         // Create the image information object, and add it to the collection ...
528         return new MediaInfo(nodePath, nodeName, mediaType, props);
529     }
530 
531     /**
532      * Extract informations from a specific node.
533      * 
534      * @param node - node, that contains informations.
535      * @return a properties of keys/values.
536      * @throws RepositoryException
537      * @throws IllegalStateException
538      * @throws ValueFormatException
539      */
540     private Properties extractJavaInfo( Node node ) throws ValueFormatException, IllegalStateException, RepositoryException {
541         if (node.hasProperties()) {
542             Properties properties = new Properties();
543             for (PropertyIterator propertyIter = node.getProperties(); propertyIter.hasNext();) {
544                 Property property = propertyIter.nextProperty();
545                 String name = property.getName();
546                 String stringValue = property.getValue().getString();
547                 properties.put(name, stringValue);
548             }
549             return properties;
550         }
551         return null;
552     }
553 
554     /**
555      * Utility method to create a new JCR session.
556      * 
557      * @return the session
558      * @throws RepositoryException
559      */
560     protected Session createSession() throws RepositoryException {
561         // Normally we'd just use SimpleCredentials or some other custom Credentials implementation,
562         // but that would require JAAS (since ModeShape uses that used by default). Since we don't
563         // have a JAAS implementation, we will use the SecurityContextCredentials to wrap
564         // another SecurityContext implementation. This is how you might integrate a non-JAAS security
565         // system into ModeShape. See the repository example for how to set up with JAAS.
566         SecurityContext securityContext = new MyCustomSecurityContext();
567         SecurityContextCredentials credentials = new SecurityContextCredentials(securityContext);
568         return this.repository.login(credentials, workspaceName);
569     }
570 
571     protected String getMimeType( URL file ) {
572         String filename = file.getPath().toLowerCase();
573         if (filename.endsWith(".gif")) return "image/gif";
574         if (filename.endsWith(".png")) return "image/png";
575         if (filename.endsWith(".pict")) return "image/x-pict";
576         if (filename.endsWith(".bmp")) return "image/bmp";
577         if (filename.endsWith(".jpg")) return "image/jpeg";
578         if (filename.endsWith(".jpe")) return "image/jpeg";
579         if (filename.endsWith(".jpeg")) return "image/jpeg";
580         if (filename.endsWith(".ras")) return "image/x-cmu-raster";
581         if (filename.endsWith(".mp3")) return "audio/mpeg";
582         if (filename.endsWith(".jar")) return "application/java-archive";
583         if (filename.endsWith(".java")) return "text/x-java-source";
584         if (filename.endsWith(".csv")) return "text/csv";
585         if (filename.endsWith(".txt")) return "text/plain";
586         if (filename.endsWith(".clazz")) return "application/x-java-class";
587         return null;
588     }
589 
590     protected class MyCustomSecurityContext implements SecurityContext {
591         /**
592          * {@inheritDoc}
593          * 
594          * @see org.modeshape.jcr.api.SecurityContext#getUserName()
595          */
596         public String getUserName() {
597             return "Fred";
598         }
599 
600         /**
601          * {@inheritDoc}
602          * 
603          * @see org.modeshape.jcr.api.SecurityContext#hasRole(java.lang.String)
604          */
605         public boolean hasRole( String roleName ) {
606             return true;
607         }
608 
609         /**
610          * {@inheritDoc}
611          * 
612          * @see org.modeshape.jcr.api.SecurityContext#logout()
613          */
614         public void logout() {
615             // do something
616         }
617     }
618 
619 }