KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > ruby > RubyMimeResolver


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 package org.netbeans.modules.ruby;
20
21 import java.io.IOException JavaDoc;
22 import java.io.InputStream JavaDoc;
23
24 import org.openide.filesystems.FileObject;
25 import org.openide.filesystems.MIMEResolver;
26
27
28 /**
29  * Recognize Ruby file types
30  *
31  * @author Tor Norbye
32  */

33 public class RubyMimeResolver extends MIMEResolver {
34     /**
35      * MIME type for Ruby. Don't change this without also consulting the various XML files
36      * that cannot reference this value directly.
37      */

38     public static final String JavaDoc RUBY_MIME_TYPE = "text/x-ruby"; // application/x-ruby is also used a fair bit.
39

40     /** Number of bytes to sniff from the file headers */
41     private static final int HEADER_LENGTH = 20;
42
43     public RubyMimeResolver() {
44     }
45
46     public String JavaDoc findMIMEType(FileObject fo) {
47         String JavaDoc ext = fo.getExt();
48         
49         if (ext.equalsIgnoreCase("rb") || ext.equalsIgnoreCase("mab") || // NOI18N
50
ext.equalsIgnoreCase("gemspec") || ext.equalsIgnoreCase("rake")) { // NOI18N
51
return RUBY_MIME_TYPE;
52         }
53
54 // // TODO - is this just a Rails thing? Maybe register in the rails support module
55
// if (ext.equalsIgnoreCase("conf")) {
56
// return RUBY_MIME_TYPE;
57
// }
58

59         String JavaDoc name = fo.getName();
60
61         if ("Rakefile".equals(name) || "rakefile".equals(name)) {
62             return RUBY_MIME_TYPE;
63         }
64         
65         // Read the file header and look for #!/usr/bin/ruby (or similar) markers
66
// but only for files without extensions or with the extension .cgi
67
if (ext.length() == 0 || ext.equals("cgi")) {
68             byte[] header = readHeader(fo);
69
70             if (header != null) {
71                 if (isRubyHeader(header)) {
72                     return RUBY_MIME_TYPE;
73                 }
74             }
75         }
76
77         return null;
78     }
79
80     public static boolean isRubyHeader(byte[] header) {
81         int max = header.length;
82
83         if ((max < 2) || (header[0] != '#') || (header[1] != '!')) {
84             return false;
85         }
86
87         // See if we have either
88
// #!/usr/bin/ruby
89
// or some variation of that, e.g.
90
// #! C:\programs\ruby.exe
91
// or the env variety
92
// #!/usr/bin/env ruby
93
// or some variety of that
94

95         // Skip spaces
96
int index = 2;
97
98         while ((index < max) && (header[index] == ' ')) {
99             index++;
100         }
101
102         // Look for the end of the path
103
while ((index < max) && (header[index] != '\n') && (header[index] != ' ')) {
104             index++;
105         }
106
107         index--;
108
109         // Back up and see what the last word was
110
while ((index >= 2) && (header[index] != '/') && (header[index] != '\\') &&
111                 (header[index] != ' ')) {
112             index--;
113         }
114
115         index++;
116
117         // See if it's "ruby", "jruby", or "env" ?
118
if ((((index + 3) < max) && (header[index] == 'r') && (header[index + 1] == 'u') &&
119                 (header[index + 2] == 'b') && (header[index + 3] == 'y')) ||
120                 (((index + 4) < max) && (header[index] == 'j') && (header[index + 1] == 'r') &&
121                 (header[index + 2] == 'u') && (header[index + 3] == 'b') &&
122                 (header[index + 4] == 'y'))) {
123             // It's ruby or jruby
124
// See if the suffix is okay
125
if (header[index] == 'j') {
126                 index += 5;
127             } else {
128                 index += 4;
129             }
130
131             if ((index >= max) || (header[index] == '\n') || (header[index] == ' ')) {
132                 return true;
133             }
134
135             if ((header[index] == '.') && ((index + 3) < max) && (header[index + 1] == 'e') &&
136                     (header[index + 2] == 'x') && (header[index + 3] == 'e')) {
137                 return true;
138             }
139
140             return false;
141         } else if (((index + 2) < max) && (header[index] == 'e') && (header[index + 1] == 'n') &&
142                 (header[index + 2] == 'v')) {
143             index += 3;
144
145             // It's env
146
if ((header[index] == ' ') ||
147                     ((header[index] == '.') && ((index + 4) < max) && (header[index + 1] == 'e') &&
148                     (header[index + 2] == 'x') && (header[index + 3] == 'e') &&
149                     (header[index + 4] == ' '))) {
150                 // Find the next space and look for ruby or jruby
151
if (header[index] == '.') {
152                     index += 4;
153                 }
154
155                 while ((index < max) && (header[index] == ' ')) {
156                     index++;
157                 }
158
159                 // Make sure we have "ruby" or "jruby" (or ruby.exe)?
160
if ((((index + 3) < max) && (header[index] == 'r') && (header[index + 1] == 'u') &&
161                         (header[index + 2] == 'b') && (header[index + 3] == 'y')) ||
162                         (((index + 4) < max) && (header[index] == 'j') &&
163                         (header[index + 1] == 'r') && (header[index + 2] == 'u') &&
164                         (header[index + 3] == 'b') && (header[index + 4] == 'y'))) {
165                     // Ensure that nothing FOLLOWS ruby or jruby
166
if (header[index] == 'j') {
167                         index += 5;
168                     } else {
169                         index += 4;
170                     }
171
172                     if ((index == max) || (header[index] == '\n') || (header[index] == ' ') ||
173                             ((header[index] == '.') && ((index + 3) < max) &&
174                             (header[index + 1] == 'e') && (header[index + 2] == 'x') &&
175                             (header[index + 3] == 'e'))) {
176                         return true;
177                     }
178                 }
179             }
180         }
181
182         return false;
183     }
184
185     private byte[] readHeader(FileObject fo) {
186         // See if it looks like a Ruby file based on the shebang line
187
byte[] header = new byte[HEADER_LENGTH];
188
189         InputStream JavaDoc in = null;
190
191         try {
192             in = fo.getInputStream();
193
194             for (int i = 0; i < HEADER_LENGTH;) {
195                 try {
196                     int read = in.read(header, i, HEADER_LENGTH - i);
197
198                     if (read < 0) {
199                         return null; // unexpected end
200
}
201
202                     i += read;
203                 } catch (IOException JavaDoc ex) {
204                     return null; // unexpected end
205
}
206             }
207         } catch (IOException JavaDoc openex) {
208             return null; // unexpected end
209
} finally {
210             try {
211                 if (in != null) {
212                     in.close();
213                 }
214             } catch (IOException JavaDoc ioe) {
215                 // already closed
216
}
217         }
218
219         return header;
220     }
221 }
222
Popular Tags