1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 package com.sun.star.help; 25 26 import java.io.FileInputStream; 27 import java.io.FileOutputStream; 28 import java.util.Arrays; 29 import java.util.HashSet; 30 import java.util.List; 31 import java.util.zip.ZipEntry; 32 import java.util.zip.ZipOutputStream; 33 import java.util.zip.CRC32; 34 import org.apache.lucene.analysis.standard.StandardAnalyzer; 35 import org.apache.lucene.analysis.cjk.CJKAnalyzer; 36 import org.apache.lucene.analysis.Analyzer; 37 import org.apache.lucene.index.IndexWriter; 38 import org.apache.lucene.util.Version; 39 import org.apache.lucene.store.NIOFSDirectory; 40 41 import java.io.File; 42 import java.io.FileNotFoundException; 43 import java.io.IOException; 44 import java.util.Date; 45 46 public class HelpIndexerTool 47 { 48 public HelpIndexerTool() 49 { 50 } 51 52 53 /** 54 * @param args the command line arguments 55 */ 56 public static void main( String[] args ) 57 { 58 boolean bExtensionMode = false; 59 mainImpl( args, bExtensionMode ); 60 } 61 62 public static void mainImpl( String[] args, boolean bExtensionMode ) 63 { 64 String aDirToZipStr = ""; 65 String aSrcDirStr = ""; 66 String aLanguageStr = ""; 67 String aModule = ""; 68 String aTargetZipFileStr = ""; 69 String aCfsName = ""; 70 String aSegmentName = ""; 71 72 // Scan arguments 73 //If this tool is invoked in the build process for extensions help, 74 //then -extension must be set. 75 boolean bExtension = false; 76 boolean bLang = false; 77 boolean bMod = false; 78 boolean bZipDir = false; 79 boolean bSrcDir = false; 80 boolean bOutput = false; 81 boolean bCfsName = false; 82 boolean bSegmentName = false; 83 84 int nArgCount = args.length; 85 for( int i = 0 ; i < nArgCount ; i++ ) 86 { 87 if( "-extension".equals(args[i]) ) 88 { 89 bExtension = true; 90 } 91 else if( "-lang".equals(args[i]) ) 92 { 93 if( i + 1 < nArgCount ) 94 { 95 aLanguageStr = args[i + 1]; 96 bLang = true; 97 } 98 i++; 99 } 100 else if( "-mod".equals(args[i]) ) 101 { 102 if( i + 1 < nArgCount ) 103 { 104 aModule = args[i + 1]; 105 bMod = true; 106 } 107 i++; 108 } 109 else if( "-zipdir".equals(args[i]) ) 110 { 111 if( i + 1 < nArgCount ) 112 { 113 aDirToZipStr = args[i + 1]; 114 bZipDir = true; 115 } 116 i++; 117 } 118 else if( "-srcdir".equals(args[i]) ) 119 { 120 if( i + 1 < nArgCount ) 121 { 122 aSrcDirStr = args[i + 1]; 123 bSrcDir = true; 124 } 125 i++; 126 } 127 else if( "-o".equals(args[i]) ) 128 { 129 if( i + 1 < nArgCount ) 130 { 131 aTargetZipFileStr = args[i + 1]; 132 bOutput = true; 133 } 134 i++; 135 } 136 else if( "-checkcfsandsegname".equals(args[i]) ) 137 { 138 if( i + 1 < nArgCount ) 139 { 140 aCfsName = args[i + 1] + ".cfs"; 141 bCfsName = true; 142 } 143 i++; 144 if( i + 1 < nArgCount ) 145 { 146 aSegmentName = "segments" + args[i + 1]; 147 bSegmentName = true; 148 } 149 i++; 150 if (!(bCfsName && bSegmentName)) 151 { 152 System.out.println("Usage: HelpIndexer -checkcfsandsegname _0 _3 (2 arguments needed)"); 153 System.exit( -1 ); 154 } 155 } 156 } 157 158 if( !bLang || !bMod || !bZipDir || (!bOutput && !bExtensionMode && !bExtension) ) 159 { 160 if( bExtensionMode ) 161 return; 162 163 System.out.println("Usage: HelpIndexer -lang ISOLangCode -mod HelpModule -zipdir TempZipDir -o OutputZipFile"); 164 System.out.println("Usage: HelpIndexer -extension -lang ISOLangCode -mod HelpModule -zipdir PathToLangDir"); 165 System.exit( -1 ); 166 } 167 168 String aIndexDirName = aModule + ".idxl"; 169 File aIndexDir = new File( aDirToZipStr + File.separator + aIndexDirName ); 170 if( !bSrcDir ) 171 aSrcDirStr = aDirToZipStr; 172 File aCaptionFilesDir = new File( aSrcDirStr + File.separator + "caption" ); 173 File aContentFilesDir = new File( aSrcDirStr + File.separator + "content" ); 174 175 try 176 { 177 Date start = new Date(); 178 Analyzer analyzer = aLanguageStr.equals("ja") ? (Analyzer)new CJKAnalyzer(Version.LUCENE_29) : (Analyzer)new StandardAnalyzer(Version.LUCENE_29); 179 IndexWriter writer = new IndexWriter( NIOFSDirectory.open(aIndexDir), analyzer, true, IndexWriter.MaxFieldLength.LIMITED ); 180 if( !bExtensionMode ) 181 System.out.println( "Lucene: Indexing to directory '" + aIndexDir + "'..." ); 182 int nRet = indexDocs( writer, aModule, bExtensionMode, aCaptionFilesDir, aContentFilesDir ); 183 if( nRet != -1 ) 184 { 185 if( !bExtensionMode ) 186 { 187 System.out.println(); 188 System.out.println( "Optimizing ..." ); 189 } 190 writer.optimize(); 191 } 192 writer.close(); 193 194 boolean bCfsFileOk = true; 195 boolean bSegmentFileOk = true; 196 if( bCfsName && bSegmentName && !bExtensionMode && nRet != -1 ) 197 { 198 String aCompleteCfsFileName = aDirToZipStr + File.separator + aIndexDirName + File.separator + aCfsName; 199 String aCompleteSegmentFileName = aDirToZipStr + File.separator + aIndexDirName + File.separator + aSegmentName; 200 File aCfsFile = new File( aCompleteCfsFileName ); 201 File aSegmentFile = new File( aCompleteSegmentFileName ); 202 bCfsFileOk = aCfsFile.exists(); 203 bSegmentFileOk = aSegmentFile.exists(); 204 System.out.println( "Checking cfs file " + aCfsName+ ": " + (bCfsFileOk ? "Found" : "Not found") ); 205 System.out.println( "Checking segment file " + aSegmentName+ ": " + (bSegmentFileOk ? "Found" : "Not found") ); 206 } 207 208 if( bExtensionMode || bExtension) 209 { 210 if( !bSrcDir ) 211 { 212 deleteRecursively( aCaptionFilesDir ); 213 deleteRecursively( aContentFilesDir ); 214 } 215 } 216 else 217 { 218 if( nRet == -1 ) 219 deleteRecursively( aIndexDir ); 220 221 if( bCfsFileOk && bSegmentFileOk ) 222 System.out.println( "Zipping ..." ); 223 File aDirToZipFile = new File( aDirToZipStr ); 224 createZipFile( aDirToZipFile, aTargetZipFileStr ); 225 deleteRecursively( aDirToZipFile ); 226 } 227 228 if( !bCfsFileOk ) 229 { 230 System.out.println( "cfs file check failed, terminating..." ); 231 System.exit( -1 ); 232 } 233 234 if( !bSegmentFileOk ) 235 { 236 System.out.println( "segment file check failed, terminating..." ); 237 System.exit( -1 ); 238 } 239 240 Date end = new Date(); 241 if( !bExtensionMode ) 242 System.out.println(end.getTime() - start.getTime() + " total milliseconds"); 243 } 244 catch (IOException e) 245 { 246 if( bExtensionMode ) 247 return; 248 249 System.out.println(" caught a " + e.getClass() + 250 "\n with message: " + e.getMessage()); 251 System.exit( -1 ); 252 } 253 } 254 255 private static int indexDocs(IndexWriter writer, String aModule, boolean bExtensionMode, 256 File aCaptionFilesDir, File aContentFilesDir) throws IOException 257 { 258 if( !aCaptionFilesDir.canRead() || !aCaptionFilesDir.isDirectory() ) 259 { 260 if( !bExtensionMode ) 261 System.out.println( "Not found: " + aCaptionFilesDir ); 262 return -1; 263 } 264 if( !aContentFilesDir.canRead() || !aContentFilesDir.isDirectory() ) 265 { 266 if( !bExtensionMode ) 267 System.out.println( "Not found: " + aContentFilesDir ); 268 return -1; 269 } 270 271 String[] aCaptionFiles = aCaptionFilesDir.list(); 272 List aCaptionFilesList = Arrays.asList( aCaptionFiles ); 273 HashSet aCaptionFilesHashSet = new HashSet( aCaptionFilesList ); 274 275 String[] aContentFiles = aContentFilesDir.list(); 276 List aContentFilesList = Arrays.asList( aContentFiles ); 277 HashSet aContentFilesHashSet = new HashSet( aContentFilesList ); 278 279 // Loop over caption files and find corresponding content file 280 if( !bExtensionMode ) 281 System.out.println( "Indexing, adding files" ); 282 int nCaptionFilesLen = aCaptionFiles.length; 283 for( int i = 0 ; i < nCaptionFilesLen ; i++ ) 284 { 285 String aCaptionFileStr = aCaptionFiles[i]; 286 File aCaptionFile = new File( aCaptionFilesDir, aCaptionFileStr ); 287 File aContentFile = null; 288 if( aContentFilesHashSet.contains( aCaptionFileStr ) ) 289 aContentFile = new File( aContentFilesDir, aCaptionFileStr ); 290 291 if( !bExtensionMode ) 292 System.out.print( "." ); 293 writer.addDocument( HelpFileDocument.Document( aModule, aCaptionFile, aContentFile ) ); 294 } 295 296 // Loop over content files to find remaining files not mapped to caption files 297 int nContentFilesLen = aContentFiles.length; 298 for( int i = 0 ; i < nContentFilesLen ; i++ ) 299 { 300 String aContentFileStr = aContentFiles[i]; 301 if( !aCaptionFilesHashSet.contains( aContentFileStr ) ) 302 { 303 // Not already handled in caption files loop 304 File aCaptionFile = null; 305 File aContentFile = new File( aContentFilesDir, aContentFileStr ); 306 if( !bExtensionMode ) 307 System.out.print( "." ); 308 writer.addDocument( HelpFileDocument.Document( aModule, aCaptionFile, aContentFile ) ); 309 } 310 } 311 return 0; 312 } 313 314 public static void createZipFile( File aDirToZip, String aTargetZipFileStr ) 315 throws FileNotFoundException, IOException 316 { 317 FileOutputStream fos = new FileOutputStream( aTargetZipFileStr ); 318 ZipOutputStream zos = new ZipOutputStream( fos ); 319 320 File[] aChildrenFiles = aDirToZip.listFiles(); 321 int nFileCount = aChildrenFiles.length; 322 for( int i = 0 ; i < nFileCount ; i++ ) 323 addToZipRecursively( zos, aChildrenFiles[i], null ); 324 325 zos.close(); 326 } 327 328 public static void addToZipRecursively( ZipOutputStream zos, File aFile, String aBasePath ) 329 throws FileNotFoundException, IOException 330 { 331 if( aFile.isDirectory() ) 332 { 333 String aDirName = aFile.getName(); 334 if( aDirName.equalsIgnoreCase( "caption" ) || aDirName.equalsIgnoreCase( "content" ) ) 335 return; 336 337 File[] aChildrenFiles = aFile.listFiles(); 338 String aNewBasePath = ""; 339 if( aBasePath != null ) 340 aNewBasePath += aBasePath + File.separator; 341 aNewBasePath += aDirName; 342 343 int nFileCount = aChildrenFiles.length; 344 for( int i = 0 ; i < nFileCount ; i++ ) 345 addToZipRecursively( zos, aChildrenFiles[i], aNewBasePath ); 346 347 return; 348 } 349 350 // No directory 351 // read contents of file we are going to put in the zip 352 int fileLength = (int) aFile.length(); 353 FileInputStream fis = new FileInputStream( aFile ); 354 byte[] wholeFile = new byte[fileLength]; 355 int bytesRead = fis.read( wholeFile, 0, fileLength ); 356 fis.close(); 357 358 String aFileName = aFile.getName(); 359 String aEntryName = ""; 360 if( aBasePath != null ) 361 aEntryName += aBasePath + "/"; 362 aEntryName += aFileName; 363 ZipEntry aZipEntry = new ZipEntry( aEntryName ); 364 aZipEntry.setTime( aFile.lastModified() ); 365 aZipEntry.setSize( fileLength ); 366 367 int nMethod = ( aFileName.toLowerCase().endsWith( ".jar" ) ) 368 ? ZipEntry.STORED : ZipEntry.DEFLATED; 369 aZipEntry.setMethod( nMethod ); 370 371 CRC32 tempCRC = new CRC32(); 372 tempCRC.update( wholeFile, 0, wholeFile.length ); 373 aZipEntry.setCrc( tempCRC.getValue() ); 374 375 // write the contents into the zip element 376 zos.putNextEntry( aZipEntry ); 377 zos.write( wholeFile, 0, fileLength ); 378 zos.closeEntry(); 379 } 380 381 static public boolean deleteRecursively( File aFile ) 382 { 383 if( aFile.isDirectory() ) 384 { 385 File[] aChildrenFiles = aFile.listFiles(); 386 int nFileCount = aChildrenFiles.length; 387 for( int i = 0 ; i < nFileCount ; i++ ) 388 { 389 File aChildrenFile = aChildrenFiles[i]; 390 boolean bSuccess = deleteRecursively( aChildrenFile ); 391 if( !bSuccess ) 392 return false; 393 } 394 } 395 396 return aFile.delete(); 397 } 398 } 399 400