blob: 9d0c93abfac4345846e0452555b4f018a6efdb7c [file] [log] [blame]
/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache
* XMLBeans", nor may "Apache" appear in their name, without prior
* written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
* originally based on software copyright (c) 2000-2003 BEA Systems
* Inc., <http://www.bea.com/>. For more information on the Apache Software
* Foundation, please see <http://www.apache.org/>.
*/
package repackage;
import java.io.*;
import java.util.*;
import java.util.regex.*;
public class Repackage
{
public static void main ( String[] args ) throws Exception
{
new Repackage().repackage( args );
}
public void repackage ( String[] args ) throws Exception
{
if (args.length != 2 || !args[0].equals( "-repackage" ))
throw new RuntimeException( "Usage: repackage -repackage [spec]" );
_repackager = new Repackager( args[ 1 ] );
_fromPackages = _repackager.getFromPackages();
_toPackages = _repackager.getToPackages();
_packagePattern =
Pattern.compile( "^\\s*package\\s+((?:\\w|\\.)*)\\s*;", Pattern.MULTILINE );
_moveAlongFiles = new ArrayList();
_movedDirs = new HashMap();
File currentDir = new File( "." );
File buildDir = new File( currentDir, "build" );
File repackageDir = new File( buildDir, "repackage" );
System.out.println( "Deleting repackage dir ..." );
recursiveDelete( repackageDir );
repackageDir.mkdirs();
ArrayList files = new ArrayList();
fillFiles( files, currentDir );
System.out.println( "Repackaging " + files.size() + " files ..." );
int prefixLength = currentDir.getCanonicalPath().length();
_sourceBase = currentDir;
_targetBase = repackageDir;
for ( int i = 0 ; i < files.size() ; i++ )
{
File from = (File) files.get( i );
String name = from.getCanonicalPath().substring( prefixLength + 1 );
repackageFile( name );
}
finishMovingFiles();
}
public void repackageFile ( String name )
throws IOException
{
if (name.endsWith( ".java" ))
repackageJavaFile( name );
else if (name.endsWith( ".xsdconfig" ))
repackageNonJavaFile( name );
else if (name.startsWith( "bin" + File.separatorChar ))
repackageNonJavaFile( name );
else
moveAlongWithJavaFiles( name );
}
public void moveAlongWithJavaFiles( String name )
{
_moveAlongFiles.add(name);
}
public void finishMovingFiles ( )
throws IOException
{
for ( Iterator i = _moveAlongFiles.iterator(); i.hasNext(); )
{
String name = (String) i.next();
String toName = name;
String srcDir = Repackager.dirForPath( name );
String toDir = (String) _movedDirs.get( srcDir );
if (toDir != null)
toName = new File( toDir, new File( name ).getName() ).toString();
if (name.endsWith( ".html" ))
repackageNonJavaFile( name, toName );
else
copyFile( new File( _sourceBase, name ), new File( _targetBase, toName ) );
}
}
public void repackageNonJavaFile ( String name )
throws IOException
{
StringBuffer sb = readFile( new File( _sourceBase, name ) );
_repackager.repackage( sb );
writeFile( new File( _targetBase, name ), sb );
}
public void repackageNonJavaFile ( String sourceName, String targetName )
throws IOException
{
StringBuffer sb = readFile( new File( _sourceBase, sourceName ) );
_repackager.repackage( sb );
writeFile( new File( _targetBase, targetName ), sb );
}
public void repackageJavaFile ( String name )
throws IOException
{
StringBuffer sb = readFile( new File( _sourceBase, name ) );
Matcher packageMatcher = _packagePattern.matcher( sb );
if (packageMatcher.find())
{
String pkg = packageMatcher.group( 1 );
int pkgStart = packageMatcher.start( 1 );
int pkgEnd = packageMatcher.end( 1 );
if (packageMatcher.find())
throw new RuntimeException( "Two package specifications found: " + name );
List filePath = Repackager.splitPath( name, File.separatorChar );
String srcDir = Repackager.dirForPath( name );
// Sort the repackage spec so that longer from's are first to match
// longest package first
for ( ; ; )
{
boolean swapped = false;
for ( int i = 1 ; i < filePath.size() ; i++ )
{
String spec1 = (String) filePath.get( i - 1 );
String spec2 = (String) filePath.get( i );
if (spec1.indexOf( ':' ) < spec2.indexOf( ':' ))
{
filePath.set( i - 1, spec2 );
filePath.set( i, spec1 );
swapped = true;
}
}
if (!swapped)
break;
}
List pkgPath = Repackager.splitPath( pkg, '.' );
int f = filePath.size() - 2;
for ( int i = pkgPath.size() - 1 ; i >= 0 ; i-- )
{
if (!pkgPath.get( i ).equals( filePath.get( f-- ) ))
throw new RuntimeException( "Package spec differs from file path: " + name );
}
List changeTo = null;
List changeFrom = null;
from:
for ( int i = 0 ; i < _fromPackages.size() ; i ++ )
{
List from = (List) _fromPackages.get( i );
if (from.size() <= pkgPath.size())
{
for ( int j = 0 ; j < from.size() ; j++ )
if (!from.get( j ).equals( pkgPath.get( j )))
continue from;
changeFrom = from;
changeTo = (List) _toPackages.get( i );
break;
}
}
if (changeTo != null)
{
String newPkg = "";
String newName = "";
for ( int i = 0 ; i < changeTo.size() ; i++ )
{
if (i > 0)
{
newPkg += ".";
newName += File.separatorChar;
}
newPkg += changeTo.get( i );
newName += changeTo.get( i );
}
for ( int i = filePath.size() - pkgPath.size() - 2 ; i >= 0 ; i-- )
newName = (String) filePath.get( i ) + File.separatorChar + newName;
for ( int i = changeFrom.size() ; i < pkgPath.size() ; i++ )
{
newName += File.separatorChar + (String) pkgPath.get( i );
newPkg += '.' + (String) pkgPath.get( i );
}
newName += File.separatorChar + (String) filePath.get( filePath.size() - 1 );
sb.replace( pkgStart, pkgEnd, newPkg );
name = newName;
String newDir = Repackager.dirForPath( name );
if (!srcDir.equals(newDir))
{
_movedDirs.put(srcDir, newDir);
}
}
}
_repackager.repackage( sb );
writeFile( new File( _targetBase, name ), sb );
}
void writeFile ( File f, StringBuffer chars )
throws IOException
{
f.getParentFile().mkdirs();
OutputStream out = new FileOutputStream( f );
Writer w = new OutputStreamWriter( out );
Reader r = new StringReader( chars.toString() );
copy( r, w );
r.close();
w.close();
out.close();
}
StringBuffer readFile ( File f )
throws IOException
{
InputStream in = new FileInputStream( f );
Reader r = new InputStreamReader( in );
StringWriter w = new StringWriter();
copy( r, w );
w.close();
r.close();
in.close();
return w.getBuffer();
}
public void copyFile ( File from, File to ) throws IOException
{
to.getParentFile().mkdirs();
FileInputStream in = new FileInputStream( from );
FileOutputStream out = new FileOutputStream( to );
copy( in, out );
out.close();
in.close();
}
public void copy ( InputStream in, OutputStream out ) throws IOException
{
byte[] buffer = new byte [ 1024 * 16 ];
for ( ; ; )
{
int n = in.read( buffer, 0, buffer.length );
if (n < 0)
break;
out.write( buffer, 0, n );
}
}
public void copy ( Reader r, Writer w ) throws IOException
{
char[] buffer = new char [ 1024 * 16 ];
for ( ; ; )
{
int n = r.read( buffer, 0, buffer.length );
if (n < 0)
break;
w.write( buffer, 0, n );
}
}
public void fillFiles ( ArrayList files, File file ) throws IOException
{
if (!file.isDirectory())
{
files.add( file );
return;
}
// Exclude the build directory
if (file.getName().equals( "build" ))
return;
// Exclude CVS directories
if (file.getName().equals( "CVS" ))
return;
String[] entries = file.list();
for ( int i = 0 ; i < entries.length ; i++ )
fillFiles( files, new File( file, entries[ i ] ) );
}
public void recursiveDelete ( File file ) throws IOException
{
if (!file.exists())
return;
if (file.isDirectory())
{
String[] entries = file.list();
for ( int i = 0 ; i < entries.length ; i++ )
recursiveDelete( new File( file, entries[ i ] ) );
}
file.delete();
}
private File _sourceBase;
private File _targetBase;
private List _fromPackages;
private List _toPackages;
private Pattern _packagePattern;
private Repackager _repackager;
private Map _movedDirs;
private List _moveAlongFiles;
}