Source Code Cross Referenced for GuardDB.java in  » Development » yguardlib » com » yworks » yguard » obf » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Development » yguardlib » com.yworks.yguard.obf 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /**
002:         * YGuard -- an obfuscation library for Java(TM) classfiles.
003:         *
004:         * Original Copyright (c) 1999 Mark Welsh (markw@retrologic.com)
005:         * Modifications Copyright (c) 2002 yWorks GmbH (yguard@yworks.com)
006:         *
007:         * This library is free software; you can redistribute it and/or
008:         * modify it under the terms of the GNU Lesser General Public
009:         * License as published by the Free Software Foundation; either
010:         * version 2 of the License, or (at your option) any later version.
011:         *
012:         * This library is distributed in the hope that it will be useful,
013:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
014:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015:         * Lesser General Public License for more details.
016:         *
017:         * You should have received a copy of the GNU Lesser General Public
018:         * License along with this library; if not, write to the Free Software
019:         * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
020:         *
021:         * The author may be contacted at yguard@yworks.com
022:         *
023:         * Java and all Java-based marks are trademarks or registered
024:         * trademarks of Sun Microsystems, Inc. in the U.S. and other countries.
025:         */package com.yworks.yguard.obf;
026:
027:        import java.io.*;
028:        import java.util.*;
029:        import java.util.zip.*;
030:        import java.util.jar.*;
031:        import java.security.*;
032:        import java.lang.reflect.Modifier;
033:
034:        import com.yworks.yguard.*;
035:        import com.yworks.yguard.obf.classfile.*;
036:        import java.util.AbstractMap;
037:        import java.util.jar.Attributes;
038:        import java.util.jar.Manifest;
039:
040:        /**
041:         * Classfile database for obfuscation.
042:         *
043:         * @author      Mark Welsh
044:         */
045:        public class GuardDB implements  ClassConstants {
046:            // Constants -------------------------------------------------------------
047:            private static final String STREAM_NAME_MANIFEST = "META-INF/MANIFEST.MF";
048:            private static final String MANIFEST_NAME_TAG = "Name";
049:            private static final String MANIFEST_DIGESTALG_TAG = "Digest-Algorithms";
050:            private static final String CLASS_EXT = ".class";
051:            private static final String SIGNATURE_PREFIX = "META-INF/";
052:            private static final String SIGNATURE_EXT = ".SF";
053:            private static final String LOG_MEMORY_USED = "  Memory in use after class data structure built: ";
054:            private static final String LOG_MEMORY_TOTAL = "  Total memory available                        : ";
055:            private static final String LOG_MEMORY_BYTES = " bytes";
056:            private static final String WARNING_SCRIPT_ENTRY_ABSENT = "<!-- WARNING - identifier from script file not found in JAR: ";
057:            private static final String ERROR_CORRUPT_CLASS = "<!-- ERROR - corrupt class file: ";
058:
059:            // Fields ----------------------------------------------------------------
060:            private JarFile[] inJar; // JAR file for obfuscation
061:            private Manifest[] oldManifest; // MANIFEST.MF
062:            private Manifest[] newManifest; // MANIFEST.MF
063:            private ClassTree classTree; // Tree of packages, classes. methods, fields
064:            private boolean hasMap = false;
065:
066:            /** Utility field holding list of Listeners. */
067:            private transient java.util.ArrayList listenerList;
068:
069:            /** Holds value of property replaceClassNameStrings. */
070:            private boolean replaceClassNameStrings;
071:
072:            /** Holds value of property pedantic. */
073:            private boolean pedantic;
074:
075:            private ResourceHandler resourceHandler;
076:            private String[] digestStrings;
077:
078:            // Has the mapping been generated already?
079:
080:            // Class Methods ---------------------------------------------------------
081:
082:            // Instance Methods ------------------------------------------------------
083:            /** A classfile database for obfuscation. */
084:            public GuardDB(File[] inFile) throws java.io.IOException {
085:                inJar = new JarFile[inFile.length];
086:                for (int i = 0; i < inFile.length; i++)
087:                    inJar[i] = new JarFile(inFile[i]);
088:            }
089:
090:            /** Close input JAR file and log-file at GC-time. */
091:            protected void finalize() throws java.io.IOException {
092:                close();
093:            }
094:
095:            public void setResourceHandler(ResourceHandler handler) {
096:                resourceHandler = handler;
097:            }
098:
099:            public String getOutName(String inName) {
100:                return classTree.getOutName(inName);
101:            }
102:
103:            /**
104:             * Go through database marking certain entities for retention, while
105:             * maintaining polymorphic integrity.
106:             */
107:            public void retain(Collection rgsEntries, PrintWriter log)
108:                    throws java.io.IOException {
109:
110:                // Build database if not already done, or if a mapping has already been generated
111:                if (classTree == null || hasMap) {
112:                    hasMap = false;
113:                    buildClassTree(log);
114:                }
115:
116:                // Enumerate the entries in the RGS script
117:                for (Iterator it = rgsEntries.iterator(); it.hasNext();) {
118:                    YGuardRule entry = (YGuardRule) it.next();
119:                    try {
120:                        switch (entry.type) {
121:                        case YGuardRule.TYPE_LINE_NUMBER_MAPPER:
122:                            classTree.retainLineNumberTable(entry.name,
123:                                    entry.lineNumberTableMapper);
124:                            break;
125:                        case YGuardRule.TYPE_SOURCE_ATTRIBUTE_MAP:
126:                            classTree.retainSourceFileAttributeMap(entry.name,
127:                                    entry.obfName);
128:                            break;
129:                        case YGuardRule.TYPE_ATTR:
130:                            classTree.retainAttribute(entry.name);
131:                            break;
132:                        case YGuardRule.TYPE_ATTR2:
133:                            classTree.retainAttributeForClass(entry.descriptor,
134:                                    entry.name);
135:                            break;
136:                        case YGuardRule.TYPE_CLASS:
137:                            classTree.retainClass(entry.name,
138:                                    entry.retainClasses, entry.retainMethods,
139:                                    entry.retainFields, true);
140:                            break;
141:                        case YGuardRule.TYPE_METHOD:
142:                            classTree
143:                                    .retainMethod(entry.name, entry.descriptor);
144:                            break;
145:                        case YGuardRule.TYPE_PACKAGE:
146:                            classTree.retainPackage(entry.name);
147:                            break;
148:                        case YGuardRule.TYPE_FIELD:
149:                            classTree.retainField(entry.name);
150:                            break;
151:                        case YGuardRule.TYPE_PACKAGE_MAP:
152:                            classTree.retainPackageMap(entry.name,
153:                                    entry.obfName);
154:                            break;
155:                        case YGuardRule.TYPE_CLASS_MAP:
156:                            classTree.retainClassMap(entry.name, entry.obfName);
157:                            break;
158:                        case YGuardRule.TYPE_METHOD_MAP:
159:                            classTree.retainMethodMap(entry.name,
160:                                    entry.descriptor, entry.obfName);
161:                            break;
162:                        case YGuardRule.TYPE_FIELD_MAP:
163:                            classTree.retainFieldMap(entry.name, entry.obfName);
164:                            break;
165:                        default:
166:                            throw new ParseException("Illegal type: "
167:                                    + entry.type);
168:                        }
169:                    } catch (RuntimeException e) {
170:                        // DEBUG
171:                        // e.printStackTrace();
172:                        log.println(WARNING_SCRIPT_ENTRY_ABSENT + entry.name
173:                                + " -->");
174:                    }
175:                }
176:            }
177:
178:            /** Remap each class based on the remap database, and remove attributes. */
179:            public void remapTo(File[] out, Filter fileFilter, PrintWriter log,
180:                    boolean conserveManifest) throws java.io.IOException,
181:                    ClassNotFoundException {
182:                // Build database if not already done
183:                if (classTree == null) {
184:                    buildClassTree(log);
185:                }
186:
187:                // Generate map table if not already done
188:                if (!hasMap) {
189:                    createMap(log);
190:                }
191:
192:                oldManifest = new Manifest[out.length];
193:                newManifest = new Manifest[out.length];
194:                parseManifest();
195:
196:                StringBuffer replaceNameLog = new StringBuffer();
197:                StringBuffer replaceContentsLog = new StringBuffer();
198:
199:                JarOutputStream outJar = null;
200:                // Open the entry and prepare to process it
201:                DataInputStream inStream = null;
202:                OutputStream os = null;
203:                for (int i = 0; i < inJar.length; i++) {
204:                    os = null;
205:                    outJar = null;
206:                    //store the whole jar in memory, I known this might be alot, but anyway
207:                    //this is the best option, if you want to create correct jar files...
208:                    List jarEntries = new ArrayList();
209:                    try {
210:                        // Go through the input Jar, removing attributes and remapping the Constant Pool
211:                        // for each class file. Other files are copied through unchanged, except for manifest
212:                        // and any signature files - these are deleted and the manifest is regenerated.
213:                        Enumeration entries = inJar[i].entries();
214:                        fireObfuscatingJar(inJar[i].getName(), out[i].getName());
215:                        ByteArrayOutputStream baos = new ByteArrayOutputStream(
216:                                2048);
217:                        while (entries.hasMoreElements()) {
218:                            // Get the next entry from the input Jar
219:                            JarEntry inEntry = (JarEntry) entries.nextElement();
220:
221:                            // Ignore directories
222:                            if (inEntry.isDirectory()) {
223:                                continue;
224:                            }
225:
226:                            inStream = new DataInputStream(
227:                                    new BufferedInputStream(inJar[i]
228:                                            .getInputStream(inEntry)));
229:                            String inName = inEntry.getName();
230:                            if (inName.endsWith(CLASS_EXT)) {
231:                                if (fileFilter == null
232:                                        || fileFilter.accepts(inName)) {
233:                                    // Write the obfuscated version of the class to the output Jar
234:                                    ClassFile cf = ClassFile.create(inStream);
235:                                    fireObfuscatingClass(Conversion
236:                                            .toJavaClass(cf.getName()));
237:                                    cf.remap(classTree,
238:                                            replaceClassNameStrings, log);
239:                                    JarEntry outEntry = new JarEntry(cf
240:                                            .getName()
241:                                            + CLASS_EXT);
242:
243:                                    DataOutputStream classOutputStream;
244:                                    MessageDigest[] digests;
245:                                    if (digestStrings == null) {
246:                                        digestStrings = new String[] { "SHA-1",
247:                                                "MD5" };
248:                                    }
249:                                    digests = new MessageDigest[digestStrings.length];
250:                                    OutputStream stream = baos;
251:                                    // Create an OutputStream piped through a number of digest generators for the manifest
252:
253:                                    for (int j = 0; j < digestStrings.length; j++) {
254:                                        String digestString = digestStrings[j];
255:                                        MessageDigest digest = MessageDigest
256:                                                .getInstance(digestString);
257:                                        digests[j] = digest;
258:                                        stream = new DigestOutputStream(stream,
259:                                                digest);
260:                                    }
261:                                    classOutputStream = new DataOutputStream(
262:                                            stream);
263:
264:                                    // Dump the classfile, while creating the digests
265:                                    cf.write(classOutputStream);
266:                                    classOutputStream.flush();
267:                                    jarEntries.add(new Object[] { outEntry,
268:                                            baos.toByteArray() });
269:                                    baos.reset();
270:                                    // Now update the manifest entry for the class with new name and new digests
271:                                    updateManifest(i, inName, cf.getName()
272:                                            + CLASS_EXT, digests);
273:                                }
274:                            } else if (STREAM_NAME_MANIFEST.equals(inName
275:                                    .toUpperCase())
276:                                    || (inName.length() > (SIGNATURE_PREFIX
277:                                            .length() + 1 + SIGNATURE_EXT
278:                                            .length())
279:                                            && inName.indexOf(SIGNATURE_PREFIX) != -1 && inName
280:                                            .substring(
281:                                                    inName.length()
282:                                                            - SIGNATURE_EXT
283:                                                                    .length(),
284:                                                    inName.length()).equals(
285:                                                    SIGNATURE_EXT))) {
286:                                // Don't pass through the manifest or signature files
287:                                continue;
288:                            } else {
289:                                // Copy the non-class entry through unchanged
290:                                long size = inEntry.getSize();
291:                                if (size != -1) {
292:
293:                                    // Create an OutputStream piped through a number of digest generators for the manifest
294:                                    MessageDigest shaDigest = MessageDigest
295:                                            .getInstance("SHA");
296:                                    MessageDigest md5Digest = MessageDigest
297:                                            .getInstance("MD5");
298:                                    DataOutputStream dataOutputStream = new DataOutputStream(
299:                                            new DigestOutputStream(
300:                                                    new DigestOutputStream(
301:                                                            baos, shaDigest),
302:                                                    md5Digest));
303:
304:                                    String outName;
305:
306:                                    StringBuffer outNameBuffer = new StringBuffer(
307:                                            80);
308:
309:                                    if (resourceHandler != null
310:                                            && resourceHandler.filterName(
311:                                                    inName, outNameBuffer)) {
312:                                        outName = outNameBuffer.toString();
313:                                        if (!outName.equals(inName)) {
314:                                            replaceNameLog
315:                                                    .append("  <resource name=\"");
316:                                            replaceNameLog.append(ClassTree
317:                                                    .toUtf8XmlString(inName));
318:                                            replaceNameLog.append("\" map=\"");
319:                                            replaceNameLog.append(ClassTree
320:                                                    .toUtf8XmlString(outName));
321:                                            replaceNameLog.append("\"/>\n");
322:                                        }
323:                                    } else {
324:                                        outName = classTree.getOutName(inName);
325:                                    }
326:
327:                                    if (resourceHandler == null
328:                                            || !resourceHandler.filterContent(
329:                                                    inStream, dataOutputStream,
330:                                                    inName)) {
331:                                        byte[] bytes = new byte[(int) size];
332:                                        inStream.readFully(bytes);
333:
334:                                        // outName = classTree.getOutName(inName);
335:                                        // Dump the data, while creating the digests
336:                                        dataOutputStream.write(bytes, 0,
337:                                                bytes.length);
338:                                    } else {
339:                                        replaceContentsLog
340:                                                .append("  <resource name=\"");
341:                                        replaceContentsLog.append(ClassTree
342:                                                .toUtf8XmlString(inName));
343:                                        replaceContentsLog.append("\"/>\n");
344:                                    }
345:
346:                                    dataOutputStream.flush();
347:                                    JarEntry outEntry = new JarEntry(outName);
348:
349:                                    jarEntries.add(new Object[] { outEntry,
350:                                            baos.toByteArray() });
351:                                    baos.reset();
352:                                    // Now update the manifest entry for the entry with new name and new digests
353:                                    MessageDigest[] digests = { shaDigest,
354:                                            md5Digest };
355:                                    updateManifest(i, inName, outName, digests);
356:                                }
357:                            }
358:                        }
359:
360:                        os = new FileOutputStream(out[i]);
361:                        if (conserveManifest) {
362:                            outJar = new JarOutputStream(
363:                                    new BufferedOutputStream(os),
364:                                    oldManifest[i]);
365:                        } else {
366:                            outJar = new JarOutputStream(
367:                                    new BufferedOutputStream(os),
368:                                    newManifest[i]);
369:                        }
370:                        outJar.setComment(Version.getJarComment());
371:
372:                        // sort the entries in ascending order
373:                        Collections.sort(jarEntries, new Comparator() {
374:                            public int compare(Object a, Object b) {
375:                                Object[] array1 = (Object[]) a;
376:                                JarEntry entry1 = (JarEntry) array1[0];
377:                                Object[] array2 = (Object[]) b;
378:                                JarEntry entry2 = (JarEntry) array2[0];
379:                                return entry1.getName().compareTo(
380:                                        entry2.getName());
381:                            }
382:                        });
383:                        // Finally, write the big bunch of data
384:                        Set directoriesWritten = new HashSet();
385:                        for (int j = 0; j < jarEntries.size(); j++) {
386:                            Object[] array = (Object[]) jarEntries.get(j);
387:                            JarEntry entry = (JarEntry) array[0];
388:                            String name = entry.getName();
389:                            // make sure the directory entries are written to the jar file
390:                            if (!entry.isDirectory()) {
391:                                int index = 0;
392:                                while ((index = name.indexOf("/", index + 1)) >= 0) {
393:                                    String directory = name.substring(0,
394:                                            index + 1);
395:                                    if (!directoriesWritten.contains(directory)) {
396:                                        directoriesWritten.add(directory);
397:                                        JarEntry directoryEntry = new JarEntry(
398:                                                directory);
399:                                        outJar.putNextEntry(directoryEntry);
400:                                        outJar.closeEntry();
401:                                    }
402:                                }
403:                            }
404:                            // write the entry itself
405:                            byte[] bytes = (byte[]) array[1];
406:                            outJar.putNextEntry(entry);
407:                            outJar.write(bytes);
408:                            outJar.closeEntry();
409:                        }
410:
411:                    } catch (Exception e) {
412:                        // Log exceptions before exiting
413:                        log.println();
414:                        log.println("<!-- An exception has occured.");
415:                        if (e instanceof  java.util.zip.ZipException) {
416:                            log
417:                                    .println("This is most likely due to a duplicate .class file in your jar!");
418:                            log
419:                                    .println("Please check that there are no out-of-date or backup duplicate .class files in your jar!");
420:                        }
421:                        log.println(e.toString());
422:                        e.printStackTrace(log);
423:                        log.println("-->");
424:                        throw new IOException(
425:                                "An error ('"
426:                                        + e.getMessage()
427:                                        + "') occured during the remapping! See the log!)");
428:                    } finally {
429:                        inJar[i].close();
430:                        if (inStream != null) {
431:                            inStream.close();
432:                        }
433:                        if (outJar != null) {
434:                            outJar.close();
435:                        }
436:                        if (os != null) {
437:                            os.close();
438:                        }
439:                    }
440:                }
441:                // Write the mapping table to the log file
442:                classTree.dump(log);
443:                if (replaceContentsLog.length() > 0
444:                        || replaceNameLog.length() > 0) {
445:                    log.println("<!--");
446:                    if (replaceNameLog.length() > 0) {
447:                        log.println("\n<adjust replaceName=\"true\">");
448:                        log.print(replaceNameLog);
449:                        log.println("</adjust>");
450:                    }
451:                    if (replaceContentsLog.length() > 0) {
452:                        log.println("\n<adjust replaceContents=\"true\">");
453:                        log.print(replaceContentsLog);
454:                        log.println("</adjust>");
455:                    }
456:                    log.println("-->");
457:                }
458:
459:            }
460:
461:            /** Close input JAR file. */
462:            public void close() throws java.io.IOException {
463:                for (int i = 0; i < inJar.length; i++) {
464:                    if (inJar[i] != null) {
465:                        inJar[i].close();
466:                        inJar[i] = null;
467:                    }
468:                }
469:            }
470:
471:            // Parse the RFC822-style MANIFEST.MF file
472:            private void parseManifest() throws java.io.IOException {
473:                for (int i = 0; i < oldManifest.length; i++) {
474:                    // The manifest file is the first in the jar and is called
475:                    // (case insensitively) 'MANIFEST.MF'
476:                    oldManifest[i] = inJar[i].getManifest();
477:
478:                    if (oldManifest[i] == null) {
479:                        oldManifest[i] = new Manifest();
480:                    }
481:
482:                    // Create a fresh manifest, with a version header
483:                    newManifest[i] = new Manifest();
484:
485:                    // copy all main attributes
486:                    for (Iterator it = oldManifest[i].getMainAttributes()
487:                            .entrySet().iterator(); it.hasNext();) {
488:                        Map.Entry entry = (Map.Entry) it.next();
489:                        Attributes.Name name = (Attributes.Name) entry.getKey();
490:                        String value = (String) entry.getValue();
491:                        if (resourceHandler != null) {
492:                            name = new Attributes.Name(resourceHandler
493:                                    .filterString(name.toString(),
494:                                            "META-INF/MANIFEST.MF"));
495:                            value = resourceHandler.filterString(value,
496:                                    "META-INF/MANIFEST.MF");
497:                        }
498:                        newManifest[i].getMainAttributes().putValue(
499:                                name.toString(), value);
500:                    }
501:
502:                    newManifest[i].getMainAttributes().putValue(
503:                            "Created-by",
504:                            "yGuard Bytecode Obfuscator "
505:                                    + Version.getVersion());
506:
507:                    // copy all directory entries
508:                    for (Iterator it = oldManifest[i].getEntries().entrySet()
509:                            .iterator(); it.hasNext();) {
510:                        Map.Entry entry = (Map.Entry) it.next();
511:                        String name = (String) entry.getKey();
512:                        if (name.endsWith("/")) {
513:                            newManifest[i].getEntries().put(name,
514:                                    (Attributes) entry.getValue());
515:                        }
516:                    }
517:                }
518:            }
519:
520:            // Update an entry in the manifest file
521:            private void updateManifest(int manifestIndex, String inName,
522:                    String outName, MessageDigest[] digests) {
523:                // Create fresh section for entry, and enter "Name" header
524:
525:                Manifest nm = newManifest[manifestIndex];
526:                Manifest om = oldManifest[manifestIndex];
527:
528:                Attributes oldAtts = om.getAttributes(inName);
529:                Attributes newAtts = new Attributes();
530:                //newAtts.putValue(MANIFEST_NAME_TAG, outName);
531:
532:                // copy over non-name and none digest entries
533:                if (oldAtts != null) {
534:                    for (Iterator it = oldAtts.entrySet().iterator(); it
535:                            .hasNext();) {
536:                        Map.Entry entry = (Map.Entry) it.next();
537:                        Object key = entry.getKey();
538:                        String name = key.toString();
539:                        if (!name.equalsIgnoreCase(MANIFEST_NAME_TAG)
540:                                && name.indexOf("Digest") == -1) {
541:                            newAtts.remove(name);
542:                            newAtts.putValue(name, (String) entry.getValue());
543:                        }
544:                    }
545:                }
546:
547:                // Create fresh digest entries in the new section
548:                if (digests != null && digests.length > 0) {
549:                    // Digest-Algorithms header
550:                    StringBuffer sb = new StringBuffer();
551:                    for (int i = 0; i < digests.length; i++) {
552:                        sb.append(digests[i].getAlgorithm());
553:                        if (i < digests.length - 1) {
554:                            sb.append(", ");
555:                        }
556:                    }
557:                    newAtts.remove(MANIFEST_DIGESTALG_TAG);
558:                    newAtts.putValue(MANIFEST_DIGESTALG_TAG, sb.toString());
559:
560:                    // *-Digest headers
561:                    for (int i = 0; i < digests.length; i++) {
562:                        newAtts.remove(digests[i].getAlgorithm() + "-Digest");
563:                        newAtts.putValue(digests[i].getAlgorithm() + "-Digest",
564:                                Tools.toBase64(digests[i].digest()));
565:                    }
566:                }
567:
568:                if (!newAtts.isEmpty()) {
569:                    // Append the new section to the new manifest
570:                    nm.getEntries().put(outName, newAtts);
571:                }
572:            }
573:
574:            // Create a classfile database.
575:            private void buildClassTree(PrintWriter log)
576:                    throws java.io.IOException {
577:                // Go through the input Jar, adding each class file to the database
578:                classTree = new ClassTree();
579:                classTree.setPedantic(isPedantic());
580:                classTree.setReplaceClassNameStrings(replaceClassNameStrings);
581:                ClassFile.resetDangerHeader();
582:
583:                Map parsedClasses = new HashMap();
584:                for (int i = 0; i < inJar.length; i++) {
585:                    Enumeration entries = inJar[i].entries();
586:                    fireParsingJar(inJar[i].getName());
587:                    while (entries.hasMoreElements()) {
588:                        // Get the next entry from the input Jar
589:                        ZipEntry inEntry = (ZipEntry) entries.nextElement();
590:                        String name = inEntry.getName();
591:                        if (name.endsWith(CLASS_EXT)) {
592:                            fireParsingClass(Conversion.toJavaClass(name));
593:                            // Create a full internal representation of the class file
594:                            DataInputStream inStream = new DataInputStream(
595:                                    new BufferedInputStream(inJar[i]
596:                                            .getInputStream(inEntry)));
597:                            ClassFile cf = null;
598:                            try {
599:                                cf = ClassFile.create(inStream);
600:                            } catch (Exception e) {
601:                                log.println(ERROR_CORRUPT_CLASS
602:                                        + createJarName(inJar[i], name)
603:                                        + " -->");
604:                                e.printStackTrace(log);
605:                                throw new ParseException(e);
606:                            } finally {
607:                                inStream.close();
608:                            }
609:
610:                            if (cf != null) {
611:                                Object[] old = (Object[]) parsedClasses.get(cf
612:                                        .getName());
613:                                if (old != null) {
614:                                    int jarIndex = ((Integer) old[0])
615:                                            .intValue();
616:                                    String warning = "yGuard detected a duplicate class definition "
617:                                            + "for \n    "
618:                                            + Conversion.toJavaClass(cf
619:                                                    .getName())
620:                                            + "\n    ["
621:                                            + createJarName(inJar[jarIndex],
622:                                                    old[1].toString())
623:                                            + "] in \n    ["
624:                                            + createJarName(inJar[i], name)
625:                                            + "]";
626:                                    log.write("<!-- \n" + warning + "\n-->\n");
627:                                    if (jarIndex == i) {
628:                                        throw new IOException(
629:                                                warning
630:                                                        + "\nPlease remove inappropriate duplicates first!");
631:                                    } else {
632:                                        if (pedantic) {
633:                                            throw new IOException(
634:                                                    warning
635:                                                            + "\nMake sure these files are of the same version!");
636:                                        }
637:                                    }
638:                                } else {
639:                                    parsedClasses
640:                                            .put(cf.getName(), new Object[] {
641:                                                    new Integer(i), name });
642:                                }
643:
644:                                // Check the classfile for references to 'dangerous' methods
645:                                cf.logDangerousMethods(log,
646:                                        replaceClassNameStrings);
647:                                classTree.addClassFile(cf);
648:                            }
649:
650:                        }
651:                    }
652:                }
653:
654:                // set the java access modifiers from the containing class (muellese)
655:                final ClassTree ct = classTree;
656:                ct.walkTree(new TreeAction() {
657:                    public void classAction(Cl cl) {
658:                        if (cl.isInnerClass()) {
659:                            Cl parent = (Cl) cl.getParent();
660:                            cl.access = parent.getInnerClassModifier(cl
661:                                    .getInName());
662:                        }
663:                    }
664:                });
665:            }
666:
667:            private static String createJarName(JarFile jar, String name) {
668:                return "jar:" + jar.getName() + "|" + name;
669:            }
670:
671:            // Generate a mapping table for obfuscation.
672:            private void createMap(PrintWriter log)
673:                    throws ClassNotFoundException {
674:                // Traverse the class tree, generating obfuscated names within
675:                // package and class namespaces
676:                classTree.generateNames();
677:
678:                // Resolve the polymorphic dependencies of each class, generating
679:                // non-private method and field names for each namespace
680:                classTree.resolveClasses();
681:
682:                // Signal that the namespace maps have been created
683:                hasMap = true;
684:
685:                // Write the memory usage at this point to the log file
686:                Runtime rt = Runtime.getRuntime();
687:                rt.gc();
688:                log.println("<!--");
689:                log.println(LOG_MEMORY_USED
690:                        + Long.toString(rt.totalMemory() - rt.freeMemory())
691:                        + LOG_MEMORY_BYTES);
692:                log.println(LOG_MEMORY_TOTAL + Long.toString(rt.totalMemory())
693:                        + LOG_MEMORY_BYTES);
694:                log.println("-->");
695:
696:            }
697:
698:            protected void fireParsingJar(String jar) {
699:                if (listenerList == null)
700:                    return;
701:                for (int i = 0, j = listenerList.size(); i < j; i++) {
702:                    ((ObfuscationListener) listenerList.get(i)).parsingJar(jar);
703:                }
704:            }
705:
706:            protected void fireParsingClass(String className) {
707:                if (listenerList == null)
708:                    return;
709:                for (int i = 0, j = listenerList.size(); i < j; i++) {
710:                    ((ObfuscationListener) listenerList.get(i))
711:                            .parsingClass(className);
712:                }
713:            }
714:
715:            protected void fireObfuscatingJar(String inJar, String outJar) {
716:                if (listenerList == null)
717:                    return;
718:                for (int i = 0, j = listenerList.size(); i < j; i++) {
719:                    ((ObfuscationListener) listenerList.get(i)).obfuscatingJar(
720:                            inJar, outJar);
721:                }
722:            }
723:
724:            protected void fireObfuscatingClass(String className) {
725:                if (listenerList == null)
726:                    return;
727:                for (int i = 0, j = listenerList.size(); i < j; i++) {
728:                    ((ObfuscationListener) listenerList.get(i))
729:                            .obfuscatingClass(className);
730:                }
731:            }
732:
733:            /** Registers Listener to receive events.
734:             * @param listener The listener to register.
735:             */
736:            public synchronized void addListener(
737:                    com.yworks.yguard.ObfuscationListener listener) {
738:                if (listenerList == null) {
739:                    listenerList = new java.util.ArrayList();
740:                }
741:                listenerList.add(listener);
742:            }
743:
744:            /** Removes Listener from the list of listeners.
745:             * @param listener The listener to remove.
746:             */
747:            public synchronized void removeListener(
748:                    com.yworks.yguard.ObfuscationListener listener) {
749:                if (listenerList != null) {
750:                    listenerList.remove(listener);
751:                }
752:            }
753:
754:            /** Getter for property replaceClassNameStrings.
755:             * @return Value of property replaceClassNameStrings.
756:             *
757:             */
758:            public boolean isReplaceClassNameStrings() {
759:                return this .replaceClassNameStrings;
760:            }
761:
762:            /** Setter for property replaceClassNameStrings.
763:             * @param replaceClassNameStrings New value of property replaceClassNameStrings.
764:             *
765:             */
766:            public void setReplaceClassNameStrings(
767:                    boolean replaceClassNameStrings) {
768:                this .replaceClassNameStrings = replaceClassNameStrings;
769:            }
770:
771:            /** Getter for property pedantic.
772:             * @return Value of property pedantic.
773:             *
774:             */
775:            public boolean isPedantic() {
776:                return this .pedantic;
777:            }
778:
779:            /** Setter for property pedantic.
780:             * @param pedantic New value of property pedantic.
781:             *
782:             */
783:            public void setPedantic(boolean pedantic) {
784:                this .pedantic = pedantic;
785:                Cl.setPedantic(pedantic);
786:            }
787:
788:            /**
789:             * Returns the obfuscated file name of the java class.
790:             * The ending ".class" is omitted.
791:             * @param javaClass the fully qualified name of an unobfuscated class.
792:             */
793:            public String translateJavaFile(String javaClass) {
794:                Cl cl = classTree.findClassForName(javaClass.replace('/', '.'));
795:                if (cl != null) {
796:                    return cl.getFullOutName();
797:                } else {
798:                    return javaClass;
799:                }
800:            }
801:
802:            public String translateJavaClass(String javaClass) {
803:                Cl cl = classTree.findClassForName(javaClass);
804:                if (cl != null) {
805:                    return cl.getFullOutName().replace('/', '.');
806:                } else {
807:                    return javaClass;
808:                }
809:            }
810:
811:            public void setDigests(String[] digestStrings) {
812:                this.digestStrings = digestStrings;
813:            }
814:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.