trunk contents moved to root

This commit is contained in:
Jindra Petřík
2014-05-10 20:50:57 +02:00
parent 1b851e66a8
commit 199a4d0c2b
2296 changed files with 0 additions and 0 deletions

73
libsrc/jpacker/build.xml Normal file
View File

@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- You may freely edit this file. See commented blocks below for -->
<!-- some examples of how to customize the build. -->
<!-- (If you delete it and reopen the project it will be recreated.) -->
<!-- By default, only the Clean and Build commands use this build script. -->
<!-- Commands such as Run, Debug, and Test only use this build script if -->
<!-- the Compile on Save feature is turned off for the project. -->
<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
<!-- in the project's Project Properties dialog box.-->
<project name="jpacker" default="default" basedir=".">
<description>Builds, tests, and runs the project jpacker.</description>
<import file="nbproject/build-impl.xml"/>
<!--
There exist several targets which are by default empty and which can be
used for execution of your tasks. These targets are usually executed
before and after some main targets. They are:
-pre-init: called before initialization of project properties
-post-init: called after initialization of project properties
-pre-compile: called before javac compilation
-post-compile: called after javac compilation
-pre-compile-single: called before javac compilation of single file
-post-compile-single: called after javac compilation of single file
-pre-compile-test: called before javac compilation of JUnit tests
-post-compile-test: called after javac compilation of JUnit tests
-pre-compile-test-single: called before javac compilation of single JUnit test
-post-compile-test-single: called after javac compilation of single JUunit test
-pre-jar: called before JAR building
-post-jar: called after JAR building
-post-clean: called after cleaning build products
(Targets beginning with '-' are not intended to be called on their own.)
Example of inserting an obfuscator after compilation could look like this:
<target name="-post-compile">
<obfuscate>
<fileset dir="${build.classes.dir}"/>
</obfuscate>
</target>
For list of available properties check the imported
nbproject/build-impl.xml file.
Another way to customize the build is by overriding existing main targets.
The targets of interest are:
-init-macrodef-javac: defines macro for javac compilation
-init-macrodef-junit: defines macro for junit execution
-init-macrodef-debug: defines macro for class debugging
-init-macrodef-java: defines macro for class execution
-do-jar: JAR building
run: execution of project
-javadoc-build: Javadoc generation
test-report: JUnit report generation
An example of overriding the target for project execution could look like this:
<target name="run" depends="jpacker-impl.jar">
<exec dir="bin" executable="launcher.exe">
<arg file="${dist.jar}"/>
</exec>
</target>
Notice that the overridden target depends on the jar target and not only on
the compile target as the regular run target does. Again, for a list of available
properties which you can use, check the target you are overriding in the
nbproject/build-impl.xml file.
-->
</project>

BIN
libsrc/jpacker/jargs.jar Normal file

Binary file not shown.

View File

@@ -0,0 +1,3 @@
Manifest-Version: 1.0
X-COMMENT: Main-Class will be added automatically by build

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
build.xml.data.CRC32=811ea359
build.xml.script.CRC32=f4a6aa27
build.xml.stylesheet.CRC32=8064a381@1.74.1.48
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
nbproject/build-impl.xml.data.CRC32=811ea359
nbproject/build-impl.xml.script.CRC32=a8ed580a
nbproject/build-impl.xml.stylesheet.CRC32=876e7a8f@1.74.1.48

View File

@@ -0,0 +1,77 @@
annotation.processing.enabled=true
annotation.processing.enabled.in.editor=false
annotation.processing.processors.list=
annotation.processing.run.all.processors=true
annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
application.title=jpacker
application.vendor=
build.classes.dir=${build.dir}/classes
build.classes.excludes=**/*.java,**/*.form
# This directory is removed when the project is cleaned:
build.dir=build
build.generated.dir=${build.dir}/generated
build.generated.sources.dir=${build.dir}/generated-sources
# Only compile against the classpath explicitly listed here:
build.sysclasspath=ignore
build.test.classes.dir=${build.dir}/test/classes
build.test.results.dir=${build.dir}/test/results
# Uncomment to specify the preferred debugger connection transport:
#debug.transport=dt_socket
debug.classpath=\
${run.classpath}
debug.test.classpath=\
${run.test.classpath}
# Files in build.classes.dir which should be excluded from distribution jar
dist.archive.excludes=
# This directory is removed when the project is cleaned:
dist.dir=dist
dist.jar=../../lib/jpacker.jar
dist.javadoc.dir=${dist.dir}/javadoc
endorsed.classpath=
excludes=
file.reference.jargs.jar=jargs.jar
includes=**
jar.compress=false
javac.classpath=\
${file.reference.jargs.jar}
# Space-separated list of extra javac options
javac.compilerargs=
javac.deprecation=false
javac.processorpath=\
${javac.classpath}
javac.source=1.7
javac.target=1.7
javac.test.classpath=\
${javac.classpath}:\
${build.classes.dir}
javac.test.processorpath=\
${javac.test.classpath}
javadoc.additionalparam=
javadoc.author=false
javadoc.encoding=${source.encoding}
javadoc.noindex=false
javadoc.nonavbar=false
javadoc.notree=false
javadoc.private=false
javadoc.splitindex=true
javadoc.use=true
javadoc.version=false
javadoc.windowtitle=
main.class=com.jpacker.JPacker
manifest.file=manifest.mf
meta.inf.dir=${src.dir}/META-INF
mkdist.disabled=true
platform.active=default_platform
run.classpath=\
${javac.classpath}:\
${build.classes.dir}
# Space-separated list of JVM arguments used when running the project.
# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value.
# To set system properties for unit tests define test-sys-prop.name=value:
run.jvmargs=
run.test.classpath=\
${javac.test.classpath}:\
${build.test.classes.dir}
source.encoding=UTF-8
src.dir=src
test.src.dir=test

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://www.netbeans.org/ns/project/1">
<type>org.netbeans.modules.java.j2seproject</type>
<configuration>
<data xmlns="http://www.netbeans.org/ns/j2se-project/3">
<name>jpacker</name>
<source-roots>
<root id="src.dir"/>
</source-roots>
<test-roots>
<root id="test.src.dir"/>
</test-roots>
</data>
</configuration>
</project>

View File

