diff options
| author | 2014-07-31 22:27:26 -0400 | |
|---|---|---|
| committer | 2014-07-31 22:27:26 -0400 | |
| commit | faae0a6514c2565a10f9a62dd18c5d79fbbe4156 (patch) | |
| tree | 9369f3b920919dd4a4bb2aa449c3dc467d4a43ea /src | |
| parent | switched to line-by-line mergable, human-readable file format for mappings (diff) | |
| download | enigma-fork-faae0a6514c2565a10f9a62dd18c5d79fbbe4156.tar.gz enigma-fork-faae0a6514c2565a10f9a62dd18c5d79fbbe4156.tar.xz enigma-fork-faae0a6514c2565a10f9a62dd18c5d79fbbe4156.zip | |
fixed bug with save mappings menu
gui shows deobfuscated classes list now
working on name validation/sanitization
Diffstat (limited to 'src')
| -rw-r--r-- | src/cuchaz/enigma/ClassFile.java | 34 | ||||
| -rw-r--r-- | src/cuchaz/enigma/Deobfuscator.java | 60 | ||||
| -rw-r--r-- | src/cuchaz/enigma/gui/ClassListCellRenderer.java (renamed from src/cuchaz/enigma/gui/ObfuscatedClassListCellRenderer.java) | 4 | ||||
| -rw-r--r-- | src/cuchaz/enigma/gui/Gui.java | 64 | ||||
| -rw-r--r-- | src/cuchaz/enigma/gui/GuiController.java | 18 | ||||
| -rw-r--r-- | src/cuchaz/enigma/mapping/NameValidator.java | 67 |
6 files changed, 178 insertions, 69 deletions
diff --git a/src/cuchaz/enigma/ClassFile.java b/src/cuchaz/enigma/ClassFile.java index 221a119..c3c72a4 100644 --- a/src/cuchaz/enigma/ClassFile.java +++ b/src/cuchaz/enigma/ClassFile.java | |||
| @@ -10,36 +10,42 @@ | |||
| 10 | ******************************************************************************/ | 10 | ******************************************************************************/ |
| 11 | package cuchaz.enigma; | 11 | package cuchaz.enigma; |
| 12 | 12 | ||
| 13 | import java.util.regex.Pattern; | ||
| 14 | 13 | ||
| 15 | public class ClassFile | 14 | public class ClassFile |
| 16 | { | 15 | { |
| 17 | private static Pattern m_obfuscatedClassPattern; | 16 | private String m_obfName; |
| 17 | private String m_deobfName; | ||
| 18 | 18 | ||
| 19 | static | 19 | public ClassFile( String obfName ) |
| 20 | { | 20 | { |
| 21 | m_obfuscatedClassPattern = Pattern.compile( "^[a-z]+$" ); | 21 | m_obfName = obfName; |
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | private String m_name; | 24 | public String getName( ) |
| 25 | |||
| 26 | public ClassFile( String name ) | ||
| 27 | { | 25 | { |
| 28 | m_name = name; | 26 | if( m_deobfName != null ) |
| 27 | { | ||
| 28 | return m_deobfName; | ||
| 29 | } | ||
| 30 | return m_obfName; | ||
| 29 | } | 31 | } |
| 30 | 32 | ||
| 31 | public String getName( ) | 33 | public String getObfName( ) |
| 32 | { | 34 | { |
| 33 | return m_name; | 35 | return m_obfName; |
| 34 | } | 36 | } |
| 35 | 37 | ||
| 36 | public boolean isObfuscated( ) | 38 | public String getDeobfName( ) |
| 37 | { | 39 | { |
| 38 | return m_obfuscatedClassPattern.matcher( m_name ).matches(); | 40 | return m_deobfName; |
| 39 | } | 41 | } |
| 40 | 42 | public void setDeobfName( String val ) | |
| 43 | { | ||
| 44 | m_deobfName = val; | ||
| 45 | } | ||
| 46 | |||
| 41 | public String getPath( ) | 47 | public String getPath( ) |
| 42 | { | 48 | { |
| 43 | return m_name.replace( ".", "/" ) + ".class"; | 49 | return m_deobfName.replace( ".", "/" ) + ".class"; |
| 44 | } | 50 | } |
| 45 | } | 51 | } |
diff --git a/src/cuchaz/enigma/Deobfuscator.java b/src/cuchaz/enigma/Deobfuscator.java index 7be5706..619eebf 100644 --- a/src/cuchaz/enigma/Deobfuscator.java +++ b/src/cuchaz/enigma/Deobfuscator.java | |||
| @@ -15,9 +15,6 @@ import java.io.FileInputStream; | |||
| 15 | import java.io.IOException; | 15 | import java.io.IOException; |
| 16 | import java.io.InputStream; | 16 | import java.io.InputStream; |
| 17 | import java.io.StringWriter; | 17 | import java.io.StringWriter; |
| 18 | import java.util.ArrayList; | ||
| 19 | import java.util.Collections; | ||
| 20 | import java.util.Comparator; | ||
| 21 | import java.util.Enumeration; | 18 | import java.util.Enumeration; |
| 22 | import java.util.List; | 19 | import java.util.List; |
| 23 | import java.util.jar.JarEntry; | 20 | import java.util.jar.JarEntry; |
| @@ -30,10 +27,12 @@ import com.strobel.decompiler.PlainTextOutput; | |||
| 30 | import cuchaz.enigma.mapping.Ancestries; | 27 | import cuchaz.enigma.mapping.Ancestries; |
| 31 | import cuchaz.enigma.mapping.ArgumentEntry; | 28 | import cuchaz.enigma.mapping.ArgumentEntry; |
| 32 | import cuchaz.enigma.mapping.ClassEntry; | 29 | import cuchaz.enigma.mapping.ClassEntry; |
| 30 | import cuchaz.enigma.mapping.ClassMapping; | ||
| 33 | import cuchaz.enigma.mapping.Entry; | 31 | import cuchaz.enigma.mapping.Entry; |
| 34 | import cuchaz.enigma.mapping.FieldEntry; | 32 | import cuchaz.enigma.mapping.FieldEntry; |
| 35 | import cuchaz.enigma.mapping.Mappings; | 33 | import cuchaz.enigma.mapping.Mappings; |
| 36 | import cuchaz.enigma.mapping.MethodEntry; | 34 | import cuchaz.enigma.mapping.MethodEntry; |
| 35 | import cuchaz.enigma.mapping.NameValidator; | ||
| 37 | import cuchaz.enigma.mapping.Renamer; | 36 | import cuchaz.enigma.mapping.Renamer; |
| 38 | import cuchaz.enigma.mapping.TranslationDirection; | 37 | import cuchaz.enigma.mapping.TranslationDirection; |
| 39 | import cuchaz.enigma.mapping.Translator; | 38 | import cuchaz.enigma.mapping.Translator; |
| @@ -47,25 +46,6 @@ public class Deobfuscator | |||
| 47 | private Mappings m_mappings; | 46 | private Mappings m_mappings; |
| 48 | private Renamer m_renamer; | 47 | private Renamer m_renamer; |
| 49 | 48 | ||
| 50 | private static Comparator<ClassFile> m_obfuscatedClassSorter; | ||
| 51 | |||
| 52 | static | ||
| 53 | { | ||
| 54 | m_obfuscatedClassSorter = new Comparator<ClassFile>( ) | ||
| 55 | { | ||
| 56 | @Override | ||
| 57 | public int compare( ClassFile a, ClassFile b ) | ||
| 58 | { | ||
| 59 | if( a.getName().length() != b.getName().length() ) | ||
| 60 | { | ||
| 61 | return a.getName().length() - b.getName().length(); | ||
| 62 | } | ||
| 63 | |||
| 64 | return a.getName().compareTo( b.getName() ); | ||
| 65 | } | ||
| 66 | }; | ||
| 67 | } | ||
| 68 | |||
| 69 | public Deobfuscator( File file ) | 49 | public Deobfuscator( File file ) |
| 70 | throws IOException | 50 | throws IOException |
| 71 | { | 51 | { |
| @@ -120,48 +100,38 @@ public class Deobfuscator | |||
| 120 | ) ); | 100 | ) ); |
| 121 | } | 101 | } |
| 122 | 102 | ||
| 123 | public List<ClassFile> getObfuscatedClasses( ) | 103 | public void getSortedClasses( List<ClassFile> obfClasses, List<ClassFile> deobfClasses ) |
| 124 | { | 104 | { |
| 125 | List<ClassFile> classes = new ArrayList<ClassFile>(); | ||
| 126 | Enumeration<JarEntry> entries = m_jar.entries(); | 105 | Enumeration<JarEntry> entries = m_jar.entries(); |
| 127 | while( entries.hasMoreElements() ) | 106 | while( entries.hasMoreElements() ) |
| 128 | { | 107 | { |
| 129 | JarEntry entry = entries.nextElement(); | 108 | JarEntry entry = entries.nextElement(); |
| 130 | 109 | ||
| 131 | // get the class name | 110 | // get the class name |
| 132 | String className = toClassName( entry.getName() ); | 111 | String obfName = NameValidator.fileNameToClassName( entry.getName() ); |
| 133 | if( className == null ) | 112 | if( obfName == null ) |
| 134 | { | 113 | { |
| 135 | continue; | 114 | continue; |
| 136 | } | 115 | } |
| 137 | 116 | ||
| 138 | ClassFile classFile = new ClassFile( className ); | 117 | ClassFile classFile = new ClassFile( obfName ); |
| 139 | if( classFile.isObfuscated() ) | 118 | ClassMapping classMapping = m_mappings.getClassByObf( classFile.getName() ); |
| 119 | if( classMapping != null ) | ||
| 140 | { | 120 | { |
| 141 | classes.add( classFile ); | 121 | classFile.setDeobfName( classMapping.getDeobfName() ); |
| 122 | deobfClasses.add( classFile ); | ||
| 123 | } | ||
| 124 | else | ||
| 125 | { | ||
| 126 | obfClasses.add( classFile ); | ||
| 142 | } | 127 | } |
| 143 | } | 128 | } |
| 144 | Collections.sort( classes, m_obfuscatedClassSorter ); | ||
| 145 | return classes; | ||
| 146 | } | ||
| 147 | |||
| 148 | // TODO: could go somewhere more generic | ||
| 149 | private static String toClassName( String fileName ) | ||
| 150 | { | ||
| 151 | final String suffix = ".class"; | ||
| 152 | |||
| 153 | if( !fileName.endsWith( suffix ) ) | ||
| 154 | { | ||
| 155 | return null; | ||
| 156 | } | ||
| 157 | |||
| 158 | return fileName.substring( 0, fileName.length() - suffix.length() ).replace( "/", "." ); | ||
| 159 | } | 129 | } |
| 160 | 130 | ||
| 161 | public String getSource( final ClassFile classFile ) | 131 | public String getSource( final ClassFile classFile ) |
| 162 | { | 132 | { |
| 163 | StringWriter buf = new StringWriter(); | 133 | StringWriter buf = new StringWriter(); |
| 164 | Decompiler.decompile( classFile.getName(), new PlainTextOutput( buf ), m_settings ); | 134 | Decompiler.decompile( classFile.getObfName(), new PlainTextOutput( buf ), m_settings ); |
| 165 | return buf.toString(); | 135 | return buf.toString(); |
| 166 | } | 136 | } |
| 167 | 137 | ||
diff --git a/src/cuchaz/enigma/gui/ObfuscatedClassListCellRenderer.java b/src/cuchaz/enigma/gui/ClassListCellRenderer.java index 0badb3b..302f140 100644 --- a/src/cuchaz/enigma/gui/ObfuscatedClassListCellRenderer.java +++ b/src/cuchaz/enigma/gui/ClassListCellRenderer.java | |||
| @@ -19,11 +19,11 @@ import javax.swing.ListCellRenderer; | |||
| 19 | 19 | ||
| 20 | import cuchaz.enigma.ClassFile; | 20 | import cuchaz.enigma.ClassFile; |
| 21 | 21 | ||
| 22 | public class ObfuscatedClassListCellRenderer implements ListCellRenderer<ClassFile> | 22 | public class ClassListCellRenderer implements ListCellRenderer<ClassFile> |
| 23 | { | 23 | { |
| 24 | private DefaultListCellRenderer m_defaultRenderer; | 24 | private DefaultListCellRenderer m_defaultRenderer; |
| 25 | 25 | ||
| 26 | public ObfuscatedClassListCellRenderer( ) | 26 | public ClassListCellRenderer( ) |
| 27 | { | 27 | { |
| 28 | m_defaultRenderer = new DefaultListCellRenderer(); | 28 | m_defaultRenderer = new DefaultListCellRenderer(); |
| 29 | } | 29 | } |
diff --git a/src/cuchaz/enigma/gui/Gui.java b/src/cuchaz/enigma/gui/Gui.java index a86ff9b..d448dc2 100644 --- a/src/cuchaz/enigma/gui/Gui.java +++ b/src/cuchaz/enigma/gui/Gui.java | |||
| @@ -21,6 +21,8 @@ import java.awt.event.ActionListener; | |||
| 21 | import java.awt.event.MouseAdapter; | 21 | import java.awt.event.MouseAdapter; |
| 22 | import java.awt.event.MouseEvent; | 22 | import java.awt.event.MouseEvent; |
| 23 | import java.io.IOException; | 23 | import java.io.IOException; |
| 24 | import java.util.Collections; | ||
| 25 | import java.util.Comparator; | ||
| 24 | import java.util.List; | 26 | import java.util.List; |
| 25 | import java.util.Vector; | 27 | import java.util.Vector; |
| 26 | 28 | ||
| @@ -58,6 +60,25 @@ import cuchaz.enigma.mapping.MethodEntry; | |||
| 58 | 60 | ||
| 59 | public class Gui | 61 | public class Gui |
| 60 | { | 62 | { |
| 63 | private static Comparator<ClassFile> m_obfuscatedClassSorter; | ||
| 64 | |||
| 65 | static | ||
| 66 | { | ||
| 67 | m_obfuscatedClassSorter = new Comparator<ClassFile>( ) | ||
| 68 | { | ||
| 69 | @Override | ||
| 70 | public int compare( ClassFile a, ClassFile b ) | ||
| 71 | { | ||
| 72 | if( a.getName().length() != b.getName().length() ) | ||
| 73 | { | ||
| 74 | return a.getName().length() - b.getName().length(); | ||
| 75 | } | ||
| 76 | |||
| 77 | return a.getName().compareTo( b.getName() ); | ||
| 78 | } | ||
| 79 | }; | ||
| 80 | } | ||
| 81 | |||
| 61 | private GuiController m_controller; | 82 | private GuiController m_controller; |
| 62 | 83 | ||
| 63 | // controls | 84 | // controls |
| @@ -101,7 +122,7 @@ public class Gui | |||
| 101 | m_obfClasses = new JList<ClassFile>(); | 122 | m_obfClasses = new JList<ClassFile>(); |
| 102 | m_obfClasses.setSelectionMode( ListSelectionModel.SINGLE_SELECTION ); | 123 | m_obfClasses.setSelectionMode( ListSelectionModel.SINGLE_SELECTION ); |
| 103 | m_obfClasses.setLayoutOrientation( JList.VERTICAL ); | 124 | m_obfClasses.setLayoutOrientation( JList.VERTICAL ); |
| 104 | m_obfClasses.setCellRenderer( new ObfuscatedClassListCellRenderer() ); | 125 | m_obfClasses.setCellRenderer( new ClassListCellRenderer() ); |
| 105 | m_obfClasses.addMouseListener( new MouseAdapter() | 126 | m_obfClasses.addMouseListener( new MouseAdapter() |
| 106 | { | 127 | { |
| 107 | public void mouseClicked( MouseEvent event ) | 128 | public void mouseClicked( MouseEvent event ) |
| @@ -124,8 +145,23 @@ public class Gui | |||
| 124 | 145 | ||
| 125 | // init deobfuscated classes list | 146 | // init deobfuscated classes list |
| 126 | m_deobfClasses = new JList<ClassFile>(); | 147 | m_deobfClasses = new JList<ClassFile>(); |
| 127 | m_obfClasses.setSelectionMode( ListSelectionModel.SINGLE_SELECTION ); | 148 | m_deobfClasses.setSelectionMode( ListSelectionModel.SINGLE_SELECTION ); |
| 128 | m_obfClasses.setLayoutOrientation( JList.VERTICAL ); | 149 | m_deobfClasses.setLayoutOrientation( JList.VERTICAL ); |
| 150 | m_deobfClasses.setCellRenderer( new ClassListCellRenderer() ); | ||
| 151 | m_deobfClasses.addMouseListener( new MouseAdapter() | ||
| 152 | { | ||
| 153 | public void mouseClicked( MouseEvent event ) | ||
| 154 | { | ||
| 155 | if( event.getClickCount() == 2 ) | ||
| 156 | { | ||
| 157 | ClassFile selected = m_deobfClasses.getSelectedValue(); | ||
| 158 | if( selected != null ) | ||
| 159 | { | ||
| 160 | m_controller.deobfuscateClass( selected ); | ||
| 161 | } | ||
| 162 | } | ||
| 163 | } | ||
| 164 | } ); | ||
| 129 | JScrollPane deobfScroller = new JScrollPane( m_deobfClasses ); | 165 | JScrollPane deobfScroller = new JScrollPane( m_deobfClasses ); |
| 130 | JPanel deobfPanel = new JPanel(); | 166 | JPanel deobfPanel = new JPanel(); |
| 131 | deobfPanel.setLayout( new BorderLayout() ); | 167 | deobfPanel.setLayout( new BorderLayout() ); |
| @@ -248,7 +284,6 @@ public class Gui | |||
| 248 | try | 284 | try |
| 249 | { | 285 | { |
| 250 | m_controller.openMappings( m_mappingFileChooser.getSelectedFile() ); | 286 | m_controller.openMappings( m_mappingFileChooser.getSelectedFile() ); |
| 251 | m_saveMappingsMenu.setEnabled( true ); | ||
| 252 | } | 287 | } |
| 253 | catch( IOException ex ) | 288 | catch( IOException ex ) |
| 254 | { | 289 | { |
| @@ -383,7 +418,9 @@ public class Gui | |||
| 383 | { | 418 | { |
| 384 | if( classes != null ) | 419 | if( classes != null ) |
| 385 | { | 420 | { |
| 386 | m_obfClasses.setListData( new Vector<ClassFile>( classes ) ); | 421 | Vector<ClassFile> sortedClasses = new Vector<ClassFile>( classes ); |
| 422 | Collections.sort( sortedClasses, m_obfuscatedClassSorter ); | ||
| 423 | m_obfClasses.setListData( sortedClasses ); | ||
| 387 | } | 424 | } |
| 388 | else | 425 | else |
| 389 | { | 426 | { |
| @@ -391,6 +428,23 @@ public class Gui | |||
| 391 | } | 428 | } |
| 392 | } | 429 | } |
| 393 | 430 | ||
| 431 | public void setDeobfClasses( List<ClassFile> classes ) | ||
| 432 | { | ||
| 433 | if( classes != null ) | ||
| 434 | { | ||
| 435 | m_deobfClasses.setListData( new Vector<ClassFile>( classes ) ); | ||
| 436 | } | ||
| 437 | else | ||
| 438 | { | ||
| 439 | m_deobfClasses.setListData( new Vector<ClassFile>() ); | ||
| 440 | } | ||
| 441 | } | ||
| 442 | |||
| 443 | public void setMappingsLoaded( boolean isLoaded ) | ||
| 444 | { | ||
| 445 | m_saveMappingsMenu.setEnabled( isLoaded ); | ||
| 446 | } | ||
| 447 | |||
| 394 | public void setSource( String source ) | 448 | public void setSource( String source ) |
| 395 | { | 449 | { |
| 396 | setSource( source, null ); | 450 | setSource( source, null ); |
diff --git a/src/cuchaz/enigma/gui/GuiController.java b/src/cuchaz/enigma/gui/GuiController.java index fb22b96..ce1c31b 100644 --- a/src/cuchaz/enigma/gui/GuiController.java +++ b/src/cuchaz/enigma/gui/GuiController.java | |||
| @@ -14,6 +14,8 @@ import java.io.File; | |||
| 14 | import java.io.FileReader; | 14 | import java.io.FileReader; |
| 15 | import java.io.FileWriter; | 15 | import java.io.FileWriter; |
| 16 | import java.io.IOException; | 16 | import java.io.IOException; |
| 17 | import java.util.ArrayList; | ||
| 18 | import java.util.List; | ||
| 17 | 19 | ||
| 18 | import cuchaz.enigma.ClassFile; | 20 | import cuchaz.enigma.ClassFile; |
| 19 | import cuchaz.enigma.Deobfuscator; | 21 | import cuchaz.enigma.Deobfuscator; |
| @@ -45,7 +47,7 @@ public class GuiController | |||
| 45 | { | 47 | { |
| 46 | m_deobfuscator = new Deobfuscator( file ); | 48 | m_deobfuscator = new Deobfuscator( file ); |
| 47 | m_gui.onOpenJar( m_deobfuscator.getJarName() ); | 49 | m_gui.onOpenJar( m_deobfuscator.getJarName() ); |
| 48 | m_gui.setObfClasses( m_deobfuscator.getObfuscatedClasses() ); | 50 | refreshClasses(); |
| 49 | } | 51 | } |
| 50 | 52 | ||
| 51 | public void closeJar( ) | 53 | public void closeJar( ) |
| @@ -60,8 +62,8 @@ public class GuiController | |||
| 60 | FileReader in = new FileReader( file ); | 62 | FileReader in = new FileReader( file ); |
| 61 | m_deobfuscator.setMappings( new MappingsReader().read( in ) ); | 63 | m_deobfuscator.setMappings( new MappingsReader().read( in ) ); |
| 62 | in.close(); | 64 | in.close(); |
| 63 | // TEMP | 65 | m_gui.setMappingsLoaded( true ); |
| 64 | System.out.println( m_deobfuscator.getMappings() ); | 66 | refreshClasses(); |
| 65 | refreshOpenFiles(); | 67 | refreshOpenFiles(); |
| 66 | } | 68 | } |
| 67 | 69 | ||
| @@ -76,6 +78,7 @@ public class GuiController | |||
| 76 | public void closeMappings( ) | 78 | public void closeMappings( ) |
| 77 | { | 79 | { |
| 78 | m_deobfuscator.setMappings( null ); | 80 | m_deobfuscator.setMappings( null ); |
| 81 | m_gui.setMappingsLoaded( false ); | ||
| 79 | refreshOpenFiles(); | 82 | refreshOpenFiles(); |
| 80 | } | 83 | } |
| 81 | 84 | ||
| @@ -119,6 +122,15 @@ public class GuiController | |||
| 119 | refreshOpenFiles(); | 122 | refreshOpenFiles(); |
| 120 | } | 123 | } |
| 121 | 124 | ||
| 125 | private void refreshClasses( ) | ||
| 126 | { | ||
| 127 | List<ClassFile> obfClasses = new ArrayList<ClassFile>(); | ||
| 128 | List<ClassFile> deobfClasses = new ArrayList<ClassFile>(); | ||
| 129 | m_deobfuscator.getSortedClasses( obfClasses, deobfClasses ); | ||
| 130 | m_gui.setObfClasses( obfClasses ); | ||
| 131 | m_gui.setDeobfClasses( deobfClasses ); | ||
| 132 | } | ||
| 133 | |||
| 122 | private void refreshOpenFiles( ) | 134 | private void refreshOpenFiles( ) |
| 123 | { | 135 | { |
| 124 | if( m_currentFile != null ) | 136 | if( m_currentFile != null ) |
diff --git a/src/cuchaz/enigma/mapping/NameValidator.java b/src/cuchaz/enigma/mapping/NameValidator.java new file mode 100644 index 0000000..30982dc --- /dev/null +++ b/src/cuchaz/enigma/mapping/NameValidator.java | |||
| @@ -0,0 +1,67 @@ | |||
| 1 | /******************************************************************************* | ||
| 2 | * Copyright (c) 2014 Jeff Martin. | ||
| 3 | * All rights reserved. This program and the accompanying materials | ||
| 4 | * are made available under the terms of the GNU Public License v3.0 | ||
| 5 | * which accompanies this distribution, and is available at | ||
| 6 | * http://www.gnu.org/licenses/gpl.html | ||
| 7 | * | ||
| 8 | * Contributors: | ||
| 9 | * Jeff Martin - initial API and implementation | ||
| 10 | ******************************************************************************/ | ||
| 11 | package cuchaz.enigma.mapping; | ||
| 12 | |||
| 13 | import java.util.regex.Pattern; | ||
| 14 | |||
| 15 | public class NameValidator | ||
| 16 | { | ||
| 17 | private static final String IdentifierPattern; | ||
| 18 | private static final Pattern ClassPattern; | ||
| 19 | |||
| 20 | static | ||
| 21 | { | ||
| 22 | // java allows all kinds of weird characters... | ||
| 23 | StringBuilder startChars = new StringBuilder(); | ||
| 24 | StringBuilder partChars = new StringBuilder(); | ||
| 25 | for( int i = Character.MIN_CODE_POINT; i <= Character.MAX_CODE_POINT; i++ ) | ||
| 26 | { | ||
| 27 | if( Character.isJavaIdentifierStart( i ) ) | ||
| 28 | { | ||
| 29 | startChars.appendCodePoint( i ); | ||
| 30 | } | ||
| 31 | if( Character.isJavaIdentifierPart( i ) ) | ||
| 32 | { | ||
| 33 | partChars.appendCodePoint( i ); | ||
| 34 | } | ||
| 35 | } | ||
| 36 | |||
| 37 | IdentifierPattern = String.format( "[\\Q%s\\E][\\Q%s\\E]*", startChars.toString(), partChars.toString() ); | ||
| 38 | ClassPattern = Pattern.compile( String.format( "^(%s(\\.|/))*(%s)$", IdentifierPattern, IdentifierPattern ) ); | ||
| 39 | } | ||
| 40 | |||
| 41 | public String validateClassName( String name ) | ||
| 42 | { | ||
| 43 | if( !ClassPattern.matcher( name ).matches() ) | ||
| 44 | { | ||
| 45 | throw new IllegalArgumentException( "Illegal name: " + name ); | ||
| 46 | } | ||
| 47 | |||
| 48 | return classNameToJavaName( name ); | ||
| 49 | } | ||
| 50 | |||
| 51 | public static String fileNameToClassName( String fileName ) | ||
| 52 | { | ||
| 53 | final String suffix = ".class"; | ||
| 54 | |||
| 55 | if( !fileName.endsWith( suffix ) ) | ||
| 56 | { | ||
| 57 | return null; | ||
| 58 | } | ||
| 59 | |||
| 60 | return fileName.substring( 0, fileName.length() - suffix.length() ).replace( "/", "." ); | ||
| 61 | } | ||
| 62 | |||
| 63 | public static String classNameToJavaName( String className ) | ||
| 64 | { | ||
| 65 | return className.replace( ".", "/" ); | ||
| 66 | } | ||
| 67 | } | ||