1 package org.apache.maven.jxr.pacman;
2
3 /*
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
19 * under the License.
20 */
21
22 import org.codehaus.plexus.util.StringUtils;
23
24 import java.io.File;
25 import java.io.FileInputStream;
26 import java.io.FileReader;
27 import java.io.IOException;
28 import java.io.InputStreamReader;
29 import java.io.Reader;
30 import java.io.StreamTokenizer;
31
32 /**
33 * PacMan implementation of a JavaFile. This will parse out the file and
34 * determine package, class, and imports
35 *
36 * @author <a href="mailto:burton@apache.org">Kevin A. Burton</a>
37 * @version $Id: JavaFileImpl.java 524441 2007-03-31 15:44:15Z dennisl $
38 */
39 public class JavaFileImpl
40 extends JavaFile
41 {
42 private Reader reader;
43
44 /**
45 * Create a new JavaFileImpl that points to a given file...
46 *
47 * @param filename
48 * @throws IOException
49 */
50 public JavaFileImpl( String filename, String encoding )
51 throws IOException
52 {
53 this.setFilename( filename );
54 this.setEncoding( encoding );
55
56 //always add java.lang.* to the package imports because the JVM always
57 //does this implicitly. Unless we add this to the ImportTypes JXR
58 //won't pick up on this.
59
60 this.addImportType( new ImportType( "java.lang.*" ) );
61
62 //now parse out this file.
63
64 this.parse();
65 }
66
67 /**
68 * Open up the file and try to determine package, class and import
69 * statements.
70 */
71 private void parse()
72 throws IOException
73 {
74 StreamTokenizer stok = null;
75 try
76 {
77 stok = this.getTokenizer();
78
79 while ( stok.nextToken() != StreamTokenizer.TT_EOF )
80 {
81
82 if ( stok.sval == null )
83 {
84 continue;
85 }
86
87 //set the package
88 if ( "package".equals( stok.sval ) && stok.ttype != '\"' )
89 {
90 stok.nextToken();
91 this.setPackageType( new PackageType( stok.sval ) );
92 }
93
94 //set the imports
95 if ( "import".equals( stok.sval ) && stok.ttype != '\"' )
96 {
97 stok.nextToken();
98
99 String name = stok.sval;
100
101 /*
102 WARNING: this is a bug/non-feature in the current
103 StreamTokenizer. We needed to set the comment char as "*"
104 and packages that are imported with this (ex "test.*") will be
105 stripped( and become "test." ). Here we need to test for this
106 and if necessary re-add the char.
107 */
108 if ( name.charAt( name.length() - 1 ) == '.' )
109 {
110 name = name + "*";
111 }
112
113 this.addImportType( new ImportType( name ) );
114 }
115
116 // Add the class or classes. There can be several classes in one file so
117 // continue with the while loop to get them all.
118 if ( ( "class".equals( stok.sval ) || "interface".equals( stok.sval ) || "enum".equals( stok.sval ) )
119 && stok.ttype != '\"' )
120 {
121 stok.nextToken();
122 this.addClassType( new ClassType( stok.sval,
123 getFilenameWithoutPathOrExtension( this.getFilename() ) ) );
124 }
125
126 }
127 }
128 finally
129 {
130 stok = null;
131 if ( this.reader != null )
132 {
133 this.reader.close();
134 }
135 }
136 }
137
138 /**
139 * Remove the path and the ".java" extension from a filename.
140 */
141 private static String getFilenameWithoutPathOrExtension( String filename )
142 {
143 String newFilename;
144 // Remove the ".java" extension from the filename, if it exists
145 int extensionIndex = filename.lastIndexOf( ".java" );
146 if ( extensionIndex == -1 )
147 {
148 newFilename = filename;
149 }
150 else
151 {
152 newFilename = filename.substring( 0, extensionIndex );
153 }
154
155 // Remove the path, after unifying path separators
156 newFilename = StringUtils.replace( newFilename, "\\", "/" );
157 int pathIndex = newFilename.lastIndexOf( "/" );
158 if ( pathIndex == -1 )
159 {
160 return newFilename;
161 }
162 else
163 {
164 return newFilename.substring( pathIndex + 1 );
165 }
166 }
167
168 /**
169 * Get a StreamTokenizer for this file.
170 */
171 private StreamTokenizer getTokenizer()
172 throws IOException
173 {
174
175 if ( !new File( this.getFilename() ).exists() )
176 {
177 throw new IOException( this.getFilename() + " does not exist!" );
178 }
179
180 if ( this.getEncoding() != null )
181 {
182 this.reader = new InputStreamReader( new FileInputStream( this.getFilename() ), this.getEncoding() );
183 }
184 else
185 {
186 this.reader = new FileReader( this.getFilename() );
187 }
188
189 StreamTokenizer stok = new StreamTokenizer( reader );
190 //int tok;
191
192 stok.commentChar( '*' );
193 stok.wordChars( '_', '_' );
194
195 // set tokenizer to skip comments
196 stok.slashStarComments( true );
197 stok.slashSlashComments( true );
198
199 return stok;
200 }
201
202 }