@@ -0,0 +1,197 @@
/**
* Packer version 3.0 (final)
* Copyright 2004-2007, Dean Edwards
* Web: {@link http://dean.edwards.name/}
*
* This software is licensed under the MIT license
* Web: {@link http://www.opensource.org/licenses/mit-license}
*
* Ported to Java by Pablo Santiago based on C# version by Jesse Hansen, <twindagger2k @ msn.com>
* Web: {@link http://jpacker.googlecode.com/}
* Email: <pablo.santiago @ gmail.com>
*/
package com.jpacker;
import com.jpacker.exceptions.EmptyFileException;
import jargs.gnu.CmdLineParser;
import jargs.gnu.CmdLineParser.IllegalOptionValueException;
import jargs.gnu.CmdLineParser.Option;
import jargs.gnu.CmdLineParser.UnknownOptionException;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
/**
*
* @author Pablo Santiago <pablo.santiago @ gmail.com>
*/
public class JPacker {
/**
* @param args
* the command line arguments
*/
public static void main(String[] args) throws FileNotFoundException, IOException {
long startTime = System.currentTimeMillis();
CmdLineParser parser = new CmdLineParser();
Option baseOpt = parser.addIntegerOption('b', "base");
Option columnsOpt = parser.addIntegerOption('c', "column");
Option helpOpt = parser.addBooleanOption('h', "help");
Option minifyOpt = parser.addBooleanOption('m', "minify");
Option outputFilenameOpt = parser.addStringOption('o', "output");
Option quietOpt = parser.addBooleanOption('q', "quiet");
Option shrinkVariablesOpt = parser.addBooleanOption('s', "shrink-variables");
Writer out = null;
BufferedReader in = null;
try {
if (args.length == 0) {
throw new RuntimeException("No input file");
}
parser.parse(args);
Boolean help = (Boolean) parser.getOptionValue(helpOpt);
if (help != null && help.booleanValue()) {
printUsage();
System.exit(0);
}
boolean minify = parser.getOptionValue(minifyOpt) != null;
boolean shrinkVariables = parser.getOptionValue(shrinkVariablesOpt) != null;
boolean quiet = parser.getOptionValue(quietOpt) != null;
Integer base = (Integer) parser.getOptionValue(baseOpt);
Integer columns = (Integer) parser.getOptionValue(columnsOpt);
if (parser.getRemainingArgs().length == 0) {
throw new FileNotFoundException("No input file was provided");
}
String inputFilename = parser.getRemainingArgs()[0];
String outputFilename = (String) parser.getOptionValue(outputFilenameOpt);
JPackerExecuter executer;
if (base == null) {
executer = new JPackerExecuter(JPackerEncoding.NONE);
} else {
executer = new JPackerExecuter(getEncoding(baseOpt, base));
}
in = new BufferedReader(new FileReader(new File(inputFilename)));
String unpacked = buildStringFromTextFile(in);
if (unpacked.isEmpty()) {
throw new EmptyFileException("The file is empty");
}
String packed = executer.pack(unpacked, minify, shrinkVariables);
if (outputFilename == null) {
out = new OutputStreamWriter(System.out);
} else {
out = new OutputStreamWriter(new FileOutputStream(outputFilename));
}
if (columns != null) {
packed = wrapLines(packed, columns);
}
out.write(packed.replace("\n", System.getProperty("line.separator")));
out.close();
if (!quiet) {
long endTime = System.currentTimeMillis();
System.out.printf("Reduced to %.2f%% of its original size in %.4f seconds.\n",
((double) packed.length() / (double) unpacked.length()) * 100,
(double) (endTime - startTime) / 1000);
}
} catch (FileNotFoundException e) {
System.out.println("File not found: " + e.getLocalizedMessage());
System.exit(1);
} catch (IllegalOptionValueException e) {
System.out.println("Illegal option: " + e.getValue() + " - " + e.getOption());
System.exit(1);
} catch (UnknownOptionException e) {
printUsage();
System.exit(1);
} catch (Exception e) {
System.out.println(e.getLocalizedMessage());
System.exit(1);
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
System.out.println(e.getLocalizedMessage());
}
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
System.out.println(e.getLocalizedMessage());
}
}
}
}
private static void printUsage() {
System.out.println("\nUsage: java -jar jpacker-x.y.z.jar [options] [input file]\n\n"
+ "Options\n"
+ " -b, --base Encoding base. Options are: 10, 36, 52, 62 \n"
+ " and 95. Ignored if --minify option is set.\n"
+ " -c, --column <column> Insert a line break after the specified column \n"
+ " number.\n"
+ " -h, --help Displays this information.\n"
+ " -m, --minify Minify only, do not obfuscate.\n"
+ " --minify and --base values will be ignored.\n"
+ " -o <file>, --output <file> Place the output into <file>.\n"
+ " Defaults to stdout.\n"
+ " -q, --quiet Quiet mode, no message.\n"
+ " -s, --shrink-variables Shrink variables. Ignored if --minify option \n"
+ " is set.\n");
}
private static String wrapLines(String packedScript, Integer columns) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < packedScript.length(); i++) {
int end = ((i + columns) > (packedScript.length()) ? packedScript.length() : i + columns);
sb.append(packedScript.substring(i, end)).append(System.getProperty("line.separator"));
i = end + 1;
}
return sb.toString();
}
private static String buildStringFromTextFile(BufferedReader reader) throws FileNotFoundException, IOException {
StringBuilder sb = new StringBuilder();
String s;
while ((s = reader.readLine()) != null) {
sb.append(s).append(System.getProperty("line.separator"));
}
reader.close();
return sb.toString();
}
private static JPackerEncoding getEncoding(Option option, Integer base) throws IllegalOptionValueException {
switch (base) {
case 10:
return JPackerEncoding.NUMERIC;
case 36:
return JPackerEncoding.MID;
case 52:
return JPackerEncoding.BASIC;
case 62:
return JPackerEncoding.NORMAL;
case 95:
return JPackerEncoding.HIGH_ASCII;
default:
throw new IllegalOptionValueException(option, "Encoding base option not valid");
}
}
}

View File

@@ -0,0 +1,75 @@
/**
* Packer version 3.0 (final)
* Copyright 2004-2007, Dean Edwards
* Web: {@link http://dean.edwards.name/}
*
* This software is licensed under the MIT license
* Web: {@link http://www.opensource.org/licenses/mit-license}
*
* Ported to Java by Pablo Santiago based on C# version by Jesse Hansen, <twindagger2k @ msn.com>
* Web: {@link http://jpacker.googlecode.com/}
* Email: <pablo.santiago @ gmail.com>
*/
package com.jpacker;
import com.jpacker.encoders.BasicEncoder;
import com.jpacker.encoders.Encoder;
import com.jpacker.encoders.HighAsciiEncoder;
import com.jpacker.encoders.MidEncoder;
import com.jpacker.encoders.NormalEncoder;
import com.jpacker.encoders.NumericEncoder;
/**
* Enum of encoding levels
*
* @author Pablo Santiago <pablo.santiago @ gmail.com>
*
*/
public enum JPackerEncoding {
/**
* No encoding
*/
NONE(0, "", null),
/**
* Base<sub>10</sub> : [0-9]
*/
NUMERIC(10, "String", new NumericEncoder()),
/**
* Base<sub>36</sub> : [0-z]
*/
MID(36, "function(c){return c.toString(a)}", new MidEncoder()),
/**
* Base<sub>52</sub> : [a-Z]
*/
BASIC(52, "function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>25?String.fromCharCode(c+39):String.fromCharCode(c+97));", new BasicEncoder()),
/**
* Base<sub>62</sub> : [0-Z]
*/
NORMAL(62, "function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))}", new NormalEncoder()),
/**
* Base<sub>95</sub> : [¡-ÿ]
*/
HIGH_ASCII(95, "function(c){return(c<a?\"\":e(c/a))String.fromCharCode(c%a+161)}", new HighAsciiEncoder());
private final int encodingBase;
private final String encode;
private Encoder encoder;
JPackerEncoding(int encodingBase, String encode, Encoder encoder) {
this.encodingBase = encodingBase;
this.encode = encode;
this.encoder = encoder;
}
public int getEncodingBase() {
return encodingBase;
}
public String getEncode() {
return encode;
}
public Encoder getEncoder() {
return encoder;
}
}

View File

@@ -0,0 +1,329 @@
/**
* Packer version 3.0 (final)
* Copyright 2004-2007, Dean Edwards
* Web: {@link http://dean.edwards.name/}
*
* This software is licensed under the MIT license
* Web: {@link http://www.opensource.org/licenses/mit-license}
*
* Ported to Java by Pablo Santiago based on C# version by Jesse Hansen, <twindagger2k @ msn.com>
* Web: {@link http://jpacker.googlecode.com/}
* Email: <pablo.santiago @ gmail.com>
*/
package com.jpacker;
import java.util.ArrayList;
import java.util.Formatter;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.jpacker.encoders.BasicEncoder;
import com.jpacker.encoders.Encoder;
import com.jpacker.strategies.DefaultReplacementStrategy;
import com.jpacker.strategies.ReplacementStrategy;
/**
* Packer class.
*
* Main jPacker class that packs the script.
*
* @author Pablo Santiago <pablo.santiago @ gmail.com>
*/
public class JPackerExecuter {
private JPackerEncoding encoding;
private static final String UNPACK = "eval(function(p,a,c,k,e,r){e=%5$s;if(!''.replace(/^/,String)){while(c--)r[%6$s]=k[c]"
+ "||%6$s;k=[function(e){return r[e]}];e=function(){return'\\\\w+'};c=1};while(c--)if(k[c])p=p."
+ "replace(new RegExp('\\\\b'+e(c)+'\\\\b','g'),k[c]);return p}('%1$s',%2$s,%3$s,'%4$s'.split('|'),0,{}))";
/**
* Constructor
*
* @param encoding
* The encoding level for this instance
*/
public JPackerExecuter(JPackerEncoding encoding) {
setEncoding(encoding);
}
/**
* Packs the script
*
* @param script
* The script to pack
* @param minifyOnly
* True if script should only be minified and not encoded and/or
* its variables shrunk, false otherwise.
* @param shrinkVariables
* True if variables should be shrunk, false otherwise. If
* minifyOnly is true, this option has no side effect.
* @return The packed script
*/
public String pack(String script, boolean minifyOnly, boolean shrinkVariables) {
script += "\n";
script = minify(script);
if (!minifyOnly) {
if (shrinkVariables) {
script = shrinkVariables(script);
}
if (encoding != JPackerEncoding.NONE) {
script = encode(script);
}
}
return script;
}
// zero encoding - just removal of whitespace and comments
private String minify(String script) {
JPackerParser parser = new JPackerParser();
ReplacementStrategy defaultStrat = new DefaultReplacementStrategy();
// protect data
parser = addDataRegEx(parser);
script = parser.exec(script, defaultStrat);
// remove white-space
parser = addWhiteSpaceRegEx(parser);
script = parser.exec(script, defaultStrat);
// clean
parser = addCleanUpRegEx(parser);
script = parser.exec(script, defaultStrat);
// done
return script;
}
private JPackerParser addDataRegEx(JPackerParser parser) {
final String COMMENT1 = "(\\/\\/|;;;)[^\\n]*";
final String COMMENT2 = "\\/\\*[^*]*\\*+([^\\/][^*]*\\*+)*\\/";
final String REGEX = "\\/(\\\\[\\/\\\\]|[^*\\/])(\\\\.|[^\\/\\n\\\\])*\\/[gim]*";
// Packer.CONTINUE
parser.remove("\\\\\\r?\\n");
parser.ignore("'(\\\\.|[^'\\\\])*'");
parser.ignore("\"(\\\\.|[^\"\\\\])*\"");
parser.ignore("\\/\\*@|@\\*\\/|\\/\\/@[^\\n]*\\n");
parser.replace("(" + COMMENT1 + ")\\n\\s*(" + REGEX + ")?", "\n$3");
parser.replace("(" + COMMENT2 + ")\\s*(" + REGEX + ")?", " $3");
parser.replace("([\\[\\(\\^=,{}:;&|!*?])\\s*(" + REGEX + ")", "$1$2");
return parser;
}
private JPackerParser addCleanUpRegEx(JPackerParser parser) {
parser.replace("\\(\\s*;\\s*;\\s*\\)", "(;;)");
parser.ignore("throw[};]+[};]"); // safari 1.3 bug
parser.replace(";+\\s*([};])", "$1");
parser.remove(";;[^\\n\\r]+[\\n\\r]");
return parser;
}
private JPackerParser addWhiteSpaceRegEx(JPackerParser parser) {
parser.replace("(\\d)\\s+(\\.\\s*[a-z\\$_\\[\\(])", "$1 $2");
parser.replace("([+\\-])\\s+([+\\-])", "$1 $2");
parser.replace("(\\b|\\$)\\s+(\\b|\\$)", "$1 $2");
parser.replace("\\b\\s+\\$\\s+\\b", " $ ");
parser.replace("\\$\\s+\\b", "$ ");
parser.replace("\\b\\s+\\$", " $");
parser.replace("\\b\\s+\\b", " ");
parser.remove("\\s+");
return parser;
}
private String shrinkVariables(String script) {
final Pattern pattern = Pattern.compile("^[^'\"]\\/");
// identify blocks, particularly identify function blocks (which define
// scope)
Pattern blockPattern = Pattern.compile("(function\\s*[\\w$]*\\s*\\(\\s*([^\\)]*)\\s*\\)\\s*)?(\\{([^{}]*)\\})");
List<String> blocks = new ArrayList<String>(); // store program blocks
// (anything between
// braces {})
final List<String> data = new ArrayList<String>(); // encoded strings
// and regular
// expressions
JPackerParser parser = new JPackerParser();
parser = addDataRegEx(parser);
script = parser.exec(script, new ReplacementStrategy() {
@Override
public String replace(List<JPackerPattern> patterns, Matcher matcher) {
String replacement = "#" + data.size();
String string = matcher.group();
if (pattern.matcher(string).find()) {
replacement = string.charAt(0) + replacement;
string = string.substring(1);
}
data.add(string);
return replacement;
}
});
do {
// put the blocks back
Matcher blockMatcher = blockPattern.matcher(script);
StringBuffer sb = new StringBuffer();
while (blockMatcher.find()) {
blockMatcher.appendReplacement(sb, encodeBlock(blockMatcher, blocks));
}
blockMatcher.appendTail(sb);
script = sb.toString();
} while (blockPattern.matcher(script).find());
while (Pattern.compile("~(\\d+)~").matcher(script).find()) {
script = decodeBlock(script, blocks);
}
// put strings and regular expressions back
Matcher storeMatcher = Pattern.compile("#(\\d+)").matcher(script);
StringBuffer sb2 = new StringBuffer();
while (storeMatcher.find()) {
int num = Integer.parseInt(storeMatcher.group(1));
storeMatcher.appendReplacement(sb2, Matcher.quoteReplacement(data.get(num)));
}
storeMatcher.appendTail(sb2);
return sb2.toString();
}
private String encode(String script) {
JPackerWords words = new JPackerWords(script, encoding);
Pattern wordsPattern = Pattern.compile("\\w+");
Matcher wordsMatcher = wordsPattern.matcher(script);
StringBuffer sb = new StringBuffer();
while (wordsMatcher.find()) {
JPackerWord tempWord = new JPackerWord(wordsMatcher.group());
wordsMatcher.appendReplacement(sb, words.find(tempWord).getEncoded());
}
wordsMatcher.appendTail(sb);
int ascii = Math.min(Math.max(words.getWords().size(), 2), encoding.getEncodingBase());
String p = escape(sb.toString());
String a = String.valueOf(ascii);
String c = String.valueOf(words.getWords().size());
String k = words.toString();
String e = getEncode(ascii);
String r = ascii > 10 ? "e(c)" : "c";
return new Formatter().format(UNPACK, p, a, c, k, e, r).toString();
}
// encoder for program blocks
private String encodeBlock(Matcher matcher, List<String> blocks) {
String block = matcher.group();
String func = matcher.group(1);
String args = matcher.group(2);
if (func != null && !func.isEmpty()) { // the block is a function block
// decode the function block (THIS IS THE IMPORTANT BIT)
// We are retrieving all sub-blocks and will re-parse them in light
// of newly shrunk variables
while (Pattern.compile("~(\\d+)~").matcher(block).find()) {
block = decodeBlock(block, blocks);
}
// create the list of variable and argument names
Pattern varNamePattern = Pattern.compile("var\\s+[\\w$]+");
Matcher varNameMatcher = varNamePattern.matcher(block);
StringBuilder sb = new StringBuilder();
while (varNameMatcher.find()) {
sb.append(varNameMatcher.group()).append(",");
}
String vars = "";
if (!sb.toString().isEmpty()) {
vars = sb.deleteCharAt(sb.length() - 1).toString().replaceAll("var\\s+", "");
}
String[] ids = concat(args.split("\\s*,\\s*"), vars.split("\\s*,\\s*"));
Set<String> idList = new LinkedHashSet<String>();
for (String s : ids) {
if (!s.isEmpty()) {
idList.add(s);
}
}
// process each identifier
int count = 0;
String shortId;
for (String id : idList) {
id = id.trim();
if (id.length() > 1) { // > 1 char
id = Matcher.quoteReplacement(id);
// find the next free short name (check everything in the
// current scope)
Encoder e = new BasicEncoder();
do {
shortId = e.encode(count++);
} while (Pattern.compile("[^\\w$.]" + shortId + "[^\\w$:]").matcher(block).find());
// replace the long name with the short name
while (Pattern.compile("([^\\w$.])" + id + "([^\\w$:])").matcher(block).find()) {
block = block.replaceAll("([^\\w$.])" + id + "([^\\w$:])", "$1" + shortId + "$2");
}
block = block.replaceAll("([^{,\\w$.])" + id + ":", "$1" + shortId + ":");
}
}
}
String replacement = "~" + blocks.size() + "~";
blocks.add(block);
return replacement;
}
private String decodeBlock(String block, List<String> blocks) {
Matcher encoded = Pattern.compile("~(\\d+)~").matcher(block);
StringBuffer sbe = new StringBuffer();
while (encoded.find()) {
int num = Integer.parseInt(encoded.group(1));
encoded.appendReplacement(sbe, Matcher.quoteReplacement(blocks.get(num)));
}
encoded.appendTail(sbe);
return sbe.toString();
}
private String[] concat(String[] a, String[] b) {
String[] c = new String[a.length + b.length];
System.arraycopy(a, 0, c, 0, a.length);
System.arraycopy(b, 0, c, a.length, b.length);
return c;
}
private String getEncode(int ascii) {
if (ascii > 96) {
return JPackerEncoding.HIGH_ASCII.getEncode();
} else if (ascii > 36) {
return JPackerEncoding.NORMAL.getEncode();
} else if (ascii > 10) {
return JPackerEncoding.MID.getEncode();
} else {
return JPackerEncoding.NUMERIC.getEncode();
}
}
private String escape(String input) {
// single quotes wrap the final string so escape them
// also escape new lines required by conditional comments
return input.replaceAll("([\\\\'])", "\\\\$1").replaceAll("[\\r\\n]+", "\\n");
}
/**
* Encoding level. Options are: {@link JPackerEncoding#NONE},
* {@link JPackerEncoding#NUMERIC}, {@link JPackerEncoding#MID},
* {@link JPackerEncoding#NORMAL} and {@link JPackerEncoding#HIGH_ASCII}.
*
* @return The current encoding level
*/
public JPackerEncoding getEncoding() {
return encoding;
}
/**
* Set the encoding level to use.
*
* @param encoding
*/
public final void setEncoding(JPackerEncoding encoding) {
this.encoding = encoding;
}
}

View File

@@ -0,0 +1,182 @@
/**
* Packer version 3.0 (final)
* Copyright 2004-2007, Dean Edwards
* Web: {@link http://dean.edwards.name/}
*
* This software is licensed under the MIT license
* Web: {@link http://www.opensource.org/licenses/mit-license}
*
* Ported to Java by Pablo Santiago based on C# version by Jesse Hansen, <twindagger2k @ msn.com>
* Web: {@link http://jpacker.googlecode.com/}
* Email: <pablo.santiago @ gmail.com>
*/
package com.jpacker;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.jpacker.evaluators.DeleteEvaluator;
import com.jpacker.evaluators.Evaluator;
import com.jpacker.evaluators.IntegerEvaluator;
import com.jpacker.evaluators.StringEvaluator;
import com.jpacker.strategies.DefaultReplacementStrategy;
import com.jpacker.strategies.ReplacementStrategy;
/**
* Parser class that matches RegGrp.js.
*
* This class parses the script using the expressions added via
* {@link #remove(String)}, {@link #ignore(String)},
* {@link #replace(String,String)} and {@link #replace(String,Evaluator)}
*
* @author Pablo Santiago <pablo.santiago @ gmail.com>
*/
public class JPackerParser {
private static Pattern GROUPS = Pattern.compile("\\(");
private static Pattern SUB_REPLACE = Pattern.compile("\\$(\\d+)");
private static Pattern INDEXED = Pattern.compile("^\\$\\d+$");
private static Pattern ESCAPE = Pattern.compile("\\\\.");
private static Pattern ESCAPE_BRACKETS = Pattern.compile("\\(\\?[:=!]|\\[[^\\]]+\\]");
private static Pattern DELETED = Pattern.compile("\\x01[^\\x01]*\\x01");
private static String IGNORE = "$0";
private List<JPackerPattern> jpatterns = new ArrayList<JPackerPattern>();
/**
* Add an expression to be removed
*
* @param expression
* Regular expression {@link String}
*/
public void remove(String expression) {
replace(expression, "");
}
/**
* Add an expression to be ignored
*
* @param expression
* Regular expression {@link String}
*/
public void ignore(String expression) {
replace(expression, IGNORE);
}
/**
* Add an expression to be replaced with the replacement string
*
* @param expression
* Regular expression {@link String}
* @param replacement
* Replacement {@link String}. Use $1, $2, etc. for groups
*/
public void replace(String expression, String replacement) {
if (replacement.isEmpty()) {
replace(expression, new DeleteEvaluator());
return;
}
Evaluator evaluator;
// does the pattern deal with sub-expressions? and a simple lookup (e.g. $2)
if (SUB_REPLACE.matcher(replacement).matches() && INDEXED.matcher(replacement).matches()) {
evaluator = new IntegerEvaluator(Integer.parseInt(replacement.substring(1)));
} else {
evaluator = new StringEvaluator(replacement);
}
JPackerPattern jpattern = new JPackerPattern(expression, evaluator);
// count the number of sub-expressions
jpattern.setLength(countSubExpressions(expression));
jpatterns.add(jpattern);
}
/**
* Add an expression to be replaced using an {@link Evaluator} object
*
* @param expression
* Regular expression String
* @param evaluator
* The {@link Evaluator} object
*/
public void replace(String expression, Evaluator evaluator) {
JPackerPattern jpattern = new JPackerPattern(expression, evaluator);
// count the number of sub-expressions
jpattern.setLength(countSubExpressions(expression));
jpatterns.add(jpattern);
}
// builds the patterns into a single regular expression
private Pattern buildPatterns() {
StringBuilder rtrn = new StringBuilder();
for (JPackerPattern jpattern : jpatterns) {
rtrn.append(jpattern).append("|");
}
rtrn.deleteCharAt(rtrn.length() - 1);
return Pattern.compile(rtrn.toString());
}
/**
* Executes the parser in order to parse the script with the expressions
* added via {@link #remove(String)}, {@link #ignore(String)},
* {@link #replace(String,String)} and {@link #replace(String,Evaluator)}
*
* @param input
* The script to be parsed
* @return The parsed script
*/
public String exec(String input) {
return exec(input, new DefaultReplacementStrategy());
}
/**
* Executes the parser in order to parse the script with the expressions
* added via {@link #remove(String)}, {@link #ignore(String)},
* {@link #replace(String,String)} and {@link #replace(String,Evaluator)}.
* Using a {@link ReplacementStrategy} object, a custom replacement
* algorithm can be used.
*
* @param input
* The script to be parsed
* @param strategy
* The {@link ReplacementStrategy} object for custom replacement
* @return The parsed script
*/
public String exec(String input, ReplacementStrategy strategy) {
Matcher matcher = buildPatterns().matcher(input);
StringBuffer sb = new StringBuffer(input.length());
while (matcher.find()) {
String rep = strategy.replace(jpatterns, matcher);
if (rep != null && !rep.isEmpty()) {
rep = Matcher.quoteReplacement(rep);
}
matcher.appendReplacement(sb, rep);
}
matcher.appendTail(sb);
return DELETED.matcher(sb).replaceAll("");
}
// count the number of sub-expressions
private int countSubExpressions(String expression) {
int cont = 0;
Matcher matcher = GROUPS.matcher(internalEscape(expression));
while (matcher.find()) {
cont++;
}
// - add 1 because each group is itself a sub-expression
return cont + 1;
}
private String internalEscape(String str) {
return ESCAPE_BRACKETS.matcher(ESCAPE.matcher(str).replaceAll("")).replaceAll("");
}
/**
* The patterns added to this {@link JPackerParser} object as a {@link List}
* of {@link JPackerPattern}
*
* @return The {@link List} of {@link JPackerPattern} objects
*/
public List<JPackerPattern> getJPatterns() {
return jpatterns;
}
}

View File

@@ -0,0 +1,65 @@
/**
* Packer version 3.0 (final)
* Copyright 2004-2007, Dean Edwards
* Web: {@link http://dean.edwards.name/}
*
* This software is licensed under the MIT license
* Web: {@link http://www.opensource.org/licenses/mit-license}
*
* Ported to Java by Pablo Santiago based on C# version by Jesse Hansen, <twindagger2k @ msn.com>
* Web: {@link http://jpacker.googlecode.com/}
* Email: <pablo.santiago @ gmail.com>
*/
package com.jpacker;
import com.jpacker.evaluators.Evaluator;
/**
* Wrapper class for each pattern
*
* @author Pablo Santiago <pablo.santiago @ gmail.com>
*/
public class JPackerPattern {
private String expression;
private Evaluator evaluator;
private int length;
public JPackerPattern() {
}
public JPackerPattern(String expression, Evaluator evaluator) {
this.expression = expression;
this.evaluator = evaluator;
evaluator.setJPattern(this);
}
public String getExpression() {
return expression;
}
public void setExpression(String expression) {
this.expression = expression;
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
public Evaluator getEvaluator() {
return evaluator;
}
public void setEvaluator(Evaluator evaluator) {
this.evaluator = evaluator;
}
@Override
public String toString() {
return "(" + expression + ")";
}
}

View File

@@ -0,0 +1,98 @@
/**
* Packer version 3.0 (final)
* Copyright 2004-2007, Dean Edwards
* Web: {@link http://dean.edwards.name/}
*
* This software is licensed under the MIT license
* Web: {@link http://www.opensource.org/licenses/mit-license}
*
* Ported to Java by Pablo Santiago based on C# version by Jesse Hansen, <twindagger2k @ msn.com>
* Web: {@link http://jpacker.googlecode.com/}
* Email: <pablo.santiago @ gmail.com>
*/
package com.jpacker;
/**
* Wrapper class for a keyword
*
* @author Pablo Santiago <pablo.santiago @ gmail.com>
*/
public class JPackerWord {
private int count = 0;
private String encoded = "";
private int index = -1;
private String word;
private String replacement;
public JPackerWord(String word) {
this.word = word;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public String getEncoded() {
return encoded;
}
public void setEncoded(String encoded) {
this.encoded = encoded;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public String getWord() {
return word;
}
public void setWord(String word) {
this.word = word;
}
public String getReplacement() {
return replacement;
}
public void setReplacement(String replacement) {
this.replacement = replacement;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final JPackerWord other = (JPackerWord) obj;
if ((this.word == null) ? (other.word != null) : !this.word.equals(other.word)) {
return false;
}
return true;
}
@Override
public int hashCode() {
int hash = 3;
hash = 37 * hash + (this.word != null ? this.word.hashCode() : 0);
return hash;
}
@Override
public String toString() {
return word;
}
}

View File

@@ -0,0 +1,149 @@
/**
* Packer version 3.0 (final)
* Copyright 2004-2007, Dean Edwards
* Web: {@link http://dean.edwards.name/}
*
* This software is licensed under the MIT license
* Web: {@link http://www.opensource.org/licenses/mit-license}
*
* Ported to Java by Pablo Santiago based on C# version by Jesse Hansen, <twindagger2k @ msn.com>
* Web: {@link http://jpacker.googlecode.com/}
* Email: <pablo.santiago @ gmail.com>
*/
package com.jpacker;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Wrapper class for a {@link JPackerWord} list built based on script's keywords (later
* wrapped into a JPackerWord list)
*
* @author Pablo Santiago <pablo.santiago @ gmail.com>
*/
public final class JPackerWords {
private JPackerEncoding encoding;
private static final Pattern WORDS = Pattern.compile("\\w+");
private List<JPackerWord> words = new ArrayList<JPackerWord>();
/**
* Constructor
*
* @param script
* The input script to look up for keywords
* @param encoding
* The encoding level to use
*/
public JPackerWords(String script, JPackerEncoding encoding) {
this.encoding = encoding;
Matcher matcher = WORDS.matcher(script);
while (matcher.find()) {
add(new JPackerWord(matcher.group()));
}
encode();
}
private void add(JPackerWord word) {
if (!words.contains(word)) {
words.add(word);
}
JPackerWord w = find(word);
w.setCount(w.getCount() + 1);
}
private void encode() {
// sort by frequency
Collections.sort(words, new Comparator<JPackerWord>() {
@Override
public int compare(JPackerWord x, JPackerWord y) {
return y.getCount() - x.getCount();
}
});
// a dictionary of encoding base -> base10
Map<String, Integer> encoded = new HashMap<String, Integer>();
for (int i = 0; i < words.size(); i++) {
encoded.put(encoding.getEncoder().encode(i), i);
}
int index = 0;
for (JPackerWord word : words) {
if (encoded.containsKey(word.getWord())) {
word.setIndex(encoded.get(word.getWord()));
word.setReplacement("");
} else {
while (words.contains(new JPackerWord(encoding.getEncoder().encode(index)))) {
index++;
}
word.setIndex(index++);
word.setReplacement(word.getWord());
}
word.setEncoded(encoding.getEncoder().encode(word.getIndex()));
}
// sort by encoding
Collections.sort(words, new Comparator<JPackerWord>() {
@Override
public int compare(JPackerWord x, JPackerWord y) {
return x.getIndex() - y.getIndex();
}
});
}
/**
* Find a word in the JPackerWord list
*
* @param word
* The JPackerWord object to find in the list
* @return The JPackerWord object if found, null otherwise
*/
public JPackerWord find(JPackerWord word) {
Iterator<JPackerWord> it = words.iterator();
while (it.hasNext() == true) {
JPackerWord pw = it.next();
if (pw.equals(word)) {
return pw;
}
}
return null;
}
/**
* Gets the list of JPackerWord objects
*
* @return The list of JPackerWord objects
*/
public List<JPackerWord> getWords() {
return words;
}
/**
* This method has been overridden to return the list of JPackerWord objects
* as a single String object separated by the '|' character
*
* @return A List of JPackerWord objects as a single String object separated
* by the '|' character
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
for (JPackerWord word : words) {
sb.append(word.getReplacement()).append('|');
}
sb.deleteCharAt(sb.length() - 1);
return sb.toString();
}
}

View File

@@ -0,0 +1,27 @@
/**
* Packer version 3.0 (final)
* Copyright 2004-2007, Dean Edwards
* Web: {@link http://dean.edwards.name/}
*
* This software is licensed under the MIT license
* Web: {@link http://www.opensource.org/licenses/mit-license}
*
* Ported to Java by Pablo Santiago based on C# version by Jesse Hansen, <twindagger2k @ msn.com>
* Web: {@link http://jpacker.googlecode.com/}
* Email: <pablo.santiago @ gmail.com>
*/
package com.jpacker.encoders;
/**
* Basic (base52) encoder: [a-Z]
*
* @author Pablo Santiago <pablo.santiago @ gmail.com>
*
*/
public class BasicEncoder implements Encoder {
@Override
public String encode(int c) {
return (c < 52 ? "" : encode(c / 52)) + (((c = c % 52)) > 25 ? String.valueOf((char) (c + 39)) : String.valueOf((char) (c + 97)));
}
}

View File

@@ -0,0 +1,23 @@
/**
* Packer version 3.0 (final)
* Copyright 2004-2007, Dean Edwards
* Web: {@link http://dean.edwards.name/}
*
* This software is licensed under the MIT license
* Web: {@link http://www.opensource.org/licenses/mit-license}
*
* Ported to Java by Pablo Santiago based on C# version by Jesse Hansen, <twindagger2k @ msn.com>
* Web: {@link http://jpacker.googlecode.com/}
* Email: <pablo.santiago @ gmail.com>
*/
package com.jpacker.encoders;
/**
* Encoder interface to build encoder objects of different base
*
* @author Pablo Santiago <pablo.santiago @ gmail.com>
*/
public interface Encoder {
public String encode(int code);
}

View File

@@ -0,0 +1,36 @@
/**
* Packer version 3.0 (final)
* Copyright 2004-2007, Dean Edwards
* Web: {@link http://dean.edwards.name/}
*
* This software is licensed under the MIT license
* Web: {@link http://www.opensource.org/licenses/mit-license}
*
* Ported to Java by Pablo Santiago based on C# version by Jesse Hansen, <twindagger2k @ msn.com>
* Web: {@link http://jpacker.googlecode.com/}
* Email: <pablo.santiago @ gmail.com>
*/
package com.jpacker.encoders;
/**
* High-Ascii (base95) encoder: [¡-ÿ] SHOULD BE USED WITH CAUTION! Not fully
* tested.
*
* @author Pablo Santiago <pablo.santiago @ gmail.com>
*/
public class HighAsciiEncoder implements Encoder {
private static String LOOKUP_95 = "¡¢£€¥Š§š©ª«¬­®¯°±²³Žµ¶·ž¹º»ŒœŸ¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ";
@Override
public String encode(int code) {
String encoded = "";
int i = 0;
do {
int digit = (code / (int) Math.pow(95, i)) % 95;
encoded = LOOKUP_95.charAt(digit) + encoded;
code -= digit * (int) Math.pow(95, i++);
} while (code > 0);
return encoded;
}
}

View File

@@ -0,0 +1,38 @@
/**
* Packer version 3.0 (final)
* Copyright 2004-2007, Dean Edwards
* Web: {@link http://dean.edwards.name/}
*
* This software is licensed under the MIT license
* Web: {@link http://www.opensource.org/licenses/mit-license}
*
* Ported to Java by Pablo Santiago based on C# version by Jesse Hansen, <twindagger2k @ msn.com>
* Web: {@link http://jpacker.googlecode.com/}
* Email: <pablo.santiago @ gmail.com>
*/
package com.jpacker.encoders;
/**
* Mid base36 encoder: [0-z]
*
* @author Pablo Santiago <pablo.santiago @ gmail.com>
*
*/
public class MidEncoder implements Encoder {
// lookups seemed like the easiest way to do this since
// I don't know of an equivalent to .toString(36)
private static String LOOKUP_36 = "0123456789abcdefghijklmnopqrstuvwxyz";
@Override
public String encode(int code) {
String encoded = "";
int i = 0;
do {
int digit = (code / (int) Math.pow(36, i)) % 36;
encoded = LOOKUP_36.charAt(digit) + encoded;
code -= digit * (int) Math.pow(36, i++);
} while (code > 0);
return encoded;
}
}

View File

@@ -0,0 +1,27 @@
/**
* Packer version 3.0 (final)
* Copyright 2004-2007, Dean Edwards
* Web: {@link http://dean.edwards.name/}
*
* This software is licensed under the MIT license
* Web: {@link http://www.opensource.org/licenses/mit-license}
*
* Ported to Java by Pablo Santiago based on C# version by Jesse Hansen, <twindagger2k @ msn.com>
* Web: {@link http://jpacker.googlecode.com/}
* Email: <pablo.santiago @ gmail.com>
*/
package com.jpacker.encoders;
/**
* Normal (base62) encoder: [0-Z]
*
* @author Pablo Santiago <pablo.santiago @ gmail.com>
*
*/
public class NormalEncoder implements Encoder {
@Override
public String encode(int c) {
return (c < 62 ? "" : encode(c / 62)) + ((c = c % 62) > 35 ? String.valueOf((char) (c + 29)) : Integer.toString(c, 36));
}
}

View File

@@ -0,0 +1,27 @@
/**
* Packer version 3.0 (final)
* Copyright 2004-2007, Dean Edwards
* Web: {@link http://dean.edwards.name/}
*
* This software is licensed under the MIT license
* Web: {@link http://www.opensource.org/licenses/mit-license}
*
* Ported to Java by Pablo Santiago based on C# version by Jesse Hansen, <twindagger2k @ msn.com>
* Web: {@link http://jpacker.googlecode.com/}
* Email: <pablo.santiago @ gmail.com>
*/
package com.jpacker.encoders;
/**
* Numeric (base10) encoder: [0-9]
*
* @author Pablo Santiago <pablo.santiago @ gmail.com>
*
*/
public class NumericEncoder implements Encoder {
@Override
public String encode(int code) {
return String.valueOf(code);
}
}

View File

@@ -0,0 +1,48 @@
/**
* Packer version 3.0 (final)
* Copyright 2004-2007, Dean Edwards
* Web: {@link http://dean.edwards.name/}
*
* This software is licensed under the MIT license
* Web: {@link http://www.opensource.org/licenses/mit-license}
*
* Ported to Java by Pablo Santiago based on C# version by Jesse Hansen, <twindagger2k @ msn.com>
* Web: {@link http://jpacker.googlecode.com/}
* Email: <pablo.santiago @ gmail.com>
*/
package com.jpacker.evaluators;
import com.jpacker.JPackerPattern;
/**
* Abstract class for {@link Evaluator} objects. Its purpose is to provide the
* implementation of a getter and setter of a {@link JPackerPattern} object.
*
* @author Pablo Santiago <pablo.santiago @ gmail.com>
*/
public abstract class AbstractEvaluator implements Evaluator {
private JPackerPattern jpattern;
/**
* Gets the {@link JPackerPattern} object
*
* @return The {@link JPackerPattern} object
*/
@Override
public JPackerPattern getJPattern() {
return jpattern;
}
/**
* Sets the {@link JPackerPattern} object for this {@link Evaluator} object
*
* @param jpattern
* The {@link JPackerPattern} object to set
*/
@Override
public void setJPattern(JPackerPattern jpattern) {
this.jpattern = jpattern;
}
}

View File

@@ -0,0 +1,29 @@
/**
* Packer version 3.0 (final)
* Copyright 2004-2007, Dean Edwards
* Web: {@link http://dean.edwards.name/}
*
* This software is licensed under the MIT license
* Web: {@link http://www.opensource.org/licenses/mit-license}
*
* Ported to Java by Pablo Santiago based on C# version by Jesse Hansen, <twindagger2k @ msn.com>
* Web: {@link http://jpacker.googlecode.com/}
* Email: <pablo.santiago @ gmail.com>
*/
package com.jpacker.evaluators;
import java.util.regex.Matcher;
/**
* An {@link Evaluator} implementation to have a {@link String} matched by an
* expression removed from the script
*
* @author Pablo Santiago <pablo.santiago @ gmail.com>
*/
public class DeleteEvaluator extends AbstractEvaluator implements Evaluator {
@Override
public String evaluate(Matcher matcher, int offset) {
return "\u0001" + matcher.group(offset) + "\u0001";
}
}

View File

@@ -0,0 +1,68 @@
/**
* Packer version 3.0 (final)
* Copyright 2004-2007, Dean Edwards
* Web: {@link http://dean.edwards.name/}
*
* This software is licensed under the MIT license
* Web: {@link http://www.opensource.org/licenses/mit-license}
*
* Ported to Java by Pablo Santiago based on C# version by Jesse Hansen, <twindagger2k @ msn.com>
* Email: <pablo.santiago @ gmail.com>
*/
package com.jpacker.evaluators;
import java.util.regex.Matcher;
import com.jpacker.JPackerParser;
import com.jpacker.JPackerPattern;
import com.jpacker.strategies.DefaultReplacementStrategy;
/**
* After expressions have been added to a {@link JPackerParser} object and a
* ReplacementStrategy has been set, each {@link JPackerPattern} should have an
* {@link Evaluator} object that'll evaluate a certain match of a pattern
* expression and return a suitable replacement String. Commonly, after all
* expressions have been added the the {@link JPackerParser} object, a one-line
* String that contains all expressions is created by the {@link JPackerParser}
* object using the {@link JPackerParser#getJPatterns()} method. In the
* {@link #evaluate(Matcher, int)} method, the offset integer parameter
* represents the position in such String that corresponds to a
* {@link JPackerPattern} object.
*
* @author Pablo Santiago <pablo.santiago @ gmail.com>
*/
public interface Evaluator {
/**
* Sets the {@link JPackerPattern} object to use
*
* @param jpattern
* The {@link JPackerPattern} object for the {@link Evaluator}
* implementations to use
*/
public void setJPattern(JPackerPattern jpattern);
/**
* Gets the {@link JPackerPattern} object
*
* @return The {@link JPackerPattern} object if it has been set, null
* otherwise
*/
public JPackerPattern getJPattern();
/**
* Evaluates the string matched by the {@link Matcher} object and returns a
* suitable replacement String.
*
* @param matcher
* The {@link Matcher} object that contains a match (and its
* groups)
* @param offset
* The offset in the String object returned by the
* {@link JPackerParser#getJPatterns()} method in the
* {@link JPackerParser} object
* @return A replacement string (either text or group expressions, i.e.: $1)
* @see DefaultReplacementStrategy
*/
public String evaluate(Matcher matcher, int offset);
}

View File

@@ -0,0 +1,43 @@
/**
* Packer version 3.0 (final)
* Copyright 2004-2007, Dean Edwards
* Web: {@link http://dean.edwards.name/}
*
* This software is licensed under the MIT license
* Web: {@link http://www.opensource.org/licenses/mit-license}
*
* Ported to Java by Pablo Santiago based on C# version by Jesse Hansen, <twindagger2k @ msn.com>
* Web: {@link http://jpacker.googlecode.com/}
* Email: <pablo.santiago @ gmail.com>
*/
package com.jpacker.evaluators;
import java.util.regex.Matcher;
/**
* An {@link Evaluator} implementation for replacement {@link String} objects
* such as "$1" or "$2". Must be a simple group reference (i.e.: NOT
* "Hello $3 $2")
*
* @author Pablo Santiago <pablo.santiago @ gmail.com>
*/
public class IntegerEvaluator extends AbstractEvaluator implements Evaluator {
private int replacement;
/**
* Constructor
*
* @param replacement
* If replacement String is "$1" then 1 would be the replacement
* parameter
*/
public IntegerEvaluator(int replacement) {
this.replacement = replacement;
}
@Override
public String evaluate(Matcher matcher, int offset) {
return matcher.group(replacement + offset);
}
}

View File

@@ -0,0 +1,39 @@
/**
* Packer version 3.0 (final)
* Copyright 2004-2007, Dean Edwards
* Web: {@link http://dean.edwards.name/}
*
* This software is licensed under the MIT license
* Web: {@link http://www.opensource.org/licenses/mit-license}
*
* Ported to Java by Pablo Santiago based on C# version by Jesse Hansen, <twindagger2k @ msn.com>
* Web: {@link http://jpacker.googlecode.com/}
* Email: <pablo.santiago @ gmail.com>
*/
package com.jpacker.evaluators;
import java.util.regex.Matcher;
public class StringEvaluator extends AbstractEvaluator implements Evaluator {
private String replacement;
public StringEvaluator(String replacement) {
this.replacement = replacement;
}
/**
* Replacement function for complicated lookups (e.g. Hello $3 $2)
*
*/
@Override
public String evaluate(Matcher matcher, int offset) {
int length = getJPattern().getLength();
String result = replacement;
while (length-- > 0) {
String mg = matcher.group(offset + length);
result = result.replace("$" + length, mg == null ? "" : mg);
}
return result;
}
}

View File

@@ -0,0 +1,29 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.jpacker.exceptions;
import java.io.IOException;
/**
*
* @author poly
*/
public class EmptyFileException extends IOException {
public EmptyFileException(){
super();
}
public EmptyFileException(String message){
super(message);
}
private EmptyFileException(String path, String reason) {
super(path + ((reason == null)
? ""
: " (" + reason + ")"));
}
}

View File

@@ -0,0 +1,57 @@
/**
* Packer version 3.0 (final)
* Copyright 2004-2007, Dean Edwards
* Web: {@link http://dean.edwards.name/}
*
* This software is licensed under the MIT license
* Web: {@link http://www.opensource.org/licenses/mit-license}
*
* Ported to Java by Pablo Santiago based on C# version by Jesse Hansen, <twindagger2k @ msn.com>
* Web: {@link http://jpacker.googlecode.com/}
* Email: <pablo.santiago @ gmail.com>
*/
package com.jpacker.strategies;
import java.util.List;
import java.util.regex.Matcher;
import com.jpacker.JPackerPattern;
/**
* Default replacement strategy class.
*
* @author Pablo Santiago <pablo.santiago @ gmail.com>
*/
public class DefaultReplacementStrategy implements ReplacementStrategy {
/**
* Default replacement function. Called once for each match found
*
* @param jpatterns
* A List<JPackerPattern> that contains all
* {@link JPackerPattern} objects that wrap expressions to be
* evaluated
* @param matcher
* A {@link Matcher} object that corresponds to a match in the
* script
*/
@Override
public String replace(List<JPackerPattern> jpatterns, Matcher matcher) {
int i = 1;
// loop through the patterns
for (JPackerPattern jpattern : jpatterns) {
// do we have a result?
if (isMatch(matcher.group(i))) {
return jpattern.getEvaluator().evaluate(matcher, i);
} else { // skip over references to sub-expressions
i += jpattern.getLength();
}
}
return matcher.group(); // should never be hit, but you never know
}
// check that match is not an empty string
private boolean isMatch(String match) {
return match != null && !match.isEmpty();
}
}

View File

@@ -0,0 +1,38 @@
/**
* Packer version 3.0 (final)
* Copyright 2004-2007, Dean Edwards
* Web: {@link http://dean.edwards.name/}
*
* This software is licensed under the MIT license
* Web: {@link http://www.opensource.org/licenses/mit-license}
*
* Ported to Java by Pablo Santiago based on C# version by Jesse Hansen, <twindagger2k @ msn.com>
* Email: <pablo.santiago @ gmail.com>
*/
package com.jpacker.strategies;
import java.util.List;
import java.util.regex.Matcher;
import com.jpacker.JPackerPattern;
/**
* An interface to build replacement strategies
*
* @author Pablo Santiago <pablo.santiago @ gmail.com>
*/
public interface ReplacementStrategy {
/**
* Replacement function. Called once for each match found
*
* @param patterns
* A List<JPackerPattern> that contains all
* {@link JPackerPattern} objects that wrap expressions to be
* evaluated
* @param matcher
* A {@link Matcher} object that corresponds to a match in the
* script
*/
public String replace(List<JPackerPattern> patterns, Matcher matcher);
}