From 5c007c4df046e2d4283e4c9f8564d255ae3c1e04 Mon Sep 17 00:00:00 2001 From: neilellis Date: Fri, 7 Jul 2017 15:34:09 +0100 Subject: [PATCH 001/135] Moving over to Maven --- .idea/hotswap_agent.xml | 6 + .idea/vcs.xml | 6 + pom.xml | 359 +++++++++++ .../java/com/innowhere/relproxy/RelProxy.java | 38 +- .../innowhere/relproxy/RelProxyException.java | 92 +-- .../relproxy/RelProxyOnReloadListener.java | 58 +- .../com/innowhere/relproxy/gproxy/GProxy.java | 136 ++-- .../relproxy/gproxy/GProxyConfig.java | 86 +-- .../gproxy/GProxyGroovyScriptEngine.java | 62 +- .../innowhere/relproxy/gproxy/package.html | 26 +- .../com/innowhere/relproxy/impl/FileExt.java | 64 +- .../impl/GenericProxyConfigBaseImpl.java | 48 +- .../relproxy/impl/GenericProxyImpl.java | 122 ++-- .../impl/GenericProxyInvocationHandler.java | 0 .../impl/GenericProxyVersionedObject.java | 334 +++++----- .../impl/gproxy/GProxyConfigImpl.java | 78 +-- .../impl/gproxy/GProxyDefaultImpl.java | 82 +-- .../relproxy/impl/gproxy/core/GProxyImpl.java | 68 +- .../gproxy/core/GProxyInvocationHandler.java | 42 +- .../gproxy/core/GProxyVersionedObject.java | 96 +-- .../impl/jproxy/JProxyConfigImpl.java | 316 ++++----- .../impl/jproxy/JProxyDefaultImpl.java | 172 ++--- .../relproxy/impl/jproxy/JProxyUtil.java | 326 +++++----- .../relproxy/impl/jproxy/core/JProxyImpl.java | 180 +++--- .../jproxy/core/JProxyInvocationHandler.java | 44 +- .../jproxy/core/JProxyVersionedObject.java | 76 +-- .../jproxy/core/clsmgr/FolderSourceList.java | 0 .../jproxy/core/clsmgr/JProxyClassLoader.java | 300 ++++----- .../impl/jproxy/core/clsmgr/JProxyEngine.java | 604 ++++++++--------- ...JProxyEngineChangeDetectorAndCompiler.java | 610 +++++++++--------- .../jproxy/core/clsmgr/JavaSourcesSearch.java | 386 +++++------ .../core/clsmgr/cldesc/ClassDescriptor.java | 230 +++---- .../clsmgr/cldesc/ClassDescriptorInner.java | 54 +- .../cldesc/ClassDescriptorSourceFileJava.java | 56 +- .../ClassDescriptorSourceFileRegistry.java | 184 +++--- .../cldesc/ClassDescriptorSourceScript.java | 368 +++++------ .../cldesc/ClassDescriptorSourceUnit.java | 292 ++++----- .../comp/JProxyCompilationException.java | 50 +- .../clsmgr/comp/JProxyCompilerContext.java | 142 ++-- .../clsmgr/comp/JProxyCompilerInMemory.java | 0 .../clsmgr/comp/JavaFileManagerInMemory.java | 256 ++++---- ...leObjectInputClassFinderByClassLoader.java | 426 ++++++------ .../comp/jfo/JProxyJavaFileObjectInput.java | 20 +- .../jfo/JavaFileObjectInputClassInFile.java | 82 +-- .../JavaFileObjectInputClassInFileSystem.java | 184 +++--- .../jfo/JavaFileObjectInputClassInJar.java | 74 +-- .../jfo/JavaFileObjectInputClassInMemory.java | 0 .../jfo/JavaFileObjectInputSourceBase.java | 130 ++-- .../jfo/JavaFileObjectInputSourceInFile.java | 72 +-- .../JavaFileObjectInputSourceInMemory.java | 62 +- .../comp/jfo/JavaFileObjectOutputClass.java | 118 ++-- .../clsmgr/srcunit/SourceFileJavaNormal.java | 0 .../core/clsmgr/srcunit/SourceScriptRoot.java | 30 +- .../clsmgr/srcunit/SourceScriptRootFile.java | 0 .../srcunit/SourceScriptRootFileJavaExt.java | 48 +- .../srcunit/SourceScriptRootFileOtherExt.java | 70 +- .../srcunit/SourceScriptRootInMemory.java | 112 ++-- .../core/clsmgr/srcunit/SourceUnit.java | 72 +-- .../impl/jproxy/screngine/BindingsImpl.java | 28 +- .../JProxyScriptEngineDelegateImpl.java | 0 .../JProxyScriptEngineFactoryImpl.java | 358 +++++----- .../screngine/JProxyScriptEngineImpl.java | 244 +++---- .../jproxy/shell/JProxyShellClassLoader.java | 94 +-- .../shell/JProxyShellCodeSnippetImpl.java | 122 ++-- .../impl/jproxy/shell/JProxyShellImpl.java | 0 .../shell/JProxyShellInteractiveImpl.java | 0 .../shell/JProxyShellScriptFileImpl.java | 156 ++--- .../impl/jproxy/shell/inter/Command.java | 206 +++--- .../shell/inter/CommandCodeChangerBase.java | 0 .../jproxy/shell/inter/CommandDelete.java | 0 .../impl/jproxy/shell/inter/CommandEdit.java | 0 .../impl/jproxy/shell/inter/CommandError.java | 50 +- .../jproxy/shell/inter/CommandInsert.java | 0 .../impl/jproxy/shell/inter/CommandLoad.java | 156 ++--- .../impl/jproxy/shell/inter/CommandOther.java | 220 +++---- .../impl/jproxy/shell/inter/CommandSave.java | 122 ++-- .../shell/inter/JProxyShellProcessor.java | 430 ++++++------ .../impl/jproxy/shell/inter/Keyboard.java | 0 .../inter/KeyboardNotUsingClipboard.java | 604 ++++++++--------- .../shell/inter/KeyboardUsingClipboard.java | 132 ++-- .../shell/inter/LinuxUnicodeKeyboard.java | 122 ++-- .../shell/inter/MacOSXUnicodeKeyboard.java | 100 +-- .../shell/inter/WindowUnicodeKeyboard.java | 0 .../com/innowhere/relproxy/jproxy/JProxy.java | 236 +++---- .../jproxy/JProxyCompilerListener.java | 30 +- .../relproxy/jproxy/JProxyConfig.java | 328 +++++----- .../jproxy/JProxyDiagnosticsListener.java | 40 +- ...JProxyInputSourceFileExcludedListener.java | 42 +- .../relproxy/jproxy/JProxyScriptEngine.java | 0 .../jproxy/JProxyScriptEngineFactory.java | 44 +- .../relproxy/jproxy/JProxyShell.java | 46 +- .../innowhere/relproxy/jproxy/package.html | 26 +- .../java/com/innowhere/relproxy/package.html | 26 +- 93 files changed, 6141 insertions(+), 5770 deletions(-) create mode 100644 .idea/hotswap_agent.xml create mode 100644 .idea/vcs.xml create mode 100644 pom.xml rename {relproxy/src => src}/main/java/com/innowhere/relproxy/RelProxy.java (94%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/RelProxyException.java (96%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/RelProxyOnReloadListener.java (97%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/gproxy/GProxy.java (95%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/gproxy/GProxyConfig.java (97%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/gproxy/GProxyGroovyScriptEngine.java (90%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/gproxy/package.html (95%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/FileExt.java (96%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/GenericProxyConfigBaseImpl.java (94%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/GenericProxyImpl.java (96%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/GenericProxyInvocationHandler.java (100%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/GenericProxyVersionedObject.java (97%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/gproxy/GProxyConfigImpl.java (96%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/gproxy/GProxyDefaultImpl.java (96%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyImpl.java (96%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyInvocationHandler.java (95%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyVersionedObject.java (96%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/JProxyConfigImpl.java (96%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/JProxyDefaultImpl.java (95%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/JProxyUtil.java (96%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyImpl.java (97%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyInvocationHandler.java (95%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyVersionedObject.java (96%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java (100%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java (97%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java (97%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java (98%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java (98%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java (97%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java (95%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java (96%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java (97%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java (97%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java (96%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java (96%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java (97%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java (100%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java (98%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java (97%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JProxyJavaFileObjectInput.java (94%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java (96%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java (96%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java (95%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java (100%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java (96%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java (95%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java (95%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java (96%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java (100%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRoot.java (95%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java (100%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java (96%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java (97%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootInMemory.java (96%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java (96%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/screngine/BindingsImpl.java (94%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java (100%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java (96%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java (96%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java (96%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java (97%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/shell/JProxyShellImpl.java (100%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java (100%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java (97%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/Command.java (96%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java (100%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandDelete.java (100%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandEdit.java (100%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandError.java (93%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandInsert.java (100%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandLoad.java (96%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandOther.java (97%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandSave.java (96%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java (97%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/Keyboard.java (100%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java (97%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java (96%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/LinuxUnicodeKeyboard.java (96%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/MacOSXUnicodeKeyboard.java (96%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/WindowUnicodeKeyboard.java (100%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/jproxy/JProxy.java (95%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/jproxy/JProxyCompilerListener.java (96%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/jproxy/JProxyConfig.java (93%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/jproxy/JProxyDiagnosticsListener.java (96%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java (97%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/jproxy/JProxyScriptEngine.java (100%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/jproxy/JProxyScriptEngineFactory.java (96%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/jproxy/JProxyShell.java (96%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/jproxy/package.html (95%) rename {relproxy/src => src}/main/java/com/innowhere/relproxy/package.html (96%) diff --git a/.idea/hotswap_agent.xml b/.idea/hotswap_agent.xml new file mode 100644 index 0000000..8a869d9 --- /dev/null +++ b/.idea/hotswap_agent.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..09c6838 --- /dev/null +++ b/pom.xml @@ -0,0 +1,359 @@ + + + 4.0.0 + + com.sillelien.dollar + relproxy + LATEST + + + 2.0.2 + 2.4 + 2.8 + 2.6 + 3.4 + 3.3.9 + 1.8 + 3.0.2 + + + + + + + com.versioneye + versioneye-maven-plugin + 3.11.4 + + 0c797be864338a3649f0 + neilellis_orga + Owners + + + + + org.apache.rat + apache-rat-plugin + 0.11 + + true + true + + src/test/** + src/main/webapp/** + dist/** + dist-skel/** + **/*.markdown + **/*.ds + **/*.md + **/*.sh + **/*.yml + **/*.iml + **/*.html + key.txt + + + + + org.codehaus.mojo + findbugs-maven-plugin + ${findbugs-maven-plugin.version} + + Default + High + true + + target/site + + + + org.apache.maven.plugins + maven-project-info-reports-plugin + ${maven-project-info-reports-plugin.version} + + + com.google.code.findbugs + bcel + ${bcel.version} + + + org.apache.maven.shared + maven-shared-jar + 1.1 + + + org.apache.bcel + bcel + + + + + + + org.apache.maven.plugins + maven-site-plugin + ${maven-site-plugin.version} + + + attach-descriptor + + attach-descriptor + + + + + en + + + + org.apache.maven.doxia + doxia-module-markdown + 1.6 + + + org.apache.maven.skins + maven-fluido-skin + 1.4 + + + + + + + + + + + org.complykit + license-check-maven-plugin + 0.5.2 + + + + + + + + + + + + + + + + + + agpl-3.0 + + gpl-2.0 + + gpl-3.0 + + + + + + org.apache.maven.plugins + maven-clean-plugin + 2.5 + + + org.apache.maven.plugins + maven-install-plugin + 2.4 + + + org.apache.maven.plugins + maven-deploy-plugin + 2.7 + + + org.apache.maven.plugins + maven-resources-plugin + ${maven-resources-plugin.version} + + + org.apache.maven.plugins + maven-jar-plugin + ${maven-jar-plugin.version} + + + org.apache.maven.plugins + maven-enforcer-plugin + 1.4 + + + enforce-versions + + enforce + + + + + + + + + [,${maven.version}] + + + ${jdk.version} + + + unix + + + Best Practice is to always define plugin versions! + true + true + true + clean,deploy,site + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.3 + + ${jdk.version} + ${jdk.version} + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.18.1 + + + + + **/*Test.java + + 4 + true + -Xmx256m + methods + 32 + + + + org.apache.maven.surefire + surefire-junit47 + 2.18.1 + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.3 + + + + attach-javadocs + + jar + + + + + + + + maven-scm-plugin + 1.9.4 + + ${project.artifactId}-${project.version} + + + + org.apache.maven.plugins + maven-site-plugin + + + + + + + + + + + + + + + + + org.codehaus.mojo + versions-maven-plugin + 2.2 + + + org.codehaus.mojo + findbugs-maven-plugin + ${findbugs-maven-plugin.version} + + + org.apache.rat + apache-rat-plugin + 0.11 + + + verify + + check + + + + + + + org.pitest + pitest-maven + 1.1.6 + + + com.sillelien.* + + + com.sillelien.* + + 0 + 0 + + + + + + org.springframework.build + aws-maven + 5.0.0.RELEASE + + + + + + + aws-release + AWS Release Repository + s3://dollar-repo/release + + + aws-snapshot + AWS Snapshot Repository + s3://dollar-repo/snapshot + + + + + diff --git a/relproxy/src/main/java/com/innowhere/relproxy/RelProxy.java b/src/main/java/com/innowhere/relproxy/RelProxy.java similarity index 94% rename from relproxy/src/main/java/com/innowhere/relproxy/RelProxy.java rename to src/main/java/com/innowhere/relproxy/RelProxy.java index 8341873..2209333 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/RelProxy.java +++ b/src/main/java/com/innowhere/relproxy/RelProxy.java @@ -1,19 +1,19 @@ -package com.innowhere.relproxy; - -/** - * Is the root of RelProxy - * - * @author Jose Maria Arranz Santamaria - */ -public class RelProxy -{ - /** - * Returns the version of this RelProxy library. - * - * @return the version of the library. - */ - public static String getVersion() - { - return "0.8.8"; - } -} +package com.innowhere.relproxy; + +/** + * Is the root of RelProxy + * + * @author Jose Maria Arranz Santamaria + */ +public class RelProxy +{ + /** + * Returns the version of this RelProxy library. + * + * @return the version of the library. + */ + public static String getVersion() + { + return "0.8.8"; + } +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/RelProxyException.java b/src/main/java/com/innowhere/relproxy/RelProxyException.java similarity index 96% rename from relproxy/src/main/java/com/innowhere/relproxy/RelProxyException.java rename to src/main/java/com/innowhere/relproxy/RelProxyException.java index f8e4666..aeafaad 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/RelProxyException.java +++ b/src/main/java/com/innowhere/relproxy/RelProxyException.java @@ -1,46 +1,46 @@ -package com.innowhere.relproxy; - -/** - * Internal checked exceptions thrown by RelProxy and library specific errors are wrapped into this exception class. - * - * @author Jose Maria Arranz Santamaria - */ -public class RelProxyException extends RuntimeException -{ - /** - * Constructs a new exception with the specified message and cause. - * - *

Parameters are passed to the super constructor.

- * - * @param message the detail message - * @param cause the cause - */ - public RelProxyException(String message, Throwable cause) - { - super(message, cause); - } - - /** - * Constructs a new exception with the specified message. - * - *

Parameter is passed to the super constructor.

- * - * @param message the detail message - */ - public RelProxyException(String message) - { - super(message); - } - - /** - * Constructs a new exception with the specified cause. - * - *

Parameter is passed to the super constructor.

- * - * @param cause the cause - */ - public RelProxyException(Throwable cause) - { - super(cause); - } -} +package com.innowhere.relproxy; + +/** + * Internal checked exceptions thrown by RelProxy and library specific errors are wrapped into this exception class. + * + * @author Jose Maria Arranz Santamaria + */ +public class RelProxyException extends RuntimeException +{ + /** + * Constructs a new exception with the specified message and cause. + * + *

Parameters are passed to the super constructor.

+ * + * @param message the detail message + * @param cause the cause + */ + public RelProxyException(String message, Throwable cause) + { + super(message, cause); + } + + /** + * Constructs a new exception with the specified message. + * + *

Parameter is passed to the super constructor.

+ * + * @param message the detail message + */ + public RelProxyException(String message) + { + super(message); + } + + /** + * Constructs a new exception with the specified cause. + * + *

Parameter is passed to the super constructor.

+ * + * @param cause the cause + */ + public RelProxyException(Throwable cause) + { + super(cause); + } +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/RelProxyOnReloadListener.java b/src/main/java/com/innowhere/relproxy/RelProxyOnReloadListener.java similarity index 97% rename from relproxy/src/main/java/com/innowhere/relproxy/RelProxyOnReloadListener.java rename to src/main/java/com/innowhere/relproxy/RelProxyOnReloadListener.java index 2fc287d..faf1c62 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/RelProxyOnReloadListener.java +++ b/src/main/java/com/innowhere/relproxy/RelProxyOnReloadListener.java @@ -1,29 +1,29 @@ -package com.innowhere.relproxy; - -import java.lang.reflect.Method; - -/** - * Is the interface needed to register a class reload listener. - * - *

An object implementing this interface can optionally be registered on RelProxy to listen when the method of a proxy object has been called - * and the class of the original object associated has been reloaded (and a new "original" object based on the new class was created to replace it). - *

- * - * - * @see com.innowhere.relproxy.jproxy.JProxyConfig#setRelProxyOnReloadListener(com.innowhere.relproxy.RelProxyOnReloadListener) - * @see com.innowhere.relproxy.gproxy.GProxyConfig#setRelProxyOnReloadListener(com.innowhere.relproxy.RelProxyOnReloadListener) - * @author Jose Maria Arranz Santamaria - */ -public interface RelProxyOnReloadListener -{ - /** - * Called when some source code change has happened and a new class has been compiled and reloaded. - * - * @param objOld the old object before class reload. - * @param objNew the new object based on the new class loaded by the new class loader. - * @param proxy the proxy object created by {@link java.lang.reflect.Proxy} being used. - * @param method the method being called through the proxy object. - * @param args the parameters being used in the method call. - */ - public void onReload(Object objOld,Object objNew,Object proxy, Method method, Object[] args); -} +package com.innowhere.relproxy; + +import java.lang.reflect.Method; + +/** + * Is the interface needed to register a class reload listener. + * + *

An object implementing this interface can optionally be registered on RelProxy to listen when the method of a proxy object has been called + * and the class of the original object associated has been reloaded (and a new "original" object based on the new class was created to replace it). + *

+ * + * + * @see com.innowhere.relproxy.jproxy.JProxyConfig#setRelProxyOnReloadListener(com.innowhere.relproxy.RelProxyOnReloadListener) + * @see com.innowhere.relproxy.gproxy.GProxyConfig#setRelProxyOnReloadListener(com.innowhere.relproxy.RelProxyOnReloadListener) + * @author Jose Maria Arranz Santamaria + */ +public interface RelProxyOnReloadListener +{ + /** + * Called when some source code change has happened and a new class has been compiled and reloaded. + * + * @param objOld the old object before class reload. + * @param objNew the new object based on the new class loaded by the new class loader. + * @param proxy the proxy object created by {@link java.lang.reflect.Proxy} being used. + * @param method the method being called through the proxy object. + * @param args the parameters being used in the method call. + */ + public void onReload(Object objOld,Object objNew,Object proxy, Method method, Object[] args); +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/gproxy/GProxy.java b/src/main/java/com/innowhere/relproxy/gproxy/GProxy.java similarity index 95% rename from relproxy/src/main/java/com/innowhere/relproxy/gproxy/GProxy.java rename to src/main/java/com/innowhere/relproxy/gproxy/GProxy.java index 1ec80b2..942b56e 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/gproxy/GProxy.java +++ b/src/main/java/com/innowhere/relproxy/gproxy/GProxy.java @@ -1,68 +1,68 @@ - -package com.innowhere.relproxy.gproxy; - -import com.innowhere.relproxy.impl.gproxy.GProxyConfigImpl; -import com.innowhere.relproxy.impl.gproxy.GProxyDefaultImpl; - -/** - * Is the class to create Java proxy objects based on Groovy objects and keep track of Groovy source code changes reloading Groovy classes when detected. - * - * @author Jose Maria Arranz Santamaria - */ -public class GProxy -{ - /** - * Creates a {@link GProxyConfig} object to be used to configure GProxy. - * - * @return a new configuration object. - * @see #init(GProxyConfig) - */ - public static GProxyConfig createGProxyConfig() - { - return GProxyDefaultImpl.createGProxyConfig(); - } - - /** - * Initializes GProxy with the provided configuration object. - * - * @param config - */ - public static void init(GProxyConfig config) - { - GProxyDefaultImpl.initStatic((GProxyConfigImpl)config); - } - - /** - * Creates a proxy object using java.lang.reflect.Proxy based on the provided Groovy object and the class of the implemented Java interface. - * - *

This method is a simplification for a single interface (the most common case) of {@link #create(Object,Class[])} .

- * - * @param the interface implemented by the original object and proxy object returned. - * @param obj the original object to proxy. - * @param clasz the class of the interface implemented by the original object and proxy object returned. - * @return the java.lang.reflect.Proxy object associated or the original object when GProxy is disabled. - */ - public static T create(T obj,Class clasz) - { - return GProxyDefaultImpl.createStatic(obj, clasz); - } - - /** - * Creates a proxy object using java.lang.reflect.Proxy based on the provided Groovy object and the classes of the implemented Java interfaces. - * - *

If GProxy has been configured and is enabled this method returns a java.lang.reflect.Proxy object implementing instead of - * the original object provided. Methods called in proxy object are received by GProxy and forwarded to the original object, if source code - * managed by GProxy has been changed, the class of the original object is reloaded based on the new source and the original object - * is recreated with the new class and fields are re-set in the new object, then the method is called on the new original object.

- * - *

If GProxy is disabled returns the original object provided with no performance penalty.

- * - * @param obj the original object to proxy. - * @param classes the classes of the interfaces implemented by the original object and proxy object returned. - * @return the java.lang.reflect.Proxy object associated or the original object when GProxy is disabled. - */ - public static Object create(Object obj,Class[] classes) - { - return GProxyDefaultImpl.createStatic(obj, classes); - } -} + +package com.innowhere.relproxy.gproxy; + +import com.innowhere.relproxy.impl.gproxy.GProxyConfigImpl; +import com.innowhere.relproxy.impl.gproxy.GProxyDefaultImpl; + +/** + * Is the class to create Java proxy objects based on Groovy objects and keep track of Groovy source code changes reloading Groovy classes when detected. + * + * @author Jose Maria Arranz Santamaria + */ +public class GProxy +{ + /** + * Creates a {@link GProxyConfig} object to be used to configure GProxy. + * + * @return a new configuration object. + * @see #init(GProxyConfig) + */ + public static GProxyConfig createGProxyConfig() + { + return GProxyDefaultImpl.createGProxyConfig(); + } + + /** + * Initializes GProxy with the provided configuration object. + * + * @param config config + */ + public static void init(GProxyConfig config) + { + GProxyDefaultImpl.initStatic((GProxyConfigImpl)config); + } + + /** + * Creates a proxy object using java.lang.reflect.Proxy based on the provided Groovy object and the class of the implemented Java interface. + * + *

This method is a simplification for a single interface (the most common case) of {@link #create(Object,Class[])} .

+ * + * @param the interface implemented by the original object and proxy object returned. + * @param obj the original object to proxy. + * @param clasz the class of the interface implemented by the original object and proxy object returned. + * @return the java.lang.reflect.Proxy object associated or the original object when GProxy is disabled. + */ + public static T create(T obj,Class clasz) + { + return GProxyDefaultImpl.createStatic(obj, clasz); + } + + /** + * Creates a proxy object using java.lang.reflect.Proxy based on the provided Groovy object and the classes of the implemented Java interfaces. + * + *

If GProxy has been configured and is enabled this method returns a java.lang.reflect.Proxy object implementing instead of + * the original object provided. Methods called in proxy object are received by GProxy and forwarded to the original object, if source code + * managed by GProxy has been changed, the class of the original object is reloaded based on the new source and the original object + * is recreated with the new class and fields are re-set in the new object, then the method is called on the new original object.

+ * + *

If GProxy is disabled returns the original object provided with no performance penalty.

+ * + * @param obj the original object to proxy. + * @param classes the classes of the interfaces implemented by the original object and proxy object returned. + * @return the java.lang.reflect.Proxy object associated or the original object when GProxy is disabled. + */ + public static Object create(Object obj,Class[] classes) + { + return GProxyDefaultImpl.createStatic(obj, classes); + } +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/gproxy/GProxyConfig.java b/src/main/java/com/innowhere/relproxy/gproxy/GProxyConfig.java similarity index 97% rename from relproxy/src/main/java/com/innowhere/relproxy/gproxy/GProxyConfig.java rename to src/main/java/com/innowhere/relproxy/gproxy/GProxyConfig.java index 0184f5f..4e517fa 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/gproxy/GProxyConfig.java +++ b/src/main/java/com/innowhere/relproxy/gproxy/GProxyConfig.java @@ -1,43 +1,43 @@ - -package com.innowhere.relproxy.gproxy; - -import com.innowhere.relproxy.RelProxyOnReloadListener; - -/** - * Interface implemented by the configuration object needed to initialize GProxy. - * - * - * @see GProxy#init(GProxyConfig) - * @author Jose Maria Arranz Santamaria - */ -public interface GProxyConfig -{ - /** - * Sets whether automatic detection of source code changes is enabled. - * - *

If set to false other configuration parameters are ignored, there is no automatic source code change detection/reload and original objects are returned - * instead of proxies, performance penalty is zero. Setting to false is recommended in production whether source code change detection/reload is not required.

- * - * @param enabled whether automatic source code change detection and reload is enabled. By default is true. - * @return this object for flow API use. - */ - public GProxyConfig setEnabled(boolean enabled); - - /** - * Sets the class reload listener. - * - * @param relListener the class reload listener. By default is null. - * @return this object for flow API use. - */ - public GProxyConfig setRelProxyOnReloadListener(RelProxyOnReloadListener relListener); - - /** - * Sets the object implementing the GroovyScriptEngine wrapper used to reload Groovy classes. - * - *

This parameter is required otherwise there is no bridge between RelProxy and Groovy because there is no explicit Groovy dependency in RelProxy. - * - * @param engine the GroovyScriptEngine wrapper. - * @return this object for flow API use. - */ - public GProxyConfig setGProxyGroovyScriptEngine(GProxyGroovyScriptEngine engine); -} + +package com.innowhere.relproxy.gproxy; + +import com.innowhere.relproxy.RelProxyOnReloadListener; + +/** + * Interface implemented by the configuration object needed to initialize GProxy. + * + * + * @see GProxy#init(GProxyConfig) + * @author Jose Maria Arranz Santamaria + */ +public interface GProxyConfig +{ + /** + * Sets whether automatic detection of source code changes is enabled. + * + *

If set to false other configuration parameters are ignored, there is no automatic source code change detection/reload and original objects are returned + * instead of proxies, performance penalty is zero. Setting to false is recommended in production whether source code change detection/reload is not required.

+ * + * @param enabled whether automatic source code change detection and reload is enabled. By default is true. + * @return this object for flow API use. + */ + public GProxyConfig setEnabled(boolean enabled); + + /** + * Sets the class reload listener. + * + * @param relListener the class reload listener. By default is null. + * @return this object for flow API use. + */ + public GProxyConfig setRelProxyOnReloadListener(RelProxyOnReloadListener relListener); + + /** + * Sets the object implementing the GroovyScriptEngine wrapper used to reload Groovy classes. + * + *

This parameter is required otherwise there is no bridge between RelProxy and Groovy because there is no explicit Groovy dependency in RelProxy. + * + * @param engine the GroovyScriptEngine wrapper. + * @return this object for flow API use. + */ + public GProxyConfig setGProxyGroovyScriptEngine(GProxyGroovyScriptEngine engine); +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/gproxy/GProxyGroovyScriptEngine.java b/src/main/java/com/innowhere/relproxy/gproxy/GProxyGroovyScriptEngine.java similarity index 90% rename from relproxy/src/main/java/com/innowhere/relproxy/gproxy/GProxyGroovyScriptEngine.java rename to src/main/java/com/innowhere/relproxy/gproxy/GProxyGroovyScriptEngine.java index 7294bcd..47d09d7 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/gproxy/GProxyGroovyScriptEngine.java +++ b/src/main/java/com/innowhere/relproxy/gproxy/GProxyGroovyScriptEngine.java @@ -1,31 +1,31 @@ -package com.innowhere.relproxy.gproxy; - -/** - * Interface to implement the object implementing the GroovyScriptEngine wrapper used to reload Groovy classes. - * - *

The following is a very simple example of the required implementation, groovyEngine is the groovy.util.GroovyScriptEngine - * object:

- - def gproxyGroovyEngine = { - String scriptName -> return (java.lang.Class)groovyEngine.loadScriptByName(scriptName) - } as GProxyGroovyScriptEngine; - - * - * - * @see GProxyConfig#setGProxyGroovyScriptEngine(GProxyGroovyScriptEngine) - * @author Jose Maria Arranz Santamaria - */ -public interface GProxyGroovyScriptEngine -{ - /** - * The class implementing this method must call the method groovy.util.GroovyScriptEngine.loadScriptByName(String scriptName) passing - * the scriptName. - * - *

This method is called by GProxy when it needs to get the Class associated to the specified Groovy script/class to check if this class - * has changed because Groovy has reloaded the class when a source code has been detected. - * - * @param scriptName the name of the Groovy script/class. - * @return the class associated to the specified Groovy script. - */ - public Class loadScriptByName(String scriptName); -} +package com.innowhere.relproxy.gproxy; + +/** + * Interface to implement the object implementing the GroovyScriptEngine wrapper used to reload Groovy classes. + * + *

The following is a very simple example of the required implementation, groovyEngine is the groovy.util.GroovyScriptEngine + * object:

+ + def gproxyGroovyEngine = { + String scriptName -> return (java.lang.Class)groovyEngine.loadScriptByName(scriptName) + } as GProxyGroovyScriptEngine; + + * + * + * @see GProxyConfig#setGProxyGroovyScriptEngine(GProxyGroovyScriptEngine) + * @author Jose Maria Arranz Santamaria + */ +public interface GProxyGroovyScriptEngine +{ + /** + * The class implementing this method must call the method groovy.util.GroovyScriptEngine.loadScriptByName(String scriptName) passing + * the scriptName. + * + *

This method is called by GProxy when it needs to get the Class associated to the specified Groovy script/class to check if this class + * has changed because Groovy has reloaded the class when a source code has been detected. + * + * @param scriptName the name of the Groovy script/class. + * @return the class associated to the specified Groovy script. + */ + public Class loadScriptByName(String scriptName); +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/gproxy/package.html b/src/main/java/com/innowhere/relproxy/gproxy/package.html similarity index 95% rename from relproxy/src/main/java/com/innowhere/relproxy/gproxy/package.html rename to src/main/java/com/innowhere/relproxy/gproxy/package.html index 3cbf0dc..3edbfbf 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/gproxy/package.html +++ b/src/main/java/com/innowhere/relproxy/gproxy/package.html @@ -1,13 +1,13 @@ - - - - - - - -Contains the classes related with Groovy support of RelProxy. - - - + + + + + + + +Contains the classes related with Groovy support of RelProxy. + + + diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/FileExt.java b/src/main/java/com/innowhere/relproxy/impl/FileExt.java similarity index 96% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/FileExt.java rename to src/main/java/com/innowhere/relproxy/impl/FileExt.java index 0533f75..bc3fa3d 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/FileExt.java +++ b/src/main/java/com/innowhere/relproxy/impl/FileExt.java @@ -1,32 +1,32 @@ -package com.innowhere.relproxy.impl; - -import com.innowhere.relproxy.RelProxyException; -import java.io.File; -import java.io.IOException; - -/** - * - * @author jmarranz - */ -public class FileExt -{ - protected final File file; - protected final String cannonicalPath; // El obtener el cannonicalPath exige acceder al sistema de archivos, por eso nos inventamos esta clase, para evitar sucesivas llamadas a File.getCanonicalPath() - - public FileExt(File file) - { - this.file = file; - try { this.cannonicalPath = file.getCanonicalPath(); } - catch (IOException ex) { throw new RelProxyException(ex); } - } - - public File getFile() - { - return file; - } - - public String getCanonicalPath() - { - return cannonicalPath; - } -} +package com.innowhere.relproxy.impl; + +import com.innowhere.relproxy.RelProxyException; +import java.io.File; +import java.io.IOException; + +/** + * + * @author jmarranz + */ +public class FileExt +{ + protected final File file; + protected final String cannonicalPath; // El obtener el cannonicalPath exige acceder al sistema de archivos, por eso nos inventamos esta clase, para evitar sucesivas llamadas a File.getCanonicalPath() + + public FileExt(File file) + { + this.file = file; + try { this.cannonicalPath = file.getCanonicalPath(); } + catch (IOException ex) { throw new RelProxyException(ex); } + } + + public File getFile() + { + return file; + } + + public String getCanonicalPath() + { + return cannonicalPath; + } +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/GenericProxyConfigBaseImpl.java b/src/main/java/com/innowhere/relproxy/impl/GenericProxyConfigBaseImpl.java similarity index 94% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/GenericProxyConfigBaseImpl.java rename to src/main/java/com/innowhere/relproxy/impl/GenericProxyConfigBaseImpl.java index 72863e3..f1fda6d 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/GenericProxyConfigBaseImpl.java +++ b/src/main/java/com/innowhere/relproxy/impl/GenericProxyConfigBaseImpl.java @@ -1,24 +1,24 @@ -package com.innowhere.relproxy.impl; - -import com.innowhere.relproxy.RelProxyOnReloadListener; - -/** - * - * @author jmarranz - */ -public class GenericProxyConfigBaseImpl -{ - protected boolean enabled = true; - protected RelProxyOnReloadListener relListener; - - public boolean isEnabled() - { - return enabled; - } - - public RelProxyOnReloadListener getRelProxyOnReloadListener() - { - return relListener; - } - -} +package com.innowhere.relproxy.impl; + +import com.innowhere.relproxy.RelProxyOnReloadListener; + +/** + * + * @author jmarranz + */ +public class GenericProxyConfigBaseImpl +{ + protected boolean enabled = true; + protected RelProxyOnReloadListener relListener; + + public boolean isEnabled() + { + return enabled; + } + + public RelProxyOnReloadListener getRelProxyOnReloadListener() + { + return relListener; + } + +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/GenericProxyImpl.java b/src/main/java/com/innowhere/relproxy/impl/GenericProxyImpl.java similarity index 96% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/GenericProxyImpl.java rename to src/main/java/com/innowhere/relproxy/impl/GenericProxyImpl.java index 7a0afcf..a24ba38 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/GenericProxyImpl.java +++ b/src/main/java/com/innowhere/relproxy/impl/GenericProxyImpl.java @@ -1,61 +1,61 @@ -package com.innowhere.relproxy.impl; - -import com.innowhere.relproxy.RelProxyException; -import com.innowhere.relproxy.RelProxyOnReloadListener; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Proxy; - -/** - * - * @author jmarranz - */ -public abstract class GenericProxyImpl -{ - protected RelProxyOnReloadListener reloadListener; - - public GenericProxyImpl() - { - } - - public static void checkSingletonNull(GenericProxyImpl singleton) - { - if (singleton != null) - throw new RelProxyException("Already initialized"); - } - - protected static void checkSingletonExists(GenericProxyImpl singleton) - { - if (singleton == null) - throw new RelProxyException("Execute first the init method"); - } - - protected void init(GenericProxyConfigBaseImpl config) - { - this.reloadListener = config.getRelProxyOnReloadListener(); - } - - public RelProxyOnReloadListener getRelProxyOnReloadListener() - { - return reloadListener; - } - - public T create(T obj,Class clasz) - { - if (obj == null) return null; - - return (T)create(obj,new Class[] { clasz }); - } - - public Object create(Object obj,Class[] classes) - { - if (obj == null) return null; - - InvocationHandler handler = createGenericProxyInvocationHandler(obj); - - Object proxy = Proxy.newProxyInstance(obj.getClass().getClassLoader(),classes, handler); - return proxy; - } - - - public abstract GenericProxyInvocationHandler createGenericProxyInvocationHandler(Object obj); -} +package com.innowhere.relproxy.impl; + +import com.innowhere.relproxy.RelProxyException; +import com.innowhere.relproxy.RelProxyOnReloadListener; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Proxy; + +/** + * + * @author jmarranz + */ +public abstract class GenericProxyImpl +{ + protected RelProxyOnReloadListener reloadListener; + + public GenericProxyImpl() + { + } + + public static void checkSingletonNull(GenericProxyImpl singleton) + { + if (singleton != null) + throw new RelProxyException("Already initialized"); + } + + protected static void checkSingletonExists(GenericProxyImpl singleton) + { + if (singleton == null) + throw new RelProxyException("Execute first the init method"); + } + + protected void init(GenericProxyConfigBaseImpl config) + { + this.reloadListener = config.getRelProxyOnReloadListener(); + } + + public RelProxyOnReloadListener getRelProxyOnReloadListener() + { + return reloadListener; + } + + public T create(T obj,Class clasz) + { + if (obj == null) return null; + + return (T)create(obj,new Class[] { clasz }); + } + + public Object create(Object obj,Class[] classes) + { + if (obj == null) return null; + + InvocationHandler handler = createGenericProxyInvocationHandler(obj); + + Object proxy = Proxy.newProxyInstance(obj.getClass().getClassLoader(),classes, handler); + return proxy; + } + + + public abstract GenericProxyInvocationHandler createGenericProxyInvocationHandler(Object obj); +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/GenericProxyInvocationHandler.java b/src/main/java/com/innowhere/relproxy/impl/GenericProxyInvocationHandler.java similarity index 100% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/GenericProxyInvocationHandler.java rename to src/main/java/com/innowhere/relproxy/impl/GenericProxyInvocationHandler.java diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/GenericProxyVersionedObject.java b/src/main/java/com/innowhere/relproxy/impl/GenericProxyVersionedObject.java similarity index 97% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/GenericProxyVersionedObject.java rename to src/main/java/com/innowhere/relproxy/impl/GenericProxyVersionedObject.java index 10dc262..f7165a6 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/GenericProxyVersionedObject.java +++ b/src/main/java/com/innowhere/relproxy/impl/GenericProxyVersionedObject.java @@ -1,167 +1,167 @@ -package com.innowhere.relproxy.impl; - -import com.innowhere.relproxy.RelProxyException; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * - * @author jmarranz - */ -public abstract class GenericProxyVersionedObject -{ - protected Object obj; - protected GenericProxyInvocationHandler parent; - - public GenericProxyVersionedObject(Object obj,GenericProxyInvocationHandler parent) - { - this.obj = obj; - this.parent = parent; - } - - protected static void getTreeFields(Class clasz,Object obj,ArrayList fieldList,ArrayList valueList) throws IllegalAccessException - { - getFields(clasz,obj,fieldList,valueList); - Class superClass = clasz.getSuperclass(); - if (superClass != null) - getTreeFields(superClass,obj,fieldList,valueList); - } - - protected static void getFields(Class clasz,Object obj,ArrayList fieldList,ArrayList valueList) throws IllegalAccessException - { - Field[] fieldListClass = clasz.getDeclaredFields(); - for(int i = 0; i < fieldListClass.length; i++) - { - Field field = fieldListClass[i]; - fieldList.add(field); - if (valueList != null) - { - field.setAccessible(true); - Object value = field.get(obj); - valueList.add(value); - } - } - } - - public Object getCurrent() - { - return obj; - } - - public Object getNewVersion() throws Throwable - { - Class newClass = reloadClass(); - if (newClass == null) - return obj; - - Class oldClass = obj.getClass(); - if (newClass != oldClass) - { - this.obj = copy(oldClass,obj,newClass); - } - - return obj; - } - - private Object copy(Class oldClass,Object oldObj,Class newClass) throws IllegalAccessException, InstantiationException, IllegalArgumentException, InvocationTargetException - { - Object newObj; - - ArrayList fieldListOld = new ArrayList(); - ArrayList valueListOld = new ArrayList(); - - getTreeFields(oldClass,oldObj,fieldListOld,valueListOld); - - Class enclosingClassNew = newClass.getEnclosingClass(); - if (enclosingClassNew == null) - { - Constructor construc; - try - { - construc = newClass.getConstructor(new Class[0]); - } - catch(NoSuchMethodException ex) - { - throw new RelProxyException("Cannot reload " + newClass.getName() + " a default empty of params constructor is required",ex); - } - newObj = construc.newInstance(); - } - else - { - // En el caso de inner class o anonymous inner class el constructor por defecto se obtiene de forma diferente, útil para los EventListener de ItsNat - Constructor construc; - try - { - construc = newClass.getDeclaredConstructor(new Class[]{enclosingClassNew}); - } - catch(NoSuchMethodException ex) // Yo creo que nunca ocurre al menos no en anonymous inner classes pero por si acaso - { - throw new RelProxyException("Cannot reload " + newClass.getName() + " a default empty of params constructor is required",ex); - } - construc.setAccessible(true); // Necesario - - // http://stackoverflow.com/questions/1816458/getting-hold-of-the-outer-class-object-from-the-inner-class-object - - - Field enclosingFieldOld; - try { enclosingFieldOld = oldClass.getDeclaredField("this$0"); } - catch (NoSuchFieldException ex) { throw new RelProxyException(ex); } - enclosingFieldOld.setAccessible(true); - Object enclosingObjectOld = enclosingFieldOld.get(oldObj); - Object enclosingObjectNew = copy(enclosingObjectOld.getClass(),enclosingObjectOld,enclosingClassNew); - - newObj = construc.newInstance(enclosingObjectNew); - } - - - ArrayList fieldListNew = new ArrayList(); - - getTreeFields(newClass,newObj,fieldListNew,null); - - if (fieldListOld.size() != fieldListNew.size()) throw new RelProxyException("Cannot reload " + newClass.getName() + " number of fields have changed, redeploy"); - - for(int i = 0; i < fieldListOld.size(); i++) - { - Field fieldOld = fieldListOld.get(i); - Field fieldNew = fieldListNew.get(i); - if (enclosingClassNew != null && fieldOld.getName().equals("this$0") && fieldNew.getName().equals("this$0")) - continue; // Ya están correctamente definidos - - if ( (!ignoreField(fieldOld) && !fieldOld.getName().equals(fieldNew.getName())) || - !fieldOld.getType().equals(fieldNew.getType())) - throw new RelProxyException("Cannot reload " + newClass.getName() + " fields have changed, redeploy"); - - Object fieldObj = valueListOld.get(i); - fieldNew.setAccessible(true); - int modifiersNew = fieldNew.getModifiers(); - boolean isStaticFinal = Modifier.isStatic(modifiersNew) && Modifier.isFinal(modifiersNew); - Field modifiersField = null; - if (isStaticFinal) - { - // http://stackoverflow.com/questions/3301635/change-private-static-final-field-using-java-reflection - try { - modifiersField = Field.class.getDeclaredField("modifiers"); - } - catch (NoSuchFieldException ex) { throw new RelProxyException(ex); } - modifiersField.setAccessible(true); - modifiersField.setInt(fieldNew, fieldNew.getModifiers() & ~Modifier.FINAL); // Quitamos el modifier final - } - - fieldNew.set(newObj, fieldObj); - - if (modifiersField != null) - { - modifiersField.setInt(fieldNew, fieldNew.getModifiers() & ~Modifier.FINAL); // Restauramos el modifier final - } - } - return newObj; - } - - protected abstract Class reloadClass(); - protected abstract boolean ignoreField(Field field); -} +package com.innowhere.relproxy.impl; + +import com.innowhere.relproxy.RelProxyException; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * @author jmarranz + */ +public abstract class GenericProxyVersionedObject +{ + protected Object obj; + protected GenericProxyInvocationHandler parent; + + public GenericProxyVersionedObject(Object obj,GenericProxyInvocationHandler parent) + { + this.obj = obj; + this.parent = parent; + } + + protected static void getTreeFields(Class clasz,Object obj,ArrayList fieldList,ArrayList valueList) throws IllegalAccessException + { + getFields(clasz,obj,fieldList,valueList); + Class superClass = clasz.getSuperclass(); + if (superClass != null) + getTreeFields(superClass,obj,fieldList,valueList); + } + + protected static void getFields(Class clasz,Object obj,ArrayList fieldList,ArrayList valueList) throws IllegalAccessException + { + Field[] fieldListClass = clasz.getDeclaredFields(); + for(int i = 0; i < fieldListClass.length; i++) + { + Field field = fieldListClass[i]; + fieldList.add(field); + if (valueList != null) + { + field.setAccessible(true); + Object value = field.get(obj); + valueList.add(value); + } + } + } + + public Object getCurrent() + { + return obj; + } + + public Object getNewVersion() throws Throwable + { + Class newClass = reloadClass(); + if (newClass == null) + return obj; + + Class oldClass = obj.getClass(); + if (newClass != oldClass) + { + this.obj = copy(oldClass,obj,newClass); + } + + return obj; + } + + private Object copy(Class oldClass,Object oldObj,Class newClass) throws IllegalAccessException, InstantiationException, IllegalArgumentException, InvocationTargetException + { + Object newObj; + + ArrayList fieldListOld = new ArrayList(); + ArrayList valueListOld = new ArrayList(); + + getTreeFields(oldClass,oldObj,fieldListOld,valueListOld); + + Class enclosingClassNew = newClass.getEnclosingClass(); + if (enclosingClassNew == null) + { + Constructor construc; + try + { + construc = newClass.getConstructor(new Class[0]); + } + catch(NoSuchMethodException ex) + { + throw new RelProxyException("Cannot reload " + newClass.getName() + " a default empty of params constructor is required",ex); + } + newObj = construc.newInstance(); + } + else + { + // En el caso de inner class o anonymous inner class el constructor por defecto se obtiene de forma diferente, útil para los EventListener de ItsNat + Constructor construc; + try + { + construc = newClass.getDeclaredConstructor(new Class[]{enclosingClassNew}); + } + catch(NoSuchMethodException ex) // Yo creo que nunca ocurre al menos no en anonymous inner classes pero por si acaso + { + throw new RelProxyException("Cannot reload " + newClass.getName() + " a default empty of params constructor is required",ex); + } + construc.setAccessible(true); // Necesario + + // http://stackoverflow.com/questions/1816458/getting-hold-of-the-outer-class-object-from-the-inner-class-object + + + Field enclosingFieldOld; + try { enclosingFieldOld = oldClass.getDeclaredField("this$0"); } + catch (NoSuchFieldException ex) { throw new RelProxyException(ex); } + enclosingFieldOld.setAccessible(true); + Object enclosingObjectOld = enclosingFieldOld.get(oldObj); + Object enclosingObjectNew = copy(enclosingObjectOld.getClass(),enclosingObjectOld,enclosingClassNew); + + newObj = construc.newInstance(enclosingObjectNew); + } + + + ArrayList fieldListNew = new ArrayList(); + + getTreeFields(newClass,newObj,fieldListNew,null); + + if (fieldListOld.size() != fieldListNew.size()) throw new RelProxyException("Cannot reload " + newClass.getName() + " number of fields have changed, redeploy"); + + for(int i = 0; i < fieldListOld.size(); i++) + { + Field fieldOld = fieldListOld.get(i); + Field fieldNew = fieldListNew.get(i); + if (enclosingClassNew != null && fieldOld.getName().equals("this$0") && fieldNew.getName().equals("this$0")) + continue; // Ya están correctamente definidos + + if ( (!ignoreField(fieldOld) && !fieldOld.getName().equals(fieldNew.getName())) || + !fieldOld.getType().equals(fieldNew.getType())) + throw new RelProxyException("Cannot reload " + newClass.getName() + " fields have changed, redeploy"); + + Object fieldObj = valueListOld.get(i); + fieldNew.setAccessible(true); + int modifiersNew = fieldNew.getModifiers(); + boolean isStaticFinal = Modifier.isStatic(modifiersNew) && Modifier.isFinal(modifiersNew); + Field modifiersField = null; + if (isStaticFinal) + { + // http://stackoverflow.com/questions/3301635/change-private-static-final-field-using-java-reflection + try { + modifiersField = Field.class.getDeclaredField("modifiers"); + } + catch (NoSuchFieldException ex) { throw new RelProxyException(ex); } + modifiersField.setAccessible(true); + modifiersField.setInt(fieldNew, fieldNew.getModifiers() & ~Modifier.FINAL); // Quitamos el modifier final + } + + fieldNew.set(newObj, fieldObj); + + if (modifiersField != null) + { + modifiersField.setInt(fieldNew, fieldNew.getModifiers() & ~Modifier.FINAL); // Restauramos el modifier final + } + } + return newObj; + } + + protected abstract Class reloadClass(); + protected abstract boolean ignoreField(Field field); +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/gproxy/GProxyConfigImpl.java b/src/main/java/com/innowhere/relproxy/impl/gproxy/GProxyConfigImpl.java similarity index 96% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/gproxy/GProxyConfigImpl.java rename to src/main/java/com/innowhere/relproxy/impl/gproxy/GProxyConfigImpl.java index 95fa423..247cc6d 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/gproxy/GProxyConfigImpl.java +++ b/src/main/java/com/innowhere/relproxy/impl/gproxy/GProxyConfigImpl.java @@ -1,39 +1,39 @@ -package com.innowhere.relproxy.impl.gproxy; - -import com.innowhere.relproxy.RelProxyOnReloadListener; -import com.innowhere.relproxy.gproxy.GProxyConfig; -import com.innowhere.relproxy.gproxy.GProxyGroovyScriptEngine; -import com.innowhere.relproxy.impl.GenericProxyConfigBaseImpl; - -/** - * - * @author jmarranz - */ -public class GProxyConfigImpl extends GenericProxyConfigBaseImpl implements GProxyConfig -{ - protected GProxyGroovyScriptEngine engine; - - public GProxyConfig setEnabled(boolean enabled) - { - this.enabled = enabled; - return this; - } - - public GProxyConfig setRelProxyOnReloadListener(RelProxyOnReloadListener relListener) - { - this.relListener = relListener; - return this; - } - - public GProxyConfig setGProxyGroovyScriptEngine(GProxyGroovyScriptEngine engine) - { - this.engine = engine; - return this; - } - - public GProxyGroovyScriptEngine getGProxyGroovyScriptEngine() - { - return engine; - } - -} +package com.innowhere.relproxy.impl.gproxy; + +import com.innowhere.relproxy.RelProxyOnReloadListener; +import com.innowhere.relproxy.gproxy.GProxyConfig; +import com.innowhere.relproxy.gproxy.GProxyGroovyScriptEngine; +import com.innowhere.relproxy.impl.GenericProxyConfigBaseImpl; + +/** + * + * @author jmarranz + */ +public class GProxyConfigImpl extends GenericProxyConfigBaseImpl implements GProxyConfig +{ + protected GProxyGroovyScriptEngine engine; + + public GProxyConfig setEnabled(boolean enabled) + { + this.enabled = enabled; + return this; + } + + public GProxyConfig setRelProxyOnReloadListener(RelProxyOnReloadListener relListener) + { + this.relListener = relListener; + return this; + } + + public GProxyConfig setGProxyGroovyScriptEngine(GProxyGroovyScriptEngine engine) + { + this.engine = engine; + return this; + } + + public GProxyGroovyScriptEngine getGProxyGroovyScriptEngine() + { + return engine; + } + +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/gproxy/GProxyDefaultImpl.java b/src/main/java/com/innowhere/relproxy/impl/gproxy/GProxyDefaultImpl.java similarity index 96% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/gproxy/GProxyDefaultImpl.java rename to src/main/java/com/innowhere/relproxy/impl/gproxy/GProxyDefaultImpl.java index f47f734..2c8b0dd 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/gproxy/GProxyDefaultImpl.java +++ b/src/main/java/com/innowhere/relproxy/impl/gproxy/GProxyDefaultImpl.java @@ -1,41 +1,41 @@ -package com.innowhere.relproxy.impl.gproxy; - -import com.innowhere.relproxy.gproxy.GProxyConfig; -import com.innowhere.relproxy.impl.gproxy.core.GProxyImpl; - -/** - * - * @author jmarranz - */ -public class GProxyDefaultImpl extends GProxyImpl -{ - public static GProxyConfig createGProxyConfig() - { - return new GProxyConfigImpl(); - } - - public static void initStatic(GProxyConfigImpl config) - { - if (!config.isEnabled()) return; - - checkSingletonNull(SINGLETON); - SINGLETON = new GProxyDefaultImpl(); - SINGLETON.init(config); - } - - public static T createStatic(T obj,Class clasz) - { - if (SINGLETON == null) - return obj; // No se ha llamado al init o enabled = false - - return SINGLETON.create(obj, clasz); - } - - public static Object createStatic(Object obj,Class[] classes) - { - if (SINGLETON == null) - return obj; // No se ha llamado al init o enabled = false - - return SINGLETON.create(obj, classes); - } -} +package com.innowhere.relproxy.impl.gproxy; + +import com.innowhere.relproxy.gproxy.GProxyConfig; +import com.innowhere.relproxy.impl.gproxy.core.GProxyImpl; + +/** + * + * @author jmarranz + */ +public class GProxyDefaultImpl extends GProxyImpl +{ + public static GProxyConfig createGProxyConfig() + { + return new GProxyConfigImpl(); + } + + public static void initStatic(GProxyConfigImpl config) + { + if (!config.isEnabled()) return; + + checkSingletonNull(SINGLETON); + SINGLETON = new GProxyDefaultImpl(); + SINGLETON.init(config); + } + + public static T createStatic(T obj,Class clasz) + { + if (SINGLETON == null) + return obj; // No se ha llamado al init o enabled = false + + return SINGLETON.create(obj, clasz); + } + + public static Object createStatic(Object obj,Class[] classes) + { + if (SINGLETON == null) + return obj; // No se ha llamado al init o enabled = false + + return SINGLETON.create(obj, classes); + } +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyImpl.java b/src/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyImpl.java similarity index 96% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyImpl.java rename to src/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyImpl.java index 25064d4..c20285b 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyImpl.java +++ b/src/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyImpl.java @@ -1,34 +1,34 @@ -package com.innowhere.relproxy.impl.gproxy.core; - -import com.innowhere.relproxy.impl.gproxy.GProxyConfigImpl; -import com.innowhere.relproxy.gproxy.GProxyGroovyScriptEngine; -import com.innowhere.relproxy.impl.GenericProxyImpl; -import com.innowhere.relproxy.impl.GenericProxyInvocationHandler; - - -/** - * - * @author jmarranz - */ -public abstract class GProxyImpl extends GenericProxyImpl -{ - public static GProxyImpl SINGLETON; - protected GProxyGroovyScriptEngine engine; - - public void init(GProxyConfigImpl config) - { - super.init(config); - this.engine = config.getGProxyGroovyScriptEngine(); - } - - public GProxyGroovyScriptEngine getGProxyGroovyScriptEngine() - { - return engine; - } - - @Override - public GenericProxyInvocationHandler createGenericProxyInvocationHandler(Object obj) - { - return new GProxyInvocationHandler(obj,this); - } -} +package com.innowhere.relproxy.impl.gproxy.core; + +import com.innowhere.relproxy.impl.gproxy.GProxyConfigImpl; +import com.innowhere.relproxy.gproxy.GProxyGroovyScriptEngine; +import com.innowhere.relproxy.impl.GenericProxyImpl; +import com.innowhere.relproxy.impl.GenericProxyInvocationHandler; + + +/** + * + * @author jmarranz + */ +public abstract class GProxyImpl extends GenericProxyImpl +{ + public static GProxyImpl SINGLETON; + protected GProxyGroovyScriptEngine engine; + + public void init(GProxyConfigImpl config) + { + super.init(config); + this.engine = config.getGProxyGroovyScriptEngine(); + } + + public GProxyGroovyScriptEngine getGProxyGroovyScriptEngine() + { + return engine; + } + + @Override + public GenericProxyInvocationHandler createGenericProxyInvocationHandler(Object obj) + { + return new GProxyInvocationHandler(obj,this); + } +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyInvocationHandler.java b/src/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyInvocationHandler.java similarity index 95% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyInvocationHandler.java rename to src/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyInvocationHandler.java index 439a081..6bacae7 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyInvocationHandler.java +++ b/src/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyInvocationHandler.java @@ -1,22 +1,22 @@ -package com.innowhere.relproxy.impl.gproxy.core; - -import com.innowhere.relproxy.impl.GenericProxyInvocationHandler; - -/** - * - * @author jmarranz - */ -public class GProxyInvocationHandler extends GenericProxyInvocationHandler -{ - public GProxyInvocationHandler(Object obj,GProxyImpl root) - { - super(root); - this.verObj = new GProxyVersionedObject(obj,this); - } - - public GProxyImpl getGProxyImpl() - { - return (GProxyImpl)root; - } - +package com.innowhere.relproxy.impl.gproxy.core; + +import com.innowhere.relproxy.impl.GenericProxyInvocationHandler; + +/** + * + * @author jmarranz + */ +public class GProxyInvocationHandler extends GenericProxyInvocationHandler +{ + public GProxyInvocationHandler(Object obj,GProxyImpl root) + { + super(root); + this.verObj = new GProxyVersionedObject(obj,this); + } + + public GProxyImpl getGProxyImpl() + { + return (GProxyImpl)root; + } + } \ No newline at end of file diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyVersionedObject.java b/src/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyVersionedObject.java similarity index 96% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyVersionedObject.java rename to src/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyVersionedObject.java index d1a8106..38f574c 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyVersionedObject.java +++ b/src/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyVersionedObject.java @@ -1,48 +1,48 @@ -package com.innowhere.relproxy.impl.gproxy.core; - -import com.innowhere.relproxy.gproxy.GProxyGroovyScriptEngine; -import com.innowhere.relproxy.impl.GenericProxyVersionedObject; -import java.lang.reflect.Field; - -/** - * - * @author jmarranz - */ -public class GProxyVersionedObject extends GenericProxyVersionedObject -{ - protected String path; - - public GProxyVersionedObject(Object obj,GProxyInvocationHandler parent) - { - super(obj,parent); - this.path = obj.getClass().getName().replace('.','/'); - } - - - public GProxyInvocationHandler getGProxyInvocationHandler() - { - return (GProxyInvocationHandler)parent; - } - - @Override - protected Class reloadClass() - { - GProxyGroovyScriptEngine engine = getGProxyInvocationHandler().getGProxyImpl().getGProxyGroovyScriptEngine(); - - try - { - return engine.loadScriptByName(path + ".groovy"); //Ej: example/groovyex/GroovyExampleLoadListener.groovy - } - catch(Exception ex) - { - ex.printStackTrace(System.err); - return null; - } - } - - @Override - protected boolean ignoreField(Field field) - { - return field.getName().startsWith("__timeStamp__"); // Este atributo cambia de nombre en cada reload, no lo consideramos - } -} +package com.innowhere.relproxy.impl.gproxy.core; + +import com.innowhere.relproxy.gproxy.GProxyGroovyScriptEngine; +import com.innowhere.relproxy.impl.GenericProxyVersionedObject; +import java.lang.reflect.Field; + +/** + * + * @author jmarranz + */ +public class GProxyVersionedObject extends GenericProxyVersionedObject +{ + protected String path; + + public GProxyVersionedObject(Object obj,GProxyInvocationHandler parent) + { + super(obj,parent); + this.path = obj.getClass().getName().replace('.','/'); + } + + + public GProxyInvocationHandler getGProxyInvocationHandler() + { + return (GProxyInvocationHandler)parent; + } + + @Override + protected Class reloadClass() + { + GProxyGroovyScriptEngine engine = getGProxyInvocationHandler().getGProxyImpl().getGProxyGroovyScriptEngine(); + + try + { + return engine.loadScriptByName(path + ".groovy"); //Ej: example/groovyex/GroovyExampleLoadListener.groovy + } + catch(Exception ex) + { + ex.printStackTrace(System.err); + return null; + } + } + + @Override + protected boolean ignoreField(Field field) + { + return field.getName().startsWith("__timeStamp__"); // Este atributo cambia de nombre en cada reload, no lo consideramos + } +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/JProxyConfigImpl.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/JProxyConfigImpl.java similarity index 96% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/JProxyConfigImpl.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/JProxyConfigImpl.java index b435a8a..8dc72f0 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/JProxyConfigImpl.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/JProxyConfigImpl.java @@ -1,158 +1,158 @@ -package com.innowhere.relproxy.impl.jproxy; - -import com.innowhere.relproxy.RelProxyException; -import com.innowhere.relproxy.RelProxyOnReloadListener; -import com.innowhere.relproxy.impl.GenericProxyConfigBaseImpl; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; -import com.innowhere.relproxy.jproxy.JProxyCompilerListener; -import com.innowhere.relproxy.jproxy.JProxyConfig; -import com.innowhere.relproxy.jproxy.JProxyDiagnosticsListener; -import com.innowhere.relproxy.jproxy.JProxyInputSourceFileExcludedListener; -import java.io.File; - -/** - * - * @author jmarranz - */ -public class JProxyConfigImpl extends GenericProxyConfigBaseImpl implements JProxyConfig -{ - protected File folderSources; - protected FolderSourceList folderSourceList; - protected FolderSourceList requiredExtraJarPaths; - protected JProxyInputSourceFileExcludedListener excludedListener; - protected JProxyCompilerListener compilerListener; - protected String classFolder; - protected long scanPeriod = -1; - protected Iterable compilationOptions; - protected JProxyDiagnosticsListener diagnosticsListener; - protected boolean test = false; - - @Override - public JProxyConfig setEnabled(boolean enabled) - { - this.enabled = enabled; - return this; - } - - @Override - public JProxyConfig setRelProxyOnReloadListener(RelProxyOnReloadListener relListener) - { - this.relListener = relListener; - return this; - } - - @Override - public JProxyConfig setInputPath(String inputPath) - { - setInputPaths(inputPath != null ? new String[]{inputPath} : null); // inputPath es null en el caso de shell interactive - return this; - } - - @Override - public JProxyConfig setInputPaths(String[] inputPaths) - { - this.folderSourceList = new FolderSourceList(inputPaths,true); // inputPaths es null en el caso de shell interactive - return this; - } - - @Override - public JProxyConfig setRequiredExtraJarPaths(String[] inputJarPaths) - { - this.requiredExtraJarPaths = new FolderSourceList(inputJarPaths,false); // inputPaths es null en el caso de shell interactive - return this; - } - - @Override - public JProxyConfig setJProxyInputSourceFileExcludedListener(JProxyInputSourceFileExcludedListener excludedListener) - { - this.excludedListener = excludedListener; - return this; - } - - @Override - public JProxyConfig setJProxyCompilerListener(JProxyCompilerListener compilerListener) - { - this.compilerListener = compilerListener; - return this; - } - - @Override - public JProxyConfig setClassFolder(String classFolder) - { - this.classFolder = classFolder; - return this; - } - - @Override - public JProxyConfig setScanPeriod(long scanPeriod) - { - if (scanPeriod == 0) throw new RelProxyException("scanPeriod cannot be zero"); - this.scanPeriod = scanPeriod; - return this; - } - - @Override - public JProxyConfig setCompilationOptions(Iterable compilationOptions) - { - this.compilationOptions = compilationOptions; - return this; - } - - @Override - public JProxyConfig setJProxyDiagnosticsListener(JProxyDiagnosticsListener diagnosticsListener) - { - this.diagnosticsListener = diagnosticsListener; - return this; - } - - public FolderSourceList getFolderSourceList() - { - return folderSourceList; - } - - public FolderSourceList getRequiredExtraJarPaths() - { - return requiredExtraJarPaths; - } - - public JProxyInputSourceFileExcludedListener getJProxyInputSourceFileExcludedListener() - { - return excludedListener; - } - - public JProxyCompilerListener getJProxyCompilerListener() - { - return compilerListener; - } - - public String getClassFolder() - { - return classFolder; - } - - public long getScanPeriod() - { - return scanPeriod; - } - - public Iterable getCompilationOptions() - { - return compilationOptions; - } - - public JProxyDiagnosticsListener getJProxyDiagnosticsListener() - { - return diagnosticsListener; - } - - public boolean isTest() - { - return test; - } - - public void setTest(boolean test) - { - this.test = test; - } - -} +package com.innowhere.relproxy.impl.jproxy; + +import com.innowhere.relproxy.RelProxyException; +import com.innowhere.relproxy.RelProxyOnReloadListener; +import com.innowhere.relproxy.impl.GenericProxyConfigBaseImpl; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import com.innowhere.relproxy.jproxy.JProxyCompilerListener; +import com.innowhere.relproxy.jproxy.JProxyConfig; +import com.innowhere.relproxy.jproxy.JProxyDiagnosticsListener; +import com.innowhere.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import java.io.File; + +/** + * + * @author jmarranz + */ +public class JProxyConfigImpl extends GenericProxyConfigBaseImpl implements JProxyConfig +{ + protected File folderSources; + protected FolderSourceList folderSourceList; + protected FolderSourceList requiredExtraJarPaths; + protected JProxyInputSourceFileExcludedListener excludedListener; + protected JProxyCompilerListener compilerListener; + protected String classFolder; + protected long scanPeriod = -1; + protected Iterable compilationOptions; + protected JProxyDiagnosticsListener diagnosticsListener; + protected boolean test = false; + + @Override + public JProxyConfig setEnabled(boolean enabled) + { + this.enabled = enabled; + return this; + } + + @Override + public JProxyConfig setRelProxyOnReloadListener(RelProxyOnReloadListener relListener) + { + this.relListener = relListener; + return this; + } + + @Override + public JProxyConfig setInputPath(String inputPath) + { + setInputPaths(inputPath != null ? new String[]{inputPath} : null); // inputPath es null en el caso de shell interactive + return this; + } + + @Override + public JProxyConfig setInputPaths(String[] inputPaths) + { + this.folderSourceList = new FolderSourceList(inputPaths,true); // inputPaths es null en el caso de shell interactive + return this; + } + + @Override + public JProxyConfig setRequiredExtraJarPaths(String[] inputJarPaths) + { + this.requiredExtraJarPaths = new FolderSourceList(inputJarPaths,false); // inputPaths es null en el caso de shell interactive + return this; + } + + @Override + public JProxyConfig setJProxyInputSourceFileExcludedListener(JProxyInputSourceFileExcludedListener excludedListener) + { + this.excludedListener = excludedListener; + return this; + } + + @Override + public JProxyConfig setJProxyCompilerListener(JProxyCompilerListener compilerListener) + { + this.compilerListener = compilerListener; + return this; + } + + @Override + public JProxyConfig setClassFolder(String classFolder) + { + this.classFolder = classFolder; + return this; + } + + @Override + public JProxyConfig setScanPeriod(long scanPeriod) + { + if (scanPeriod == 0) throw new RelProxyException("scanPeriod cannot be zero"); + this.scanPeriod = scanPeriod; + return this; + } + + @Override + public JProxyConfig setCompilationOptions(Iterable compilationOptions) + { + this.compilationOptions = compilationOptions; + return this; + } + + @Override + public JProxyConfig setJProxyDiagnosticsListener(JProxyDiagnosticsListener diagnosticsListener) + { + this.diagnosticsListener = diagnosticsListener; + return this; + } + + public FolderSourceList getFolderSourceList() + { + return folderSourceList; + } + + public FolderSourceList getRequiredExtraJarPaths() + { + return requiredExtraJarPaths; + } + + public JProxyInputSourceFileExcludedListener getJProxyInputSourceFileExcludedListener() + { + return excludedListener; + } + + public JProxyCompilerListener getJProxyCompilerListener() + { + return compilerListener; + } + + public String getClassFolder() + { + return classFolder; + } + + public long getScanPeriod() + { + return scanPeriod; + } + + public Iterable getCompilationOptions() + { + return compilationOptions; + } + + public JProxyDiagnosticsListener getJProxyDiagnosticsListener() + { + return diagnosticsListener; + } + + public boolean isTest() + { + return test; + } + + public void setTest(boolean test) + { + this.test = test; + } + +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/JProxyDefaultImpl.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/JProxyDefaultImpl.java similarity index 95% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/JProxyDefaultImpl.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/JProxyDefaultImpl.java index 1fa606d..5b9d6d0 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/JProxyDefaultImpl.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/JProxyDefaultImpl.java @@ -1,86 +1,86 @@ -package com.innowhere.relproxy.impl.jproxy; - -import com.innowhere.relproxy.impl.jproxy.core.JProxyImpl; -import com.innowhere.relproxy.jproxy.JProxyConfig; - -/** - * - * @author jmarranz - */ -public class JProxyDefaultImpl extends JProxyImpl -{ - public JProxyDefaultImpl() - { - } - - @Override - public Class getMainParamClass() - { - return null; - } - - public static JProxyConfig createJProxyConfig() - { - return new JProxyConfigImpl(); - } - - public static void initStatic(JProxyConfigImpl config) - { - if (!config.isEnabled()) return; - - checkSingletonNull(SINGLETON); - SINGLETON = new JProxyDefaultImpl(); - SINGLETON.init(config); - } - - - public static T createStatic(T obj,Class clasz) - { - if (SINGLETON == null) - return obj; // No se ha llamado al init o enabled = false - - return SINGLETON.create(obj, clasz); - } - - public static Object createStatic(Object obj,Class[] classes) - { - if (SINGLETON == null) - return obj; // No se ha llamado al init o enabled = false - - return SINGLETON.create(obj, classes); - } - - - public static boolean isEnabledStatic() - { - if (SINGLETON == null) - return false; - - return SINGLETON.isEnabled(); - } - - - public static boolean isRunningStatic() - { - if (SINGLETON == null) - return false; - - return SINGLETON.isRunning(); - } - - public static boolean stopStatic() - { - if (SINGLETON == null) - return false; - - return SINGLETON.stop(); - } - - public static boolean startStatic() - { - if (SINGLETON == null) - return false; - - return SINGLETON.start(); - } -} +package com.innowhere.relproxy.impl.jproxy; + +import com.innowhere.relproxy.impl.jproxy.core.JProxyImpl; +import com.innowhere.relproxy.jproxy.JProxyConfig; + +/** + * + * @author jmarranz + */ +public class JProxyDefaultImpl extends JProxyImpl +{ + public JProxyDefaultImpl() + { + } + + @Override + public Class getMainParamClass() + { + return null; + } + + public static JProxyConfig createJProxyConfig() + { + return new JProxyConfigImpl(); + } + + public static void initStatic(JProxyConfigImpl config) + { + if (!config.isEnabled()) return; + + checkSingletonNull(SINGLETON); + SINGLETON = new JProxyDefaultImpl(); + SINGLETON.init(config); + } + + + public static T createStatic(T obj,Class clasz) + { + if (SINGLETON == null) + return obj; // No se ha llamado al init o enabled = false + + return SINGLETON.create(obj, clasz); + } + + public static Object createStatic(Object obj,Class[] classes) + { + if (SINGLETON == null) + return obj; // No se ha llamado al init o enabled = false + + return SINGLETON.create(obj, classes); + } + + + public static boolean isEnabledStatic() + { + if (SINGLETON == null) + return false; + + return SINGLETON.isEnabled(); + } + + + public static boolean isRunningStatic() + { + if (SINGLETON == null) + return false; + + return SINGLETON.isRunning(); + } + + public static boolean stopStatic() + { + if (SINGLETON == null) + return false; + + return SINGLETON.stop(); + } + + public static boolean startStatic() + { + if (SINGLETON == null) + return false; + + return SINGLETON.start(); + } +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/JProxyUtil.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/JProxyUtil.java similarity index 96% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/JProxyUtil.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/JProxyUtil.java index cfc9873..d8e46e3 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/JProxyUtil.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/JProxyUtil.java @@ -1,163 +1,163 @@ -package com.innowhere.relproxy.impl.jproxy; - -import com.innowhere.relproxy.RelProxyException; -import java.io.BufferedReader; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.net.URL; -import java.net.URLConnection; - -/** - * - * @author jmarranz - */ -public class JProxyUtil -{ - public static String getCanonicalPath(File file) - { - try - { - return file.getCanonicalPath(); - } - catch (IOException ex) - { - throw new RelProxyException(ex); - } - } - - public static String getFileExtension(File file) - { - String path = file.getAbsolutePath(); - int pos = path.lastIndexOf('.'); - if (pos != -1) - return path.substring(pos + 1); - return ""; - } - - public static File getParentDir(File file) - { - return file.getParentFile(); - } - - public static byte[] readURL(URL url) - { - URLConnection urlCon; - try - { - urlCon = url.openConnection(); - return readInputStream(urlCon.getInputStream()); - } - catch (IOException ex) { throw new RelProxyException(ex); } - } - - public static byte[] readFile(File file) - { - FileInputStream fis = null; - try - { - fis = new FileInputStream(file); - } - catch (FileNotFoundException ex) - { - throw new RelProxyException(ex); - } - - return readInputStream(fis); - } - - public static byte[] readInputStream(InputStream is) - { - return readInputStream(is,50); // 50Kb => unas 100 lecturas 5 Mb - } - - public static byte[] readInputStream(InputStream is,int bufferSizeKb) - { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - try - { - byte[] buffer = new byte[bufferSizeKb*1024]; - - int size; - while( (size = is.read(buffer)) != -1 ) - { - out.write(buffer, 0, size); - } - } - catch (IOException ex) - { - throw new RelProxyException(ex); - } - finally - { - try { is.close(); } catch (IOException ex2) { throw new RelProxyException(ex2); } - } - - return out.toByteArray(); - } - - public static void saveFile(File file,byte[] content) - { - File parent = getParentDir(file); - if (parent != null) parent.mkdirs(); - FileOutputStream out = null; - try - { - out = new FileOutputStream(file); - out.write(content, 0, content.length); - } - catch (IOException ex) - { - throw new RelProxyException(ex); - } - finally - { - if (out != null) try { out.close(); } catch (IOException ex2) { throw new RelProxyException(ex2); } - } - } - - public static String readTextFile(File file,String encoding) - { - Reader reader = null; - try - { - reader = new InputStreamReader(new FileInputStream(file),encoding); // FileReader no permite especificar el encoding y total no hace nada que no haga InputStreamReader - } - catch(IOException ex) { throw new RelProxyException(ex); } - - return readTextFile(reader); - } - - public static String readTextFile(Reader reader) - { - BufferedReader br = null; - try - { - br = new BufferedReader(reader); // FileReader no permite especificar el encoding y total no hace nada que no haga InputStreamReader - StringBuilder sb = new StringBuilder(); - String line = br.readLine(); - - while (line != null) - { - sb.append(line); - sb.append('\n'); - line = br.readLine(); - } - return sb.toString(); - } - catch(IOException ex) - { - throw new RelProxyException(ex); - } - finally - { - if (br != null) try { br.close(); } catch (IOException ex) { throw new RelProxyException(ex); } - } - } -} +package com.innowhere.relproxy.impl.jproxy; + +import com.innowhere.relproxy.RelProxyException; +import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.net.URL; +import java.net.URLConnection; + +/** + * + * @author jmarranz + */ +public class JProxyUtil +{ + public static String getCanonicalPath(File file) + { + try + { + return file.getCanonicalPath(); + } + catch (IOException ex) + { + throw new RelProxyException(ex); + } + } + + public static String getFileExtension(File file) + { + String path = file.getAbsolutePath(); + int pos = path.lastIndexOf('.'); + if (pos != -1) + return path.substring(pos + 1); + return ""; + } + + public static File getParentDir(File file) + { + return file.getParentFile(); + } + + public static byte[] readURL(URL url) + { + URLConnection urlCon; + try + { + urlCon = url.openConnection(); + return readInputStream(urlCon.getInputStream()); + } + catch (IOException ex) { throw new RelProxyException(ex); } + } + + public static byte[] readFile(File file) + { + FileInputStream fis = null; + try + { + fis = new FileInputStream(file); + } + catch (FileNotFoundException ex) + { + throw new RelProxyException(ex); + } + + return readInputStream(fis); + } + + public static byte[] readInputStream(InputStream is) + { + return readInputStream(is,50); // 50Kb => unas 100 lecturas 5 Mb + } + + public static byte[] readInputStream(InputStream is,int bufferSizeKb) + { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + try + { + byte[] buffer = new byte[bufferSizeKb*1024]; + + int size; + while( (size = is.read(buffer)) != -1 ) + { + out.write(buffer, 0, size); + } + } + catch (IOException ex) + { + throw new RelProxyException(ex); + } + finally + { + try { is.close(); } catch (IOException ex2) { throw new RelProxyException(ex2); } + } + + return out.toByteArray(); + } + + public static void saveFile(File file,byte[] content) + { + File parent = getParentDir(file); + if (parent != null) parent.mkdirs(); + FileOutputStream out = null; + try + { + out = new FileOutputStream(file); + out.write(content, 0, content.length); + } + catch (IOException ex) + { + throw new RelProxyException(ex); + } + finally + { + if (out != null) try { out.close(); } catch (IOException ex2) { throw new RelProxyException(ex2); } + } + } + + public static String readTextFile(File file,String encoding) + { + Reader reader = null; + try + { + reader = new InputStreamReader(new FileInputStream(file),encoding); // FileReader no permite especificar el encoding y total no hace nada que no haga InputStreamReader + } + catch(IOException ex) { throw new RelProxyException(ex); } + + return readTextFile(reader); + } + + public static String readTextFile(Reader reader) + { + BufferedReader br = null; + try + { + br = new BufferedReader(reader); // FileReader no permite especificar el encoding y total no hace nada que no haga InputStreamReader + StringBuilder sb = new StringBuilder(); + String line = br.readLine(); + + while (line != null) + { + sb.append(line); + sb.append('\n'); + line = br.readLine(); + } + return sb.toString(); + } + catch(IOException ex) + { + throw new RelProxyException(ex); + } + finally + { + if (br != null) try { br.close(); } catch (IOException ex) { throw new RelProxyException(ex); } + } + } +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyImpl.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyImpl.java similarity index 97% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyImpl.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyImpl.java index 4d41301..b9ea4da 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyImpl.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyImpl.java @@ -1,90 +1,90 @@ -package com.innowhere.relproxy.impl.jproxy.core; - -import com.innowhere.relproxy.impl.GenericProxyImpl; -import com.innowhere.relproxy.impl.GenericProxyInvocationHandler; -import com.innowhere.relproxy.impl.jproxy.JProxyConfigImpl; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; -import com.innowhere.relproxy.jproxy.JProxyCompilerListener; -import com.innowhere.relproxy.jproxy.JProxyDiagnosticsListener; -import com.innowhere.relproxy.jproxy.JProxyInputSourceFileExcludedListener; - -/** - * - * @author jmarranz - */ -public abstract class JProxyImpl extends GenericProxyImpl -{ - public static JProxyImpl SINGLETON; - protected JProxyEngine engine; - - - protected JProxyImpl() - { - } - - public static ClassLoader getDefaultClassLoader() - { - return Thread.currentThread().getContextClassLoader(); - } - - public ClassDescriptorSourceScript init(JProxyConfigImpl config) - { - return init(config,null,null); - } - - public ClassDescriptorSourceScript init(JProxyConfigImpl config,SourceScriptRoot scriptFile,ClassLoader classLoader) - { - super.init(config); - - FolderSourceList folderSourceList = config.getFolderSourceList(); - FolderSourceList requiredExtraJarPaths = config.getRequiredExtraJarPaths(); - JProxyInputSourceFileExcludedListener excludedListener = config.getJProxyInputSourceFileExcludedListener(); - JProxyCompilerListener compilerListener = config.getJProxyCompilerListener(); - String classFolder = config.getClassFolder(); - long scanPeriod = config.getScanPeriod(); - Iterable compilationOptions = config.getCompilationOptions(); - JProxyDiagnosticsListener diagnosticsListener = config.getJProxyDiagnosticsListener(); - boolean enabled = config.isEnabled(); - - classLoader = classLoader != null ? classLoader : getDefaultClassLoader(); - this.engine = new JProxyEngine(this,enabled,scriptFile,classLoader,folderSourceList,requiredExtraJarPaths,classFolder,scanPeriod,excludedListener,compilerListener,compilationOptions,diagnosticsListener); - - return engine.init(); - } - - public JProxyEngine getJProxyEngine() - { - return engine; - } - - public boolean isEnabled() - { - return engine.isEnabled(); - } - - public boolean isRunning() - { - return engine.isRunning(); - } - - public boolean stop() - { - return engine.stop(); - } - - public boolean start() - { - return engine.start(); - } - - @Override - public GenericProxyInvocationHandler createGenericProxyInvocationHandler(Object obj) - { - return new JProxyInvocationHandler(obj,this); - } - - public abstract Class getMainParamClass(); -} +package com.innowhere.relproxy.impl.jproxy.core; + +import com.innowhere.relproxy.impl.GenericProxyImpl; +import com.innowhere.relproxy.impl.GenericProxyInvocationHandler; +import com.innowhere.relproxy.impl.jproxy.JProxyConfigImpl; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.innowhere.relproxy.jproxy.JProxyCompilerListener; +import com.innowhere.relproxy.jproxy.JProxyDiagnosticsListener; +import com.innowhere.relproxy.jproxy.JProxyInputSourceFileExcludedListener; + +/** + * + * @author jmarranz + */ +public abstract class JProxyImpl extends GenericProxyImpl +{ + public static JProxyImpl SINGLETON; + protected JProxyEngine engine; + + + protected JProxyImpl() + { + } + + public static ClassLoader getDefaultClassLoader() + { + return Thread.currentThread().getContextClassLoader(); + } + + public ClassDescriptorSourceScript init(JProxyConfigImpl config) + { + return init(config,null,null); + } + + public ClassDescriptorSourceScript init(JProxyConfigImpl config,SourceScriptRoot scriptFile,ClassLoader classLoader) + { + super.init(config); + + FolderSourceList folderSourceList = config.getFolderSourceList(); + FolderSourceList requiredExtraJarPaths = config.getRequiredExtraJarPaths(); + JProxyInputSourceFileExcludedListener excludedListener = config.getJProxyInputSourceFileExcludedListener(); + JProxyCompilerListener compilerListener = config.getJProxyCompilerListener(); + String classFolder = config.getClassFolder(); + long scanPeriod = config.getScanPeriod(); + Iterable compilationOptions = config.getCompilationOptions(); + JProxyDiagnosticsListener diagnosticsListener = config.getJProxyDiagnosticsListener(); + boolean enabled = config.isEnabled(); + + classLoader = classLoader != null ? classLoader : getDefaultClassLoader(); + this.engine = new JProxyEngine(this,enabled,scriptFile,classLoader,folderSourceList,requiredExtraJarPaths,classFolder,scanPeriod,excludedListener,compilerListener,compilationOptions,diagnosticsListener); + + return engine.init(); + } + + public JProxyEngine getJProxyEngine() + { + return engine; + } + + public boolean isEnabled() + { + return engine.isEnabled(); + } + + public boolean isRunning() + { + return engine.isRunning(); + } + + public boolean stop() + { + return engine.stop(); + } + + public boolean start() + { + return engine.start(); + } + + @Override + public GenericProxyInvocationHandler createGenericProxyInvocationHandler(Object obj) + { + return new JProxyInvocationHandler(obj,this); + } + + public abstract Class getMainParamClass(); +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyInvocationHandler.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyInvocationHandler.java similarity index 95% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyInvocationHandler.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyInvocationHandler.java index 408b746..ebef741 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyInvocationHandler.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyInvocationHandler.java @@ -1,23 +1,23 @@ - -package com.innowhere.relproxy.impl.jproxy.core; - -import com.innowhere.relproxy.impl.GenericProxyInvocationHandler; - -/** - * - * @author jmarranz - */ -public class JProxyInvocationHandler extends GenericProxyInvocationHandler -{ - public JProxyInvocationHandler(Object obj,JProxyImpl root) - { - super(root); - this.verObj = new JProxyVersionedObject(obj,this); - } - - public JProxyImpl getJProxyImpl() - { - return (JProxyImpl)root; - } - + +package com.innowhere.relproxy.impl.jproxy.core; + +import com.innowhere.relproxy.impl.GenericProxyInvocationHandler; + +/** + * + * @author jmarranz + */ +public class JProxyInvocationHandler extends GenericProxyInvocationHandler +{ + public JProxyInvocationHandler(Object obj,JProxyImpl root) + { + super(root); + this.verObj = new JProxyVersionedObject(obj,this); + } + + public JProxyImpl getJProxyImpl() + { + return (JProxyImpl)root; + } + } \ No newline at end of file diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyVersionedObject.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyVersionedObject.java similarity index 96% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyVersionedObject.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyVersionedObject.java index ce0c888..ded542f 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyVersionedObject.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyVersionedObject.java @@ -1,39 +1,39 @@ -package com.innowhere.relproxy.impl.jproxy.core; - -import com.innowhere.relproxy.impl.GenericProxyVersionedObject; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; -import java.lang.reflect.Field; - -/** - * - * @author jmarranz - */ -public class JProxyVersionedObject extends GenericProxyVersionedObject -{ - protected String className; - - public JProxyVersionedObject(Object obj,JProxyInvocationHandler parent) - { - super(obj,parent); - this.className = obj.getClass().getName(); - } - - public JProxyInvocationHandler getJProxyInvocationHandler() - { - return (JProxyInvocationHandler)parent; - } - - @Override - protected Class reloadClass() - { - JProxyEngine engine = getJProxyInvocationHandler().getJProxyImpl().getJProxyEngine(); - engine.reloadWhenChanged(); - return (Class)engine.findClass(className); - } - - @Override - protected boolean ignoreField(Field field) - { - return false; // Todos cuentan (útil en Groovy no en Java) - } +package com.innowhere.relproxy.impl.jproxy.core; + +import com.innowhere.relproxy.impl.GenericProxyVersionedObject; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; +import java.lang.reflect.Field; + +/** + * + * @author jmarranz + */ +public class JProxyVersionedObject extends GenericProxyVersionedObject +{ + protected String className; + + public JProxyVersionedObject(Object obj,JProxyInvocationHandler parent) + { + super(obj,parent); + this.className = obj.getClass().getName(); + } + + public JProxyInvocationHandler getJProxyInvocationHandler() + { + return (JProxyInvocationHandler)parent; + } + + @Override + protected Class reloadClass() + { + JProxyEngine engine = getJProxyInvocationHandler().getJProxyImpl().getJProxyEngine(); + engine.reloadWhenChanged(); + return (Class)engine.findClass(className); + } + + @Override + protected boolean ignoreField(Field field) + { + return false; // Todos cuentan (útil en Groovy no en Java) + } } \ No newline at end of file diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java similarity index 100% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java similarity index 97% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java index ac1a163..19c7b33 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java @@ -1,150 +1,150 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr; - -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; -import com.innowhere.relproxy.impl.jproxy.JProxyUtil; -import java.net.URL; - -/** - * - * @author jmarranz - */ -public class JProxyClassLoader extends ClassLoader -{ - protected final JProxyEngine engine; - - public JProxyClassLoader(JProxyEngine engine) - { - super(engine.getRootClassLoader()); - - this.engine = engine; - } - - public Class defineClass(ClassDescriptor classDesc) - { - Object monitor = engine.getMonitor(); - synchronized(monitor) - { - String className = classDesc.getClassName(); - byte[] classBytes = classDesc.getClassBytes(); - Class clasz = defineClass(className,classBytes, 0, classBytes.length); - classDesc.setLastLoadedClass(clasz); - return clasz; - } - } - - @Override - protected Class findClass(String name) throws ClassNotFoundException - { - Object monitor = engine.getMonitor(); - synchronized(monitor) - { - return loadClass(name,true); - - /* - Class cls = findLoadedClass(name); - if (cls == null) - return loadClass(name,true); - - //if (cls == null) - // return getParent().loadClass(name); // Dará un ClassNotFoundException si no puede cargarla - - return cls; - */ - } - } - - public Class loadClass(ClassDescriptor classDesc,boolean resolve) - { - Object monitor = engine.getMonitor(); - synchronized(monitor) - { - Class clasz = classDesc.getLastLoadedClass(); - if (clasz != null && clasz.getClassLoader() == this) return clasz; // Glup, ya fue cargada - clasz = defineClass(classDesc); - if (resolve) { - resolveClass(clasz); - } - return clasz; - } - } - - public Class loadInnerClass(ClassDescriptorSourceUnit parentDesc,String innerClassName) - { - Object monitor = engine.getMonitor(); - synchronized(monitor) - { - ClassDescriptor classDesc = parentDesc.getInnerClassDescriptor(innerClassName,false); - if (classDesc == null || classDesc.getClassBytes() == null) - { - byte[] classBytes = getClassBytesFromResource(innerClassName); - if (classBytes == null) return null; - if (classDesc == null) classDesc = parentDesc.addInnerClassDescriptor(innerClassName); - classDesc.setClassBytes(classBytes); - } - - return defineClass(classDesc); - } - } - - @Override - protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException - { - // Inspiraciones en URLClassLoader.findClass y en el propio análisis de ClassLoader.loadClass - // Lo redefinimos por si acaso porque el objetivo es recargar todas las clases hot-reloaded en este ClassLoader y no delegar en el parent - // (el comportamiento por defecto de loadClass) pues las clases cargadas con el parent tenderán a cargar las clases vinculadas con dicho ClassLoader - - // En teoría este método redefinido no es necesario porque manualmente detectamos los cambios de código fuente, recompilamos y recargamos explícitamente - // con defineClass el cual no carga también las innerclasses vinculadas, - // pero si el código fuente tiene innerclasses y no ha sido cambiado nunca, las innerclasses pueden no ser conocidas como ClassDescriptor, - // necesitamos detectar las innerclasses para cargarlas también tras la carga de la clase contenedora, - // para ello ejecutamos Class.getDeclaredClasses() para que cargue las innerclasses indirectamente, pasando entonces por aquí. - - // Hay un caso más y es el de la clase base que es una clase hot loadable con su propio archivo, al ejecutar el defineClass en la clase - // derivada la clase base también debe cargarse en ese momento y es posible que no haya sido hecho explícitamente (por ej porque no ha cambiado o su carga va después) - // por lo que pasaremos por aquí y debemos cargarla aquí, luego no hay problema de recarga explícita porque sabemos que ha sido ya cargada - // y tampoco hay problema de auto-salvado del .class o eliminación del mismo puesto que al ser un archivo fuente normal se tratará por si mismo - // aunque la carga en el class loader se haya hecho a través de una clase derivada quizás antes - - Object monitor = engine.getMonitor(); - synchronized(monitor) - { - Class cls = findLoadedClass(name); - if (cls == null) - { - ClassDescriptor classDesc = engine.getClassDescriptor(name); // Si es una inner class se crea el descriptor y se añade al source file asociado automáticamente - if (classDesc != null) - { - byte[] classBytes = classDesc.getClassBytes(); - if (classBytes == null) - { - classBytes = getClassBytesFromResource(name); // No puede ser nulo - classDesc.setClassBytes(classBytes); - } - - cls = defineClass(classDesc); - } - - if (cls == null) - { - cls = getParent().loadClass(name); // Dará un ClassNotFoundException si no puede cargarla - } - } - - if (cls == null) throw new ClassNotFoundException(name); - - if (resolve) { - resolveClass(cls); - } - return cls; - } - } - - private byte[] getClassBytesFromResource(String className) - { - String relClassPath = ClassDescriptor.getRelativeClassFilePathFromClassName(className); - URL urlClass = getResource(relClassPath); - if (urlClass == null) return null; - return JProxyUtil.readURL(urlClass); - } -} +package com.innowhere.relproxy.impl.jproxy.core.clsmgr; + +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; +import com.innowhere.relproxy.impl.jproxy.JProxyUtil; +import java.net.URL; + +/** + * + * @author jmarranz + */ +public class JProxyClassLoader extends ClassLoader +{ + protected final JProxyEngine engine; + + public JProxyClassLoader(JProxyEngine engine) + { + super(engine.getRootClassLoader()); + + this.engine = engine; + } + + public Class defineClass(ClassDescriptor classDesc) + { + Object monitor = engine.getMonitor(); + synchronized(monitor) + { + String className = classDesc.getClassName(); + byte[] classBytes = classDesc.getClassBytes(); + Class clasz = defineClass(className,classBytes, 0, classBytes.length); + classDesc.setLastLoadedClass(clasz); + return clasz; + } + } + + @Override + protected Class findClass(String name) throws ClassNotFoundException + { + Object monitor = engine.getMonitor(); + synchronized(monitor) + { + return loadClass(name,true); + + /* + Class cls = findLoadedClass(name); + if (cls == null) + return loadClass(name,true); + + //if (cls == null) + // return getParent().loadClass(name); // Dará un ClassNotFoundException si no puede cargarla + + return cls; + */ + } + } + + public Class loadClass(ClassDescriptor classDesc,boolean resolve) + { + Object monitor = engine.getMonitor(); + synchronized(monitor) + { + Class clasz = classDesc.getLastLoadedClass(); + if (clasz != null && clasz.getClassLoader() == this) return clasz; // Glup, ya fue cargada + clasz = defineClass(classDesc); + if (resolve) { + resolveClass(clasz); + } + return clasz; + } + } + + public Class loadInnerClass(ClassDescriptorSourceUnit parentDesc,String innerClassName) + { + Object monitor = engine.getMonitor(); + synchronized(monitor) + { + ClassDescriptor classDesc = parentDesc.getInnerClassDescriptor(innerClassName,false); + if (classDesc == null || classDesc.getClassBytes() == null) + { + byte[] classBytes = getClassBytesFromResource(innerClassName); + if (classBytes == null) return null; + if (classDesc == null) classDesc = parentDesc.addInnerClassDescriptor(innerClassName); + classDesc.setClassBytes(classBytes); + } + + return defineClass(classDesc); + } + } + + @Override + protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException + { + // Inspiraciones en URLClassLoader.findClass y en el propio análisis de ClassLoader.loadClass + // Lo redefinimos por si acaso porque el objetivo es recargar todas las clases hot-reloaded en este ClassLoader y no delegar en el parent + // (el comportamiento por defecto de loadClass) pues las clases cargadas con el parent tenderán a cargar las clases vinculadas con dicho ClassLoader + + // En teoría este método redefinido no es necesario porque manualmente detectamos los cambios de código fuente, recompilamos y recargamos explícitamente + // con defineClass el cual no carga también las innerclasses vinculadas, + // pero si el código fuente tiene innerclasses y no ha sido cambiado nunca, las innerclasses pueden no ser conocidas como ClassDescriptor, + // necesitamos detectar las innerclasses para cargarlas también tras la carga de la clase contenedora, + // para ello ejecutamos Class.getDeclaredClasses() para que cargue las innerclasses indirectamente, pasando entonces por aquí. + + // Hay un caso más y es el de la clase base que es una clase hot loadable con su propio archivo, al ejecutar el defineClass en la clase + // derivada la clase base también debe cargarse en ese momento y es posible que no haya sido hecho explícitamente (por ej porque no ha cambiado o su carga va después) + // por lo que pasaremos por aquí y debemos cargarla aquí, luego no hay problema de recarga explícita porque sabemos que ha sido ya cargada + // y tampoco hay problema de auto-salvado del .class o eliminación del mismo puesto que al ser un archivo fuente normal se tratará por si mismo + // aunque la carga en el class loader se haya hecho a través de una clase derivada quizás antes + + Object monitor = engine.getMonitor(); + synchronized(monitor) + { + Class cls = findLoadedClass(name); + if (cls == null) + { + ClassDescriptor classDesc = engine.getClassDescriptor(name); // Si es una inner class se crea el descriptor y se añade al source file asociado automáticamente + if (classDesc != null) + { + byte[] classBytes = classDesc.getClassBytes(); + if (classBytes == null) + { + classBytes = getClassBytesFromResource(name); // No puede ser nulo + classDesc.setClassBytes(classBytes); + } + + cls = defineClass(classDesc); + } + + if (cls == null) + { + cls = getParent().loadClass(name); // Dará un ClassNotFoundException si no puede cargarla + } + } + + if (cls == null) throw new ClassNotFoundException(name); + + if (resolve) { + resolveClass(cls); + } + return cls; + } + } + + private byte[] getClassBytesFromResource(String className) + { + String relClassPath = ClassDescriptor.getRelativeClassFilePathFromClassName(className); + URL urlClass = getResource(relClassPath); + if (urlClass == null) return null; + return JProxyUtil.readURL(urlClass); + } +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java similarity index 97% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java index ca7aedc..e662177 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java @@ -1,302 +1,302 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr; - -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorInner; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.innowhere.relproxy.impl.jproxy.core.JProxyImpl; -import com.innowhere.relproxy.jproxy.JProxyCompilerListener; -import com.innowhere.relproxy.jproxy.JProxyDiagnosticsListener; -import com.innowhere.relproxy.jproxy.JProxyInputSourceFileExcludedListener; -import java.util.LinkedList; -import java.util.Timer; -import java.util.TimerTask; - -/** - * - * @author jmarranz - */ -public class JProxyEngine -{ - protected final Object monitor = new Object(); // Podríamos usar este objeto JProxyEngine directamente pero el monitor es mejor para análisis de dependencias - protected final JProxyImpl parent; - protected final JProxyEngineChangeDetectorAndCompiler delegateChangeDetector; - protected final ClassLoader rootClassLoader; - protected JProxyClassLoader customClassLoader; - protected final long scanPeriod; - protected final String sourceEncoding = "UTF-8"; // Por ahora, provisional - public volatile boolean stop = false; - protected TimerTask task; - protected boolean pendingReload = false; - protected final boolean enabled; - - public JProxyEngine(JProxyImpl parent,boolean enabled,SourceScriptRoot scriptFile,ClassLoader rootClassLoader,FolderSourceList folderSourceList,FolderSourceList requiredExtraJarPaths, - String folderClasses,long scanPeriod,JProxyInputSourceFileExcludedListener excludedListener, - JProxyCompilerListener compilerListener,Iterable compilationOptions,JProxyDiagnosticsListener diagnosticsListener) - { - this.parent = parent; - this.enabled = enabled; - this.rootClassLoader = rootClassLoader; - this.scanPeriod = scanPeriod; - this.delegateChangeDetector = new JProxyEngineChangeDetectorAndCompiler(this,scriptFile,folderSourceList,requiredExtraJarPaths,folderClasses,excludedListener,compilationOptions,diagnosticsListener,compilerListener); - this.customClassLoader = null; //new JProxyClassLoader(this); - } - - public Object getMonitor() - { - return monitor; - } - - public JProxyImpl getJProxy() - { - return parent; - } - - public boolean isEnabled() - { - return enabled; - } - - public ClassDescriptorSourceScript init() - { - synchronized(getMonitor()) - { - ClassDescriptorSourceScript scriptFileDesc = detectChangesInSources(); // Primera vez para detectar cambios en los .java respecto a los .class mientras el servidor estaba parado - - reloadWhenChanged(); // La primera vez cargamos pues el código fuente manda sobre los .class - - startScanner(); - - return scriptFileDesc; - } - } - - /* - public JProxyClassLoader getJProxyClassLoader() - { - return customClassLoader; - } - */ - - public ClassLoader getCurrentClassLoader() - { - if (customClassLoader != null) - return customClassLoader; - return rootClassLoader; - } - - private boolean startScanner() - { - if (scanPeriod > 0) // Si es 0 o negativo sólo se recargan una vez (la inicial ya ejecutada) - { - this.task = new TimerTask() - { - @Override - public void run() - { - if (stop) - { - cancel(); - return; - } - - try - { - detectChangesInSources(); // Está sincronizado las partes que lo necesitan - } - catch(Exception ex) - { - ex.printStackTrace(System.err); // Si dejamos subir la excepción se acabó el timer - } - } - }; - - new Timer().schedule(task, scanPeriod, scanPeriod); // Ojo, después de la primera llamada a detectChangesInSources() - return true; - } - else - { - return false; - } - } - - public void setPendingReload() - { - this.pendingReload = true; - } - - - public ClassLoader getRootClassLoader() - { - return rootClassLoader; - } - - public String getSourceEncoding() - { - return sourceEncoding; - } - - public boolean isRunning() - { - synchronized(getMonitor()) - { - return task != null && scanPeriod > 0; - } - } - - public boolean stop() - { - synchronized(getMonitor()) - { - if (task != null) - { - this.stop = true; - task.cancel(); - this.task = null; - return true; - } - else - { - return false; - } - } - } - - public boolean start() - { - synchronized(getMonitor()) - { - if (task == null) - { - this.stop = false; - return startScanner(); - } - else return false; - } - } - - - - public ClassDescriptor getClassDescriptor(String className) - { - synchronized(getMonitor()) - { - return delegateChangeDetector.getClassDescriptor(className); - } - } - - public Class findClass(String className) - { - // Si ya está cargada la devuelve, y si no se cargó por ningún JProxyClassLoader se intenta cargar por el parent ClassLoader, por lo que siempre devolverá distinto de null si la clase está en el classpath, que debería ser lo normal - synchronized(getMonitor()) - { - try - { - if (customClassLoader != null) - return customClassLoader.findClass(className); - else - return rootClassLoader.loadClass(className); - } - catch (ClassNotFoundException ex) - { - return null; - } - } - } - - private void addNewClassLoader() - { - ClassDescriptorSourceFileRegistry sourceRegistry = delegateChangeDetector.getClassDescriptorSourceFileRegistry(); - - for(ClassDescriptorSourceUnit sourceFile : sourceRegistry.getClassDescriptorSourceFileColl()) - { - sourceFile.resetLastLoadedClass(); // resetea también las innerclasses - } - - this.customClassLoader = new JProxyClassLoader(this); - } - - - - private Class reloadSource(ClassDescriptorSourceUnit sourceFile) - { - Class clasz = customClassLoader.loadClass(sourceFile,true); - reloadInnerClassesOnly(sourceFile,clasz); - return clasz; - } - - private void reloadInnerClassesOnly(ClassDescriptorSourceUnit sourceFile,Class classParent) - { - - LinkedList innerClassDescList = sourceFile.getInnerClassDescriptors(); - if (innerClassDescList != null && !innerClassDescList.isEmpty()) - { - // En el caso de una clase que ha sido compilada, las inner classes se descubren todas - for(ClassDescriptorInner innerClassDesc : innerClassDescList) - { - customClassLoader.loadClass(innerClassDesc,true); - } - } - else // Auto-Detección de innerclasses: puede ser un archivo fuente que posiblemente nunca se hayan tocado desde la carga inicial y por tanto quizás se desconocen las innerclasses - { - // Aprovechando la carga de la clase, hacemos el esfuerzo de cargar todas las clases dependientes lo más posible - classParent.getDeclaredClasses(); // Provoca que las inner clases miembro indirectamente se procesen y carguen a través del JProxyClassLoader de la clase padre clasz - - // Ahora bien, lo anterior NO sirve para las anonymous inner classes, afortunadamente en ese caso podemos conocer y cargar por fuerza bruta - // http://stackoverflow.com/questions/1654889/java-reflection-how-can-i-retrieve-anonymous-inner-classes?rq=1 - - for(int i = 1; i < Integer.MAX_VALUE; i++) // No te asustes por el MAX_VALUE, se parará tras unos poquitos ciclos - { - String anonClassName = sourceFile.getClassName() + "$" + i; - Class innerClasz = customClassLoader.loadInnerClass(sourceFile,anonClassName); - if (innerClasz == null) break; // No hay más o no hay ninguna (si i es 1) - } - - // ¿Qué es lo que queda por cargar pero que no podemos hacer explícitamente? - // 1) Las clases privadas autónomas que fueron definidas en el mismo archivo que la clase principal: no las soportamos pues no podemos identificar en el ClassLoader que es una clase "hot reloadable", no son inner classes en el sentido estricto - // 2) Las clases privadas "inner" locales, es decir no anónimas declaradas dentro de un método, se cargarán la primera vez que se usen, no podemos conocerlas a priori - // porque siguen la notación className$NclassName ej. JReloadExampleDocument$1AuxMemberInMethod. No hay problema con que se carguen con un class loader antiguo pues - // el ClassLoader de la clase padre contenedora será el encargado de cargarla en cuanto se pase por el método que la declara. - } - } - - public ClassDescriptorSourceScript detectChangesInSources() - { - return delegateChangeDetector.detectChangesInSources(); - } - - public ClassDescriptorSourceScript detectChangesInSourcesAndReload() - { - ClassDescriptorSourceScript res = detectChangesInSources(); - reloadWhenChanged(); - return res; - } - - public boolean reloadWhenChanged() - { - synchronized(getMonitor()) - { - if (pendingReload) - { - addNewClassLoader(); - - ClassDescriptorSourceFileRegistry sourceRegistry = delegateChangeDetector.getClassDescriptorSourceFileRegistry(); - - for(ClassDescriptorSourceUnit sourceFile : sourceRegistry.getClassDescriptorSourceFileColl()) // sourceRegistry NUNCA es nulo pues se ejecuta una primera vez en tiempo de inicialización - { - // if (sourceFilesCompiled.contains(sourceFile)) - // continue; - // las clases deleted no están en sourceFileMap por lo que no hay que filtrarlas - reloadSource(sourceFile); // Ponemos detectInnerClasses a true porque son archivos fuente que posiblemente nunca se hayan tocado desde la carga inicial y por tanto quizás se desconocen las innerclasses - } - - this.pendingReload = false; - return true; - } - return false; - } - } - -} +package com.innowhere.relproxy.impl.jproxy.core.clsmgr; + +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorInner; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.innowhere.relproxy.impl.jproxy.core.JProxyImpl; +import com.innowhere.relproxy.jproxy.JProxyCompilerListener; +import com.innowhere.relproxy.jproxy.JProxyDiagnosticsListener; +import com.innowhere.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import java.util.LinkedList; +import java.util.Timer; +import java.util.TimerTask; + +/** + * + * @author jmarranz + */ +public class JProxyEngine +{ + protected final Object monitor = new Object(); // Podríamos usar este objeto JProxyEngine directamente pero el monitor es mejor para análisis de dependencias + protected final JProxyImpl parent; + protected final JProxyEngineChangeDetectorAndCompiler delegateChangeDetector; + protected final ClassLoader rootClassLoader; + protected JProxyClassLoader customClassLoader; + protected final long scanPeriod; + protected final String sourceEncoding = "UTF-8"; // Por ahora, provisional + public volatile boolean stop = false; + protected TimerTask task; + protected boolean pendingReload = false; + protected final boolean enabled; + + public JProxyEngine(JProxyImpl parent,boolean enabled,SourceScriptRoot scriptFile,ClassLoader rootClassLoader,FolderSourceList folderSourceList,FolderSourceList requiredExtraJarPaths, + String folderClasses,long scanPeriod,JProxyInputSourceFileExcludedListener excludedListener, + JProxyCompilerListener compilerListener,Iterable compilationOptions,JProxyDiagnosticsListener diagnosticsListener) + { + this.parent = parent; + this.enabled = enabled; + this.rootClassLoader = rootClassLoader; + this.scanPeriod = scanPeriod; + this.delegateChangeDetector = new JProxyEngineChangeDetectorAndCompiler(this,scriptFile,folderSourceList,requiredExtraJarPaths,folderClasses,excludedListener,compilationOptions,diagnosticsListener,compilerListener); + this.customClassLoader = null; //new JProxyClassLoader(this); + } + + public Object getMonitor() + { + return monitor; + } + + public JProxyImpl getJProxy() + { + return parent; + } + + public boolean isEnabled() + { + return enabled; + } + + public ClassDescriptorSourceScript init() + { + synchronized(getMonitor()) + { + ClassDescriptorSourceScript scriptFileDesc = detectChangesInSources(); // Primera vez para detectar cambios en los .java respecto a los .class mientras el servidor estaba parado + + reloadWhenChanged(); // La primera vez cargamos pues el código fuente manda sobre los .class + + startScanner(); + + return scriptFileDesc; + } + } + + /* + public JProxyClassLoader getJProxyClassLoader() + { + return customClassLoader; + } + */ + + public ClassLoader getCurrentClassLoader() + { + if (customClassLoader != null) + return customClassLoader; + return rootClassLoader; + } + + private boolean startScanner() + { + if (scanPeriod > 0) // Si es 0 o negativo sólo se recargan una vez (la inicial ya ejecutada) + { + this.task = new TimerTask() + { + @Override + public void run() + { + if (stop) + { + cancel(); + return; + } + + try + { + detectChangesInSources(); // Está sincronizado las partes que lo necesitan + } + catch(Exception ex) + { + ex.printStackTrace(System.err); // Si dejamos subir la excepción se acabó el timer + } + } + }; + + new Timer().schedule(task, scanPeriod, scanPeriod); // Ojo, después de la primera llamada a detectChangesInSources() + return true; + } + else + { + return false; + } + } + + public void setPendingReload() + { + this.pendingReload = true; + } + + + public ClassLoader getRootClassLoader() + { + return rootClassLoader; + } + + public String getSourceEncoding() + { + return sourceEncoding; + } + + public boolean isRunning() + { + synchronized(getMonitor()) + { + return task != null && scanPeriod > 0; + } + } + + public boolean stop() + { + synchronized(getMonitor()) + { + if (task != null) + { + this.stop = true; + task.cancel(); + this.task = null; + return true; + } + else + { + return false; + } + } + } + + public boolean start() + { + synchronized(getMonitor()) + { + if (task == null) + { + this.stop = false; + return startScanner(); + } + else return false; + } + } + + + + public ClassDescriptor getClassDescriptor(String className) + { + synchronized(getMonitor()) + { + return delegateChangeDetector.getClassDescriptor(className); + } + } + + public Class findClass(String className) + { + // Si ya está cargada la devuelve, y si no se cargó por ningún JProxyClassLoader se intenta cargar por el parent ClassLoader, por lo que siempre devolverá distinto de null si la clase está en el classpath, que debería ser lo normal + synchronized(getMonitor()) + { + try + { + if (customClassLoader != null) + return customClassLoader.findClass(className); + else + return rootClassLoader.loadClass(className); + } + catch (ClassNotFoundException ex) + { + return null; + } + } + } + + private void addNewClassLoader() + { + ClassDescriptorSourceFileRegistry sourceRegistry = delegateChangeDetector.getClassDescriptorSourceFileRegistry(); + + for(ClassDescriptorSourceUnit sourceFile : sourceRegistry.getClassDescriptorSourceFileColl()) + { + sourceFile.resetLastLoadedClass(); // resetea también las innerclasses + } + + this.customClassLoader = new JProxyClassLoader(this); + } + + + + private Class reloadSource(ClassDescriptorSourceUnit sourceFile) + { + Class clasz = customClassLoader.loadClass(sourceFile,true); + reloadInnerClassesOnly(sourceFile,clasz); + return clasz; + } + + private void reloadInnerClassesOnly(ClassDescriptorSourceUnit sourceFile,Class classParent) + { + + LinkedList innerClassDescList = sourceFile.getInnerClassDescriptors(); + if (innerClassDescList != null && !innerClassDescList.isEmpty()) + { + // En el caso de una clase que ha sido compilada, las inner classes se descubren todas + for(ClassDescriptorInner innerClassDesc : innerClassDescList) + { + customClassLoader.loadClass(innerClassDesc,true); + } + } + else // Auto-Detección de innerclasses: puede ser un archivo fuente que posiblemente nunca se hayan tocado desde la carga inicial y por tanto quizás se desconocen las innerclasses + { + // Aprovechando la carga de la clase, hacemos el esfuerzo de cargar todas las clases dependientes lo más posible + classParent.getDeclaredClasses(); // Provoca que las inner clases miembro indirectamente se procesen y carguen a través del JProxyClassLoader de la clase padre clasz + + // Ahora bien, lo anterior NO sirve para las anonymous inner classes, afortunadamente en ese caso podemos conocer y cargar por fuerza bruta + // http://stackoverflow.com/questions/1654889/java-reflection-how-can-i-retrieve-anonymous-inner-classes?rq=1 + + for(int i = 1; i < Integer.MAX_VALUE; i++) // No te asustes por el MAX_VALUE, se parará tras unos poquitos ciclos + { + String anonClassName = sourceFile.getClassName() + "$" + i; + Class innerClasz = customClassLoader.loadInnerClass(sourceFile,anonClassName); + if (innerClasz == null) break; // No hay más o no hay ninguna (si i es 1) + } + + // ¿Qué es lo que queda por cargar pero que no podemos hacer explícitamente? + // 1) Las clases privadas autónomas que fueron definidas en el mismo archivo que la clase principal: no las soportamos pues no podemos identificar en el ClassLoader que es una clase "hot reloadable", no son inner classes en el sentido estricto + // 2) Las clases privadas "inner" locales, es decir no anónimas declaradas dentro de un método, se cargarán la primera vez que se usen, no podemos conocerlas a priori + // porque siguen la notación className$NclassName ej. JReloadExampleDocument$1AuxMemberInMethod. No hay problema con que se carguen con un class loader antiguo pues + // el ClassLoader de la clase padre contenedora será el encargado de cargarla en cuanto se pase por el método que la declara. + } + } + + public ClassDescriptorSourceScript detectChangesInSources() + { + return delegateChangeDetector.detectChangesInSources(); + } + + public ClassDescriptorSourceScript detectChangesInSourcesAndReload() + { + ClassDescriptorSourceScript res = detectChangesInSources(); + reloadWhenChanged(); + return res; + } + + public boolean reloadWhenChanged() + { + synchronized(getMonitor()) + { + if (pendingReload) + { + addNewClassLoader(); + + ClassDescriptorSourceFileRegistry sourceRegistry = delegateChangeDetector.getClassDescriptorSourceFileRegistry(); + + for(ClassDescriptorSourceUnit sourceFile : sourceRegistry.getClassDescriptorSourceFileColl()) // sourceRegistry NUNCA es nulo pues se ejecuta una primera vez en tiempo de inicialización + { + // if (sourceFilesCompiled.contains(sourceFile)) + // continue; + // las clases deleted no están en sourceFileMap por lo que no hay que filtrarlas + reloadSource(sourceFile); // Ponemos detectInnerClasses a true porque son archivos fuente que posiblemente nunca se hayan tocado desde la carga inicial y por tanto quizás se desconocen las innerclasses + } + + this.pendingReload = false; + return true; + } + return false; + } + } + +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java similarity index 98% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java index b6f482b..e58b76b 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java @@ -1,305 +1,305 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr; - -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootInMemory; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceUnit; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootFile; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorInner; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.innowhere.relproxy.impl.jproxy.JProxyUtil; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.JProxyCompilerContext; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.JProxyCompilerInMemory; -import com.innowhere.relproxy.jproxy.JProxyCompilerListener; -import com.innowhere.relproxy.jproxy.JProxyDiagnosticsListener; -import com.innowhere.relproxy.jproxy.JProxyInputSourceFileExcludedListener; -import java.io.File; -import java.util.ArrayList; -import java.util.LinkedList; - -/** - * - * @author jmarranz - */ -public class JProxyEngineChangeDetectorAndCompiler -{ - protected final JProxyEngine engine; - protected final JProxyCompilerInMemory compiler; - protected final FolderSourceList folderSourceList; - protected final FolderSourceList requiredExtraJarPaths; - protected final SourceScriptRoot scriptFile; // Puede ser nulo - protected final String folderClasses; // Puede ser nulo (es decir NO salvar como .class los cambios) - protected final JProxyInputSourceFileExcludedListener excludedListener; - protected final JavaSourcesSearch sourcesSearch; - protected final JProxyCompilerListener compilerListener; - protected volatile ClassDescriptorSourceFileRegistry sourceRegistry; - - public JProxyEngineChangeDetectorAndCompiler(JProxyEngine engine,SourceScriptRoot scriptFile,FolderSourceList folderSourceList,FolderSourceList requiredExtraJarPaths, - String folderClasses, JProxyInputSourceFileExcludedListener excludedListener,Iterable compilationOptions,JProxyDiagnosticsListener diagnosticsListener, - JProxyCompilerListener compilerListener) - { - this.engine = engine; - this.scriptFile = scriptFile; - this.folderSourceList = folderSourceList; - this.requiredExtraJarPaths = requiredExtraJarPaths; - this.folderClasses = folderClasses; - this.excludedListener = excludedListener; - this.compiler = new JProxyCompilerInMemory(this,compilationOptions,diagnosticsListener); - this.sourcesSearch = new JavaSourcesSearch(this); - this.compilerListener = compilerListener; - } - - public JProxyEngine getJProxyEngine() - { - return engine; - } - - public FolderSourceList getFolderSourceList() - { - return folderSourceList; - } - - public FolderSourceList getRequiredExtraJarPaths() - { - return requiredExtraJarPaths; - } - - public JProxyInputSourceFileExcludedListener getJProxyInputSourceFileExcludedListener() - { - return excludedListener; - } - - public ClassDescriptorSourceFileRegistry getClassDescriptorSourceFileRegistry() - { - return sourceRegistry; - } - - public ClassDescriptor getClassDescriptor(String className) - { - return sourceRegistry.getClassDescriptor(className); - } - - private boolean isSaveClassesMode() - { - return (folderClasses != null); - } - - private JProxyCompilerListener getJProxyCompilerListener() - { - return compilerListener; - } - - private void cleanBeforeCompile(ClassDescriptorSourceUnit sourceFile) - { - if (isSaveClassesMode()) - deleteClasses(sourceFile); // Antes de que nos las carguemos en memoria la clase principal y las inner tras recompilar - - sourceFile.cleanOnSourceCodeChanged(); // El código fuente nuevo puede haber cambiado totalmente las innerclasses antiguas (añadido, eliminado) y por supuesto el bytecode necesita olvidarse - } - - private void compile(ClassDescriptorSourceUnit sourceFile,JProxyCompilerContext context) - { - if (sourceFile.getClassBytes() != null) - return; // Ya ha sido compilado seguramente por dependencia de un archivo compilado inmediatamente antes, recuerda que el atributo classBytes se pone a null antes de compilar los archivos cambiados/nuevos - - compiler.compileSourceFile(sourceFile,context,engine.getCurrentClassLoader(),sourceRegistry); - } - - public ClassDescriptorSourceScript detectChangesInSources() - { - Object monitor = getJProxyEngine().getMonitor(); - - boolean firstTime; - - synchronized(monitor) - { - if (this.sourceRegistry == null) // Es null la primera vez - { - firstTime = true; - this.sourceRegistry = new ClassDescriptorSourceFileRegistry(); - } - else - { - firstTime = false; - sourceRegistry.setAllClassDescriptorSourceFilesPendingToRemove( true ); // A medida que los vamos encontrando ponemos a false, es mucho más rápido que recrear el registro si no ha cambiado nada (lo normal) - } - } - - LinkedList updatedSourceFiles = new LinkedList(); - LinkedList newSourceFiles = new LinkedList(); - - ClassDescriptorSourceScript scriptFileDesc = sourcesSearch.sourceFileSearch(firstTime,scriptFile,sourceRegistry,updatedSourceFiles,newSourceFiles); - - LinkedList deletedSourceFiles = new LinkedList(); - - if (!firstTime) - { - synchronized(monitor) - { - // Obtenemos los deletedSourceFiles detectados (si es firstTime no tiene sentido hacer esto no haría nada pero nos ahorramos synchronized y llamada) - sourceRegistry.getAllClassDescriptorSourceFilesPendingToRemove(deletedSourceFiles); - } - } - - if (updatedSourceFiles.isEmpty() && newSourceFiles.isEmpty() && deletedSourceFiles.isEmpty()) - return scriptFileDesc; - - // También el hecho de eliminar una clase debe implicar crear un ClassLoader nuevo para que dicha clase desaparezca de las clases cargadas aunque será muy raro que sólo eliminemos un .java y no añadamos/cambiemos otros, otro motico es porque si tenemos configurado el autosalvado de .class tenemos que eliminar en ese caso - - synchronized(monitor) - { - if (!firstTime) - { - if (!deletedSourceFiles.isEmpty()) // En firstTime no tiene sentido que haya eliminados - { - for(ClassDescriptorSourceUnit classDesc : deletedSourceFiles) - sourceRegistry.removeClassDescriptorSourceUnit(classDesc.getClassName()); - } - - if (!newSourceFiles.isEmpty()) // En firstTime ya están añadidos en sourceRegistry explícitamente al recorrer los sources - { - for(ClassDescriptorSourceUnit classDesc : newSourceFiles) - sourceRegistry.addClassDescriptorSourceUnit(classDesc); - } - } - - ArrayList sourceFilesToCompile = new ArrayList(updatedSourceFiles.size() + newSourceFiles.size()); - sourceFilesToCompile.addAll(updatedSourceFiles); - sourceFilesToCompile.addAll(newSourceFiles); - - updatedSourceFiles = null; // Ya no se necesita - newSourceFiles = null; // Ya no se necesita - - if (!sourceFilesToCompile.isEmpty()) - { - // Eliminamos el estado de la anterior compilación de todas las clases que van a recompilarse antes de compilarlas porque al compilar una clase es posible que - // se necesite recompilar al mismo tiempo una dependiente de otra (ej clase base) y luego se intente compilar la dependiente y sería un problema que limpiáramos antes de compilar cada archivo - for(ClassDescriptorSourceUnit sourceFile : sourceFilesToCompile) - cleanBeforeCompile(sourceFile); - - - JProxyCompilerContext context = compiler.createJProxyCompilerContext(); - JProxyCompilerListener compilerListener = getJProxyCompilerListener(); - try - { - - for(ClassDescriptorSourceUnit sourceFile : sourceFilesToCompile) - { - File file = null; - if (compilerListener != null) - { - SourceUnit srcUnit = sourceFile.getSourceUnit(); - if (srcUnit instanceof SourceFileJavaNormal) - file = ((SourceFileJavaNormal)srcUnit).getFileExt().getFile(); - else if (srcUnit instanceof SourceScriptRootFile) - file = ((SourceScriptRootFile)srcUnit).getFileExt().getFile(); - else if (srcUnit instanceof SourceScriptRootInMemory) // Caso de shell interactive y code snippet, en ese caso NO hay listener porque no hay forma de definirlo - file = null; - } - - if (compilerListener != null && file != null) - compilerListener.beforeCompile(file); - - compile(sourceFile,context); - - if (compilerListener != null && file != null) - compilerListener.afterCompile(file); - } - } - finally - { - context.close(); - } - - if (isSaveClassesMode()) - { - for(ClassDescriptorSourceUnit sourceFile : sourceFilesToCompile) - { - saveClasses(sourceFile); - } - } - } - - if (isSaveClassesMode() && !deletedSourceFiles.isEmpty()) - for(ClassDescriptorSourceUnit sourceFile : deletedSourceFiles) - deleteClasses(sourceFile); - - deletedSourceFiles = null; // Ya no se necesita - - boolean setPendingReload = true; - if (sourceFilesToCompile.size() == 1) - { - ClassDescriptorSourceUnit sourceFile = sourceFilesToCompile.get(0); - SourceUnit sourceUnit = sourceFile.getSourceUnit(); - if ((sourceUnit instanceof SourceScriptRootInMemory) && ((SourceScriptRootInMemory)sourceUnit).isEmptyCode()) - { - // Leer notas en SourceScriptRootInMemory.isEmptyCode() de esta manera evitamos crear un ClassLoader nuevo inútilmente por culpa de una clase - // root que no sirve para nada, ello impide que el registro/desregistro en colecciones funcione bien pues la instancia - // en el proxy que añade se ha recreado y es diferente por tanto a la instancia del proxy que elimina pues hace lo mismo por su parte - // aunque el ClassLoader sea el mismo. Si hemos cambiado el código del listener tiene sentido, pero inútilmente por una clase estúpida es tontería - setPendingReload = false; - } - } - - if (setPendingReload) - engine.setPendingReload(); - } - - return scriptFileDesc; - } - - private void saveClasses(ClassDescriptorSourceUnit sourceFile) - { - // Salvamos la clase principal - { - File classFilePath = ClassDescriptor.getAbsoluteClassFilePathFromClassNameAndClassPath(sourceFile.getClassName(),folderClasses); - JProxyUtil.saveFile(classFilePath,sourceFile.getClassBytes()); - } - - // Salvamos las innerclasses si hay, no hay problema de clases inner no detectadas pues lo están todas pues sólo se salva tras una compilación - LinkedList innerClassDescList = sourceFile.getInnerClassDescriptors(); - if (innerClassDescList != null && !innerClassDescList.isEmpty()) - { - for(ClassDescriptorInner innerClassDesc : innerClassDescList) - { - File classFilePath = ClassDescriptor.getAbsoluteClassFilePathFromClassNameAndClassPath(innerClassDesc.getClassName(),folderClasses); - JProxyUtil.saveFile(classFilePath,innerClassDesc.getClassBytes()); - } - } - } - - private void deleteClasses(ClassDescriptorSourceUnit sourceFile) - { - // Puede ocurrir que esta clase nunca se haya cargado y se ha modificado el código fuente y queramos limpiar los .class correspondientes pues se van a recrear - // como no conocemos qué inner clases están asociadas para saber que .class hay que eliminar, pues lo que hacemos es directamente obtener los .class que hay - // en el directorio con el fin de eliminar todos .class que tengan el patrón de ser inner classes del source file de acuerdo a su nombre - // así conseguimos por ejemplo también eliminar las local classes (inner clases con nombre declaradas dentro de un método) que no hay manera de conocer - // a través de la carga de la clase - - // Hay un caso en el que puede haber .class que ya no están en el código fuente y es cuando tocamos el código fuente ANTES de cargar y eliminamos algún .java, - // al cargar como no existe el archivo no lo relacionamos con los .class - // La solución sería en tiempo de carga forzar una carga de todas las clases y de ahí deducir todos los .class que deben existir (excepto las clases locales - // que no podríamos detectarlas), pero el que haya .class sobrantes antiguos no es gran problema. - - File classFilePath = ClassDescriptor.getAbsoluteClassFilePathFromClassNameAndClassPath(sourceFile.getClassName(),folderClasses); - File parentDir = JProxyUtil.getParentDir(classFilePath); - String[] fileNameList = parentDir.list(); // Es más ligero que listFiles() que crea File por cada resultado - if (fileNameList != null) // Si es null es que el directorio no está creado - { - for (String fileName : fileNameList) - { - int pos = fileName.lastIndexOf(".class"); - if (pos == -1) continue; - String simpleClassName = fileName.substring(0, pos); - if (sourceFile.getSimpleClassName().equals(simpleClassName) || - sourceFile.isInnerClass(sourceFile.getPackageName() + simpleClassName)) - { - new File(parentDir,fileName).delete(); - } - } - } - } -} +package com.innowhere.relproxy.impl.jproxy.core.clsmgr; + +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootInMemory; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceUnit; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootFile; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorInner; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.innowhere.relproxy.impl.jproxy.JProxyUtil; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.JProxyCompilerContext; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.JProxyCompilerInMemory; +import com.innowhere.relproxy.jproxy.JProxyCompilerListener; +import com.innowhere.relproxy.jproxy.JProxyDiagnosticsListener; +import com.innowhere.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import java.io.File; +import java.util.ArrayList; +import java.util.LinkedList; + +/** + * + * @author jmarranz + */ +public class JProxyEngineChangeDetectorAndCompiler +{ + protected final JProxyEngine engine; + protected final JProxyCompilerInMemory compiler; + protected final FolderSourceList folderSourceList; + protected final FolderSourceList requiredExtraJarPaths; + protected final SourceScriptRoot scriptFile; // Puede ser nulo + protected final String folderClasses; // Puede ser nulo (es decir NO salvar como .class los cambios) + protected final JProxyInputSourceFileExcludedListener excludedListener; + protected final JavaSourcesSearch sourcesSearch; + protected final JProxyCompilerListener compilerListener; + protected volatile ClassDescriptorSourceFileRegistry sourceRegistry; + + public JProxyEngineChangeDetectorAndCompiler(JProxyEngine engine,SourceScriptRoot scriptFile,FolderSourceList folderSourceList,FolderSourceList requiredExtraJarPaths, + String folderClasses, JProxyInputSourceFileExcludedListener excludedListener,Iterable compilationOptions,JProxyDiagnosticsListener diagnosticsListener, + JProxyCompilerListener compilerListener) + { + this.engine = engine; + this.scriptFile = scriptFile; + this.folderSourceList = folderSourceList; + this.requiredExtraJarPaths = requiredExtraJarPaths; + this.folderClasses = folderClasses; + this.excludedListener = excludedListener; + this.compiler = new JProxyCompilerInMemory(this,compilationOptions,diagnosticsListener); + this.sourcesSearch = new JavaSourcesSearch(this); + this.compilerListener = compilerListener; + } + + public JProxyEngine getJProxyEngine() + { + return engine; + } + + public FolderSourceList getFolderSourceList() + { + return folderSourceList; + } + + public FolderSourceList getRequiredExtraJarPaths() + { + return requiredExtraJarPaths; + } + + public JProxyInputSourceFileExcludedListener getJProxyInputSourceFileExcludedListener() + { + return excludedListener; + } + + public ClassDescriptorSourceFileRegistry getClassDescriptorSourceFileRegistry() + { + return sourceRegistry; + } + + public ClassDescriptor getClassDescriptor(String className) + { + return sourceRegistry.getClassDescriptor(className); + } + + private boolean isSaveClassesMode() + { + return (folderClasses != null); + } + + private JProxyCompilerListener getJProxyCompilerListener() + { + return compilerListener; + } + + private void cleanBeforeCompile(ClassDescriptorSourceUnit sourceFile) + { + if (isSaveClassesMode()) + deleteClasses(sourceFile); // Antes de que nos las carguemos en memoria la clase principal y las inner tras recompilar + + sourceFile.cleanOnSourceCodeChanged(); // El código fuente nuevo puede haber cambiado totalmente las innerclasses antiguas (añadido, eliminado) y por supuesto el bytecode necesita olvidarse + } + + private void compile(ClassDescriptorSourceUnit sourceFile,JProxyCompilerContext context) + { + if (sourceFile.getClassBytes() != null) + return; // Ya ha sido compilado seguramente por dependencia de un archivo compilado inmediatamente antes, recuerda que el atributo classBytes se pone a null antes de compilar los archivos cambiados/nuevos + + compiler.compileSourceFile(sourceFile,context,engine.getCurrentClassLoader(),sourceRegistry); + } + + public ClassDescriptorSourceScript detectChangesInSources() + { + Object monitor = getJProxyEngine().getMonitor(); + + boolean firstTime; + + synchronized(monitor) + { + if (this.sourceRegistry == null) // Es null la primera vez + { + firstTime = true; + this.sourceRegistry = new ClassDescriptorSourceFileRegistry(); + } + else + { + firstTime = false; + sourceRegistry.setAllClassDescriptorSourceFilesPendingToRemove( true ); // A medida que los vamos encontrando ponemos a false, es mucho más rápido que recrear el registro si no ha cambiado nada (lo normal) + } + } + + LinkedList updatedSourceFiles = new LinkedList(); + LinkedList newSourceFiles = new LinkedList(); + + ClassDescriptorSourceScript scriptFileDesc = sourcesSearch.sourceFileSearch(firstTime,scriptFile,sourceRegistry,updatedSourceFiles,newSourceFiles); + + LinkedList deletedSourceFiles = new LinkedList(); + + if (!firstTime) + { + synchronized(monitor) + { + // Obtenemos los deletedSourceFiles detectados (si es firstTime no tiene sentido hacer esto no haría nada pero nos ahorramos synchronized y llamada) + sourceRegistry.getAllClassDescriptorSourceFilesPendingToRemove(deletedSourceFiles); + } + } + + if (updatedSourceFiles.isEmpty() && newSourceFiles.isEmpty() && deletedSourceFiles.isEmpty()) + return scriptFileDesc; + + // También el hecho de eliminar una clase debe implicar crear un ClassLoader nuevo para que dicha clase desaparezca de las clases cargadas aunque será muy raro que sólo eliminemos un .java y no añadamos/cambiemos otros, otro motico es porque si tenemos configurado el autosalvado de .class tenemos que eliminar en ese caso + + synchronized(monitor) + { + if (!firstTime) + { + if (!deletedSourceFiles.isEmpty()) // En firstTime no tiene sentido que haya eliminados + { + for(ClassDescriptorSourceUnit classDesc : deletedSourceFiles) + sourceRegistry.removeClassDescriptorSourceUnit(classDesc.getClassName()); + } + + if (!newSourceFiles.isEmpty()) // En firstTime ya están añadidos en sourceRegistry explícitamente al recorrer los sources + { + for(ClassDescriptorSourceUnit classDesc : newSourceFiles) + sourceRegistry.addClassDescriptorSourceUnit(classDesc); + } + } + + ArrayList sourceFilesToCompile = new ArrayList(updatedSourceFiles.size() + newSourceFiles.size()); + sourceFilesToCompile.addAll(updatedSourceFiles); + sourceFilesToCompile.addAll(newSourceFiles); + + updatedSourceFiles = null; // Ya no se necesita + newSourceFiles = null; // Ya no se necesita + + if (!sourceFilesToCompile.isEmpty()) + { + // Eliminamos el estado de la anterior compilación de todas las clases que van a recompilarse antes de compilarlas porque al compilar una clase es posible que + // se necesite recompilar al mismo tiempo una dependiente de otra (ej clase base) y luego se intente compilar la dependiente y sería un problema que limpiáramos antes de compilar cada archivo + for(ClassDescriptorSourceUnit sourceFile : sourceFilesToCompile) + cleanBeforeCompile(sourceFile); + + + JProxyCompilerContext context = compiler.createJProxyCompilerContext(); + JProxyCompilerListener compilerListener = getJProxyCompilerListener(); + try + { + + for(ClassDescriptorSourceUnit sourceFile : sourceFilesToCompile) + { + File file = null; + if (compilerListener != null) + { + SourceUnit srcUnit = sourceFile.getSourceUnit(); + if (srcUnit instanceof SourceFileJavaNormal) + file = ((SourceFileJavaNormal)srcUnit).getFileExt().getFile(); + else if (srcUnit instanceof SourceScriptRootFile) + file = ((SourceScriptRootFile)srcUnit).getFileExt().getFile(); + else if (srcUnit instanceof SourceScriptRootInMemory) // Caso de shell interactive y code snippet, en ese caso NO hay listener porque no hay forma de definirlo + file = null; + } + + if (compilerListener != null && file != null) + compilerListener.beforeCompile(file); + + compile(sourceFile,context); + + if (compilerListener != null && file != null) + compilerListener.afterCompile(file); + } + } + finally + { + context.close(); + } + + if (isSaveClassesMode()) + { + for(ClassDescriptorSourceUnit sourceFile : sourceFilesToCompile) + { + saveClasses(sourceFile); + } + } + } + + if (isSaveClassesMode() && !deletedSourceFiles.isEmpty()) + for(ClassDescriptorSourceUnit sourceFile : deletedSourceFiles) + deleteClasses(sourceFile); + + deletedSourceFiles = null; // Ya no se necesita + + boolean setPendingReload = true; + if (sourceFilesToCompile.size() == 1) + { + ClassDescriptorSourceUnit sourceFile = sourceFilesToCompile.get(0); + SourceUnit sourceUnit = sourceFile.getSourceUnit(); + if ((sourceUnit instanceof SourceScriptRootInMemory) && ((SourceScriptRootInMemory)sourceUnit).isEmptyCode()) + { + // Leer notas en SourceScriptRootInMemory.isEmptyCode() de esta manera evitamos crear un ClassLoader nuevo inútilmente por culpa de una clase + // root que no sirve para nada, ello impide que el registro/desregistro en colecciones funcione bien pues la instancia + // en el proxy que añade se ha recreado y es diferente por tanto a la instancia del proxy que elimina pues hace lo mismo por su parte + // aunque el ClassLoader sea el mismo. Si hemos cambiado el código del listener tiene sentido, pero inútilmente por una clase estúpida es tontería + setPendingReload = false; + } + } + + if (setPendingReload) + engine.setPendingReload(); + } + + return scriptFileDesc; + } + + private void saveClasses(ClassDescriptorSourceUnit sourceFile) + { + // Salvamos la clase principal + { + File classFilePath = ClassDescriptor.getAbsoluteClassFilePathFromClassNameAndClassPath(sourceFile.getClassName(),folderClasses); + JProxyUtil.saveFile(classFilePath,sourceFile.getClassBytes()); + } + + // Salvamos las innerclasses si hay, no hay problema de clases inner no detectadas pues lo están todas pues sólo se salva tras una compilación + LinkedList innerClassDescList = sourceFile.getInnerClassDescriptors(); + if (innerClassDescList != null && !innerClassDescList.isEmpty()) + { + for(ClassDescriptorInner innerClassDesc : innerClassDescList) + { + File classFilePath = ClassDescriptor.getAbsoluteClassFilePathFromClassNameAndClassPath(innerClassDesc.getClassName(),folderClasses); + JProxyUtil.saveFile(classFilePath,innerClassDesc.getClassBytes()); + } + } + } + + private void deleteClasses(ClassDescriptorSourceUnit sourceFile) + { + // Puede ocurrir que esta clase nunca se haya cargado y se ha modificado el código fuente y queramos limpiar los .class correspondientes pues se van a recrear + // como no conocemos qué inner clases están asociadas para saber que .class hay que eliminar, pues lo que hacemos es directamente obtener los .class que hay + // en el directorio con el fin de eliminar todos .class que tengan el patrón de ser inner classes del source file de acuerdo a su nombre + // así conseguimos por ejemplo también eliminar las local classes (inner clases con nombre declaradas dentro de un método) que no hay manera de conocer + // a través de la carga de la clase + + // Hay un caso en el que puede haber .class que ya no están en el código fuente y es cuando tocamos el código fuente ANTES de cargar y eliminamos algún .java, + // al cargar como no existe el archivo no lo relacionamos con los .class + // La solución sería en tiempo de carga forzar una carga de todas las clases y de ahí deducir todos los .class que deben existir (excepto las clases locales + // que no podríamos detectarlas), pero el que haya .class sobrantes antiguos no es gran problema. + + File classFilePath = ClassDescriptor.getAbsoluteClassFilePathFromClassNameAndClassPath(sourceFile.getClassName(),folderClasses); + File parentDir = JProxyUtil.getParentDir(classFilePath); + String[] fileNameList = parentDir.list(); // Es más ligero que listFiles() que crea File por cada resultado + if (fileNameList != null) // Si es null es que el directorio no está creado + { + for (String fileName : fileNameList) + { + int pos = fileName.lastIndexOf(".class"); + if (pos == -1) continue; + String simpleClassName = fileName.substring(0, pos); + if (sourceFile.getSimpleClassName().equals(simpleClassName) || + sourceFile.isInnerClass(sourceFile.getPackageName() + simpleClassName)) + { + new File(parentDir,fileName).delete(); + } + } + } + } +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java similarity index 98% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java index 8c7b3a6..d6d8a6a 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java @@ -1,193 +1,193 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr; - -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootFileJavaExt; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceUnit; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileJava; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.innowhere.relproxy.RelProxyException; -import com.innowhere.relproxy.impl.FileExt; -import com.innowhere.relproxy.impl.jproxy.JProxyUtil; -import com.innowhere.relproxy.jproxy.JProxyInputSourceFileExcludedListener; -import java.io.File; -import java.net.URL; -import java.util.LinkedList; - -/** - * - * @author jmarranz - */ -public class JavaSourcesSearch -{ - protected final JProxyEngineChangeDetectorAndCompiler parent; - - public JavaSourcesSearch(JProxyEngineChangeDetectorAndCompiler parent) - { - this.parent = parent; - } - - public JProxyEngineChangeDetectorAndCompiler getJProxyEngineChangeDetectorAndCompiler() - { - return parent; - } - - public ClassDescriptorSourceScript sourceFileSearch(boolean firstTime,SourceScriptRoot scriptFile,ClassDescriptorSourceFileRegistry sourceRegistry,LinkedList updatedSourceFiles,LinkedList newSourceFiles) - { - ClassDescriptorSourceScript scriptFileDesc = (scriptFile == null) ? null : processSourceFileScript(firstTime,scriptFile,sourceRegistry,updatedSourceFiles,newSourceFiles); - FileExt[] folderSourceList = parent.getFolderSourceList().getArray(); - if (folderSourceList == null) // Es el caso de shell interactivo o code snippet - return scriptFileDesc; - - boolean allEmpty = true; - - String scriptFileJavaCannonPath = (scriptFile != null && (scriptFile instanceof SourceScriptRootFileJavaExt)) ? ((SourceScriptRootFileJavaExt)scriptFile).getFileExt().getCanonicalPath() : null; - - for(int i = 0; i < folderSourceList.length; i++) - { - FileExt rootFolderOfSources = folderSourceList[i]; - String[] children = rootFolderOfSources.getFile().list(); - if (children == null) continue; // El que ha configurado los rootFolders es tonto y ha puesto alguno nulo o no es válido el path - if (children.length == 0) continue; // Empty - - if (allEmpty) allEmpty = false; - recursiveSourceFileJavaSearch(firstTime,scriptFileJavaCannonPath, i ,rootFolderOfSources,children,sourceRegistry,updatedSourceFiles,newSourceFiles); - } - - if (allEmpty) - throw new RelProxyException("All specified input source folders are empty"); - - return scriptFileDesc; - } - - private void recursiveSourceFileJavaSearch(boolean firstTime,String scriptFileJavaCannonPath,int rootFolderOfSourcesIndex,FileExt parentPath,String[] relPathList,ClassDescriptorSourceFileRegistry sourceRegistry,LinkedList updatedSourceFiles,LinkedList newSourceFiles) - { - FileExt rootFolderOfSources = parent.getFolderSourceList().getArray()[rootFolderOfSourcesIndex]; - JProxyInputSourceFileExcludedListener listener = parent.getJProxyInputSourceFileExcludedListener(); - - for(String relPath : relPathList) - { - File file = new File(parentPath.getCanonicalPath() + "/" + relPath); - FileExt fileExt = new FileExt(file); - if (file.isDirectory()) - { - if (listener != null && listener.isExcluded(file,rootFolderOfSources.getFile())) - continue; - - String[] children = file.list(); // Si está vacío el array está vacío pero existe - recursiveSourceFileJavaSearch(firstTime,scriptFileJavaCannonPath,rootFolderOfSourcesIndex,fileExt,children,sourceRegistry,updatedSourceFiles,newSourceFiles); - } - else - { - String ext = JProxyUtil.getFileExtension(file); // Si no tiene extensión devuelve "" - if (!"java".equals(ext)) continue; - //if (!"jsh".equals(ext)) continue; - - String cannonPath = JProxyUtil.getCanonicalPath(file); - if (scriptFileJavaCannonPath != null && scriptFileJavaCannonPath.equals(cannonPath)) - continue; // Es el propio archivo script inicial que es .java, así evitamos considerarlo dos veces - - if (listener != null && listener.isExcluded(file,rootFolderOfSources.getFile())) - continue; - - SourceFileJavaNormal sourceFile = new SourceFileJavaNormal(fileExt,rootFolderOfSources); - processSourceFileJava(firstTime,sourceFile,sourceRegistry,updatedSourceFiles,newSourceFiles); - } - } - } - - private ClassDescriptorSourceScript processSourceFileScript(boolean firstTime,SourceScriptRoot file,ClassDescriptorSourceFileRegistry sourceRegistry,LinkedList updatedSourceFiles,LinkedList newSourceFiles) - { - return (ClassDescriptorSourceScript)processSourceFile(firstTime,file,true,sourceRegistry,updatedSourceFiles,newSourceFiles); - } - - private ClassDescriptorSourceFileJava processSourceFileJava(boolean firstTime,SourceFileJavaNormal file,ClassDescriptorSourceFileRegistry sourceRegistry,LinkedList updatedSourceFiles,LinkedList newSourceFiles) - { - return (ClassDescriptorSourceFileJava)processSourceFile(firstTime,file,false,sourceRegistry,updatedSourceFiles,newSourceFiles); - } - - private ClassDescriptorSourceUnit processSourceFile(boolean firstTime,SourceUnit file,boolean script,ClassDescriptorSourceFileRegistry sourceRegistry,LinkedList updatedSourceFiles,LinkedList newSourceFiles) - { - JProxyEngine engine = parent.getJProxyEngine(); - String className = file.getClassName(); - - long timestampSourceFile = file.lastModified(); - ClassDescriptorSourceUnit sourceFile; - if (!firstTime) - { - Object monitor = engine.getMonitor(); - synchronized(monitor) - { - sourceFile = sourceRegistry.getClassDescriptorSourceUnit(className); - } - - if (sourceFile != null) // Cambiado - { - long oldTimestamp = sourceFile.getTimestamp(); - - if (timestampSourceFile > oldTimestamp) - { - synchronized(monitor) - { - sourceFile.updateTimestamp(timestampSourceFile); - } - updatedSourceFiles.add(sourceFile); - } - - sourceFile.setPendingToRemove( false ); // Encontrado, no se elimina porque sigue existiendo - } - else // Clase nueva - { - sourceFile = ClassDescriptorSourceUnit.create(script,engine,className,file,timestampSourceFile); - sourceFile.setPendingToRemove( false ); // Está ya por defecto pero para que quede claro - newSourceFiles.add(sourceFile); - } - } - else // Primera vez, vemos si el código fuente se ha cambiado respecto a los .class en el sistema de archivos - { - String relClassPath = ClassDescriptor.getRelativeClassFilePathFromClassName(className); - ClassLoader parentClassLoader = engine.getRootClassLoader(); - URL urlClass = parentClassLoader.getResource(relClassPath); - if (urlClass != null) - { - String urlClassExt = urlClass.toExternalForm(); - // Si el .class está en un JAR podríamos obtener el timestamp del archivo dentro del jar pero que haya un .java "fuera" reloadable indica que queremos "reemplazar" el del jar por lo que siempre se considerará que el archivo fuente ha sido modificado más reciente - long timestampCompiledClass = urlClassExt.startsWith("file:") ? new File(urlClass.getPath()).lastModified() : 0; // 0 cuando está en un JAR - - if (timestampSourceFile > timestampCompiledClass) - { - sourceFile = ClassDescriptorSourceUnit.create(script,engine,className,file,timestampSourceFile); - updatedSourceFiles.add(sourceFile); // Hay que recompilar -//System.out.println("UPDATED: " + className + " " + urlClass.toExternalForm() + " " + (timestampSourceFile - timestampCompiledClass)); - } - else - { - // Esto es lo normal en carga si no hemos tocado el código tras el deploy, que el .class sea más reciente que el .java - sourceFile = ClassDescriptorSourceUnit.create(script,engine,className,file,timestampCompiledClass); - byte[] classBytes = JProxyUtil.readURL(urlClass); - sourceFile.setClassBytes(classBytes); - // Falta cargar las posibles inner classes, hay que tener en cuenta que este archivo NO se va a compilar porque no ha cambiado respecto a .class conocido -//System.out.println("NOT UPDATED: " + className + " " + urlClass.toExternalForm() + " " + (timestampSourceFile - timestampCompiledClass)); - } - - } - else // No hay .class, es un archivo fuente nuevo creado antes de cargar la app web, hay que compilar si o si - { - sourceFile = ClassDescriptorSourceUnit.create(script,engine,className,file,timestampSourceFile); - newSourceFiles.add(sourceFile); - } - - Object monitor = engine.getMonitor(); - synchronized(monitor) - { - sourceRegistry.addClassDescriptorSourceUnit(sourceFile); // El registro de archivos se hace por primera vez por lo que hay que añadirlos todos inicialmente, updatedSourceFiles y newSourceFiles indicarán en este caso los que hay que recompilar además - } - } - - return sourceFile; - } - -} +package com.innowhere.relproxy.impl.jproxy.core.clsmgr; + +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootFileJavaExt; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceUnit; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileJava; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.innowhere.relproxy.RelProxyException; +import com.innowhere.relproxy.impl.FileExt; +import com.innowhere.relproxy.impl.jproxy.JProxyUtil; +import com.innowhere.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import java.io.File; +import java.net.URL; +import java.util.LinkedList; + +/** + * + * @author jmarranz + */ +public class JavaSourcesSearch +{ + protected final JProxyEngineChangeDetectorAndCompiler parent; + + public JavaSourcesSearch(JProxyEngineChangeDetectorAndCompiler parent) + { + this.parent = parent; + } + + public JProxyEngineChangeDetectorAndCompiler getJProxyEngineChangeDetectorAndCompiler() + { + return parent; + } + + public ClassDescriptorSourceScript sourceFileSearch(boolean firstTime,SourceScriptRoot scriptFile,ClassDescriptorSourceFileRegistry sourceRegistry,LinkedList updatedSourceFiles,LinkedList newSourceFiles) + { + ClassDescriptorSourceScript scriptFileDesc = (scriptFile == null) ? null : processSourceFileScript(firstTime,scriptFile,sourceRegistry,updatedSourceFiles,newSourceFiles); + FileExt[] folderSourceList = parent.getFolderSourceList().getArray(); + if (folderSourceList == null) // Es el caso de shell interactivo o code snippet + return scriptFileDesc; + + boolean allEmpty = true; + + String scriptFileJavaCannonPath = (scriptFile != null && (scriptFile instanceof SourceScriptRootFileJavaExt)) ? ((SourceScriptRootFileJavaExt)scriptFile).getFileExt().getCanonicalPath() : null; + + for(int i = 0; i < folderSourceList.length; i++) + { + FileExt rootFolderOfSources = folderSourceList[i]; + String[] children = rootFolderOfSources.getFile().list(); + if (children == null) continue; // El que ha configurado los rootFolders es tonto y ha puesto alguno nulo o no es válido el path + if (children.length == 0) continue; // Empty + + if (allEmpty) allEmpty = false; + recursiveSourceFileJavaSearch(firstTime,scriptFileJavaCannonPath, i ,rootFolderOfSources,children,sourceRegistry,updatedSourceFiles,newSourceFiles); + } + + if (allEmpty) + throw new RelProxyException("All specified input source folders are empty"); + + return scriptFileDesc; + } + + private void recursiveSourceFileJavaSearch(boolean firstTime,String scriptFileJavaCannonPath,int rootFolderOfSourcesIndex,FileExt parentPath,String[] relPathList,ClassDescriptorSourceFileRegistry sourceRegistry,LinkedList updatedSourceFiles,LinkedList newSourceFiles) + { + FileExt rootFolderOfSources = parent.getFolderSourceList().getArray()[rootFolderOfSourcesIndex]; + JProxyInputSourceFileExcludedListener listener = parent.getJProxyInputSourceFileExcludedListener(); + + for(String relPath : relPathList) + { + File file = new File(parentPath.getCanonicalPath() + "/" + relPath); + FileExt fileExt = new FileExt(file); + if (file.isDirectory()) + { + if (listener != null && listener.isExcluded(file,rootFolderOfSources.getFile())) + continue; + + String[] children = file.list(); // Si está vacío el array está vacío pero existe + recursiveSourceFileJavaSearch(firstTime,scriptFileJavaCannonPath,rootFolderOfSourcesIndex,fileExt,children,sourceRegistry,updatedSourceFiles,newSourceFiles); + } + else + { + String ext = JProxyUtil.getFileExtension(file); // Si no tiene extensión devuelve "" + if (!"java".equals(ext)) continue; + //if (!"jsh".equals(ext)) continue; + + String cannonPath = JProxyUtil.getCanonicalPath(file); + if (scriptFileJavaCannonPath != null && scriptFileJavaCannonPath.equals(cannonPath)) + continue; // Es el propio archivo script inicial que es .java, así evitamos considerarlo dos veces + + if (listener != null && listener.isExcluded(file,rootFolderOfSources.getFile())) + continue; + + SourceFileJavaNormal sourceFile = new SourceFileJavaNormal(fileExt,rootFolderOfSources); + processSourceFileJava(firstTime,sourceFile,sourceRegistry,updatedSourceFiles,newSourceFiles); + } + } + } + + private ClassDescriptorSourceScript processSourceFileScript(boolean firstTime,SourceScriptRoot file,ClassDescriptorSourceFileRegistry sourceRegistry,LinkedList updatedSourceFiles,LinkedList newSourceFiles) + { + return (ClassDescriptorSourceScript)processSourceFile(firstTime,file,true,sourceRegistry,updatedSourceFiles,newSourceFiles); + } + + private ClassDescriptorSourceFileJava processSourceFileJava(boolean firstTime,SourceFileJavaNormal file,ClassDescriptorSourceFileRegistry sourceRegistry,LinkedList updatedSourceFiles,LinkedList newSourceFiles) + { + return (ClassDescriptorSourceFileJava)processSourceFile(firstTime,file,false,sourceRegistry,updatedSourceFiles,newSourceFiles); + } + + private ClassDescriptorSourceUnit processSourceFile(boolean firstTime,SourceUnit file,boolean script,ClassDescriptorSourceFileRegistry sourceRegistry,LinkedList updatedSourceFiles,LinkedList newSourceFiles) + { + JProxyEngine engine = parent.getJProxyEngine(); + String className = file.getClassName(); + + long timestampSourceFile = file.lastModified(); + ClassDescriptorSourceUnit sourceFile; + if (!firstTime) + { + Object monitor = engine.getMonitor(); + synchronized(monitor) + { + sourceFile = sourceRegistry.getClassDescriptorSourceUnit(className); + } + + if (sourceFile != null) // Cambiado + { + long oldTimestamp = sourceFile.getTimestamp(); + + if (timestampSourceFile > oldTimestamp) + { + synchronized(monitor) + { + sourceFile.updateTimestamp(timestampSourceFile); + } + updatedSourceFiles.add(sourceFile); + } + + sourceFile.setPendingToRemove( false ); // Encontrado, no se elimina porque sigue existiendo + } + else // Clase nueva + { + sourceFile = ClassDescriptorSourceUnit.create(script,engine,className,file,timestampSourceFile); + sourceFile.setPendingToRemove( false ); // Está ya por defecto pero para que quede claro + newSourceFiles.add(sourceFile); + } + } + else // Primera vez, vemos si el código fuente se ha cambiado respecto a los .class en el sistema de archivos + { + String relClassPath = ClassDescriptor.getRelativeClassFilePathFromClassName(className); + ClassLoader parentClassLoader = engine.getRootClassLoader(); + URL urlClass = parentClassLoader.getResource(relClassPath); + if (urlClass != null) + { + String urlClassExt = urlClass.toExternalForm(); + // Si el .class está en un JAR podríamos obtener el timestamp del archivo dentro del jar pero que haya un .java "fuera" reloadable indica que queremos "reemplazar" el del jar por lo que siempre se considerará que el archivo fuente ha sido modificado más reciente + long timestampCompiledClass = urlClassExt.startsWith("file:") ? new File(urlClass.getPath()).lastModified() : 0; // 0 cuando está en un JAR + + if (timestampSourceFile > timestampCompiledClass) + { + sourceFile = ClassDescriptorSourceUnit.create(script,engine,className,file,timestampSourceFile); + updatedSourceFiles.add(sourceFile); // Hay que recompilar +//System.out.println("UPDATED: " + className + " " + urlClass.toExternalForm() + " " + (timestampSourceFile - timestampCompiledClass)); + } + else + { + // Esto es lo normal en carga si no hemos tocado el código tras el deploy, que el .class sea más reciente que el .java + sourceFile = ClassDescriptorSourceUnit.create(script,engine,className,file,timestampCompiledClass); + byte[] classBytes = JProxyUtil.readURL(urlClass); + sourceFile.setClassBytes(classBytes); + // Falta cargar las posibles inner classes, hay que tener en cuenta que este archivo NO se va a compilar porque no ha cambiado respecto a .class conocido +//System.out.println("NOT UPDATED: " + className + " " + urlClass.toExternalForm() + " " + (timestampSourceFile - timestampCompiledClass)); + } + + } + else // No hay .class, es un archivo fuente nuevo creado antes de cargar la app web, hay que compilar si o si + { + sourceFile = ClassDescriptorSourceUnit.create(script,engine,className,file,timestampSourceFile); + newSourceFiles.add(sourceFile); + } + + Object monitor = engine.getMonitor(); + synchronized(monitor) + { + sourceRegistry.addClassDescriptorSourceUnit(sourceFile); // El registro de archivos se hace por primera vez por lo que hay que añadirlos todos inicialmente, updatedSourceFiles y newSourceFiles indicarán en este caso los que hay que recompilar además + } + } + + return sourceFile; + } + +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java similarity index 97% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java index 233b2c3..11c443d 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java @@ -1,115 +1,115 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc; - -import java.io.File; - -/** - * - * @author jmarranz - */ -public abstract class ClassDescriptor -{ - protected final String className; // El nombre basado en puntos pero usando $ en el caso de innerclasses - protected final String simpleClassName; // className sin el package - protected final String packageName; // El package pero acabado en un "." o bien "" si no hay package, el motivo de acabar en un punto es simplemente para poder concatenar ciegamente el package y el simpleClassName - protected byte[] classBytes; - protected Class clasz; - - public ClassDescriptor(String className) - { - this.className = className; - int pos = className.lastIndexOf('.'); - this.simpleClassName = (pos != -1) ? className.substring(pos + 1) : className; - this.packageName = (pos != -1) ? className.substring(0,pos + 1) : ""; // SE INCLUYE EL . en el caso de existir package - } - - public abstract boolean isInnerClass(); - - public String getClassName() - { - return className; - } - - public String getSimpleClassName() - { - return simpleClassName; - } - - public String getPackageName() - { - return packageName; - } - - public byte[] getClassBytes() - { - return classBytes; - } - - public void setClassBytes(byte[] classBytes) - { - this.classBytes = classBytes; - } - - public Class getLastLoadedClass() - { - return clasz; - } - - public void setLastLoadedClass(Class clasz) - { - this.clasz = clasz; - } - - public void resetLastLoadedClass() - { - setLastLoadedClass(null); - } - - /* - public String getClassFileNameFromClassName() - { - return getClassFileNameFromClassName(className); - } - */ - - public static String getClassFileNameFromClassName(String className) - { - // Es válido también para las innerclasses (ej Nombre$Otro => Nombre$Otro.class, Nombre$1 => Nombre$1.class, Nombre$1Nombre => Nombre$1Nombre.class - int pos = className.lastIndexOf("."); - if(pos != -1) className = className.substring(pos + 1); - return className + ".class"; - } - - public static String getRelativeClassFilePathFromClassName(String className) - { - return className.replace('.','/') + ".class"; // alternativa: className.replaceAll("\\.", "/") + ".class" - } - - public static String getRelativePackagePathFromClassName(String className) - { - String packageName = className.replace('.','/'); - int pos = packageName.lastIndexOf('/'); - if (pos == -1) return packageName; - return packageName.substring(0,pos); - } - - public static File getAbsoluteClassFilePathFromClassNameAndClassPath(String className,String classPath) - { - String relativePath = getRelativeClassFilePathFromClassName(className); - classPath = classPath.trim(); - if (!classPath.endsWith("/") && !classPath.endsWith("\\")) classPath += File.separatorChar; - return new File(classPath + relativePath); - } - - public static String getClassNameFromRelativeClassFilePath(String path) - { - // Ej. org/w3c/dom/Element.class => org.w3c.dom.Element - String binaryName = path.replaceAll("/", "."); - return binaryName.replaceAll(".class$", ""); // El $ indica "el .class del final" - } - - public static String getClassNameFromPackageAndClassFileName(String packageName,String fileName) - { - String className = packageName + "." + fileName; - return className.replaceAll(".class$", ""); // El $ indica "el .class del final" - } -} +package com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc; + +import java.io.File; + +/** + * + * @author jmarranz + */ +public abstract class ClassDescriptor +{ + protected final String className; // El nombre basado en puntos pero usando $ en el caso de innerclasses + protected final String simpleClassName; // className sin el package + protected final String packageName; // El package pero acabado en un "." o bien "" si no hay package, el motivo de acabar en un punto es simplemente para poder concatenar ciegamente el package y el simpleClassName + protected byte[] classBytes; + protected Class clasz; + + public ClassDescriptor(String className) + { + this.className = className; + int pos = className.lastIndexOf('.'); + this.simpleClassName = (pos != -1) ? className.substring(pos + 1) : className; + this.packageName = (pos != -1) ? className.substring(0,pos + 1) : ""; // SE INCLUYE EL . en el caso de existir package + } + + public abstract boolean isInnerClass(); + + public String getClassName() + { + return className; + } + + public String getSimpleClassName() + { + return simpleClassName; + } + + public String getPackageName() + { + return packageName; + } + + public byte[] getClassBytes() + { + return classBytes; + } + + public void setClassBytes(byte[] classBytes) + { + this.classBytes = classBytes; + } + + public Class getLastLoadedClass() + { + return clasz; + } + + public void setLastLoadedClass(Class clasz) + { + this.clasz = clasz; + } + + public void resetLastLoadedClass() + { + setLastLoadedClass(null); + } + + /* + public String getClassFileNameFromClassName() + { + return getClassFileNameFromClassName(className); + } + */ + + public static String getClassFileNameFromClassName(String className) + { + // Es válido también para las innerclasses (ej Nombre$Otro => Nombre$Otro.class, Nombre$1 => Nombre$1.class, Nombre$1Nombre => Nombre$1Nombre.class + int pos = className.lastIndexOf("."); + if(pos != -1) className = className.substring(pos + 1); + return className + ".class"; + } + + public static String getRelativeClassFilePathFromClassName(String className) + { + return className.replace('.','/') + ".class"; // alternativa: className.replaceAll("\\.", "/") + ".class" + } + + public static String getRelativePackagePathFromClassName(String className) + { + String packageName = className.replace('.','/'); + int pos = packageName.lastIndexOf('/'); + if (pos == -1) return packageName; + return packageName.substring(0,pos); + } + + public static File getAbsoluteClassFilePathFromClassNameAndClassPath(String className,String classPath) + { + String relativePath = getRelativeClassFilePathFromClassName(className); + classPath = classPath.trim(); + if (!classPath.endsWith("/") && !classPath.endsWith("\\")) classPath += File.separatorChar; + return new File(classPath + relativePath); + } + + public static String getClassNameFromRelativeClassFilePath(String path) + { + // Ej. org/w3c/dom/Element.class => org.w3c.dom.Element + String binaryName = path.replaceAll("/", "."); + return binaryName.replaceAll(".class$", ""); // El $ indica "el .class del final" + } + + public static String getClassNameFromPackageAndClassFileName(String packageName,String fileName) + { + String className = packageName + "." + fileName; + return className.replaceAll(".class$", ""); // El $ indica "el .class del final" + } +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java similarity index 95% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java index c1c41ba..d78d72b 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java @@ -1,27 +1,27 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc; - -/** - * - * @author jmarranz - */ -public class ClassDescriptorInner extends ClassDescriptor -{ - protected final ClassDescriptorSourceUnit parent; - - public ClassDescriptorInner(String className,ClassDescriptorSourceUnit parent) - { - super(className); - this.parent = parent; - } - - @Override - public boolean isInnerClass() - { - return true; - } - - public ClassDescriptorSourceUnit getClassDescriptorSourceUnit() - { - return parent; - } -} +package com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc; + +/** + * + * @author jmarranz + */ +public class ClassDescriptorInner extends ClassDescriptor +{ + protected final ClassDescriptorSourceUnit parent; + + public ClassDescriptorInner(String className,ClassDescriptorSourceUnit parent) + { + super(className); + this.parent = parent; + } + + @Override + public boolean isInnerClass() + { + return true; + } + + public ClassDescriptorSourceUnit getClassDescriptorSourceUnit() + { + return parent; + } +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java similarity index 96% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java index 598d539..0586c19 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java @@ -1,28 +1,28 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc; - -import com.innowhere.relproxy.impl.FileExt; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; - -/** - * - * @author jmarranz - */ -public class ClassDescriptorSourceFileJava extends ClassDescriptorSourceUnit -{ - public ClassDescriptorSourceFileJava(JProxyEngine engine,String className, SourceFileJavaNormal sourceFile, long timestamp) - { - super(engine,className, sourceFile, timestamp); - } - - public SourceFileJavaNormal getSourceFileJavaNormal() - { - return (SourceFileJavaNormal)sourceUnit; - } - - public FileExt getSourceFile() - { - return getSourceFileJavaNormal().getFileExt(); - } - -} +package com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc; + +import com.innowhere.relproxy.impl.FileExt; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; + +/** + * + * @author jmarranz + */ +public class ClassDescriptorSourceFileJava extends ClassDescriptorSourceUnit +{ + public ClassDescriptorSourceFileJava(JProxyEngine engine,String className, SourceFileJavaNormal sourceFile, long timestamp) + { + super(engine,className, sourceFile, timestamp); + } + + public SourceFileJavaNormal getSourceFileJavaNormal() + { + return (SourceFileJavaNormal)sourceUnit; + } + + public FileExt getSourceFile() + { + return getSourceFileJavaNormal().getFileExt(); + } + +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java similarity index 97% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java index d3108cd..ba2e1d7 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java @@ -1,92 +1,92 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc; - -import java.util.Collection; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.Map; - -/** - * - * @author jmarranz - */ -public class ClassDescriptorSourceFileRegistry -{ - protected final Map sourceUnitMapByClassName; - - public ClassDescriptorSourceFileRegistry() - { - this.sourceUnitMapByClassName = new HashMap(); - } - - public ClassDescriptorSourceFileRegistry(ClassDescriptorSourceFileRegistry origin) - { - this.sourceUnitMapByClassName = new HashMap( origin.sourceUnitMapByClassName ); - } - - public boolean isEmpty() - { - return sourceUnitMapByClassName.isEmpty(); - } - - public Collection getClassDescriptorSourceFileColl() - { - return sourceUnitMapByClassName.values(); - } - - public ClassDescriptorSourceUnit getClassDescriptorSourceUnit(String className) - { - return sourceUnitMapByClassName.get(className); - } - - public ClassDescriptorSourceUnit removeClassDescriptorSourceUnit(String className) - { - return sourceUnitMapByClassName.remove(className); - } - - public void addClassDescriptorSourceUnit(ClassDescriptorSourceUnit sourceFile) - { - sourceUnitMapByClassName.put(sourceFile.getClassName(), sourceFile); - } - - public void setAllClassDescriptorSourceFilesPendingToRemove(boolean pending) - { - for(Map.Entry entries : sourceUnitMapByClassName.entrySet()) - entries.getValue().setPendingToRemove(pending); - } - - public LinkedList getAllClassDescriptorSourceFilesPendingToRemove(LinkedList deletedSourceFiles) - { - for(Map.Entry entries : sourceUnitMapByClassName.entrySet()) - { - ClassDescriptorSourceUnit classDesc = entries.getValue(); - boolean pending = classDesc.isPendingToRemove(); - if (pending) - deletedSourceFiles.add(classDesc); - } - return deletedSourceFiles; - } - - public ClassDescriptor getClassDescriptor(String className) - { - // Puede ser el de una innerclass - // Las innerclasses no están como tales en sourceFileMap pues sólo está la clase contenedora pero también la consideramos hotloadable - String parentClassName; - int pos = className.lastIndexOf('$'); - boolean inner; - if (pos != -1) - { - parentClassName = className.substring(0, pos); - inner = true; - } - else - { - parentClassName = className; - inner = false; - } - ClassDescriptorSourceUnit sourceDesc = sourceUnitMapByClassName.get(parentClassName); - if (sourceDesc == null) - return null; - if (!inner) return sourceDesc; - return sourceDesc.getInnerClassDescriptor(className,true); - } -} +package com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc; + +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; + +/** + * + * @author jmarranz + */ +public class ClassDescriptorSourceFileRegistry +{ + protected final Map sourceUnitMapByClassName; + + public ClassDescriptorSourceFileRegistry() + { + this.sourceUnitMapByClassName = new HashMap(); + } + + public ClassDescriptorSourceFileRegistry(ClassDescriptorSourceFileRegistry origin) + { + this.sourceUnitMapByClassName = new HashMap( origin.sourceUnitMapByClassName ); + } + + public boolean isEmpty() + { + return sourceUnitMapByClassName.isEmpty(); + } + + public Collection getClassDescriptorSourceFileColl() + { + return sourceUnitMapByClassName.values(); + } + + public ClassDescriptorSourceUnit getClassDescriptorSourceUnit(String className) + { + return sourceUnitMapByClassName.get(className); + } + + public ClassDescriptorSourceUnit removeClassDescriptorSourceUnit(String className) + { + return sourceUnitMapByClassName.remove(className); + } + + public void addClassDescriptorSourceUnit(ClassDescriptorSourceUnit sourceFile) + { + sourceUnitMapByClassName.put(sourceFile.getClassName(), sourceFile); + } + + public void setAllClassDescriptorSourceFilesPendingToRemove(boolean pending) + { + for(Map.Entry entries : sourceUnitMapByClassName.entrySet()) + entries.getValue().setPendingToRemove(pending); + } + + public LinkedList getAllClassDescriptorSourceFilesPendingToRemove(LinkedList deletedSourceFiles) + { + for(Map.Entry entries : sourceUnitMapByClassName.entrySet()) + { + ClassDescriptorSourceUnit classDesc = entries.getValue(); + boolean pending = classDesc.isPendingToRemove(); + if (pending) + deletedSourceFiles.add(classDesc); + } + return deletedSourceFiles; + } + + public ClassDescriptor getClassDescriptor(String className) + { + // Puede ser el de una innerclass + // Las innerclasses no están como tales en sourceFileMap pues sólo está la clase contenedora pero también la consideramos hotloadable + String parentClassName; + int pos = className.lastIndexOf('$'); + boolean inner; + if (pos != -1) + { + parentClassName = className.substring(0, pos); + inner = true; + } + else + { + parentClassName = className; + inner = false; + } + ClassDescriptorSourceUnit sourceDesc = sourceUnitMapByClassName.get(parentClassName); + if (sourceDesc == null) + return null; + if (!inner) return sourceDesc; + return sourceDesc.getInnerClassDescriptor(className,true); + } +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java similarity index 97% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java index e4790e1..780c575 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java @@ -1,184 +1,184 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc; - -import com.innowhere.relproxy.RelProxyException; -import com.innowhere.relproxy.impl.jproxy.core.JProxyImpl; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.LinkedList; -import javax.script.ScriptContext; -import javax.script.ScriptEngine; - -/** - * - * @author jmarranz - */ -public class ClassDescriptorSourceScript extends ClassDescriptorSourceUnit -{ - protected String source; - - public ClassDescriptorSourceScript(JProxyEngine engine,String className,SourceScriptRoot sourceFile,long timestamp) - { - super(engine,className, sourceFile, timestamp); - - generateSourceCode(); - } - - - public SourceScriptRoot getSourceScript() - { - return (SourceScriptRoot)sourceUnit; - } - - private void generateSourceCode() - { - boolean[] hasHashBang = new boolean[1]; - - String scriptCode = getSourceScript().getScriptCode(getEncoding(),hasHashBang); - - boolean completeClass = isCompleteClass(scriptCode); - - StringBuilder finalCode = new StringBuilder(); - if (completeClass) - { - if (hasHashBang[0]) finalCode.append("\n"); // Como hemos quitado la línea #! añadimos una nueva para que los números de línea en caso de error coincidan con el original - finalCode.append(scriptCode); - } - else - { - JProxyImpl jproxy = engine.getJProxy(); - String mainParamsDec = null; - String mainReturnType = null; - - Class mainParamClass = jproxy.getMainParamClass(); - if (mainParamClass.equals(String[].class)) - { - mainParamsDec = "String[] args"; - mainReturnType = "void"; - } - else if (mainParamClass.equals(ScriptContext.class)) - { - mainParamsDec = ScriptEngine.class.getName() + " engine," + ScriptContext.class.getName() + " context"; - mainReturnType = "Object"; - - if (scriptCode.equals("")) scriptCode = "return null;"; - } - - finalCode.append("public class " + className + " { public static " + mainReturnType + " main(" + mainParamsDec + ") {\n"); // Lo ponemos todo en una línea para que en caso de error la línea de error coincida con el script original pues hemos quitado la primera línea #! - finalCode.append(scriptCode); - finalCode.append(" }\n"); - finalCode.append("}\n"); - } - this.source = finalCode.toString(); - } - - private boolean isCompleteClass(String code) - { - // Buscamos si hay un " class ..." o un "import..." al comienzo para soportar la definición de una clase completa como script - int pos = code.indexOf("class"); - if (pos == -1) return false; - // Hay al menos un "class", ojo que puede ser parte de una variable o dentro de un comentario, pero si no existiera desde luego que no es clase completa - - pos = getFirstPosIgnoringCommentsAndSeparators(code); - if (pos == -1) return false; - - // Lo primero que nos tenemos encontrar es un import o una declaración de class - int pos2 = code.indexOf("import",pos); - if (pos2 == pos) - return true; // Si hay un import hay declaración de clase - - // Vemos si es un "public class..." o similar - int posClass = code.indexOf("class", pos); - String visibility = code.substring(pos, posClass); - visibility = visibility.trim(); // No consideramos \n hay que ser retorcido poner un \n entre el public y el class por ejemplo - if (visibility.isEmpty()) return true; // No hay visibilidad, que no compile no es cosa nuestra - return ("private".equals(visibility) || "public".equals(visibility) || "protected".equals(visibility)); - } - - private int getFirstPosIgnoringCommentsAndSeparators(String code) - { - int i = -1; - for(i = 0; i < code.length(); i++) - { - char c = code.charAt(i); - if (c == ' ' || c == '\n' || c == '\t') continue; - else if (c == '/' && i + 1 < code.length()) - { - char c2 = code.charAt(i + 1); - if (c2 == '/') - { - i = getFirstPosIgnoringOneLineComment(code,i); - if (i == -1) return -1; // Comentario mal formado - } - else if (c2 == '*') - { - i = getFirstPosIgnoringMultiLineComment(code,i); - if (i == -1) return -1; // Comentario mal formado - } - } - else break; - } - return i; - } - - private int getFirstPosIgnoringOneLineComment(String code,int start) - { - return code.indexOf('\n',start); - } - - private int getFirstPosIgnoringMultiLineComment(String code,int start) - { - return code.indexOf("*/", start); - } - - @Override - public void updateTimestamp(long timestamp) - { - long oldTimestamp = this.timestamp; - if (oldTimestamp != timestamp) - generateSourceCode(); - super.updateTimestamp(timestamp); - } - - public String getSourceCode() - { - return source; - } - - public void callMainMethod(LinkedList argsToScript) throws Throwable - { - try - { - Class scriptClass = getLastLoadedClass(); - Method method = scriptClass.getDeclaredMethod("main",new Class[]{ String[].class }); - String[] argsToScriptArr = argsToScript.size() > 0 ? argsToScript.toArray(new String[argsToScript.size()]) : new String[0]; - method.invoke(null, new Object[]{ argsToScriptArr }); - } - catch (IllegalAccessException ex) { throw new RelProxyException(ex); } - catch (NoSuchMethodException ex) { throw new RelProxyException(ex); } - catch (SecurityException ex) { throw new RelProxyException(ex); } - catch (IllegalArgumentException ex) { throw new RelProxyException(ex); } - catch (InvocationTargetException ex) { throw ex.getCause(); } // Los errores de ejecución se envuelven en un InvocationTargetException - } - - public Object callMainMethod(ScriptEngine engine,ScriptContext context) throws Throwable - { - Class scriptClass = getLastLoadedClass(); - return callMainMethod(scriptClass,engine,context); - } - - public static Object callMainMethod(Class scriptClass,ScriptEngine engine,ScriptContext context) throws Throwable - { - try - { - Method method = scriptClass.getDeclaredMethod("main",new Class[]{ ScriptEngine.class,ScriptContext.class }); - return method.invoke(null, new Object[]{ engine, context }); - } - catch (IllegalAccessException ex) { throw new RelProxyException(ex); } - catch (NoSuchMethodException ex) { throw new RelProxyException(ex); } - catch (SecurityException ex) { throw new RelProxyException(ex); } - catch (IllegalArgumentException ex) { throw new RelProxyException(ex); } - catch (InvocationTargetException ex) { throw ex.getCause(); } // Los errores de ejecución se envuelven en un InvocationTargetException - } -} +package com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc; + +import com.innowhere.relproxy.RelProxyException; +import com.innowhere.relproxy.impl.jproxy.core.JProxyImpl; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.LinkedList; +import javax.script.ScriptContext; +import javax.script.ScriptEngine; + +/** + * + * @author jmarranz + */ +public class ClassDescriptorSourceScript extends ClassDescriptorSourceUnit +{ + protected String source; + + public ClassDescriptorSourceScript(JProxyEngine engine,String className,SourceScriptRoot sourceFile,long timestamp) + { + super(engine,className, sourceFile, timestamp); + + generateSourceCode(); + } + + + public SourceScriptRoot getSourceScript() + { + return (SourceScriptRoot)sourceUnit; + } + + private void generateSourceCode() + { + boolean[] hasHashBang = new boolean[1]; + + String scriptCode = getSourceScript().getScriptCode(getEncoding(),hasHashBang); + + boolean completeClass = isCompleteClass(scriptCode); + + StringBuilder finalCode = new StringBuilder(); + if (completeClass) + { + if (hasHashBang[0]) finalCode.append("\n"); // Como hemos quitado la línea #! añadimos una nueva para que los números de línea en caso de error coincidan con el original + finalCode.append(scriptCode); + } + else + { + JProxyImpl jproxy = engine.getJProxy(); + String mainParamsDec = null; + String mainReturnType = null; + + Class mainParamClass = jproxy.getMainParamClass(); + if (mainParamClass.equals(String[].class)) + { + mainParamsDec = "String[] args"; + mainReturnType = "void"; + } + else if (mainParamClass.equals(ScriptContext.class)) + { + mainParamsDec = ScriptEngine.class.getName() + " engine," + ScriptContext.class.getName() + " context"; + mainReturnType = "Object"; + + if (scriptCode.equals("")) scriptCode = "return null;"; + } + + finalCode.append("public class " + className + " { public static " + mainReturnType + " main(" + mainParamsDec + ") {\n"); // Lo ponemos todo en una línea para que en caso de error la línea de error coincida con el script original pues hemos quitado la primera línea #! + finalCode.append(scriptCode); + finalCode.append(" }\n"); + finalCode.append("}\n"); + } + this.source = finalCode.toString(); + } + + private boolean isCompleteClass(String code) + { + // Buscamos si hay un " class ..." o un "import..." al comienzo para soportar la definición de una clase completa como script + int pos = code.indexOf("class"); + if (pos == -1) return false; + // Hay al menos un "class", ojo que puede ser parte de una variable o dentro de un comentario, pero si no existiera desde luego que no es clase completa + + pos = getFirstPosIgnoringCommentsAndSeparators(code); + if (pos == -1) return false; + + // Lo primero que nos tenemos encontrar es un import o una declaración de class + int pos2 = code.indexOf("import",pos); + if (pos2 == pos) + return true; // Si hay un import hay declaración de clase + + // Vemos si es un "public class..." o similar + int posClass = code.indexOf("class", pos); + String visibility = code.substring(pos, posClass); + visibility = visibility.trim(); // No consideramos \n hay que ser retorcido poner un \n entre el public y el class por ejemplo + if (visibility.isEmpty()) return true; // No hay visibilidad, que no compile no es cosa nuestra + return ("private".equals(visibility) || "public".equals(visibility) || "protected".equals(visibility)); + } + + private int getFirstPosIgnoringCommentsAndSeparators(String code) + { + int i = -1; + for(i = 0; i < code.length(); i++) + { + char c = code.charAt(i); + if (c == ' ' || c == '\n' || c == '\t') continue; + else if (c == '/' && i + 1 < code.length()) + { + char c2 = code.charAt(i + 1); + if (c2 == '/') + { + i = getFirstPosIgnoringOneLineComment(code,i); + if (i == -1) return -1; // Comentario mal formado + } + else if (c2 == '*') + { + i = getFirstPosIgnoringMultiLineComment(code,i); + if (i == -1) return -1; // Comentario mal formado + } + } + else break; + } + return i; + } + + private int getFirstPosIgnoringOneLineComment(String code,int start) + { + return code.indexOf('\n',start); + } + + private int getFirstPosIgnoringMultiLineComment(String code,int start) + { + return code.indexOf("*/", start); + } + + @Override + public void updateTimestamp(long timestamp) + { + long oldTimestamp = this.timestamp; + if (oldTimestamp != timestamp) + generateSourceCode(); + super.updateTimestamp(timestamp); + } + + public String getSourceCode() + { + return source; + } + + public void callMainMethod(LinkedList argsToScript) throws Throwable + { + try + { + Class scriptClass = getLastLoadedClass(); + Method method = scriptClass.getDeclaredMethod("main",new Class[]{ String[].class }); + String[] argsToScriptArr = argsToScript.size() > 0 ? argsToScript.toArray(new String[argsToScript.size()]) : new String[0]; + method.invoke(null, new Object[]{ argsToScriptArr }); + } + catch (IllegalAccessException ex) { throw new RelProxyException(ex); } + catch (NoSuchMethodException ex) { throw new RelProxyException(ex); } + catch (SecurityException ex) { throw new RelProxyException(ex); } + catch (IllegalArgumentException ex) { throw new RelProxyException(ex); } + catch (InvocationTargetException ex) { throw ex.getCause(); } // Los errores de ejecución se envuelven en un InvocationTargetException + } + + public Object callMainMethod(ScriptEngine engine,ScriptContext context) throws Throwable + { + Class scriptClass = getLastLoadedClass(); + return callMainMethod(scriptClass,engine,context); + } + + public static Object callMainMethod(Class scriptClass,ScriptEngine engine,ScriptContext context) throws Throwable + { + try + { + Method method = scriptClass.getDeclaredMethod("main",new Class[]{ ScriptEngine.class,ScriptContext.class }); + return method.invoke(null, new Object[]{ engine, context }); + } + catch (IllegalAccessException ex) { throw new RelProxyException(ex); } + catch (NoSuchMethodException ex) { throw new RelProxyException(ex); } + catch (SecurityException ex) { throw new RelProxyException(ex); } + catch (IllegalArgumentException ex) { throw new RelProxyException(ex); } + catch (InvocationTargetException ex) { throw ex.getCause(); } // Los errores de ejecución se envuelven en un InvocationTargetException + } +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java similarity index 96% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java index f975152..3e2c858 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java @@ -1,146 +1,146 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc; - -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceUnit; -import java.util.LinkedList; - -/** - * - * @author jmarranz - */ -public abstract class ClassDescriptorSourceUnit extends ClassDescriptor -{ - protected final JProxyEngine engine; - protected volatile long timestamp; - protected final SourceUnit sourceUnit; - protected LinkedList innerClasses; - protected boolean pendingToRemove = false; // Se usa como monohilo, no hay problemas de sincronización - - public ClassDescriptorSourceUnit(JProxyEngine engine,String className,SourceUnit sourceFile, long timestamp) - { - super(className); - this.engine = engine; - this.sourceUnit = sourceFile; - this.timestamp = timestamp; - } - - public static ClassDescriptorSourceUnit create(boolean script,JProxyEngine engine,String className,SourceUnit sourceFile, long timestamp) - { - if (sourceFile instanceof SourceScriptRoot) - return new ClassDescriptorSourceScript(engine,className,(SourceScriptRoot)sourceFile,timestamp); - else if (sourceFile instanceof SourceFileJavaNormal) - return new ClassDescriptorSourceFileJava(engine,className,(SourceFileJavaNormal)sourceFile,timestamp); - else - return null; // WTF!! - } - - public SourceUnit getSourceUnit() - { - return sourceUnit; - } - - public String getEncoding() - { - return engine.getSourceEncoding(); - } - - @Override - public boolean isInnerClass() - { - return false; - } - - public long getTimestamp() - { - return timestamp; - } - - public void updateTimestamp(long timestamp) - { - this.timestamp = timestamp; - } - - public boolean isPendingToRemove() - { - return pendingToRemove; - } - - public void setPendingToRemove(boolean pendingToRemove) - { - this.pendingToRemove = pendingToRemove; - } - - - public void cleanOnSourceCodeChanged() - { - // Como ha cambiado la clase, reseteamos las dependencias - setClassBytes(null); - setLastLoadedClass(null); - clearInnerClassDescriptors(); // El código fuente nuevo puede haber cambiado totalmente las innerclasses antiguas (añadido, eliminado) - } - - public boolean isInnerClass(String className) - { - int pos = className.lastIndexOf('$'); - if (pos == -1) - return false; // No es innerclass - String baseClassName = className.substring(0, pos); - return this.className.equals(baseClassName); // Si es false es que es una innerclass pero de otra clase - } - - public LinkedList getInnerClassDescriptors() - { - return innerClasses; - } - - public void clearInnerClassDescriptors() - { - if (innerClasses != null) - innerClasses.clear(); - } - - public ClassDescriptorInner getInnerClassDescriptor(String className,boolean addWhenMissing) - { - if (innerClasses != null) - { - for(ClassDescriptorInner classDesc : innerClasses) - { - if (classDesc.getClassName().equals(className)) - return classDesc; - } - } - - if (!addWhenMissing) return null; - - return addInnerClassDescriptor(className); - } - - public ClassDescriptorInner addInnerClassDescriptor(String className) - { - if (!isInnerClass(className)) - return null; - - if (innerClasses == null) - innerClasses = new LinkedList(); - - ClassDescriptorInner classDesc = new ClassDescriptorInner(className,this); - innerClasses.add(classDesc); - return classDesc; - } - - @Override - public void resetLastLoadedClass() - { - super.resetLastLoadedClass(); - - LinkedList innerClassDescList = getInnerClassDescriptors(); - if (innerClassDescList != null) - { - for(ClassDescriptorInner innerClassDesc : innerClassDescList) - innerClassDesc.resetLastLoadedClass(); - } - } - -} +package com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc; + +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceUnit; +import java.util.LinkedList; + +/** + * + * @author jmarranz + */ +public abstract class ClassDescriptorSourceUnit extends ClassDescriptor +{ + protected final JProxyEngine engine; + protected volatile long timestamp; + protected final SourceUnit sourceUnit; + protected LinkedList innerClasses; + protected boolean pendingToRemove = false; // Se usa como monohilo, no hay problemas de sincronización + + public ClassDescriptorSourceUnit(JProxyEngine engine,String className,SourceUnit sourceFile, long timestamp) + { + super(className); + this.engine = engine; + this.sourceUnit = sourceFile; + this.timestamp = timestamp; + } + + public static ClassDescriptorSourceUnit create(boolean script,JProxyEngine engine,String className,SourceUnit sourceFile, long timestamp) + { + if (sourceFile instanceof SourceScriptRoot) + return new ClassDescriptorSourceScript(engine,className,(SourceScriptRoot)sourceFile,timestamp); + else if (sourceFile instanceof SourceFileJavaNormal) + return new ClassDescriptorSourceFileJava(engine,className,(SourceFileJavaNormal)sourceFile,timestamp); + else + return null; // WTF!! + } + + public SourceUnit getSourceUnit() + { + return sourceUnit; + } + + public String getEncoding() + { + return engine.getSourceEncoding(); + } + + @Override + public boolean isInnerClass() + { + return false; + } + + public long getTimestamp() + { + return timestamp; + } + + public void updateTimestamp(long timestamp) + { + this.timestamp = timestamp; + } + + public boolean isPendingToRemove() + { + return pendingToRemove; + } + + public void setPendingToRemove(boolean pendingToRemove) + { + this.pendingToRemove = pendingToRemove; + } + + + public void cleanOnSourceCodeChanged() + { + // Como ha cambiado la clase, reseteamos las dependencias + setClassBytes(null); + setLastLoadedClass(null); + clearInnerClassDescriptors(); // El código fuente nuevo puede haber cambiado totalmente las innerclasses antiguas (añadido, eliminado) + } + + public boolean isInnerClass(String className) + { + int pos = className.lastIndexOf('$'); + if (pos == -1) + return false; // No es innerclass + String baseClassName = className.substring(0, pos); + return this.className.equals(baseClassName); // Si es false es que es una innerclass pero de otra clase + } + + public LinkedList getInnerClassDescriptors() + { + return innerClasses; + } + + public void clearInnerClassDescriptors() + { + if (innerClasses != null) + innerClasses.clear(); + } + + public ClassDescriptorInner getInnerClassDescriptor(String className,boolean addWhenMissing) + { + if (innerClasses != null) + { + for(ClassDescriptorInner classDesc : innerClasses) + { + if (classDesc.getClassName().equals(className)) + return classDesc; + } + } + + if (!addWhenMissing) return null; + + return addInnerClassDescriptor(className); + } + + public ClassDescriptorInner addInnerClassDescriptor(String className) + { + if (!isInnerClass(className)) + return null; + + if (innerClasses == null) + innerClasses = new LinkedList(); + + ClassDescriptorInner classDesc = new ClassDescriptorInner(className,this); + innerClasses.add(classDesc); + return classDesc; + } + + @Override + public void resetLastLoadedClass() + { + super.resetLastLoadedClass(); + + LinkedList innerClassDescList = getInnerClassDescriptors(); + if (innerClassDescList != null) + { + for(ClassDescriptorInner innerClassDesc : innerClassDescList) + innerClassDesc.resetLastLoadedClass(); + } + } + +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java similarity index 96% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java index d72ab12..7bf171a 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java @@ -1,25 +1,25 @@ - -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp; - -import com.innowhere.relproxy.RelProxyException; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; - -/** - * - * @author jmarranz - */ -public class JProxyCompilationException extends RelProxyException -{ - protected ClassDescriptorSourceUnit sourceUnit; - - public JProxyCompilationException(ClassDescriptorSourceUnit sourceUnit) - { - super("Compilation error"); - this.sourceUnit = sourceUnit; - } - - public ClassDescriptorSourceUnit getClassDescriptorSourceUnit() - { - return sourceUnit; - } -} + +package com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp; + +import com.innowhere.relproxy.RelProxyException; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; + +/** + * + * @author jmarranz + */ +public class JProxyCompilationException extends RelProxyException +{ + protected ClassDescriptorSourceUnit sourceUnit; + + public JProxyCompilationException(ClassDescriptorSourceUnit sourceUnit) + { + super("Compilation error"); + this.sourceUnit = sourceUnit; + } + + public ClassDescriptorSourceUnit getClassDescriptorSourceUnit() + { + return sourceUnit; + } +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java similarity index 97% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java index ebbfc36..ab483ec 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java @@ -1,71 +1,71 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp; - -import com.innowhere.relproxy.RelProxyException; -import com.innowhere.relproxy.jproxy.JProxyDiagnosticsListener; -import java.io.IOException; -import java.util.List; -import javax.tools.Diagnostic; -import javax.tools.DiagnosticCollector; -import javax.tools.JavaFileObject; -import javax.tools.StandardJavaFileManager; - -/** - * - * @author jmarranz - */ -public class JProxyCompilerContext -{ - protected StandardJavaFileManager standardFileManager; - protected DiagnosticCollector diagnostics; - protected JProxyDiagnosticsListener diagnosticsListener; - - public JProxyCompilerContext(StandardJavaFileManager standardFileManager,DiagnosticCollector diagnostics,JProxyDiagnosticsListener diagnosticsListener) - { - this.standardFileManager = standardFileManager; - this.diagnostics = diagnostics; - this.diagnosticsListener = diagnosticsListener; - } - - public StandardJavaFileManager getStandardFileManager() - { - return standardFileManager; - } - - public DiagnosticCollector getDiagnosticCollector() - { - return diagnostics; - } - - public void close() - { - try { this.standardFileManager.close(); } - catch (IOException ex) { throw new RelProxyException(ex); } - - List> diagList = diagnostics.getDiagnostics(); - if (!diagList.isEmpty()) - { - if (diagnosticsListener != null) - { - diagnosticsListener.onDiagnostics(diagnostics); - } - else - { - int i = 1; - for (Diagnostic diagnostic : diagList) - { - System.err.println("Diagnostic " + i); - System.err.println(" code: " + diagnostic.getCode()); - System.err.println(" kind: " + diagnostic.getKind()); - System.err.println(" line number: " + diagnostic.getLineNumber()); - System.err.println(" column number: " + diagnostic.getColumnNumber()); - System.err.println(" start position: " + diagnostic.getStartPosition()); - System.err.println(" position: " + diagnostic.getPosition()); - System.err.println(" end position: " + diagnostic.getEndPosition()); - System.err.println(" source: " + diagnostic.getSource()); - System.err.println(" message: " + diagnostic.getMessage(null)); - i++; - } - } - } - } -} +package com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp; + +import com.innowhere.relproxy.RelProxyException; +import com.innowhere.relproxy.jproxy.JProxyDiagnosticsListener; +import java.io.IOException; +import java.util.List; +import javax.tools.Diagnostic; +import javax.tools.DiagnosticCollector; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; + +/** + * + * @author jmarranz + */ +public class JProxyCompilerContext +{ + protected StandardJavaFileManager standardFileManager; + protected DiagnosticCollector diagnostics; + protected JProxyDiagnosticsListener diagnosticsListener; + + public JProxyCompilerContext(StandardJavaFileManager standardFileManager,DiagnosticCollector diagnostics,JProxyDiagnosticsListener diagnosticsListener) + { + this.standardFileManager = standardFileManager; + this.diagnostics = diagnostics; + this.diagnosticsListener = diagnosticsListener; + } + + public StandardJavaFileManager getStandardFileManager() + { + return standardFileManager; + } + + public DiagnosticCollector getDiagnosticCollector() + { + return diagnostics; + } + + public void close() + { + try { this.standardFileManager.close(); } + catch (IOException ex) { throw new RelProxyException(ex); } + + List> diagList = diagnostics.getDiagnostics(); + if (!diagList.isEmpty()) + { + if (diagnosticsListener != null) + { + diagnosticsListener.onDiagnostics(diagnostics); + } + else + { + int i = 1; + for (Diagnostic diagnostic : diagList) + { + System.err.println("Diagnostic " + i); + System.err.println(" code: " + diagnostic.getCode()); + System.err.println(" kind: " + diagnostic.getKind()); + System.err.println(" line number: " + diagnostic.getLineNumber()); + System.err.println(" column number: " + diagnostic.getColumnNumber()); + System.err.println(" start position: " + diagnostic.getStartPosition()); + System.err.println(" position: " + diagnostic.getPosition()); + System.err.println(" end position: " + diagnostic.getEndPosition()); + System.err.println(" source: " + diagnostic.getSource()); + System.err.println(" message: " + diagnostic.getMessage(null)); + i++; + } + } + } + } +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java similarity index 100% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java similarity index 98% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java index 4ac011f..d1f39bd 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java @@ -1,129 +1,129 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp; - -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JProxyJavaFileObjectInput; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInMemory; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInFileSystem; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectOutputClass; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; -import java.io.IOException; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; -import javax.tools.FileObject; -import javax.tools.ForwardingJavaFileManager; -import javax.tools.JavaFileObject; -import javax.tools.JavaFileObject.Kind; -import javax.tools.StandardJavaFileManager; -import javax.tools.StandardLocation; - - -/** - * - * http://www.javablogging.com/dynamic-in-memory-compilation/ - * http://atamur.blogspot.com.es/2009/10/using-built-in-javacompiler-with-custom.html - * http://grepcode.com/file/repo1.maven.org/maven2/org.st-js/generator/3.0.3/org/stjs/generator/javac/CustomClassloaderJavaFileManager.java - * - * @author jmarranz - */ -public class JavaFileManagerInMemory extends ForwardingJavaFileManager -{ - private final LinkedList outputClassList = new LinkedList(); - private final JavaFileObjectInputClassFinderByClassLoader classFinder; - private final ClassDescriptorSourceFileRegistry sourceRegistry; - - public JavaFileManagerInMemory(StandardJavaFileManager standardFileManager,ClassLoader classLoader,ClassDescriptorSourceFileRegistry sourceRegistry,FolderSourceList requiredExtraJarPaths) - { - super(standardFileManager); - this.sourceRegistry = sourceRegistry; - this.classFinder = new JavaFileObjectInputClassFinderByClassLoader(classLoader,requiredExtraJarPaths); - } - - public LinkedList getJavaFileObjectOutputClassList() - { - return outputClassList; - } - - @Override - public JavaFileObject getJavaFileForOutput(Location location,String className, Kind kind, FileObject sibling) throws IOException - { - // Normalmente sólo habrá un resultado pero se da el caso de compilar una clase con una o varias inner classes, el compilador las compila de una vez - JavaFileObjectOutputClass outClass = new JavaFileObjectOutputClass(className, kind); - outputClassList.add(outClass); - return outClass; - } - - @Override - public Iterable list(Location location, String packageName, Set kinds, boolean recurse) throws IOException - { - if (location == StandardLocation.PLATFORM_CLASS_PATH) // let standard manager hanfle - return super.list(location, packageName, kinds, recurse); // En este caso nunca (con PLATFORM_CLASS_PATH) va a encontrar nuestros sources ni .class - else if (location == StandardLocation.CLASS_PATH && kinds.contains(JavaFileObject.Kind.CLASS)) - { - if (packageName.equals("java") || packageName.startsWith("java.")) // a hack to let standard manager handle locations like "java.lang" or "java.util", clases sólo cargables por el system class loader. Estrictamente no es necesario pero derivamos la inmensa mayoría de las clases estándar al método por defecto, NO añadimos "javax." pues hay extensiones tal y como el estándar servlet que no forma parte del Java core - return super.list(location, packageName, kinds, recurse); - else - { - // El StandardJavaFileManager al que hacemos forward es "configurado" por el compilador al que está asociado cuando hay una tarea de compilación - // dicha configuración es por ejemplo el classpath tanto para encontrar .class como .java - // En nuestro caso no disponemos del classpath de los .class, disponemos del ClassLoader a través del cual podemos obtener "a mano" via resources los - // JavaFileObject de los .class que necesitamos. - // Ahora bien, no es el caso de los archivos fuente en donde sí tenemos un path claro el cual pasamos como classpath al compilador y por tanto un super.list(location, packageName, kinds, recurse) - // nos devolverá los .java (como JavaFileObject claro) si encuentra archivos correspondientes al package buscado. - - LinkedList result = new LinkedList(); - - Iterable inFileMgr = super.list(location, packageName, kinds, recurse); // Esperamos o archivos fuente o .class de clases no recargables - if (inFileMgr instanceof Collection) - { - result.addAll((Collection)inFileMgr); - } - else - { - for(Iterator it = inFileMgr.iterator(); it.hasNext(); ) - { - JavaFileObject file = (JavaFileObject)it.next(); - result.add(file); - } - } - - List classList = classFinder.find(packageName); - - // Reemplazamos los .class de classList que son los que están en archivo "deployados" que pueden ser más antiguos que los que están en memoria - for(JavaFileObjectInputClassInFileSystem fileObj : classList) - { - String className = fileObj.getBinaryName(); - ClassDescriptorSourceUnit sourceFileDesc = sourceRegistry.getClassDescriptorSourceUnit(className); - if (sourceFileDesc != null && sourceFileDesc.getClassBytes() != null) - { - JavaFileObjectInputClassInMemory fileInput = new JavaFileObjectInputClassInMemory(className,sourceFileDesc.getClassBytes(),sourceFileDesc.getTimestamp()); - result.add(fileInput); - } - else - { - result.add(fileObj); - } - } - - // Los JavaFileObject de archivos fuente pueden ser los mimas clases que los de .class, el compilador se encargará de comparar los timestamp y elegir el .class o el source - - return result; - } - } - return Collections.emptyList(); - } - - @Override - public String inferBinaryName(Location location, JavaFileObject file) - { - if (file instanceof JProxyJavaFileObjectInput) - return ((JProxyJavaFileObjectInput)file).getBinaryName(); - - return super.inferBinaryName(location, file); - } - +package com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp; + +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JProxyJavaFileObjectInput; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInMemory; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInFileSystem; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectOutputClass; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import javax.tools.FileObject; +import javax.tools.ForwardingJavaFileManager; +import javax.tools.JavaFileObject; +import javax.tools.JavaFileObject.Kind; +import javax.tools.StandardJavaFileManager; +import javax.tools.StandardLocation; + + +/** + * + * http://www.javablogging.com/dynamic-in-memory-compilation/ + * http://atamur.blogspot.com.es/2009/10/using-built-in-javacompiler-with-custom.html + * http://grepcode.com/file/repo1.maven.org/maven2/org.st-js/generator/3.0.3/org/stjs/generator/javac/CustomClassloaderJavaFileManager.java + * + * @author jmarranz + */ +public class JavaFileManagerInMemory extends ForwardingJavaFileManager +{ + private final LinkedList outputClassList = new LinkedList(); + private final JavaFileObjectInputClassFinderByClassLoader classFinder; + private final ClassDescriptorSourceFileRegistry sourceRegistry; + + public JavaFileManagerInMemory(StandardJavaFileManager standardFileManager,ClassLoader classLoader,ClassDescriptorSourceFileRegistry sourceRegistry,FolderSourceList requiredExtraJarPaths) + { + super(standardFileManager); + this.sourceRegistry = sourceRegistry; + this.classFinder = new JavaFileObjectInputClassFinderByClassLoader(classLoader,requiredExtraJarPaths); + } + + public LinkedList getJavaFileObjectOutputClassList() + { + return outputClassList; + } + + @Override + public JavaFileObject getJavaFileForOutput(Location location,String className, Kind kind, FileObject sibling) throws IOException + { + // Normalmente sólo habrá un resultado pero se da el caso de compilar una clase con una o varias inner classes, el compilador las compila de una vez + JavaFileObjectOutputClass outClass = new JavaFileObjectOutputClass(className, kind); + outputClassList.add(outClass); + return outClass; + } + + @Override + public Iterable list(Location location, String packageName, Set kinds, boolean recurse) throws IOException + { + if (location == StandardLocation.PLATFORM_CLASS_PATH) // let standard manager hanfle + return super.list(location, packageName, kinds, recurse); // En este caso nunca (con PLATFORM_CLASS_PATH) va a encontrar nuestros sources ni .class + else if (location == StandardLocation.CLASS_PATH && kinds.contains(JavaFileObject.Kind.CLASS)) + { + if (packageName.equals("java") || packageName.startsWith("java.")) // a hack to let standard manager handle locations like "java.lang" or "java.util", clases sólo cargables por el system class loader. Estrictamente no es necesario pero derivamos la inmensa mayoría de las clases estándar al método por defecto, NO añadimos "javax." pues hay extensiones tal y como el estándar servlet que no forma parte del Java core + return super.list(location, packageName, kinds, recurse); + else + { + // El StandardJavaFileManager al que hacemos forward es "configurado" por el compilador al que está asociado cuando hay una tarea de compilación + // dicha configuración es por ejemplo el classpath tanto para encontrar .class como .java + // En nuestro caso no disponemos del classpath de los .class, disponemos del ClassLoader a través del cual podemos obtener "a mano" via resources los + // JavaFileObject de los .class que necesitamos. + // Ahora bien, no es el caso de los archivos fuente en donde sí tenemos un path claro el cual pasamos como classpath al compilador y por tanto un super.list(location, packageName, kinds, recurse) + // nos devolverá los .java (como JavaFileObject claro) si encuentra archivos correspondientes al package buscado. + + LinkedList result = new LinkedList(); + + Iterable inFileMgr = super.list(location, packageName, kinds, recurse); // Esperamos o archivos fuente o .class de clases no recargables + if (inFileMgr instanceof Collection) + { + result.addAll((Collection)inFileMgr); + } + else + { + for(Iterator it = inFileMgr.iterator(); it.hasNext(); ) + { + JavaFileObject file = (JavaFileObject)it.next(); + result.add(file); + } + } + + List classList = classFinder.find(packageName); + + // Reemplazamos los .class de classList que son los que están en archivo "deployados" que pueden ser más antiguos que los que están en memoria + for(JavaFileObjectInputClassInFileSystem fileObj : classList) + { + String className = fileObj.getBinaryName(); + ClassDescriptorSourceUnit sourceFileDesc = sourceRegistry.getClassDescriptorSourceUnit(className); + if (sourceFileDesc != null && sourceFileDesc.getClassBytes() != null) + { + JavaFileObjectInputClassInMemory fileInput = new JavaFileObjectInputClassInMemory(className,sourceFileDesc.getClassBytes(),sourceFileDesc.getTimestamp()); + result.add(fileInput); + } + else + { + result.add(fileObj); + } + } + + // Los JavaFileObject de archivos fuente pueden ser los mimas clases que los de .class, el compilador se encargará de comparar los timestamp y elegir el .class o el source + + return result; + } + } + return Collections.emptyList(); + } + + @Override + public String inferBinaryName(Location location, JavaFileObject file) + { + if (file instanceof JProxyJavaFileObjectInput) + return ((JProxyJavaFileObjectInput)file).getBinaryName(); + + return super.inferBinaryName(location, file); + } + } \ No newline at end of file diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java similarity index 97% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java index 3151ba4..fab17f4 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java @@ -1,214 +1,214 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp; - -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInFile; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInFileSystem; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInJar; -import com.innowhere.relproxy.RelProxyException; -import com.innowhere.relproxy.impl.FileExt; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; -import java.io.File; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.net.JarURLConnection; -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URL; -import java.net.URLDecoder; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Enumeration; -import java.util.List; -import java.util.jar.JarEntry; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; - -/** - * http://atamur.blogspot.com.es/2009/10/using-built-in-javacompiler-with-custom.html - * - * @author jmarranz - */ -public class JavaFileObjectInputClassFinderByClassLoader -{ - private static final String CLASS_FILE_EXTENSION = ".class"; - - private final ClassLoader classLoader; - private final FolderSourceList requiredExtraJarPaths; - - public JavaFileObjectInputClassFinderByClassLoader(ClassLoader classLoader,FolderSourceList requiredExtraJarPaths) - { - this.classLoader = classLoader; - this.requiredExtraJarPaths = requiredExtraJarPaths; - } - - public List find(String packageName) throws IOException - { - // http://www.dzone.com/snippets/get-all-classes-within-package - // http://sourceforge.net/p/scannotation/code/HEAD/tree/scannotation/src/main/java/org/scannotation/ClasspathUrlFinder.java#l124 - - String packagePath = packageName.replaceAll("\\.", "/"); - - List result = new ArrayList(); - - Enumeration urlEnumeration = classLoader.getResources(packagePath); - if (urlEnumeration.hasMoreElements()) - { - while (urlEnumeration.hasMoreElements()) - { // one URL for each jar on the classpath that has the given package - URL packageFolderURL = urlEnumeration.nextElement(); - listUnder(packageName,packageFolderURL,result); - } - } - else - { - // Enumeration vacía, chungo, esto nos ha ocurrido con el jar lib/ext/portlet.jar del Tomcat 6.2 del bundle liferay-portal-6.2-ce-ga3 - // daba un error de de javax.portlet.PortletRquest not found. - // En teoría debería responder a la búsqueda classLoader.getResources("javax/portlet") devolviendo el jar, pero devuelve un Enumeration vacío - // quizás es porque el jar no tiene un "Name: javax/portlet" en el META-INF/MANIFEST.MF (otros jar no tienen Name y funcionan no tengo claro el criterio, - // el problema debe estar en una opción del MANIFEST.MF que confunde al compilador), añadiendo el "Name: javax/portlet" funciona - // pero en plan majo permitimos al usuario que nos indique los paths de los jars "conflictivos" obtenemos los .class hijos directos por fuerza bruta del package - // requerido en el parámetro de este método find() y le evitamos modificar un jar de infraestructura que queda muy feo e inmantenible respecto a una solución - // basada en configuración del usuario. - - if (requiredExtraJarPaths != null) - { - FileExt[] jarFileList = requiredExtraJarPaths.getArray(); - if (jarFileList != null) - { - for (FileExt jarFile : jarFileList) - { - listUnderJarCustom(packagePath,jarFile,result); - } - } - } - } - - return result; - } - - - private void listUnder(String packageName, URL packageFolderURL,Collection result) - { - String pkgPath = packageFolderURL.toExternalForm(); //packageFolderURL.getFile(); El problema de getFile es que también está URL-encoded (un espacio es %20) lo cual no es compatible con File - - if (pkgPath.startsWith("file:")) - { - listUnderDir(packageName,pkgPath,result); - } - else - { // browse a jar file - listUnderJar(packageFolderURL,result); - } // maybe there can be something else for more involved class loaders - } - - private void listUnderDir(String packageName,String pkgPath,Collection result) - { - pkgPath = pkgPath.substring("file:".length()); - - try { pkgPath = URLDecoder.decode(pkgPath, "UTF-8"); } // Detecté el problema con Vaadin en un path con "Documents%20and%20Settings" con %20 obviamente no es un path correcto, deben ser espacios - catch (UnsupportedEncodingException ex) { throw new RelProxyException(ex); } - - File directory = new File(pkgPath); - if (!directory.isDirectory()) - throw new RelProxyException("Internal Error:" + pkgPath); - - // browse local .class files - useful for local execution - - File[] childFiles = directory.listFiles(); - for (File childFile : childFiles) - { - if (!childFile.isFile()) continue; - - // We only want the .class files. - String name = childFile.getName(); - if (name.endsWith(CLASS_FILE_EXTENSION)) - { - String binaryName = ClassDescriptor.getClassNameFromPackageAndClassFileName(packageName,name); - result.add(new JavaFileObjectInputClassInFile(childFile,binaryName, childFile.toURI())); - } - } - } - - private void listUnderJar(URL packageFolderURL,Collection result) - { - try - { - String jarUri = packageFolderURL.toExternalForm().split("!")[0]; - - JarURLConnection jarConn = (JarURLConnection) packageFolderURL.openConnection(); - String rootEntryName = jarConn.getEntryName(); - int rootEnd = rootEntryName.length() + 1; - - Enumeration entryEnum = jarConn.getJarFile().entries(); - while (entryEnum.hasMoreElements()) - { - JarEntry jarEntry = entryEnum.nextElement(); - String name = jarEntry.getName(); - // Empieza por packagePath y no hay más folders siguientes, terminando en un .class (una clase concreta) - if (name.startsWith(rootEntryName) && name.indexOf('/', rootEnd) == -1 && name.endsWith(CLASS_FILE_EXTENSION)) - { - URI uri = URI.create(jarUri + "!/" + name); - String binaryName = ClassDescriptor.getClassNameFromRelativeClassFilePath(name); - result.add(new JavaFileObjectInputClassInJar(binaryName, uri,jarEntry.getTime())); - } - } - } - catch (Exception e) - { - throw new RelProxyException("Wasn't able to open " + packageFolderURL + " as a jar file", e); - } - } - - - private void listUnderJarCustom(String packagePath,FileExt jarFile,Collection result) - { - String normalizedPath = jarFile.getCanonicalPath(); - if (normalizedPath.contains("\\")) // Windows - { - // No estoy seguro de que sea necesario normalizar pero por si acaso - normalizedPath = normalizedPath.replace("\\","/"); // "C:/folder" - normalizedPath = "/" + normalizedPath; // "/C:/folder" - } - - String urlPath = "file:" + normalizedPath; - - URL packageFolderURL; - try { packageFolderURL = new URL(urlPath); } - catch (MalformedURLException ex) { throw new RelProxyException(ex); } - - String jarUri = "jar:" + packageFolderURL.toExternalForm(); - - int posEnd = packagePath.length() + 1; - - ZipInputStream zip = null; - - try - { - zip = new ZipInputStream(packageFolderURL.openStream()); - ZipEntry zipEntry = zip.getNextEntry(); - while(zipEntry != null) - { - String name = zipEntry.getName(); - // Empieza por packagePath y no hay más folders siguientes, terminando en un .class (una clase concreta) - if (name.startsWith(packagePath) && name.indexOf('/', posEnd) == -1 && name.endsWith(CLASS_FILE_EXTENSION)) - { - URI uri = URI.create(jarUri + "!/" + name); - String binaryName = ClassDescriptor.getClassNameFromRelativeClassFilePath(name); - result.add(new JavaFileObjectInputClassInJar(binaryName, uri,zipEntry.getTime())); - } - - zipEntry = zip.getNextEntry(); - } - } - catch(IOException ex) - { - throw new RelProxyException(ex); - } - finally - { - if (zip != null) try { zip.close(); } catch (IOException ex) { throw new RelProxyException(ex); } - } - } - - +package com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp; + +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInFile; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInFileSystem; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInJar; +import com.innowhere.relproxy.RelProxyException; +import com.innowhere.relproxy.impl.FileExt; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import java.io.File; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.JarURLConnection; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.net.URLDecoder; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Enumeration; +import java.util.List; +import java.util.jar.JarEntry; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +/** + * http://atamur.blogspot.com.es/2009/10/using-built-in-javacompiler-with-custom.html + * + * @author jmarranz + */ +public class JavaFileObjectInputClassFinderByClassLoader +{ + private static final String CLASS_FILE_EXTENSION = ".class"; + + private final ClassLoader classLoader; + private final FolderSourceList requiredExtraJarPaths; + + public JavaFileObjectInputClassFinderByClassLoader(ClassLoader classLoader,FolderSourceList requiredExtraJarPaths) + { + this.classLoader = classLoader; + this.requiredExtraJarPaths = requiredExtraJarPaths; + } + + public List find(String packageName) throws IOException + { + // http://www.dzone.com/snippets/get-all-classes-within-package + // http://sourceforge.net/p/scannotation/code/HEAD/tree/scannotation/src/main/java/org/scannotation/ClasspathUrlFinder.java#l124 + + String packagePath = packageName.replaceAll("\\.", "/"); + + List result = new ArrayList(); + + Enumeration urlEnumeration = classLoader.getResources(packagePath); + if (urlEnumeration.hasMoreElements()) + { + while (urlEnumeration.hasMoreElements()) + { // one URL for each jar on the classpath that has the given package + URL packageFolderURL = urlEnumeration.nextElement(); + listUnder(packageName,packageFolderURL,result); + } + } + else + { + // Enumeration vacía, chungo, esto nos ha ocurrido con el jar lib/ext/portlet.jar del Tomcat 6.2 del bundle liferay-portal-6.2-ce-ga3 + // daba un error de de javax.portlet.PortletRquest not found. + // En teoría debería responder a la búsqueda classLoader.getResources("javax/portlet") devolviendo el jar, pero devuelve un Enumeration vacío + // quizás es porque el jar no tiene un "Name: javax/portlet" en el META-INF/MANIFEST.MF (otros jar no tienen Name y funcionan no tengo claro el criterio, + // el problema debe estar en una opción del MANIFEST.MF que confunde al compilador), añadiendo el "Name: javax/portlet" funciona + // pero en plan majo permitimos al usuario que nos indique los paths de los jars "conflictivos" obtenemos los .class hijos directos por fuerza bruta del package + // requerido en el parámetro de este método find() y le evitamos modificar un jar de infraestructura que queda muy feo e inmantenible respecto a una solución + // basada en configuración del usuario. + + if (requiredExtraJarPaths != null) + { + FileExt[] jarFileList = requiredExtraJarPaths.getArray(); + if (jarFileList != null) + { + for (FileExt jarFile : jarFileList) + { + listUnderJarCustom(packagePath,jarFile,result); + } + } + } + } + + return result; + } + + + private void listUnder(String packageName, URL packageFolderURL,Collection result) + { + String pkgPath = packageFolderURL.toExternalForm(); //packageFolderURL.getFile(); El problema de getFile es que también está URL-encoded (un espacio es %20) lo cual no es compatible con File + + if (pkgPath.startsWith("file:")) + { + listUnderDir(packageName,pkgPath,result); + } + else + { // browse a jar file + listUnderJar(packageFolderURL,result); + } // maybe there can be something else for more involved class loaders + } + + private void listUnderDir(String packageName,String pkgPath,Collection result) + { + pkgPath = pkgPath.substring("file:".length()); + + try { pkgPath = URLDecoder.decode(pkgPath, "UTF-8"); } // Detecté el problema con Vaadin en un path con "Documents%20and%20Settings" con %20 obviamente no es un path correcto, deben ser espacios + catch (UnsupportedEncodingException ex) { throw new RelProxyException(ex); } + + File directory = new File(pkgPath); + if (!directory.isDirectory()) + throw new RelProxyException("Internal Error:" + pkgPath); + + // browse local .class files - useful for local execution + + File[] childFiles = directory.listFiles(); + for (File childFile : childFiles) + { + if (!childFile.isFile()) continue; + + // We only want the .class files. + String name = childFile.getName(); + if (name.endsWith(CLASS_FILE_EXTENSION)) + { + String binaryName = ClassDescriptor.getClassNameFromPackageAndClassFileName(packageName,name); + result.add(new JavaFileObjectInputClassInFile(childFile,binaryName, childFile.toURI())); + } + } + } + + private void listUnderJar(URL packageFolderURL,Collection result) + { + try + { + String jarUri = packageFolderURL.toExternalForm().split("!")[0]; + + JarURLConnection jarConn = (JarURLConnection) packageFolderURL.openConnection(); + String rootEntryName = jarConn.getEntryName(); + int rootEnd = rootEntryName.length() + 1; + + Enumeration entryEnum = jarConn.getJarFile().entries(); + while (entryEnum.hasMoreElements()) + { + JarEntry jarEntry = entryEnum.nextElement(); + String name = jarEntry.getName(); + // Empieza por packagePath y no hay más folders siguientes, terminando en un .class (una clase concreta) + if (name.startsWith(rootEntryName) && name.indexOf('/', rootEnd) == -1 && name.endsWith(CLASS_FILE_EXTENSION)) + { + URI uri = URI.create(jarUri + "!/" + name); + String binaryName = ClassDescriptor.getClassNameFromRelativeClassFilePath(name); + result.add(new JavaFileObjectInputClassInJar(binaryName, uri,jarEntry.getTime())); + } + } + } + catch (Exception e) + { + throw new RelProxyException("Wasn't able to open " + packageFolderURL + " as a jar file", e); + } + } + + + private void listUnderJarCustom(String packagePath,FileExt jarFile,Collection result) + { + String normalizedPath = jarFile.getCanonicalPath(); + if (normalizedPath.contains("\\")) // Windows + { + // No estoy seguro de que sea necesario normalizar pero por si acaso + normalizedPath = normalizedPath.replace("\\","/"); // "C:/folder" + normalizedPath = "/" + normalizedPath; // "/C:/folder" + } + + String urlPath = "file:" + normalizedPath; + + URL packageFolderURL; + try { packageFolderURL = new URL(urlPath); } + catch (MalformedURLException ex) { throw new RelProxyException(ex); } + + String jarUri = "jar:" + packageFolderURL.toExternalForm(); + + int posEnd = packagePath.length() + 1; + + ZipInputStream zip = null; + + try + { + zip = new ZipInputStream(packageFolderURL.openStream()); + ZipEntry zipEntry = zip.getNextEntry(); + while(zipEntry != null) + { + String name = zipEntry.getName(); + // Empieza por packagePath y no hay más folders siguientes, terminando en un .class (una clase concreta) + if (name.startsWith(packagePath) && name.indexOf('/', posEnd) == -1 && name.endsWith(CLASS_FILE_EXTENSION)) + { + URI uri = URI.create(jarUri + "!/" + name); + String binaryName = ClassDescriptor.getClassNameFromRelativeClassFilePath(name); + result.add(new JavaFileObjectInputClassInJar(binaryName, uri,zipEntry.getTime())); + } + + zipEntry = zip.getNextEntry(); + } + } + catch(IOException ex) + { + throw new RelProxyException(ex); + } + finally + { + if (zip != null) try { zip.close(); } catch (IOException ex) { throw new RelProxyException(ex); } + } + } + + } \ No newline at end of file diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JProxyJavaFileObjectInput.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JProxyJavaFileObjectInput.java similarity index 94% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JProxyJavaFileObjectInput.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JProxyJavaFileObjectInput.java index d2db84a..c6d6363 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JProxyJavaFileObjectInput.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JProxyJavaFileObjectInput.java @@ -1,10 +1,10 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo; - -/** - * - * @author jmarranz - */ -public interface JProxyJavaFileObjectInput -{ - public String getBinaryName(); -} +package com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo; + +/** + * + * @author jmarranz + */ +public interface JProxyJavaFileObjectInput +{ + public String getBinaryName(); +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java similarity index 96% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java index 5a4665e..ea6136a 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java @@ -1,42 +1,42 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo; - -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInFileSystem; -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URI; - -/** - * - * @author jmarranz - */ -public class JavaFileObjectInputClassInFile extends JavaFileObjectInputClassInFileSystem -{ - protected File file; - - public JavaFileObjectInputClassInFile(File file,String binaryName, URI uri) - { - super(binaryName,uri,uri.getPath()); - this.file = file; - } - - @Override - public InputStream openInputStream() throws IOException - { - // Podríamos hacer uri.toURL().openStream() pero si tenemos el File es para algo - return new BufferedInputStream(new FileInputStream(file),10 * 1024); - } - - @Override - public long getLastModified() - { - return file.lastModified(); - } - - @Override - public String toString() { - return "JavaFileObjectInputClassInFile{uri=" + uri + '}'; - } +package com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo; + +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInFileSystem; +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; + +/** + * + * @author jmarranz + */ +public class JavaFileObjectInputClassInFile extends JavaFileObjectInputClassInFileSystem +{ + protected File file; + + public JavaFileObjectInputClassInFile(File file,String binaryName, URI uri) + { + super(binaryName,uri,uri.getPath()); + this.file = file; + } + + @Override + public InputStream openInputStream() throws IOException + { + // Podríamos hacer uri.toURL().openStream() pero si tenemos el File es para algo + return new BufferedInputStream(new FileInputStream(file),10 * 1024); + } + + @Override + public long getLastModified() + { + return file.lastModified(); + } + + @Override + public String toString() { + return "JavaFileObjectInputClassInFile{uri=" + uri + '}'; + } } \ No newline at end of file diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java similarity index 96% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java index a0a8dea..58f20b1 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java @@ -1,92 +1,92 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo; - -import java.io.IOException; -import java.io.OutputStream; -import java.io.Reader; -import java.io.Writer; -import java.net.URI; -import javax.lang.model.element.Modifier; -import javax.lang.model.element.NestingKind; -import javax.tools.JavaFileObject; - -/** - * - * @author jmarranz - */ -public abstract class JavaFileObjectInputClassInFileSystem implements JavaFileObject,JProxyJavaFileObjectInput -{ - protected final String binaryName; - protected final URI uri; - protected final String name; - - public JavaFileObjectInputClassInFileSystem(String binaryName, URI uri,String name) - { - this.uri = uri; - this.binaryName = binaryName; - this.name = name; - } - - @Override - public URI toUri() { - return uri; - } - - @Override - public String getName() { - return name; - } - - @Override - public String getBinaryName() { - return binaryName; - } - - @Override - public OutputStream openOutputStream() throws IOException { - throw new UnsupportedOperationException(); - } - - @Override - public Reader openReader(boolean ignoreEncodingErrors) throws IOException { - throw new UnsupportedOperationException(); - } - - @Override - public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { - throw new UnsupportedOperationException(); - } - - @Override - public Writer openWriter() throws IOException { - throw new UnsupportedOperationException(); - } - - @Override - public boolean delete() { - throw new UnsupportedOperationException(); - } - - @Override - public Kind getKind() { - return Kind.CLASS; - } - - @Override // copied from SimpleJavaFileManager - public boolean isNameCompatible(String simpleName, Kind kind) { - String baseName = simpleName + kind.extension; - return kind.equals(getKind()) - && (baseName.equals(getName()) - || getName().endsWith("/" + baseName)); - } - - @Override - public NestingKind getNestingKind() { - throw new UnsupportedOperationException(); - } - - @Override - public Modifier getAccessLevel() { - throw new UnsupportedOperationException(); - } - -} +package com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.net.URI; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.NestingKind; +import javax.tools.JavaFileObject; + +/** + * + * @author jmarranz + */ +public abstract class JavaFileObjectInputClassInFileSystem implements JavaFileObject,JProxyJavaFileObjectInput +{ + protected final String binaryName; + protected final URI uri; + protected final String name; + + public JavaFileObjectInputClassInFileSystem(String binaryName, URI uri,String name) + { + this.uri = uri; + this.binaryName = binaryName; + this.name = name; + } + + @Override + public URI toUri() { + return uri; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getBinaryName() { + return binaryName; + } + + @Override + public OutputStream openOutputStream() throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public Reader openReader(boolean ignoreEncodingErrors) throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public Writer openWriter() throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public boolean delete() { + throw new UnsupportedOperationException(); + } + + @Override + public Kind getKind() { + return Kind.CLASS; + } + + @Override // copied from SimpleJavaFileManager + public boolean isNameCompatible(String simpleName, Kind kind) { + String baseName = simpleName + kind.extension; + return kind.equals(getKind()) + && (baseName.equals(getName()) + || getName().endsWith("/" + baseName)); + } + + @Override + public NestingKind getNestingKind() { + throw new UnsupportedOperationException(); + } + + @Override + public Modifier getAccessLevel() { + throw new UnsupportedOperationException(); + } + +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java similarity index 95% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java index 2c0dd5c..0b4eb53 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java @@ -1,38 +1,38 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URI; - -/** - * - * @author jmarranz - */ -public class JavaFileObjectInputClassInJar extends JavaFileObjectInputClassInFileSystem -{ - protected long timestamp; - - public JavaFileObjectInputClassInJar(String binaryName, URI uri,long timestamp) - { - super(binaryName,uri,uri.getSchemeSpecificPart()); - this.timestamp = timestamp; - } - - @Override - public InputStream openInputStream() throws IOException - { - return uri.toURL().openStream(); // easy way to handle any URI! - } - - @Override - public long getLastModified() - { - return timestamp; - } - - @Override - public String toString() - { - return "JavaFileObjectInputClassInJar{uri=" + uri + '}'; - } +package com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; + +/** + * + * @author jmarranz + */ +public class JavaFileObjectInputClassInJar extends JavaFileObjectInputClassInFileSystem +{ + protected long timestamp; + + public JavaFileObjectInputClassInJar(String binaryName, URI uri,long timestamp) + { + super(binaryName,uri,uri.getSchemeSpecificPart()); + this.timestamp = timestamp; + } + + @Override + public InputStream openInputStream() throws IOException + { + return uri.toURL().openStream(); // easy way to handle any URI! + } + + @Override + public long getLastModified() + { + return timestamp; + } + + @Override + public String toString() + { + return "JavaFileObjectInputClassInJar{uri=" + uri + '}'; + } } \ No newline at end of file diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java similarity index 100% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java similarity index 96% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java index 2ed0317..66d2d8c 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java @@ -1,65 +1,65 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo; - -import com.innowhere.relproxy.RelProxyException; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; -import java.net.URI; -import javax.tools.SimpleJavaFileObject; - -/** - * http://www.javablogging.com/dynamic-in-memory-compilation/ - * - * @author jmarranz - */ -public abstract class JavaFileObjectInputSourceBase extends SimpleJavaFileObject implements JProxyJavaFileObjectInput -{ - protected String binaryName; - protected String encoding; - - public JavaFileObjectInputSourceBase(String name,String encoding) - { - super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE); // La extensión .java es necesaria aunque sea falsa sino da error - - this.binaryName = name; - this.encoding = encoding; - } - - protected abstract String getSource(); - - - @Override - public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException - { - return getSource(); - } - - public byte[] getBytes() - { - try - { - return getSource().getBytes(encoding); - } - catch (UnsupportedEncodingException ex) { throw new RelProxyException(ex); } - } - - @Override - public InputStream openInputStream() throws IOException - { - return new ByteArrayInputStream(getBytes()); - } - - @Override - public OutputStream openOutputStream() throws IOException - { - throw new UnsupportedOperationException(); - } - - public String getBinaryName() - { - return binaryName; - } - -} +package com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo; + +import com.innowhere.relproxy.RelProxyException; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import javax.tools.SimpleJavaFileObject; + +/** + * http://www.javablogging.com/dynamic-in-memory-compilation/ + * + * @author jmarranz + */ +public abstract class JavaFileObjectInputSourceBase extends SimpleJavaFileObject implements JProxyJavaFileObjectInput +{ + protected String binaryName; + protected String encoding; + + public JavaFileObjectInputSourceBase(String name,String encoding) + { + super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE); // La extensión .java es necesaria aunque sea falsa sino da error + + this.binaryName = name; + this.encoding = encoding; + } + + protected abstract String getSource(); + + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException + { + return getSource(); + } + + public byte[] getBytes() + { + try + { + return getSource().getBytes(encoding); + } + catch (UnsupportedEncodingException ex) { throw new RelProxyException(ex); } + } + + @Override + public InputStream openInputStream() throws IOException + { + return new ByteArrayInputStream(getBytes()); + } + + @Override + public OutputStream openOutputStream() throws IOException + { + throw new UnsupportedOperationException(); + } + + public String getBinaryName() + { + return binaryName; + } + +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java similarity index 95% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java index 69abf50..02b9386 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java @@ -1,36 +1,36 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo; - -import com.innowhere.relproxy.impl.jproxy.JProxyUtil; -import java.io.File; - -/** - * http://www.javablogging.com/dynamic-in-memory-compilation/ - * - * @author jmarranz - */ -public class JavaFileObjectInputSourceInFile extends JavaFileObjectInputSourceBase -{ - protected File file; - protected String source; - - public JavaFileObjectInputSourceInFile(String name,File file,String encoding) - { - super(name,encoding); - this.file = file; - } - - @Override - protected String getSource() - { - if (source != null) - return source; - this.source = JProxyUtil.readTextFile(file, encoding); - return source; - } - - @Override - public long getLastModified() - { - return file.lastModified(); - } -} +package com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo; + +import com.innowhere.relproxy.impl.jproxy.JProxyUtil; +import java.io.File; + +/** + * http://www.javablogging.com/dynamic-in-memory-compilation/ + * + * @author jmarranz + */ +public class JavaFileObjectInputSourceInFile extends JavaFileObjectInputSourceBase +{ + protected File file; + protected String source; + + public JavaFileObjectInputSourceInFile(String name,File file,String encoding) + { + super(name,encoding); + this.file = file; + } + + @Override + protected String getSource() + { + if (source != null) + return source; + this.source = JProxyUtil.readTextFile(file, encoding); + return source; + } + + @Override + public long getLastModified() + { + return file.lastModified(); + } +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java similarity index 95% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java index 95cbf0a..501d376 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java @@ -1,31 +1,31 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo; - -/** - * http://www.javablogging.com/dynamic-in-memory-compilation/ - * - * @author jmarranz - */ -public class JavaFileObjectInputSourceInMemory extends JavaFileObjectInputSourceBase -{ - protected String source; - protected long timestamp; - - public JavaFileObjectInputSourceInMemory(String name,String source,String encoding,long timestamp) - { - super(name,encoding); - this.source = source; - this.timestamp = timestamp; - } - - @Override - protected String getSource() - { - return source; - } - - @Override - public long getLastModified() - { - return timestamp; - } -} +package com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo; + +/** + * http://www.javablogging.com/dynamic-in-memory-compilation/ + * + * @author jmarranz + */ +public class JavaFileObjectInputSourceInMemory extends JavaFileObjectInputSourceBase +{ + protected String source; + protected long timestamp; + + public JavaFileObjectInputSourceInMemory(String name,String source,String encoding,long timestamp) + { + super(name,encoding); + this.source = source; + this.timestamp = timestamp; + } + + @Override + protected String getSource() + { + return source; + } + + @Override + public long getLastModified() + { + return timestamp; + } +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java similarity index 96% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java index 187bfb0..dc40de0 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java @@ -1,59 +1,59 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo; - -import com.innowhere.relproxy.RelProxyException; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.net.URI; -import javax.tools.SimpleJavaFileObject; - -/** - * http://www.javablogging.com/dynamic-in-memory-compilation/ - * - * @author jmarranz - */ -public class JavaFileObjectOutputClass extends SimpleJavaFileObject { - - /** - * Byte code created by the compiler will be stored in this - * ByteArrayOutputStream so that we can later get the - * byte array out of it - * and put it in the memory as an instance of our class. - */ - protected final ByteArrayOutputStream bos = new ByteArrayOutputStream(); - protected String binaryName; - - /** - * Registers the compiled class object under URI - * containing the class full name - * - * @param name - * Full name of the compiled class - * @param kind - * Kind of the data. It will be CLASS in our case - */ - public JavaFileObjectOutputClass(String name, Kind kind) - { - super(URI.create("string:///" + name.replace('.', '/') + kind.extension), kind); - - if (!Kind.CLASS.equals(kind)) throw new RelProxyException("Unexpected"); - this.binaryName = name; - } - - public String binaryName() - { - return binaryName; - } - - public byte[] getBytes() - { - return bos.toByteArray(); - } - - @Override - public OutputStream openOutputStream() throws IOException - { - return bos; - } - -} +package com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo; + +import com.innowhere.relproxy.RelProxyException; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.net.URI; +import javax.tools.SimpleJavaFileObject; + +/** + * http://www.javablogging.com/dynamic-in-memory-compilation/ + * + * @author jmarranz + */ +public class JavaFileObjectOutputClass extends SimpleJavaFileObject { + + /** + * Byte code created by the compiler will be stored in this + * ByteArrayOutputStream so that we can later get the + * byte array out of it + * and put it in the memory as an instance of our class. + */ + protected final ByteArrayOutputStream bos = new ByteArrayOutputStream(); + protected String binaryName; + + /** + * Registers the compiled class object under URI + * containing the class full name + * + * @param name + * Full name of the compiled class + * @param kind + * Kind of the data. It will be CLASS in our case + */ + public JavaFileObjectOutputClass(String name, Kind kind) + { + super(URI.create("string:///" + name.replace('.', '/') + kind.extension), kind); + + if (!Kind.CLASS.equals(kind)) throw new RelProxyException("Unexpected"); + this.binaryName = name; + } + + public String binaryName() + { + return binaryName; + } + + public byte[] getBytes() + { + return bos.toByteArray(); + } + + @Override + public OutputStream openOutputStream() throws IOException + { + return bos; + } + +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java similarity index 100% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRoot.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRoot.java similarity index 95% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRoot.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRoot.java index fe03688..aa522c1 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRoot.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRoot.java @@ -1,15 +1,15 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit; - -/** - * - * @author jmarranz - */ -public abstract class SourceScriptRoot extends SourceUnit -{ - public SourceScriptRoot(String className) - { - super(className); - } - - public abstract String getScriptCode(String encoding,boolean[] hasHashBang); -} +package com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit; + +/** + * + * @author jmarranz + */ +public abstract class SourceScriptRoot extends SourceUnit +{ + public SourceScriptRoot(String className) + { + super(className); + } + + public abstract String getScriptCode(String encoding,boolean[] hasHashBang); +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java similarity index 100% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java similarity index 96% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java index 263eb0d..02a6594 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java @@ -1,24 +1,24 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit; - -import com.innowhere.relproxy.impl.FileExt; -import com.innowhere.relproxy.impl.jproxy.JProxyUtil; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; - -/** - * - * @author jmarranz - */ -public class SourceScriptRootFileJavaExt extends SourceScriptRootFile -{ - public SourceScriptRootFileJavaExt(FileExt sourceFile,FolderSourceList folderSourceList) - { - super(sourceFile,folderSourceList); - } - - @Override - public String getScriptCode(String encoding,boolean[] hasHashBang) - { - hasHashBang[0] = false; - return JProxyUtil.readTextFile(sourceFile.getFile(),encoding); - } -} +package com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit; + +import com.innowhere.relproxy.impl.FileExt; +import com.innowhere.relproxy.impl.jproxy.JProxyUtil; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; + +/** + * + * @author jmarranz + */ +public class SourceScriptRootFileJavaExt extends SourceScriptRootFile +{ + public SourceScriptRootFileJavaExt(FileExt sourceFile,FolderSourceList folderSourceList) + { + super(sourceFile,folderSourceList); + } + + @Override + public String getScriptCode(String encoding,boolean[] hasHashBang) + { + hasHashBang[0] = false; + return JProxyUtil.readTextFile(sourceFile.getFile(),encoding); + } +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java similarity index 97% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java index 5437d75..ff1253d 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java @@ -1,35 +1,35 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit; - -import com.innowhere.relproxy.impl.FileExt; -import com.innowhere.relproxy.impl.jproxy.JProxyUtil; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; - -/** - * - * @author jmarranz - */ -public class SourceScriptRootFileOtherExt extends SourceScriptRootFile -{ - public SourceScriptRootFileOtherExt(FileExt sourceFile,FolderSourceList folderSourceList) - { - super(sourceFile,folderSourceList); - } - - @Override - public String getScriptCode(String encoding,boolean[] hasHashBang) - { - String codeBody = JProxyUtil.readTextFile(sourceFile.getFile(),encoding); - // Eliminamos la primera línea #! (debe estar en la primera línea y sin espacios antes) - if (codeBody.startsWith("#!")) - { - hasHashBang[0] = true; - int pos = codeBody.indexOf('\n'); - if (pos != -1) // Rarísimo que sólo esté el hash bang (script vacío) - { - codeBody = codeBody.substring(pos + 1); - } - } - else hasHashBang[0] = false; - return codeBody; - } -} +package com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit; + +import com.innowhere.relproxy.impl.FileExt; +import com.innowhere.relproxy.impl.jproxy.JProxyUtil; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; + +/** + * + * @author jmarranz + */ +public class SourceScriptRootFileOtherExt extends SourceScriptRootFile +{ + public SourceScriptRootFileOtherExt(FileExt sourceFile,FolderSourceList folderSourceList) + { + super(sourceFile,folderSourceList); + } + + @Override + public String getScriptCode(String encoding,boolean[] hasHashBang) + { + String codeBody = JProxyUtil.readTextFile(sourceFile.getFile(),encoding); + // Eliminamos la primera línea #! (debe estar en la primera línea y sin espacios antes) + if (codeBody.startsWith("#!")) + { + hasHashBang[0] = true; + int pos = codeBody.indexOf('\n'); + if (pos != -1) // Rarísimo que sólo esté el hash bang (script vacío) + { + codeBody = codeBody.substring(pos + 1); + } + } + else hasHashBang[0] = false; + return codeBody; + } +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootInMemory.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootInMemory.java similarity index 96% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootInMemory.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootInMemory.java index 973c5cd..78d7dfd 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootInMemory.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootInMemory.java @@ -1,56 +1,56 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit; - -/** - * - * @author jmarranz - */ -public class SourceScriptRootInMemory extends SourceScriptRoot -{ - public static final String DEFAULT_CLASS_NAME = "_jproxyMainClass_"; // OJO NO CAMBIAR, está ya documentada - - protected String code; - protected long timestamp; - - private SourceScriptRootInMemory(String className,String code) - { - super(className); - setScriptCode(code,System.currentTimeMillis()); - } - - public static SourceScriptRootInMemory createSourceScriptInMemory(String code) - { - return new SourceScriptRootInMemory(DEFAULT_CLASS_NAME,code); - } - - @Override - public long lastModified() - { - return timestamp; // Siempre ha sido modificado - } - - @Override - public String getScriptCode(String encoding,boolean[] hasHashBang) - { - hasHashBang[0] = false; - return code; - } - - public boolean isEmptyCode() - { - // Si code es "" la clase especial se genera pero no hace nada simplemente devuelve un null. - // Este es el caso en el que utilizamos RelProxy embebido en un framework utilizando la API ScriptEngine pero únicamente porque se usa una API basada - // en interfaces, pero tiene el inconveniente de generarse un SourceScriptRootInMemory inútil que no hace nada - return code.isEmpty(); - } - - public String getScriptCode() - { - return code; - } - - public final void setScriptCode(String code,long timestamp) - { - this.code = code; - this.timestamp = timestamp; - } -} +package com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit; + +/** + * + * @author jmarranz + */ +public class SourceScriptRootInMemory extends SourceScriptRoot +{ + public static final String DEFAULT_CLASS_NAME = "_jproxyMainClass_"; // OJO NO CAMBIAR, está ya documentada + + protected String code; + protected long timestamp; + + private SourceScriptRootInMemory(String className,String code) + { + super(className); + setScriptCode(code,System.currentTimeMillis()); + } + + public static SourceScriptRootInMemory createSourceScriptInMemory(String code) + { + return new SourceScriptRootInMemory(DEFAULT_CLASS_NAME,code); + } + + @Override + public long lastModified() + { + return timestamp; // Siempre ha sido modificado + } + + @Override + public String getScriptCode(String encoding,boolean[] hasHashBang) + { + hasHashBang[0] = false; + return code; + } + + public boolean isEmptyCode() + { + // Si code es "" la clase especial se genera pero no hace nada simplemente devuelve un null. + // Este es el caso en el que utilizamos RelProxy embebido en un framework utilizando la API ScriptEngine pero únicamente porque se usa una API basada + // en interfaces, pero tiene el inconveniente de generarse un SourceScriptRootInMemory inútil que no hace nada + return code.isEmpty(); + } + + public String getScriptCode() + { + return code; + } + + public final void setScriptCode(String code,long timestamp) + { + this.code = code; + this.timestamp = timestamp; + } +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java similarity index 96% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java index bf396c3..40f1530 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java @@ -1,36 +1,36 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit; - -import com.innowhere.relproxy.impl.FileExt; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; - -/** - * - * @author jmarranz - */ -public abstract class SourceUnit -{ - protected final String className; - - public SourceUnit(String className) - { - this.className = className; - } - - public abstract long lastModified(); - - protected static String buildClassNameFromFile(FileExt sourceFile,FolderSourceList sourceList) - { - return sourceList.buildClassNameFromFile(sourceFile); - } - - protected static String buildClassNameFromFile(FileExt sourceFile,FileExt rootFolderOfSources) - { - return FolderSourceList.buildClassNameFromFile(sourceFile,rootFolderOfSources); - } - - public String getClassName() - { - return className; - } - -} +package com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit; + +import com.innowhere.relproxy.impl.FileExt; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; + +/** + * + * @author jmarranz + */ +public abstract class SourceUnit +{ + protected final String className; + + public SourceUnit(String className) + { + this.className = className; + } + + public abstract long lastModified(); + + protected static String buildClassNameFromFile(FileExt sourceFile,FolderSourceList sourceList) + { + return sourceList.buildClassNameFromFile(sourceFile); + } + + protected static String buildClassNameFromFile(FileExt sourceFile,FileExt rootFolderOfSources) + { + return FolderSourceList.buildClassNameFromFile(sourceFile,rootFolderOfSources); + } + + public String getClassName() + { + return className; + } + +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/screngine/BindingsImpl.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/screngine/BindingsImpl.java similarity index 94% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/screngine/BindingsImpl.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/screngine/BindingsImpl.java index 26af733..b47e757 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/screngine/BindingsImpl.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/screngine/BindingsImpl.java @@ -1,14 +1,14 @@ - -package com.innowhere.relproxy.impl.jproxy.screngine; - -import java.util.HashMap; -import javax.script.Bindings; - -/** - * - * @author jmarranz - */ -public class BindingsImpl extends HashMap implements Bindings -{ - -} + +package com.innowhere.relproxy.impl.jproxy.screngine; + +import java.util.HashMap; +import javax.script.Bindings; + +/** + * + * @author jmarranz + */ +public class BindingsImpl extends HashMap implements Bindings +{ + +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java similarity index 100% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java similarity index 96% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java index d5deff3..822da32 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java @@ -1,179 +1,179 @@ -package com.innowhere.relproxy.impl.jproxy.screngine; - -import com.innowhere.relproxy.RelProxy; -import com.innowhere.relproxy.jproxy.JProxyScriptEngineFactory; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import javax.script.ScriptEngine; - -/** - * Ideas: http://grepcode.com/file/repo1.maven.org/maven2/org.codehaus.groovy/groovy/1.6.0/org/codehaus/groovy/jsr223/GroovyScriptEngineFactory.java - * - * @author jmarranz - */ -public class JProxyScriptEngineFactoryImpl extends JProxyScriptEngineFactory -{ - protected static final String SHORT_NAME = "java"; - protected static final String LANGUAGE_NAME = "Java"; - - protected static final List names; - protected static final List extensions; - protected static final List mimeTypes; - - static - { - ArrayList n; - - n = new ArrayList(2); - n.add(SHORT_NAME); - n.add(LANGUAGE_NAME); - names = Collections.unmodifiableList(n); - - n = new ArrayList(1); - n.add("java"); - extensions = Collections.unmodifiableList(n); - - n = new ArrayList(2); http://reference.sitepoint.com/html/mime-types-full - n.add("text/x-java-source"); - n.add("text/plain"); - mimeTypes = Collections.unmodifiableList(n); - } - - public JProxyScriptEngineFactoryImpl() - { - } - - public static JProxyScriptEngineFactory create() - { - return new JProxyScriptEngineFactoryImpl(); - } - - @Override - public String getEngineName() - { - return "RelProxy Java Script Engine"; - } - - @Override - public String getEngineVersion() - { - return RelProxy.getVersion(); - } - - @Override - public List getExtensions() - { - return extensions; - } - - @Override - public List getMimeTypes() - { - return mimeTypes; - } - - @Override - public List getNames() - { - return names; - } - - @Override - public String getLanguageName() - { - return LANGUAGE_NAME; - } - - @Override - public String getLanguageVersion() - { - return System.getProperty("java.version"); // Ej 1.6.0_18 - } - - @Override - public Object getParameter(String key) - { - if (ScriptEngine.NAME.equals(key)) { - return SHORT_NAME; - } else if (ScriptEngine.ENGINE.equals(key)) { - return getEngineName(); - } else if (ScriptEngine.ENGINE_VERSION.equals(key)) { - return getEngineVersion(); - } else if (ScriptEngine.LANGUAGE.equals(key)) { - return getLanguageName(); - } else if (ScriptEngine.LANGUAGE_VERSION.equals(key)) { - return getLanguageVersion(); - } else if ("THREADING".equals(key)) { - return "MULTITHREADED"; - } else { - throw new IllegalArgumentException("Invalid key"); - } - } - - @Override - public String getMethodCallSyntax(String obj, String method, String... args) - { - StringBuilder ret = new StringBuilder(); - ret.append(obj + "." + method + "("); - int len = args.length; - if (len == 0) { - ret.append(")"); - return ret.toString(); - } - - for (int i = 0; i < len; i++) { - ret.append(args[i]); - if (i != len - 1) { - ret.append(","); - } else { - ret.append(")"); - } - } - return ret.toString(); - } - - @Override - public String getOutputStatement(String toDisplay) - { - StringBuilder buf = new StringBuilder(); - buf.append("System.out.println(\""); - int len = toDisplay.length(); - for (int i = 0; i < len; i++) - { - char ch = toDisplay.charAt(i); - switch (ch) { - case '"': - buf.append("\\\""); - break; - case '\\': - buf.append("\\\\"); - break; - default: - buf.append(ch); - break; - } - } - buf.append("\")"); - return buf.toString(); - } - - @Override - public String getProgram(String... statements) - { - StringBuilder ret = new StringBuilder(); - int len = statements.length; - for (int i = 0; i < len; i++) - { - ret.append(statements[i]); - ret.append('\n'); - } - return ret.toString(); - } - - @Override - public ScriptEngine getScriptEngine() - { - return new JProxyScriptEngineImpl(this); - } -} +package com.innowhere.relproxy.impl.jproxy.screngine; + +import com.innowhere.relproxy.RelProxy; +import com.innowhere.relproxy.jproxy.JProxyScriptEngineFactory; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import javax.script.ScriptEngine; + +/** + * Ideas: http://grepcode.com/file/repo1.maven.org/maven2/org.codehaus.groovy/groovy/1.6.0/org/codehaus/groovy/jsr223/GroovyScriptEngineFactory.java + * + * @author jmarranz + */ +public class JProxyScriptEngineFactoryImpl extends JProxyScriptEngineFactory +{ + protected static final String SHORT_NAME = "java"; + protected static final String LANGUAGE_NAME = "Java"; + + protected static final List names; + protected static final List extensions; + protected static final List mimeTypes; + + static + { + ArrayList n; + + n = new ArrayList(2); + n.add(SHORT_NAME); + n.add(LANGUAGE_NAME); + names = Collections.unmodifiableList(n); + + n = new ArrayList(1); + n.add("java"); + extensions = Collections.unmodifiableList(n); + + n = new ArrayList(2); http://reference.sitepoint.com/html/mime-types-full + n.add("text/x-java-source"); + n.add("text/plain"); + mimeTypes = Collections.unmodifiableList(n); + } + + public JProxyScriptEngineFactoryImpl() + { + } + + public static JProxyScriptEngineFactory create() + { + return new JProxyScriptEngineFactoryImpl(); + } + + @Override + public String getEngineName() + { + return "RelProxy Java Script Engine"; + } + + @Override + public String getEngineVersion() + { + return RelProxy.getVersion(); + } + + @Override + public List getExtensions() + { + return extensions; + } + + @Override + public List getMimeTypes() + { + return mimeTypes; + } + + @Override + public List getNames() + { + return names; + } + + @Override + public String getLanguageName() + { + return LANGUAGE_NAME; + } + + @Override + public String getLanguageVersion() + { + return System.getProperty("java.version"); // Ej 1.6.0_18 + } + + @Override + public Object getParameter(String key) + { + if (ScriptEngine.NAME.equals(key)) { + return SHORT_NAME; + } else if (ScriptEngine.ENGINE.equals(key)) { + return getEngineName(); + } else if (ScriptEngine.ENGINE_VERSION.equals(key)) { + return getEngineVersion(); + } else if (ScriptEngine.LANGUAGE.equals(key)) { + return getLanguageName(); + } else if (ScriptEngine.LANGUAGE_VERSION.equals(key)) { + return getLanguageVersion(); + } else if ("THREADING".equals(key)) { + return "MULTITHREADED"; + } else { + throw new IllegalArgumentException("Invalid key"); + } + } + + @Override + public String getMethodCallSyntax(String obj, String method, String... args) + { + StringBuilder ret = new StringBuilder(); + ret.append(obj + "." + method + "("); + int len = args.length; + if (len == 0) { + ret.append(")"); + return ret.toString(); + } + + for (int i = 0; i < len; i++) { + ret.append(args[i]); + if (i != len - 1) { + ret.append(","); + } else { + ret.append(")"); + } + } + return ret.toString(); + } + + @Override + public String getOutputStatement(String toDisplay) + { + StringBuilder buf = new StringBuilder(); + buf.append("System.out.println(\""); + int len = toDisplay.length(); + for (int i = 0; i < len; i++) + { + char ch = toDisplay.charAt(i); + switch (ch) { + case '"': + buf.append("\\\""); + break; + case '\\': + buf.append("\\\\"); + break; + default: + buf.append(ch); + break; + } + } + buf.append("\")"); + return buf.toString(); + } + + @Override + public String getProgram(String... statements) + { + StringBuilder ret = new StringBuilder(); + int len = statements.length; + for (int i = 0; i < len; i++) + { + ret.append(statements[i]); + ret.append('\n'); + } + return ret.toString(); + } + + @Override + public ScriptEngine getScriptEngine() + { + return new JProxyScriptEngineImpl(this); + } +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java similarity index 96% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java index 928d77f..a3ac978 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java @@ -1,122 +1,122 @@ -package com.innowhere.relproxy.impl.jproxy.screngine; - -import com.innowhere.relproxy.RelProxyException; -import com.innowhere.relproxy.impl.GenericProxyImpl; -import com.innowhere.relproxy.impl.jproxy.JProxyConfigImpl; -import com.innowhere.relproxy.impl.jproxy.JProxyUtil; -import com.innowhere.relproxy.jproxy.JProxyConfig; -import com.innowhere.relproxy.jproxy.JProxyScriptEngine; -import java.io.Reader; -import javax.script.AbstractScriptEngine; -import javax.script.Bindings; -import javax.script.ScriptContext; -import javax.script.ScriptEngineFactory; -import javax.script.ScriptException; - -/** - * Methods of this class are similar to JProxyDefaultImpl - * - * @author jmarranz - */ -public class JProxyScriptEngineImpl extends AbstractScriptEngine implements JProxyScriptEngine -{ - protected JProxyScriptEngineDelegateImpl jproxy; - protected JProxyScriptEngineFactoryImpl factory; - - public JProxyScriptEngineImpl(JProxyScriptEngineFactoryImpl factory) - { - this.factory = factory; - } - - @Override - public void init(JProxyConfig config) - { - JProxyConfigImpl configImpl = (JProxyConfigImpl)config; - if (!configImpl.isEnabled()) return; // jproxy quedará null - - GenericProxyImpl.checkSingletonNull(jproxy); - this.jproxy = new JProxyScriptEngineDelegateImpl(this); - jproxy.init(configImpl); - } - - - @Override - public Object eval(String script, ScriptContext context) throws ScriptException - { - if (jproxy == null) - throw new RelProxyException("Engine is disabled"); - - return jproxy.execute(script,context); - } - - @Override - public Object eval(Reader reader, ScriptContext context) throws ScriptException - { - String script = JProxyUtil.readTextFile(reader); - return eval(script,context); - } - - @Override - public Bindings createBindings() - { - return new BindingsImpl(); - } - - @Override - public ScriptEngineFactory getFactory() - { - return factory; - } - - @Override - public T create(T obj,Class clasz) - { - if (jproxy == null) - return obj; // No se ha llamado al init o enabled = false - return jproxy.create(obj, clasz); - } - - @Override - public Object create(Object obj,Class[] classes) - { - if (jproxy == null) - return obj; // No se ha llamado al init o enabled = false - return jproxy.create(obj, classes); - } - - @Override - public boolean isEnabled() - { - if (jproxy == null) - return false; - - return jproxy.isEnabled(); - } - - @Override - public boolean isRunning() - { - if (jproxy == null) - return false; - - return jproxy.isRunning(); - } - - @Override - public boolean start() - { - if (jproxy == null) - return false; - - return jproxy.start(); - } - - @Override - public boolean stop() - { - if (jproxy == null) - return false; - - return jproxy.stop(); - } -} +package com.innowhere.relproxy.impl.jproxy.screngine; + +import com.innowhere.relproxy.RelProxyException; +import com.innowhere.relproxy.impl.GenericProxyImpl; +import com.innowhere.relproxy.impl.jproxy.JProxyConfigImpl; +import com.innowhere.relproxy.impl.jproxy.JProxyUtil; +import com.innowhere.relproxy.jproxy.JProxyConfig; +import com.innowhere.relproxy.jproxy.JProxyScriptEngine; +import java.io.Reader; +import javax.script.AbstractScriptEngine; +import javax.script.Bindings; +import javax.script.ScriptContext; +import javax.script.ScriptEngineFactory; +import javax.script.ScriptException; + +/** + * Methods of this class are similar to JProxyDefaultImpl + * + * @author jmarranz + */ +public class JProxyScriptEngineImpl extends AbstractScriptEngine implements JProxyScriptEngine +{ + protected JProxyScriptEngineDelegateImpl jproxy; + protected JProxyScriptEngineFactoryImpl factory; + + public JProxyScriptEngineImpl(JProxyScriptEngineFactoryImpl factory) + { + this.factory = factory; + } + + @Override + public void init(JProxyConfig config) + { + JProxyConfigImpl configImpl = (JProxyConfigImpl)config; + if (!configImpl.isEnabled()) return; // jproxy quedará null + + GenericProxyImpl.checkSingletonNull(jproxy); + this.jproxy = new JProxyScriptEngineDelegateImpl(this); + jproxy.init(configImpl); + } + + + @Override + public Object eval(String script, ScriptContext context) throws ScriptException + { + if (jproxy == null) + throw new RelProxyException("Engine is disabled"); + + return jproxy.execute(script,context); + } + + @Override + public Object eval(Reader reader, ScriptContext context) throws ScriptException + { + String script = JProxyUtil.readTextFile(reader); + return eval(script,context); + } + + @Override + public Bindings createBindings() + { + return new BindingsImpl(); + } + + @Override + public ScriptEngineFactory getFactory() + { + return factory; + } + + @Override + public T create(T obj,Class clasz) + { + if (jproxy == null) + return obj; // No se ha llamado al init o enabled = false + return jproxy.create(obj, clasz); + } + + @Override + public Object create(Object obj,Class[] classes) + { + if (jproxy == null) + return obj; // No se ha llamado al init o enabled = false + return jproxy.create(obj, classes); + } + + @Override + public boolean isEnabled() + { + if (jproxy == null) + return false; + + return jproxy.isEnabled(); + } + + @Override + public boolean isRunning() + { + if (jproxy == null) + return false; + + return jproxy.isRunning(); + } + + @Override + public boolean start() + { + if (jproxy == null) + return false; + + return jproxy.start(); + } + + @Override + public boolean stop() + { + if (jproxy == null) + return false; + + return jproxy.stop(); + } +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java similarity index 96% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java index 53fb839..48b84dd 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java @@ -1,47 +1,47 @@ -package com.innowhere.relproxy.impl.jproxy.shell; - -import com.innowhere.relproxy.RelProxyException; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; -import java.io.File; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLClassLoader; - -/** - * - * @author jmarranz - */ -public class JProxyShellClassLoader extends URLClassLoader -{ - public JProxyShellClassLoader(ClassLoader parent,File classFolder) - { - super(toURLArray(classFolder),parent); - } - - private static URL[] toURLArray(File file) - { - try { return new URL[]{file.toURI().toURL()}; } - catch (MalformedURLException ex) { throw new RelProxyException(ex); } - } - - @Override - protected Class findClass(String name) throws ClassNotFoundException - { - return super.findClass(name); - } - - @Override - protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException - { - return super.loadClass(name, resolve); - } - - public synchronized Class defineClass(ClassDescriptor classDesc) - { - String className = classDesc.getClassName(); - byte[] classBytes = classDesc.getClassBytes(); - Class clasz = defineClass(className,classBytes, 0, classBytes.length); - classDesc.setLastLoadedClass(clasz); - return clasz; - } -} +package com.innowhere.relproxy.impl.jproxy.shell; + +import com.innowhere.relproxy.RelProxyException; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; + +/** + * + * @author jmarranz + */ +public class JProxyShellClassLoader extends URLClassLoader +{ + public JProxyShellClassLoader(ClassLoader parent,File classFolder) + { + super(toURLArray(classFolder),parent); + } + + private static URL[] toURLArray(File file) + { + try { return new URL[]{file.toURI().toURL()}; } + catch (MalformedURLException ex) { throw new RelProxyException(ex); } + } + + @Override + protected Class findClass(String name) throws ClassNotFoundException + { + return super.findClass(name); + } + + @Override + protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException + { + return super.loadClass(name, resolve); + } + + public synchronized Class defineClass(ClassDescriptor classDesc) + { + String className = classDesc.getClassName(); + byte[] classBytes = classDesc.getClassBytes(); + Class clasz = defineClass(className,classBytes, 0, classBytes.length); + classDesc.setLastLoadedClass(clasz); + return clasz; + } +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java similarity index 97% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java index 840f51f..8977a8d 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java @@ -1,61 +1,61 @@ -package com.innowhere.relproxy.impl.jproxy.shell; - -import com.innowhere.relproxy.RelProxyException; -import com.innowhere.relproxy.impl.jproxy.JProxyConfigImpl; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootInMemory; -import java.util.LinkedList; - -/** - * - * @author jmarranz - */ -public class JProxyShellCodeSnippetImpl extends JProxyShellImpl -{ - public void init(String[] args) - { - super.init(args, null); - } - - @Override - protected void executeFirstTime(ClassDescriptorSourceScript scriptFileDesc,LinkedList argsToScript,JProxyShellClassLoader classLoader) - { - try - { - scriptFileDesc.callMainMethod(argsToScript); - } - catch(Throwable ex) - { - ex.printStackTrace(System.out); - } - } - - @Override - protected void processConfigParams(String[] args,LinkedList argsToScript,JProxyConfigImpl config) - { - super.processConfigParams(args, argsToScript, config); - - String classFolder = config.getClassFolder(); - if (classFolder != null && !classFolder.trim().isEmpty()) throw new RelProxyException("cacheClassFolder is useless to execute a code snippet"); - } - - @Override - protected SourceScriptRoot createSourceScriptRoot(String[] args,LinkedList argsToScript,FolderSourceList folderSourceList) - { - // En argsToScript no está el args[0] ni falta que hace porque es el flag "-c" - StringBuilder code = new StringBuilder(); - for(String chunk : argsToScript) - code.append(chunk); - return SourceScriptRootInMemory.createSourceScriptInMemory(code.toString()); - } - - @Override - protected JProxyShellClassLoader getJProxyShellClassLoader(JProxyConfigImpl config) - { - // No hay classFolder => no hay necesidad de nuevo ClassLoader - return null; - } - -} +package com.innowhere.relproxy.impl.jproxy.shell; + +import com.innowhere.relproxy.RelProxyException; +import com.innowhere.relproxy.impl.jproxy.JProxyConfigImpl; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootInMemory; +import java.util.LinkedList; + +/** + * + * @author jmarranz + */ +public class JProxyShellCodeSnippetImpl extends JProxyShellImpl +{ + public void init(String[] args) + { + super.init(args, null); + } + + @Override + protected void executeFirstTime(ClassDescriptorSourceScript scriptFileDesc,LinkedList argsToScript,JProxyShellClassLoader classLoader) + { + try + { + scriptFileDesc.callMainMethod(argsToScript); + } + catch(Throwable ex) + { + ex.printStackTrace(System.out); + } + } + + @Override + protected void processConfigParams(String[] args,LinkedList argsToScript,JProxyConfigImpl config) + { + super.processConfigParams(args, argsToScript, config); + + String classFolder = config.getClassFolder(); + if (classFolder != null && !classFolder.trim().isEmpty()) throw new RelProxyException("cacheClassFolder is useless to execute a code snippet"); + } + + @Override + protected SourceScriptRoot createSourceScriptRoot(String[] args,LinkedList argsToScript,FolderSourceList folderSourceList) + { + // En argsToScript no está el args[0] ni falta que hace porque es el flag "-c" + StringBuilder code = new StringBuilder(); + for(String chunk : argsToScript) + code.append(chunk); + return SourceScriptRootInMemory.createSourceScriptInMemory(code.toString()); + } + + @Override + protected JProxyShellClassLoader getJProxyShellClassLoader(JProxyConfigImpl config) + { + // No hay classFolder => no hay necesidad de nuevo ClassLoader + return null; + } + +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/JProxyShellImpl.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/JProxyShellImpl.java similarity index 100% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/JProxyShellImpl.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/shell/JProxyShellImpl.java diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java similarity index 100% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java similarity index 97% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java index 8f96551..895a901 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java @@ -1,78 +1,78 @@ -package com.innowhere.relproxy.impl.jproxy.shell; - -import com.innowhere.relproxy.RelProxyException; -import com.innowhere.relproxy.impl.FileExt; -import com.innowhere.relproxy.impl.jproxy.JProxyConfigImpl; -import com.innowhere.relproxy.impl.jproxy.JProxyUtil; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootFile; -import java.io.File; -import java.util.LinkedList; - -/** - * - * @author jmarranz - */ -public class JProxyShellScriptFileImpl extends JProxyShellImpl -{ - protected FileExt scriptFile; - - public void init(String[] args) - { - File scriptFile = new File(args[0]); - if (!scriptFile.exists()) - throw new RelProxyException("File " + args[0] + " does not exist"); - - this.scriptFile = new FileExt(scriptFile); - - File parentDir = JProxyUtil.getParentDir(scriptFile); - String inputPath = parentDir.getAbsolutePath(); - super.init(args, inputPath); - } - - @Override - protected void executeFirstTime(ClassDescriptorSourceScript scriptFileDesc,LinkedList argsToScript,JProxyShellClassLoader classLoader) - { - fixLastLoadedClass(scriptFileDesc,classLoader); - - try - { - scriptFileDesc.callMainMethod(argsToScript); - } - catch(Throwable ex) - { - ex.printStackTrace(System.out); - } - } - - @Override - protected SourceScriptRoot createSourceScriptRoot(String[] args,LinkedList argsToScript,FolderSourceList folderSourceList) - { - return SourceScriptRootFile.createSourceScriptRootFile(scriptFile,folderSourceList); - } - - @Override - protected JProxyShellClassLoader getJProxyShellClassLoader(JProxyConfigImpl config) - { - String classFolder = config.getClassFolder(); - if (classFolder != null) - return new JProxyShellClassLoader(getDefaultClassLoader(),new File(classFolder)); - else - return null; - } - - protected void fixLastLoadedClass(ClassDescriptorSourceScript scriptFileDesc,JProxyShellClassLoader classLoader) - { - Class scriptClass = scriptFileDesc.getLastLoadedClass(); - if (scriptClass != null) return; - - // Esto es esperable cuando especificamos un classFolder en donde está ya compilado el script lanzador y es más actual que el fuente - // no ha habido necesidad de crear un class loader "reloader" ni de recargar todos los archivos fuente con él - if (classLoader == null) throw new RelProxyException("INTERNAL ERROR"); - if (scriptFileDesc.getClassBytes() == null) throw new RelProxyException("INTERNAL ERROR"); - scriptClass = classLoader.defineClass(scriptFileDesc); - scriptFileDesc.setLastLoadedClass(scriptClass); - } -} +package com.innowhere.relproxy.impl.jproxy.shell; + +import com.innowhere.relproxy.RelProxyException; +import com.innowhere.relproxy.impl.FileExt; +import com.innowhere.relproxy.impl.jproxy.JProxyConfigImpl; +import com.innowhere.relproxy.impl.jproxy.JProxyUtil; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootFile; +import java.io.File; +import java.util.LinkedList; + +/** + * + * @author jmarranz + */ +public class JProxyShellScriptFileImpl extends JProxyShellImpl +{ + protected FileExt scriptFile; + + public void init(String[] args) + { + File scriptFile = new File(args[0]); + if (!scriptFile.exists()) + throw new RelProxyException("File " + args[0] + " does not exist"); + + this.scriptFile = new FileExt(scriptFile); + + File parentDir = JProxyUtil.getParentDir(scriptFile); + String inputPath = parentDir.getAbsolutePath(); + super.init(args, inputPath); + } + + @Override + protected void executeFirstTime(ClassDescriptorSourceScript scriptFileDesc,LinkedList argsToScript,JProxyShellClassLoader classLoader) + { + fixLastLoadedClass(scriptFileDesc,classLoader); + + try + { + scriptFileDesc.callMainMethod(argsToScript); + } + catch(Throwable ex) + { + ex.printStackTrace(System.out); + } + } + + @Override + protected SourceScriptRoot createSourceScriptRoot(String[] args,LinkedList argsToScript,FolderSourceList folderSourceList) + { + return SourceScriptRootFile.createSourceScriptRootFile(scriptFile,folderSourceList); + } + + @Override + protected JProxyShellClassLoader getJProxyShellClassLoader(JProxyConfigImpl config) + { + String classFolder = config.getClassFolder(); + if (classFolder != null) + return new JProxyShellClassLoader(getDefaultClassLoader(),new File(classFolder)); + else + return null; + } + + protected void fixLastLoadedClass(ClassDescriptorSourceScript scriptFileDesc,JProxyShellClassLoader classLoader) + { + Class scriptClass = scriptFileDesc.getLastLoadedClass(); + if (scriptClass != null) return; + + // Esto es esperable cuando especificamos un classFolder en donde está ya compilado el script lanzador y es más actual que el fuente + // no ha habido necesidad de crear un class loader "reloader" ni de recargar todos los archivos fuente con él + if (classLoader == null) throw new RelProxyException("INTERNAL ERROR"); + if (scriptFileDesc.getClassBytes() == null) throw new RelProxyException("INTERNAL ERROR"); + scriptClass = classLoader.defineClass(scriptFileDesc); + scriptFileDesc.setLastLoadedClass(scriptClass); + } +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/Command.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/Command.java similarity index 96% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/Command.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/Command.java index 893cf28..b99fa28 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/Command.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/Command.java @@ -1,103 +1,103 @@ -package com.innowhere.relproxy.impl.jproxy.shell.inter; - -/** - * - * @author jmarranz - */ -public abstract class Command -{ - protected JProxyShellProcessor parent; - protected String name; - - public Command(JProxyShellProcessor parent,String name) - { - this.parent = parent; - this.name = name; - } - - public static Command createCommand(JProxyShellProcessor parent,String cmd) - { - cmd = cmd.trim(); - if (cmd.equals("clear")) - { - return new CommandOther(parent,cmd); - } - else if (cmd.startsWith("delete")) - { - CommandDelete command = CommandDelete.createCommandDelete(parent,cmd); - if (command != null) - return command; - else - return new CommandError(parent); - } - else if (cmd.equals("display")) - { - return new CommandOther(parent,cmd); - } - else if (cmd.startsWith("edit")) - { - CommandEdit command = CommandEdit.createCommandEdit(parent,cmd); - if (command != null) - return command; - else - return new CommandError(parent); - } - else if (cmd.equals("exec")) - { - return new CommandOther(parent,cmd); - } - else if (cmd.equals("exit")) - { - return new CommandOther(parent,cmd); - } - else if (cmd.equals("help")) - { - return new CommandOther(parent,cmd); - } - else if (cmd.startsWith("insert")) - { - CommandInsert command = CommandInsert.createCommandInsert(parent,cmd); - if (command != null) - return command; - else - return new CommandError(parent); - } - else if (cmd.startsWith("load")) - { - CommandLoad command = CommandLoad.createCommandLoad(parent,cmd); - if (command != null) - return command; - else - return new CommandError(parent); - } - else if (cmd.equals("quit")) - { - return new CommandOther(parent,cmd); - } - else if (cmd.startsWith("save")) - { - CommandSave command = CommandSave.createCommandSave(parent,cmd); - if (command != null) - return command; - else - return new CommandError(parent); - } - - return null; // No es un comando - } - - protected static String getParameter(String cmdName,String cmd) - { - int pos = cmd.indexOf(cmdName + " "); - if (pos != 0) - return null; - pos = cmd.indexOf(' '); - String param = cmd.substring(pos + 1); - param = param.trim(); - return param; - } - - public abstract boolean run(); - - public abstract void runPostCommand(); -} +package com.innowhere.relproxy.impl.jproxy.shell.inter; + +/** + * + * @author jmarranz + */ +public abstract class Command +{ + protected JProxyShellProcessor parent; + protected String name; + + public Command(JProxyShellProcessor parent,String name) + { + this.parent = parent; + this.name = name; + } + + public static Command createCommand(JProxyShellProcessor parent,String cmd) + { + cmd = cmd.trim(); + if (cmd.equals("clear")) + { + return new CommandOther(parent,cmd); + } + else if (cmd.startsWith("delete")) + { + CommandDelete command = CommandDelete.createCommandDelete(parent,cmd); + if (command != null) + return command; + else + return new CommandError(parent); + } + else if (cmd.equals("display")) + { + return new CommandOther(parent,cmd); + } + else if (cmd.startsWith("edit")) + { + CommandEdit command = CommandEdit.createCommandEdit(parent,cmd); + if (command != null) + return command; + else + return new CommandError(parent); + } + else if (cmd.equals("exec")) + { + return new CommandOther(parent,cmd); + } + else if (cmd.equals("exit")) + { + return new CommandOther(parent,cmd); + } + else if (cmd.equals("help")) + { + return new CommandOther(parent,cmd); + } + else if (cmd.startsWith("insert")) + { + CommandInsert command = CommandInsert.createCommandInsert(parent,cmd); + if (command != null) + return command; + else + return new CommandError(parent); + } + else if (cmd.startsWith("load")) + { + CommandLoad command = CommandLoad.createCommandLoad(parent,cmd); + if (command != null) + return command; + else + return new CommandError(parent); + } + else if (cmd.equals("quit")) + { + return new CommandOther(parent,cmd); + } + else if (cmd.startsWith("save")) + { + CommandSave command = CommandSave.createCommandSave(parent,cmd); + if (command != null) + return command; + else + return new CommandError(parent); + } + + return null; // No es un comando + } + + protected static String getParameter(String cmdName,String cmd) + { + int pos = cmd.indexOf(cmdName + " "); + if (pos != 0) + return null; + pos = cmd.indexOf(' '); + String param = cmd.substring(pos + 1); + param = param.trim(); + return param; + } + + public abstract boolean run(); + + public abstract void runPostCommand(); +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java similarity index 100% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandDelete.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandDelete.java similarity index 100% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandDelete.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandDelete.java diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandEdit.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandEdit.java similarity index 100% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandEdit.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandEdit.java diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandError.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandError.java similarity index 93% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandError.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandError.java index 0465597..27a6b17 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandError.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandError.java @@ -1,25 +1,25 @@ -package com.innowhere.relproxy.impl.jproxy.shell.inter; - -/** - * - * @author jmarranz - */ -public class CommandError extends Command -{ - public CommandError(JProxyShellProcessor parent) - { - super(parent, "ERROR"); - } - - @Override - public boolean run() - { - return false; - } - - @Override - public void runPostCommand() - { - } - -} +package com.innowhere.relproxy.impl.jproxy.shell.inter; + +/** + * + * @author jmarranz + */ +public class CommandError extends Command +{ + public CommandError(JProxyShellProcessor parent) + { + super(parent, "ERROR"); + } + + @Override + public boolean run() + { + return false; + } + + @Override + public void runPostCommand() + { + } + +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandInsert.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandInsert.java similarity index 100% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandInsert.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandInsert.java diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandLoad.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandLoad.java similarity index 96% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandLoad.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandLoad.java index b30910d..491d13e 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandLoad.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandLoad.java @@ -1,78 +1,78 @@ -package com.innowhere.relproxy.impl.jproxy.shell.inter; - -import com.innowhere.relproxy.impl.jproxy.JProxyUtil; -import java.io.File; -import java.net.URI; -import java.net.URL; -import java.util.LinkedList; -import java.util.Scanner; - -/** - * - * @author jmarranz - */ -public class CommandLoad extends Command -{ - public static final String NAME = "load"; - protected String url; - - public CommandLoad(JProxyShellProcessor parent,String url) - { - super(parent,NAME); - this.url = url; - } - - public static CommandLoad createCommandLoad(JProxyShellProcessor parent,String cmd) - { - String url = getParameter(NAME,cmd); - if (url == null) - { - System.out.println("Command error: parameter is required"); - return null; - } - - return new CommandLoad(parent,url); - } - - @Override - public boolean run() - { - try - { - byte[] content; - URI uri = new URI(url); - if (uri.getScheme() == null) // Archivo - { - File file = new File(url); - content = JProxyUtil.readFile(file); - } - else // URL (incluyendo file:///...) - { - URL urlObj = new URL(url); - content = JProxyUtil.readURL(urlObj); // Como no conocemos encoding... - } - - String code = new String(content,parent.getEncoding()); // Como no conocemos encoding... - LinkedList lines = new LinkedList(); - Scanner scanner = new Scanner(code); - while (scanner.hasNextLine()) - { - String line = scanner.nextLine(); - lines.add(line); - } - - parent.setCodeBuffer(lines); - return true; - } - catch (Exception ex) - { - ex.printStackTrace(); - return false; - } - } - - @Override - public void runPostCommand() - { - } -} +package com.innowhere.relproxy.impl.jproxy.shell.inter; + +import com.innowhere.relproxy.impl.jproxy.JProxyUtil; +import java.io.File; +import java.net.URI; +import java.net.URL; +import java.util.LinkedList; +import java.util.Scanner; + +/** + * + * @author jmarranz + */ +public class CommandLoad extends Command +{ + public static final String NAME = "load"; + protected String url; + + public CommandLoad(JProxyShellProcessor parent,String url) + { + super(parent,NAME); + this.url = url; + } + + public static CommandLoad createCommandLoad(JProxyShellProcessor parent,String cmd) + { + String url = getParameter(NAME,cmd); + if (url == null) + { + System.out.println("Command error: parameter is required"); + return null; + } + + return new CommandLoad(parent,url); + } + + @Override + public boolean run() + { + try + { + byte[] content; + URI uri = new URI(url); + if (uri.getScheme() == null) // Archivo + { + File file = new File(url); + content = JProxyUtil.readFile(file); + } + else // URL (incluyendo file:///...) + { + URL urlObj = new URL(url); + content = JProxyUtil.readURL(urlObj); // Como no conocemos encoding... + } + + String code = new String(content,parent.getEncoding()); // Como no conocemos encoding... + LinkedList lines = new LinkedList(); + Scanner scanner = new Scanner(code); + while (scanner.hasNextLine()) + { + String line = scanner.nextLine(); + lines.add(line); + } + + parent.setCodeBuffer(lines); + return true; + } + catch (Exception ex) + { + ex.printStackTrace(); + return false; + } + } + + @Override + public void runPostCommand() + { + } +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandOther.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandOther.java similarity index 97% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandOther.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandOther.java index e39c52c..62e9bc1 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandOther.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandOther.java @@ -1,110 +1,110 @@ - -package com.innowhere.relproxy.impl.jproxy.shell.inter; - -import com.innowhere.relproxy.RelProxyException; - -/** - * - * @author jmarranz - */ -public class CommandOther extends Command -{ - public CommandOther(JProxyShellProcessor parent,String name) - { - super(parent,name); - } - - @Override - public boolean run() - { - if (name.equals("clear")) - { - commandClear(); - } - else if (name.equals("display")) - { - commandDisplay(); - } - else if (name.equals("exec")) - { - commandExec(); - } - else if (name.equals("exit")) - { - commandExit(); - } - else if (name.equals("help")) - { - commandHelp(); - } - else if (name.equals("quit")) - { - commandExit(); - } - else throw new RelProxyException("Internal Error"); - - return true; - } - - @Override - public void runPostCommand() - { - } - - private void commandClear() - { - parent.clearCodeBuffer(); - } - - private void commandExit() - { - System.exit(0); - } - - private void commandDisplay() - { - System.out.println("001>"); // La primera línea es siempre vacía porque en ella es donde ponemos el "public class /_jproxyShellInMemoryClass_ { " que el usuario ignora, así al dar error el número de línea será correcto respecto al "display" - - int i = 2; - for(String line : parent.getCodeBuffer()) - { - for(int j = 0; j < 3 - String.valueOf(i).length(); j++) System.out.print("0"); - System.out.print(i + ">"); - System.out.print(line); - System.out.println(); - i++; - } - } - - private void commandExec() - { - parent.executeCodeBuffer(); - } - - private void commandHelp() - { - System.out.println("Everything you write in the prompt is added to a code buffer, code buffer is compiled on the fly and executed by exec command, unless a command is detected"); - System.out.println(""); - System.out.println("Available commands:"); - System.out.println(" clear"); - System.out.println(" Clears the buffer"); - System.out.println(" display"); - System.out.println(" Shows the buffer content"); - System.out.println(" edit last | "); - System.out.println(" Edits the last introduced line code or the specified line number"); - System.out.println(" exec"); - System.out.println(" Compile and execute the buffer content"); - System.out.println(" exit"); - System.out.println(" Exits shell"); - System.out.println(" help"); - System.out.println(" This command"); - System.out.println(" insert last | "); - System.out.println(" Insert the next line of code before the last introduced line or the specified line number"); - System.out.println(" load | "); - System.out.println(" Load a file or URL into the buffer"); - System.out.println(" quit"); - System.out.println(" Same as exit"); - System.out.println(" save "); - System.out.println(" Save the current buffer to a file"); - } -} + +package com.innowhere.relproxy.impl.jproxy.shell.inter; + +import com.innowhere.relproxy.RelProxyException; + +/** + * + * @author jmarranz + */ +public class CommandOther extends Command +{ + public CommandOther(JProxyShellProcessor parent,String name) + { + super(parent,name); + } + + @Override + public boolean run() + { + if (name.equals("clear")) + { + commandClear(); + } + else if (name.equals("display")) + { + commandDisplay(); + } + else if (name.equals("exec")) + { + commandExec(); + } + else if (name.equals("exit")) + { + commandExit(); + } + else if (name.equals("help")) + { + commandHelp(); + } + else if (name.equals("quit")) + { + commandExit(); + } + else throw new RelProxyException("Internal Error"); + + return true; + } + + @Override + public void runPostCommand() + { + } + + private void commandClear() + { + parent.clearCodeBuffer(); + } + + private void commandExit() + { + System.exit(0); + } + + private void commandDisplay() + { + System.out.println("001>"); // La primera línea es siempre vacía porque en ella es donde ponemos el "public class /_jproxyShellInMemoryClass_ { " que el usuario ignora, así al dar error el número de línea será correcto respecto al "display" + + int i = 2; + for(String line : parent.getCodeBuffer()) + { + for(int j = 0; j < 3 - String.valueOf(i).length(); j++) System.out.print("0"); + System.out.print(i + ">"); + System.out.print(line); + System.out.println(); + i++; + } + } + + private void commandExec() + { + parent.executeCodeBuffer(); + } + + private void commandHelp() + { + System.out.println("Everything you write in the prompt is added to a code buffer, code buffer is compiled on the fly and executed by exec command, unless a command is detected"); + System.out.println(""); + System.out.println("Available commands:"); + System.out.println(" clear"); + System.out.println(" Clears the buffer"); + System.out.println(" display"); + System.out.println(" Shows the buffer content"); + System.out.println(" edit last | "); + System.out.println(" Edits the last introduced line code or the specified line number"); + System.out.println(" exec"); + System.out.println(" Compile and execute the buffer content"); + System.out.println(" exit"); + System.out.println(" Exits shell"); + System.out.println(" help"); + System.out.println(" This command"); + System.out.println(" insert last | "); + System.out.println(" Insert the next line of code before the last introduced line or the specified line number"); + System.out.println(" load | "); + System.out.println(" Load a file or URL into the buffer"); + System.out.println(" quit"); + System.out.println(" Same as exit"); + System.out.println(" save "); + System.out.println(" Save the current buffer to a file"); + } +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandSave.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandSave.java similarity index 96% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandSave.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandSave.java index 472d5f5..e5fc8fd 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandSave.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandSave.java @@ -1,61 +1,61 @@ -package com.innowhere.relproxy.impl.jproxy.shell.inter; - -import com.innowhere.relproxy.impl.jproxy.JProxyUtil; -import java.io.File; -import java.util.List; - -/** - * - * @author jmarranz - */ -public class CommandSave extends Command -{ - public static final String NAME = "save"; - protected String path; - - public CommandSave(JProxyShellProcessor parent,String url) - { - super(parent,NAME); - this.path = url; - } - - public static CommandSave createCommandSave(JProxyShellProcessor parent,String cmd) - { - String url = getParameter(NAME,cmd); - if (url == null) - { - System.out.println("Command error: parameter is required"); - return null; - } - - return new CommandSave(parent,url); - } - - @Override - public boolean run() - { - try - { - List codeBuffer = parent.getCodeBuffer(); - StringBuilder code = new StringBuilder(); - for(String line : codeBuffer) - { - code.append(line); - code.append("\n"); - } - byte[] content = code.toString().getBytes(parent.getEncoding()); // Como no conocemos encoding... - JProxyUtil.saveFile(new File(path),content); - return true; - } - catch (Exception ex) - { - ex.printStackTrace(); - return false; - } - } - - @Override - public void runPostCommand() - { - } -} +package com.innowhere.relproxy.impl.jproxy.shell.inter; + +import com.innowhere.relproxy.impl.jproxy.JProxyUtil; +import java.io.File; +import java.util.List; + +/** + * + * @author jmarranz + */ +public class CommandSave extends Command +{ + public static final String NAME = "save"; + protected String path; + + public CommandSave(JProxyShellProcessor parent,String url) + { + super(parent,NAME); + this.path = url; + } + + public static CommandSave createCommandSave(JProxyShellProcessor parent,String cmd) + { + String url = getParameter(NAME,cmd); + if (url == null) + { + System.out.println("Command error: parameter is required"); + return null; + } + + return new CommandSave(parent,url); + } + + @Override + public boolean run() + { + try + { + List codeBuffer = parent.getCodeBuffer(); + StringBuilder code = new StringBuilder(); + for(String line : codeBuffer) + { + code.append(line); + code.append("\n"); + } + byte[] content = code.toString().getBytes(parent.getEncoding()); // Como no conocemos encoding... + JProxyUtil.saveFile(new File(path),content); + return true; + } + catch (Exception ex) + { + ex.printStackTrace(); + return false; + } + } + + @Override + public void runPostCommand() + { + } +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java similarity index 97% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java index 4e80200..311dbd7 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java @@ -1,215 +1,215 @@ -package com.innowhere.relproxy.impl.jproxy.shell.inter; - -import com.innowhere.relproxy.RelProxy; -import com.innowhere.relproxy.RelProxyException; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.JProxyCompilationException; -import com.innowhere.relproxy.impl.jproxy.shell.JProxyShellInteractiveImpl; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.Scanner; - -/** - * - * @author jmarranz - */ -public class JProxyShellProcessor -{ - public static final int LINE_OFFSET = 2; // El índice en codeBuffer + este valor = al valor de la línea que se muestra al usuario, hay que tener en cuenta que contamos desde uno y la primera línea es siempre vacía - - protected JProxyShellInteractiveImpl parent; - protected Charset encoding = Charset.defaultCharset(); - protected ArrayList codeBuffer = new ArrayList(20); - protected Keyboard keyboard = KeyboardNotUsingClipboard.create(encoding); - protected int lastLine = -1; // Indice respecto a codeBuffer - protected int lineEditing = -1; // Indice respecto a codeBuffer - protected long codeBufferModTimestamp = 0; - protected long lastCodeCompiledTimestamp = 0; - - public JProxyShellProcessor(JProxyShellInteractiveImpl parent) - { - this.parent = parent; - } - - public Keyboard getKeyboard() - { - return keyboard; - } - - public Charset getEncoding() - { - return encoding; - } - - public int getLastLine() - { - return lastLine; - } - - public void setLineEditing(int lineEditing) - { - this.lineEditing = lineEditing; - } - - public void test() - { - try { Thread.sleep(2); } catch (InterruptedException ex){ } - execute("System.out.println(\"Hello World\");"); // "Object o = null; o.equals(null);" - } - - public void loop() - { - System.out.println("RelProxy Java Shell v" + RelProxy.getVersion()); - System.out.println("Write help for help"); - - Scanner sc = new Scanner(System.in,encoding.name()); // No encuentro nada interesante en http://docs.oracle.com/javase/6/docs/api/java/io/Console.html - System.out.print(">"); - while(true) - { - String line = sc.nextLine(); - Command command = Command.createCommand(this,line); - if (command != null) - { - if (command instanceof CommandError) // Era un comando pero con params erróneos - { - // Nada que hacer - System.out.print(">"); - } - else - { - boolean success = command.run(); - - System.out.print(">"); - - if (success) - { - command.runPostCommand(); // Lo normal es que no haga nada - } - } - } - else - { - if (lineEditing != -1) - { - setCodeBuffer(lineEditing, line); - this.lineEditing = -1; - } - else - { - addCodeBuffer(line); - } - - System.out.print(">"); - } - } - } - - public List getCodeBuffer() - { - return Collections.unmodifiableList(codeBuffer); - } - - public void setCodeBuffer(int index,String line) - { - codeBuffer.set(index, line); - this.codeBufferModTimestamp = System.currentTimeMillis(); - this.lastLine = index; - } - - public void setCodeBuffer(LinkedList codeBuffer) - { - codeBuffer.clear(); - this.codeBuffer.addAll(codeBuffer); - this.codeBufferModTimestamp = System.currentTimeMillis(); - this.lastLine = codeBuffer.size() - 1; - } - - public void insertCodeBuffer(int index,String line) - { - codeBuffer.add(index, line); - this.codeBufferModTimestamp = System.currentTimeMillis(); - this.lastLine = index; - } - - public void addCodeBuffer(String line) - { - codeBuffer.add(line); - this.codeBufferModTimestamp = System.currentTimeMillis(); - this.lastLine = codeBuffer.size() - 1; - } - - public void removeCodeBuffer(int index) - { - codeBuffer.remove(index); - this.codeBufferModTimestamp = System.currentTimeMillis(); - this.lastLine = -1; // La hemos eliminado, no existe ya - } - - public void clearCodeBuffer() - { - codeBuffer.clear(); - this.codeBufferModTimestamp = System.currentTimeMillis(); - this.lastLine = - 1; - } - - public void executeCodeBuffer() - { - StringBuilder code = new StringBuilder(); - for(String line : codeBuffer) - { - code.append(line); - code.append("\n"); - } - execute(code.toString()); - } - - private void execute(String code) - { - // Este código no es thread safe ni falta que hace. - - ClassDescriptorSourceScript classDescSourceScript = parent.getClassDescriptorSourceScript(); - - if (codeBufferModTimestamp > lastCodeCompiledTimestamp) // Incluimos el = por si acaso va todo muy seguido - { - parent.getSourceScriptInMemory().setScriptCode(code,codeBufferModTimestamp); - // Recuerda que cada vez que se obtiene el timestamp se llama a System.currentTimeMillis(), es imposible que el usuario haga algo en menos de 1ms - - JProxyEngine engine = parent.getJProxyEngine(); - - ClassDescriptorSourceScript classDescSourceScript2 = null; - try - { - classDescSourceScript2 = engine.detectChangesInSourcesAndReload(); - } - catch(JProxyCompilationException ex) - { - System.out.println("Compilation error"); - return; - } - - if (classDescSourceScript2 != classDescSourceScript) - throw new RelProxyException("Internal Error"); - - this.lastCodeCompiledTimestamp = System.currentTimeMillis(); - if (lastCodeCompiledTimestamp == codeBufferModTimestamp) // Demasiado rápido compilando - { - // El ser humano es muy raro y es posible que a alguien se le ocurra usar el shell de forma automatizada y se genere un siguiente cambio en el - // código fuente tan rápido que no cambie el ms, así nos aseguramos con total rotundidad que la modificación posterior de código fuente su timestamp es MAYOR que el de compilación último - try { Thread.sleep(1); } catch (InterruptedException ex) { throw new RelProxyException(ex); } - } - } - - try - { - classDescSourceScript.callMainMethod(new LinkedList()); - } - catch(Throwable ex) - { - ex.printStackTrace(System.out); - } - } -} +package com.innowhere.relproxy.impl.jproxy.shell.inter; + +import com.innowhere.relproxy.RelProxy; +import com.innowhere.relproxy.RelProxyException; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; +import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.JProxyCompilationException; +import com.innowhere.relproxy.impl.jproxy.shell.JProxyShellInteractiveImpl; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Scanner; + +/** + * + * @author jmarranz + */ +public class JProxyShellProcessor +{ + public static final int LINE_OFFSET = 2; // El índice en codeBuffer + este valor = al valor de la línea que se muestra al usuario, hay que tener en cuenta que contamos desde uno y la primera línea es siempre vacía + + protected JProxyShellInteractiveImpl parent; + protected Charset encoding = Charset.defaultCharset(); + protected ArrayList codeBuffer = new ArrayList(20); + protected Keyboard keyboard = KeyboardNotUsingClipboard.create(encoding); + protected int lastLine = -1; // Indice respecto a codeBuffer + protected int lineEditing = -1; // Indice respecto a codeBuffer + protected long codeBufferModTimestamp = 0; + protected long lastCodeCompiledTimestamp = 0; + + public JProxyShellProcessor(JProxyShellInteractiveImpl parent) + { + this.parent = parent; + } + + public Keyboard getKeyboard() + { + return keyboard; + } + + public Charset getEncoding() + { + return encoding; + } + + public int getLastLine() + { + return lastLine; + } + + public void setLineEditing(int lineEditing) + { + this.lineEditing = lineEditing; + } + + public void test() + { + try { Thread.sleep(2); } catch (InterruptedException ex){ } + execute("System.out.println(\"Hello World\");"); // "Object o = null; o.equals(null);" + } + + public void loop() + { + System.out.println("RelProxy Java Shell v" + RelProxy.getVersion()); + System.out.println("Write help for help"); + + Scanner sc = new Scanner(System.in,encoding.name()); // No encuentro nada interesante en http://docs.oracle.com/javase/6/docs/api/java/io/Console.html + System.out.print(">"); + while(true) + { + String line = sc.nextLine(); + Command command = Command.createCommand(this,line); + if (command != null) + { + if (command instanceof CommandError) // Era un comando pero con params erróneos + { + // Nada que hacer + System.out.print(">"); + } + else + { + boolean success = command.run(); + + System.out.print(">"); + + if (success) + { + command.runPostCommand(); // Lo normal es que no haga nada + } + } + } + else + { + if (lineEditing != -1) + { + setCodeBuffer(lineEditing, line); + this.lineEditing = -1; + } + else + { + addCodeBuffer(line); + } + + System.out.print(">"); + } + } + } + + public List getCodeBuffer() + { + return Collections.unmodifiableList(codeBuffer); + } + + public void setCodeBuffer(int index,String line) + { + codeBuffer.set(index, line); + this.codeBufferModTimestamp = System.currentTimeMillis(); + this.lastLine = index; + } + + public void setCodeBuffer(LinkedList codeBuffer) + { + codeBuffer.clear(); + this.codeBuffer.addAll(codeBuffer); + this.codeBufferModTimestamp = System.currentTimeMillis(); + this.lastLine = codeBuffer.size() - 1; + } + + public void insertCodeBuffer(int index,String line) + { + codeBuffer.add(index, line); + this.codeBufferModTimestamp = System.currentTimeMillis(); + this.lastLine = index; + } + + public void addCodeBuffer(String line) + { + codeBuffer.add(line); + this.codeBufferModTimestamp = System.currentTimeMillis(); + this.lastLine = codeBuffer.size() - 1; + } + + public void removeCodeBuffer(int index) + { + codeBuffer.remove(index); + this.codeBufferModTimestamp = System.currentTimeMillis(); + this.lastLine = -1; // La hemos eliminado, no existe ya + } + + public void clearCodeBuffer() + { + codeBuffer.clear(); + this.codeBufferModTimestamp = System.currentTimeMillis(); + this.lastLine = - 1; + } + + public void executeCodeBuffer() + { + StringBuilder code = new StringBuilder(); + for(String line : codeBuffer) + { + code.append(line); + code.append("\n"); + } + execute(code.toString()); + } + + private void execute(String code) + { + // Este código no es thread safe ni falta que hace. + + ClassDescriptorSourceScript classDescSourceScript = parent.getClassDescriptorSourceScript(); + + if (codeBufferModTimestamp > lastCodeCompiledTimestamp) // Incluimos el = por si acaso va todo muy seguido + { + parent.getSourceScriptInMemory().setScriptCode(code,codeBufferModTimestamp); + // Recuerda que cada vez que se obtiene el timestamp se llama a System.currentTimeMillis(), es imposible que el usuario haga algo en menos de 1ms + + JProxyEngine engine = parent.getJProxyEngine(); + + ClassDescriptorSourceScript classDescSourceScript2 = null; + try + { + classDescSourceScript2 = engine.detectChangesInSourcesAndReload(); + } + catch(JProxyCompilationException ex) + { + System.out.println("Compilation error"); + return; + } + + if (classDescSourceScript2 != classDescSourceScript) + throw new RelProxyException("Internal Error"); + + this.lastCodeCompiledTimestamp = System.currentTimeMillis(); + if (lastCodeCompiledTimestamp == codeBufferModTimestamp) // Demasiado rápido compilando + { + // El ser humano es muy raro y es posible que a alguien se le ocurra usar el shell de forma automatizada y se genere un siguiente cambio en el + // código fuente tan rápido que no cambie el ms, así nos aseguramos con total rotundidad que la modificación posterior de código fuente su timestamp es MAYOR que el de compilación último + try { Thread.sleep(1); } catch (InterruptedException ex) { throw new RelProxyException(ex); } + } + } + + try + { + classDescSourceScript.callMainMethod(new LinkedList()); + } + catch(Throwable ex) + { + ex.printStackTrace(System.out); + } + } +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/Keyboard.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/Keyboard.java similarity index 100% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/Keyboard.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/Keyboard.java diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java similarity index 97% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java index 3a21838..275ea10 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java @@ -1,302 +1,302 @@ -package com.innowhere.relproxy.impl.jproxy.shell.inter; - - -import com.innowhere.relproxy.RelProxyException; -import java.awt.AWTException; -import java.awt.Robot; -import static java.awt.event.KeyEvent.VK_0; -import static java.awt.event.KeyEvent.VK_1; -import static java.awt.event.KeyEvent.VK_2; -import static java.awt.event.KeyEvent.VK_3; -import static java.awt.event.KeyEvent.VK_4; -import static java.awt.event.KeyEvent.VK_5; -import static java.awt.event.KeyEvent.VK_6; -import static java.awt.event.KeyEvent.VK_7; -import static java.awt.event.KeyEvent.VK_8; -import static java.awt.event.KeyEvent.VK_9; -import static java.awt.event.KeyEvent.VK_A; -import static java.awt.event.KeyEvent.VK_B; -import static java.awt.event.KeyEvent.VK_C; -import static java.awt.event.KeyEvent.VK_D; -import static java.awt.event.KeyEvent.VK_E; -import static java.awt.event.KeyEvent.VK_F; -import static java.awt.event.KeyEvent.VK_G; -import static java.awt.event.KeyEvent.VK_H; -import static java.awt.event.KeyEvent.VK_I; -import static java.awt.event.KeyEvent.VK_J; -import static java.awt.event.KeyEvent.VK_K; -import static java.awt.event.KeyEvent.VK_L; -import static java.awt.event.KeyEvent.VK_M; -import static java.awt.event.KeyEvent.VK_N; -import static java.awt.event.KeyEvent.VK_NUMPAD0; -import static java.awt.event.KeyEvent.VK_NUMPAD1; -import static java.awt.event.KeyEvent.VK_NUMPAD2; -import static java.awt.event.KeyEvent.VK_NUMPAD3; -import static java.awt.event.KeyEvent.VK_NUMPAD4; -import static java.awt.event.KeyEvent.VK_NUMPAD5; -import static java.awt.event.KeyEvent.VK_NUMPAD6; -import static java.awt.event.KeyEvent.VK_NUMPAD7; -import static java.awt.event.KeyEvent.VK_NUMPAD8; -import static java.awt.event.KeyEvent.VK_NUMPAD9; -import static java.awt.event.KeyEvent.VK_O; -import static java.awt.event.KeyEvent.VK_P; -import static java.awt.event.KeyEvent.VK_Q; -import static java.awt.event.KeyEvent.VK_R; -import static java.awt.event.KeyEvent.VK_S; -import static java.awt.event.KeyEvent.VK_SHIFT; -import static java.awt.event.KeyEvent.VK_SPACE; -import static java.awt.event.KeyEvent.VK_T; -import static java.awt.event.KeyEvent.VK_U; -import static java.awt.event.KeyEvent.VK_V; -import static java.awt.event.KeyEvent.VK_W; -import static java.awt.event.KeyEvent.VK_X; -import static java.awt.event.KeyEvent.VK_Y; -import static java.awt.event.KeyEvent.VK_Z; -import java.nio.ByteBuffer; -import java.nio.charset.Charset; - -/** - * http://stackoverflow.com/questions/1248510/convert-string-to-keyevents - * http://en.wikipedia.org/wiki/Unicode_input#Hexadecimal_code_input - * http://stackoverflow.com/questions/9814701/accent-with-robot-keypress - * - * @author jmarranz - */ -public abstract class KeyboardNotUsingClipboard extends Keyboard -{ - protected final Robot robot; - protected Charset cs; - - - - public KeyboardNotUsingClipboard(Charset cs) - { - this.cs = cs; - try - { - this.robot = new Robot(); - } - catch (AWTException ex) - { - throw new RelProxyException(ex); - } - } - - public static KeyboardNotUsingClipboard create(Charset cs) - { - String osName = System.getProperty("os.name").toLowerCase(); - if (osName.contains("windows")) return new WindowUnicodeKeyboard(cs); - else if (osName.contains("os x")) return new MacOSXUnicodeKeyboard(cs);// https://developer.apple.com/library/mac/technotes/tn2002/tn2110.html - else return new LinuxUnicodeKeyboard(cs); - } - - private int[] getUnicodeInt(char character) - { - if (isUseCodePoint()) - { - char[] charArray = new char[]{character}; - int count = Character.codePointCount(charArray, 0,charArray.length); - int[] res = new int[count]; - for(int i = 0; i < count; i++) - res[i] = Character.codePointAt(charArray,i); - return res; - } - else - { - ByteBuffer buffer = cs.encode("" + character); - int size = buffer.limit(); - int[] res = new int[size]; - for(int i = 0; i < size; i++) - { - byte b = buffer.get(); - int bi = b & 0x000000FF; - res[i] = bi; - } - return res; - } - } - - protected String getUnicodeDigits(char character,int radix) - { - int[] uds = getUnicodeInt(character); - StringBuilder res = new StringBuilder(); - for(int i = 0; i < uds.length; i++) - { - int ud = uds[i]; - String digits; - if (radix == 10) - digits = Integer.toString(ud); - else - digits = Integer.toString(ud,radix); // Si es 16 es hexadecimal - res.append(digits); - } - return res.toString(); - } - - protected void typeNumPad(int digit) { - switch (digit) { - case 0: doType(VK_NUMPAD0); break; - case 1: doType(VK_NUMPAD1); break; - case 2: doType(VK_NUMPAD2); break; - case 3: doType(VK_NUMPAD3); break; - case 4: doType(VK_NUMPAD4); break; - case 5: doType(VK_NUMPAD5); break; - case 6: doType(VK_NUMPAD6); break; - case 7: doType(VK_NUMPAD7); break; - case 8: doType(VK_NUMPAD8); break; - case 9: doType(VK_NUMPAD9); break; - default: // Para que se calle el FindBugs - } - } - - - public void type(CharSequence characters) { - int length = characters.length(); - for (int i = 0; i < length; i++) { - char character = characters.charAt(i); - type(character); - } - } - - public boolean type(char character) { - - // He quitado todos los símbolos que son susceptibles de cambiar según el teclado pues hay que acertar exactamente la combinación de teclas del teclado - // concreto o da error, ej no vale emitir VK_COLON únicamente si en el teclado concreto es necesario un SHIFT - // En la clase derivada se procesan los caracteres no contemplados aquí - - switch (character) { - case 'a': doType(VK_A); break; - case 'b': doType(VK_B); break; - case 'c': doType(VK_C); break; - case 'd': doType(VK_D); break; - case 'e': doType(VK_E); break; - case 'f': doType(VK_F); break; - case 'g': doType(VK_G); break; - case 'h': doType(VK_H); break; - case 'i': doType(VK_I); break; - case 'j': doType(VK_J); break; - case 'k': doType(VK_K); break; - case 'l': doType(VK_L); break; - case 'm': doType(VK_M); break; - case 'n': doType(VK_N); break; - case 'o': doType(VK_O); break; - case 'p': doType(VK_P); break; - case 'q': doType(VK_Q); break; - case 'r': doType(VK_R); break; - case 's': doType(VK_S); break; - case 't': doType(VK_T); break; - case 'u': doType(VK_U); break; - case 'v': doType(VK_V); break; - case 'w': doType(VK_W); break; - case 'x': doType(VK_X); break; - case 'y': doType(VK_Y); break; - case 'z': doType(VK_Z); break; - case 'A': doType(VK_SHIFT, VK_A); break; - case 'B': doType(VK_SHIFT, VK_B); break; - case 'C': doType(VK_SHIFT, VK_C); break; - case 'D': doType(VK_SHIFT, VK_D); break; - case 'E': doType(VK_SHIFT, VK_E); break; - case 'F': doType(VK_SHIFT, VK_F); break; - case 'G': doType(VK_SHIFT, VK_G); break; - case 'H': doType(VK_SHIFT, VK_H); break; - case 'I': doType(VK_SHIFT, VK_I); break; - case 'J': doType(VK_SHIFT, VK_J); break; - case 'K': doType(VK_SHIFT, VK_K); break; - case 'L': doType(VK_SHIFT, VK_L); break; - case 'M': doType(VK_SHIFT, VK_M); break; - case 'N': doType(VK_SHIFT, VK_N); break; - case 'O': doType(VK_SHIFT, VK_O); break; - case 'P': doType(VK_SHIFT, VK_P); break; - case 'Q': doType(VK_SHIFT, VK_Q); break; - case 'R': doType(VK_SHIFT, VK_R); break; - case 'S': doType(VK_SHIFT, VK_S); break; - case 'T': doType(VK_SHIFT, VK_T); break; - case 'U': doType(VK_SHIFT, VK_U); break; - case 'V': doType(VK_SHIFT, VK_V); break; - case 'W': doType(VK_SHIFT, VK_W); break; - case 'X': doType(VK_SHIFT, VK_X); break; - case 'Y': doType(VK_SHIFT, VK_Y); break; - case 'Z': doType(VK_SHIFT, VK_Z); break; - // case '`': doType(VK_BACK_QUOTE); break; - case '0': doType(VK_0); break; - case '1': doType(VK_1); break; - case '2': doType(VK_2); break; - case '3': doType(VK_3); break; - case '4': doType(VK_4); break; - case '5': doType(VK_5); break; - case '6': doType(VK_6); break; - case '7': doType(VK_7); break; - case '8': doType(VK_8); break; - case '9': doType(VK_9); break; - /* - case '-': doType(VK_MINUS); break; - case '=': doType(VK_EQUALS); break; - case '~': doType(VK_SHIFT, VK_BACK_QUOTE); break; - case '!': doType(VK_EXCLAMATION_MARK); break; - case '@': doType(VK_AT); break; - case '#': doType(VK_NUMBER_SIGN); break; - case '$': doType(VK_DOLLAR); break; - case '%': doType(VK_SHIFT, VK_5); break; - case '^': doType(VK_CIRCUMFLEX); break; - case '&': doType(VK_AMPERSAND); break; - case '*': doType(VK_ASTERISK); break; - case '(': doType(VK_LEFT_PARENTHESIS); break; - case ')': doType(VK_RIGHT_PARENTHESIS); break; - case '_': doType(VK_UNDERSCORE); break; - case '+': doType(VK_PLUS); break; - case '\t': doType(VK_TAB); break; - case '\n': doType(VK_ENTER); break; - case '[': doType(VK_OPEN_BRACKET); break; - case ']': doType(VK_CLOSE_BRACKET); break; - case '\\': doType(VK_BACK_SLASH); break; - case '{': doType(VK_SHIFT, VK_OPEN_BRACKET); break; - case '}': doType(VK_SHIFT, VK_CLOSE_BRACKET); break; - case '|': doType(VK_SHIFT, VK_BACK_SLASH); break; - case ';': doType(VK_SEMICOLON); break; - case ':': doType(VK_COLON); break; - case '\'': doType(VK_QUOTE); break; - case '"': doType(VK_QUOTEDBL); break; - case ',': doType(VK_COMMA); break; - case '<': doType(VK_LESS); break; - case '.': doType(VK_PERIOD); break; - case '>': doType(VK_GREATER); break; - case '/': doType(VK_SLASH); break; - case '?': doType(VK_SHIFT, VK_SLASH); break; - */ - case ' ': doType(VK_SPACE); break; - default: - return false; - } - - return true; - } - - protected void doType(int... keyCodes) { - doTypeArr(keyCodes); - } - - private void doTypeArr(int[] keyCodes) { - int length = keyCodes.length; - if (length == 1) - { - doType(keyCodes[0]); - } - else // 2 - { - robot.keyPress(keyCodes[0]); - robot.keyPress(keyCodes[1]); - - robot.keyRelease(keyCodes[1]); - robot.keyRelease(keyCodes[0]); - } - } - - protected void doType(int keyCode) - { - robot.keyPress(keyCode); - robot.keyRelease(keyCode); - } - - public abstract boolean isUseCodePoint(); - -} +package com.innowhere.relproxy.impl.jproxy.shell.inter; + + +import com.innowhere.relproxy.RelProxyException; +import java.awt.AWTException; +import java.awt.Robot; +import static java.awt.event.KeyEvent.VK_0; +import static java.awt.event.KeyEvent.VK_1; +import static java.awt.event.KeyEvent.VK_2; +import static java.awt.event.KeyEvent.VK_3; +import static java.awt.event.KeyEvent.VK_4; +import static java.awt.event.KeyEvent.VK_5; +import static java.awt.event.KeyEvent.VK_6; +import static java.awt.event.KeyEvent.VK_7; +import static java.awt.event.KeyEvent.VK_8; +import static java.awt.event.KeyEvent.VK_9; +import static java.awt.event.KeyEvent.VK_A; +import static java.awt.event.KeyEvent.VK_B; +import static java.awt.event.KeyEvent.VK_C; +import static java.awt.event.KeyEvent.VK_D; +import static java.awt.event.KeyEvent.VK_E; +import static java.awt.event.KeyEvent.VK_F; +import static java.awt.event.KeyEvent.VK_G; +import static java.awt.event.KeyEvent.VK_H; +import static java.awt.event.KeyEvent.VK_I; +import static java.awt.event.KeyEvent.VK_J; +import static java.awt.event.KeyEvent.VK_K; +import static java.awt.event.KeyEvent.VK_L; +import static java.awt.event.KeyEvent.VK_M; +import static java.awt.event.KeyEvent.VK_N; +import static java.awt.event.KeyEvent.VK_NUMPAD0; +import static java.awt.event.KeyEvent.VK_NUMPAD1; +import static java.awt.event.KeyEvent.VK_NUMPAD2; +import static java.awt.event.KeyEvent.VK_NUMPAD3; +import static java.awt.event.KeyEvent.VK_NUMPAD4; +import static java.awt.event.KeyEvent.VK_NUMPAD5; +import static java.awt.event.KeyEvent.VK_NUMPAD6; +import static java.awt.event.KeyEvent.VK_NUMPAD7; +import static java.awt.event.KeyEvent.VK_NUMPAD8; +import static java.awt.event.KeyEvent.VK_NUMPAD9; +import static java.awt.event.KeyEvent.VK_O; +import static java.awt.event.KeyEvent.VK_P; +import static java.awt.event.KeyEvent.VK_Q; +import static java.awt.event.KeyEvent.VK_R; +import static java.awt.event.KeyEvent.VK_S; +import static java.awt.event.KeyEvent.VK_SHIFT; +import static java.awt.event.KeyEvent.VK_SPACE; +import static java.awt.event.KeyEvent.VK_T; +import static java.awt.event.KeyEvent.VK_U; +import static java.awt.event.KeyEvent.VK_V; +import static java.awt.event.KeyEvent.VK_W; +import static java.awt.event.KeyEvent.VK_X; +import static java.awt.event.KeyEvent.VK_Y; +import static java.awt.event.KeyEvent.VK_Z; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; + +/** + * http://stackoverflow.com/questions/1248510/convert-string-to-keyevents + * http://en.wikipedia.org/wiki/Unicode_input#Hexadecimal_code_input + * http://stackoverflow.com/questions/9814701/accent-with-robot-keypress + * + * @author jmarranz + */ +public abstract class KeyboardNotUsingClipboard extends Keyboard +{ + protected final Robot robot; + protected Charset cs; + + + + public KeyboardNotUsingClipboard(Charset cs) + { + this.cs = cs; + try + { + this.robot = new Robot(); + } + catch (AWTException ex) + { + throw new RelProxyException(ex); + } + } + + public static KeyboardNotUsingClipboard create(Charset cs) + { + String osName = System.getProperty("os.name").toLowerCase(); + if (osName.contains("windows")) return new WindowUnicodeKeyboard(cs); + else if (osName.contains("os x")) return new MacOSXUnicodeKeyboard(cs);// https://developer.apple.com/library/mac/technotes/tn2002/tn2110.html + else return new LinuxUnicodeKeyboard(cs); + } + + private int[] getUnicodeInt(char character) + { + if (isUseCodePoint()) + { + char[] charArray = new char[]{character}; + int count = Character.codePointCount(charArray, 0,charArray.length); + int[] res = new int[count]; + for(int i = 0; i < count; i++) + res[i] = Character.codePointAt(charArray,i); + return res; + } + else + { + ByteBuffer buffer = cs.encode("" + character); + int size = buffer.limit(); + int[] res = new int[size]; + for(int i = 0; i < size; i++) + { + byte b = buffer.get(); + int bi = b & 0x000000FF; + res[i] = bi; + } + return res; + } + } + + protected String getUnicodeDigits(char character,int radix) + { + int[] uds = getUnicodeInt(character); + StringBuilder res = new StringBuilder(); + for(int i = 0; i < uds.length; i++) + { + int ud = uds[i]; + String digits; + if (radix == 10) + digits = Integer.toString(ud); + else + digits = Integer.toString(ud,radix); // Si es 16 es hexadecimal + res.append(digits); + } + return res.toString(); + } + + protected void typeNumPad(int digit) { + switch (digit) { + case 0: doType(VK_NUMPAD0); break; + case 1: doType(VK_NUMPAD1); break; + case 2: doType(VK_NUMPAD2); break; + case 3: doType(VK_NUMPAD3); break; + case 4: doType(VK_NUMPAD4); break; + case 5: doType(VK_NUMPAD5); break; + case 6: doType(VK_NUMPAD6); break; + case 7: doType(VK_NUMPAD7); break; + case 8: doType(VK_NUMPAD8); break; + case 9: doType(VK_NUMPAD9); break; + default: // Para que se calle el FindBugs + } + } + + + public void type(CharSequence characters) { + int length = characters.length(); + for (int i = 0; i < length; i++) { + char character = characters.charAt(i); + type(character); + } + } + + public boolean type(char character) { + + // He quitado todos los símbolos que son susceptibles de cambiar según el teclado pues hay que acertar exactamente la combinación de teclas del teclado + // concreto o da error, ej no vale emitir VK_COLON únicamente si en el teclado concreto es necesario un SHIFT + // En la clase derivada se procesan los caracteres no contemplados aquí + + switch (character) { + case 'a': doType(VK_A); break; + case 'b': doType(VK_B); break; + case 'c': doType(VK_C); break; + case 'd': doType(VK_D); break; + case 'e': doType(VK_E); break; + case 'f': doType(VK_F); break; + case 'g': doType(VK_G); break; + case 'h': doType(VK_H); break; + case 'i': doType(VK_I); break; + case 'j': doType(VK_J); break; + case 'k': doType(VK_K); break; + case 'l': doType(VK_L); break; + case 'm': doType(VK_M); break; + case 'n': doType(VK_N); break; + case 'o': doType(VK_O); break; + case 'p': doType(VK_P); break; + case 'q': doType(VK_Q); break; + case 'r': doType(VK_R); break; + case 's': doType(VK_S); break; + case 't': doType(VK_T); break; + case 'u': doType(VK_U); break; + case 'v': doType(VK_V); break; + case 'w': doType(VK_W); break; + case 'x': doType(VK_X); break; + case 'y': doType(VK_Y); break; + case 'z': doType(VK_Z); break; + case 'A': doType(VK_SHIFT, VK_A); break; + case 'B': doType(VK_SHIFT, VK_B); break; + case 'C': doType(VK_SHIFT, VK_C); break; + case 'D': doType(VK_SHIFT, VK_D); break; + case 'E': doType(VK_SHIFT, VK_E); break; + case 'F': doType(VK_SHIFT, VK_F); break; + case 'G': doType(VK_SHIFT, VK_G); break; + case 'H': doType(VK_SHIFT, VK_H); break; + case 'I': doType(VK_SHIFT, VK_I); break; + case 'J': doType(VK_SHIFT, VK_J); break; + case 'K': doType(VK_SHIFT, VK_K); break; + case 'L': doType(VK_SHIFT, VK_L); break; + case 'M': doType(VK_SHIFT, VK_M); break; + case 'N': doType(VK_SHIFT, VK_N); break; + case 'O': doType(VK_SHIFT, VK_O); break; + case 'P': doType(VK_SHIFT, VK_P); break; + case 'Q': doType(VK_SHIFT, VK_Q); break; + case 'R': doType(VK_SHIFT, VK_R); break; + case 'S': doType(VK_SHIFT, VK_S); break; + case 'T': doType(VK_SHIFT, VK_T); break; + case 'U': doType(VK_SHIFT, VK_U); break; + case 'V': doType(VK_SHIFT, VK_V); break; + case 'W': doType(VK_SHIFT, VK_W); break; + case 'X': doType(VK_SHIFT, VK_X); break; + case 'Y': doType(VK_SHIFT, VK_Y); break; + case 'Z': doType(VK_SHIFT, VK_Z); break; + // case '`': doType(VK_BACK_QUOTE); break; + case '0': doType(VK_0); break; + case '1': doType(VK_1); break; + case '2': doType(VK_2); break; + case '3': doType(VK_3); break; + case '4': doType(VK_4); break; + case '5': doType(VK_5); break; + case '6': doType(VK_6); break; + case '7': doType(VK_7); break; + case '8': doType(VK_8); break; + case '9': doType(VK_9); break; + /* + case '-': doType(VK_MINUS); break; + case '=': doType(VK_EQUALS); break; + case '~': doType(VK_SHIFT, VK_BACK_QUOTE); break; + case '!': doType(VK_EXCLAMATION_MARK); break; + case '@': doType(VK_AT); break; + case '#': doType(VK_NUMBER_SIGN); break; + case '$': doType(VK_DOLLAR); break; + case '%': doType(VK_SHIFT, VK_5); break; + case '^': doType(VK_CIRCUMFLEX); break; + case '&': doType(VK_AMPERSAND); break; + case '*': doType(VK_ASTERISK); break; + case '(': doType(VK_LEFT_PARENTHESIS); break; + case ')': doType(VK_RIGHT_PARENTHESIS); break; + case '_': doType(VK_UNDERSCORE); break; + case '+': doType(VK_PLUS); break; + case '\t': doType(VK_TAB); break; + case '\n': doType(VK_ENTER); break; + case '[': doType(VK_OPEN_BRACKET); break; + case ']': doType(VK_CLOSE_BRACKET); break; + case '\\': doType(VK_BACK_SLASH); break; + case '{': doType(VK_SHIFT, VK_OPEN_BRACKET); break; + case '}': doType(VK_SHIFT, VK_CLOSE_BRACKET); break; + case '|': doType(VK_SHIFT, VK_BACK_SLASH); break; + case ';': doType(VK_SEMICOLON); break; + case ':': doType(VK_COLON); break; + case '\'': doType(VK_QUOTE); break; + case '"': doType(VK_QUOTEDBL); break; + case ',': doType(VK_COMMA); break; + case '<': doType(VK_LESS); break; + case '.': doType(VK_PERIOD); break; + case '>': doType(VK_GREATER); break; + case '/': doType(VK_SLASH); break; + case '?': doType(VK_SHIFT, VK_SLASH); break; + */ + case ' ': doType(VK_SPACE); break; + default: + return false; + } + + return true; + } + + protected void doType(int... keyCodes) { + doTypeArr(keyCodes); + } + + private void doTypeArr(int[] keyCodes) { + int length = keyCodes.length; + if (length == 1) + { + doType(keyCodes[0]); + } + else // 2 + { + robot.keyPress(keyCodes[0]); + robot.keyPress(keyCodes[1]); + + robot.keyRelease(keyCodes[1]); + robot.keyRelease(keyCodes[0]); + } + } + + protected void doType(int keyCode) + { + robot.keyPress(keyCode); + robot.keyRelease(keyCode); + } + + public abstract boolean isUseCodePoint(); + +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java similarity index 96% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java index b319695..bebf2c1 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java @@ -1,66 +1,66 @@ -package com.innowhere.relproxy.impl.jproxy.shell.inter; - - -import com.innowhere.relproxy.RelProxyException; -import java.awt.AWTException; -import java.awt.Robot; -import java.awt.Toolkit; -import java.awt.datatransfer.Clipboard; -import java.awt.datatransfer.ClipboardOwner; -import java.awt.datatransfer.StringSelection; -import java.awt.datatransfer.Transferable; -import java.awt.event.KeyEvent; -import java.nio.charset.Charset; - -/** - * http://stackoverflow.com/questions/1248510/convert-string-to-keyevents - * http://en.wikipedia.org/wiki/Unicode_input#Hexadecimal_code_input - * http://stackoverflow.com/questions/9814701/accent-with-robot-keypress - * - * @author jmarranz - */ -public class KeyboardUsingClipboard extends Keyboard implements ClipboardOwner -{ - protected final Robot robot; - protected Charset cs; - - - public KeyboardUsingClipboard(Charset cs) - { - this.cs = cs; - try - { - this.robot = new Robot(); - } - catch (AWTException ex) - { - throw new RelProxyException(ex); - } - } - - public static KeyboardUsingClipboard create(Charset cs) - { - return new KeyboardUsingClipboard(cs); - } - - - @Override - public void type(CharSequence characters) - { - Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); - StringSelection stringSelection = new StringSelection( characters.toString() ); - clipboard.setContents(stringSelection, this); - - robot.keyPress(KeyEvent.VK_CONTROL); - robot.keyPress(KeyEvent.VK_V); - robot.keyRelease(KeyEvent.VK_V); - robot.keyRelease(KeyEvent.VK_CONTROL); - } - - @Override - public void lostOwnership(Clipboard clipboard, Transferable contents) - { - - } - -} +package com.innowhere.relproxy.impl.jproxy.shell.inter; + + +import com.innowhere.relproxy.RelProxyException; +import java.awt.AWTException; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.ClipboardOwner; +import java.awt.datatransfer.StringSelection; +import java.awt.datatransfer.Transferable; +import java.awt.event.KeyEvent; +import java.nio.charset.Charset; + +/** + * http://stackoverflow.com/questions/1248510/convert-string-to-keyevents + * http://en.wikipedia.org/wiki/Unicode_input#Hexadecimal_code_input + * http://stackoverflow.com/questions/9814701/accent-with-robot-keypress + * + * @author jmarranz + */ +public class KeyboardUsingClipboard extends Keyboard implements ClipboardOwner +{ + protected final Robot robot; + protected Charset cs; + + + public KeyboardUsingClipboard(Charset cs) + { + this.cs = cs; + try + { + this.robot = new Robot(); + } + catch (AWTException ex) + { + throw new RelProxyException(ex); + } + } + + public static KeyboardUsingClipboard create(Charset cs) + { + return new KeyboardUsingClipboard(cs); + } + + + @Override + public void type(CharSequence characters) + { + Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); + StringSelection stringSelection = new StringSelection( characters.toString() ); + clipboard.setContents(stringSelection, this); + + robot.keyPress(KeyEvent.VK_CONTROL); + robot.keyPress(KeyEvent.VK_V); + robot.keyRelease(KeyEvent.VK_V); + robot.keyRelease(KeyEvent.VK_CONTROL); + } + + @Override + public void lostOwnership(Clipboard clipboard, Transferable contents) + { + + } + +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/LinuxUnicodeKeyboard.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/LinuxUnicodeKeyboard.java similarity index 96% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/LinuxUnicodeKeyboard.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/LinuxUnicodeKeyboard.java index 0957db5..9a4e8b3 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/LinuxUnicodeKeyboard.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/LinuxUnicodeKeyboard.java @@ -1,62 +1,62 @@ -package com.innowhere.relproxy.impl.jproxy.shell.inter; - -import static java.awt.event.KeyEvent.VK_CONTROL; -import static java.awt.event.KeyEvent.VK_SHIFT; -import static java.awt.event.KeyEvent.VK_U; -import java.nio.charset.Charset; - -/** - * - * http://superuser.com/questions/59418/how-to-type-special-characters-in-linux - * - * @author jmarranz - */ -public class LinuxUnicodeKeyboard extends KeyboardNotUsingClipboard -{ - public LinuxUnicodeKeyboard(Charset cs) - { - super(cs); - } - - @Override - public boolean isUseCodePoint() - { - return true; - } - - @Override - public boolean type(char character) - { - if (super.type(character)) - return true; - - String unicodeDigits = getUnicodeDigits(character,16); // En hexadecimal - - robot.keyPress(VK_CONTROL); - robot.keyPress(VK_SHIFT); - - doType(VK_U); // 'u' indica que después viene un valor unicode hexadecimal - - // Pero dejamos pulsadas CTRL y SHIFT mientras - // Ejemplo: 266A es una nota de solfeo - try - { - for (int i = 0; i < unicodeDigits.length(); i++) - { - char c = unicodeDigits.charAt(i); - if (Character.isDigit(c)) - typeNumPad(Integer.parseInt(unicodeDigits.substring(i, i + 1))); - else - type(c); - } - } - finally - { - robot.keyRelease(VK_CONTROL); - robot.keyRelease(VK_SHIFT); - } - - return true; - } - +package com.innowhere.relproxy.impl.jproxy.shell.inter; + +import static java.awt.event.KeyEvent.VK_CONTROL; +import static java.awt.event.KeyEvent.VK_SHIFT; +import static java.awt.event.KeyEvent.VK_U; +import java.nio.charset.Charset; + +/** + * + * http://superuser.com/questions/59418/how-to-type-special-characters-in-linux + * + * @author jmarranz + */ +public class LinuxUnicodeKeyboard extends KeyboardNotUsingClipboard +{ + public LinuxUnicodeKeyboard(Charset cs) + { + super(cs); + } + + @Override + public boolean isUseCodePoint() + { + return true; + } + + @Override + public boolean type(char character) + { + if (super.type(character)) + return true; + + String unicodeDigits = getUnicodeDigits(character,16); // En hexadecimal + + robot.keyPress(VK_CONTROL); + robot.keyPress(VK_SHIFT); + + doType(VK_U); // 'u' indica que después viene un valor unicode hexadecimal + + // Pero dejamos pulsadas CTRL y SHIFT mientras + // Ejemplo: 266A es una nota de solfeo + try + { + for (int i = 0; i < unicodeDigits.length(); i++) + { + char c = unicodeDigits.charAt(i); + if (Character.isDigit(c)) + typeNumPad(Integer.parseInt(unicodeDigits.substring(i, i + 1))); + else + type(c); + } + } + finally + { + robot.keyRelease(VK_CONTROL); + robot.keyRelease(VK_SHIFT); + } + + return true; + } + } \ No newline at end of file diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/MacOSXUnicodeKeyboard.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/MacOSXUnicodeKeyboard.java similarity index 96% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/MacOSXUnicodeKeyboard.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/MacOSXUnicodeKeyboard.java index f0ee4aa..1641153 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/MacOSXUnicodeKeyboard.java +++ b/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/MacOSXUnicodeKeyboard.java @@ -1,51 +1,51 @@ -package com.innowhere.relproxy.impl.jproxy.shell.inter; - -import static java.awt.Event.ALT_MASK; -import java.nio.charset.Charset; - -/** - * - * https://discussions.apple.com/thread/1899290 - * http://superuser.com/questions/13086/how-do-you-type-unicode-characters-using-hexadecimal-codes (buscar OS X) - * http://controlyourmac.com/2012/05/understanding-mac-keyboard.html - * - * @author jmarranz - */ -public class MacOSXUnicodeKeyboard extends KeyboardNotUsingClipboard -{ - public MacOSXUnicodeKeyboard(Charset cs) - { - super(cs); - } - - @Override - public boolean isUseCodePoint() - { - return true; - } - - @Override - public boolean type(char character) - { - if (super.type(character)) - return true; - - String unicodeDigits = getUnicodeDigits(character,16); // En hexadecimal - - robot.keyPress(ALT_MASK); // "Since the ALT_MASK modifier is the Option key in OS X" https://developer.apple.com/library/mac/documentation/java/conceptual/java14development/07-NativePlatformIntegration/NativePlatformIntegration.html - - try - { - for (int i = 0; i < unicodeDigits.length(); i++) { - type(unicodeDigits.charAt(i)); - } - } - finally - { - robot.keyRelease(ALT_MASK); - } - - return true; - } - +package com.innowhere.relproxy.impl.jproxy.shell.inter; + +import static java.awt.Event.ALT_MASK; +import java.nio.charset.Charset; + +/** + * + * https://discussions.apple.com/thread/1899290 + * http://superuser.com/questions/13086/how-do-you-type-unicode-characters-using-hexadecimal-codes (buscar OS X) + * http://controlyourmac.com/2012/05/understanding-mac-keyboard.html + * + * @author jmarranz + */ +public class MacOSXUnicodeKeyboard extends KeyboardNotUsingClipboard +{ + public MacOSXUnicodeKeyboard(Charset cs) + { + super(cs); + } + + @Override + public boolean isUseCodePoint() + { + return true; + } + + @Override + public boolean type(char character) + { + if (super.type(character)) + return true; + + String unicodeDigits = getUnicodeDigits(character,16); // En hexadecimal + + robot.keyPress(ALT_MASK); // "Since the ALT_MASK modifier is the Option key in OS X" https://developer.apple.com/library/mac/documentation/java/conceptual/java14development/07-NativePlatformIntegration/NativePlatformIntegration.html + + try + { + for (int i = 0; i < unicodeDigits.length(); i++) { + type(unicodeDigits.charAt(i)); + } + } + finally + { + robot.keyRelease(ALT_MASK); + } + + return true; + } + } \ No newline at end of file diff --git a/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/WindowUnicodeKeyboard.java b/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/WindowUnicodeKeyboard.java similarity index 100% rename from relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/WindowUnicodeKeyboard.java rename to src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/WindowUnicodeKeyboard.java diff --git a/relproxy/src/main/java/com/innowhere/relproxy/jproxy/JProxy.java b/src/main/java/com/innowhere/relproxy/jproxy/JProxy.java similarity index 95% rename from relproxy/src/main/java/com/innowhere/relproxy/jproxy/JProxy.java rename to src/main/java/com/innowhere/relproxy/jproxy/JProxy.java index e6b77f3..19945c9 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/jproxy/JProxy.java +++ b/src/main/java/com/innowhere/relproxy/jproxy/JProxy.java @@ -1,118 +1,118 @@ - -package com.innowhere.relproxy.jproxy; - -import com.innowhere.relproxy.impl.jproxy.JProxyConfigImpl; -import com.innowhere.relproxy.impl.jproxy.JProxyDefaultImpl; - -/** - * Is the class to create Java proxy objects based on Java objects and keep track of source code changes reloading classes when detected. - * - * @author Jose Maria Arranz Santamaria - */ -public class JProxy -{ - /** - * Creates a {@link JProxyConfig} object to be used to configure JProxy and {@link JProxyScriptEngineFactory}. - * - * @return a new configuration object. - * @see #init(JProxyConfig) - */ - public static JProxyConfig createJProxyConfig() - { - return JProxyDefaultImpl.createJProxyConfig(); - } - - /** - * Initializes JProxy with the provided configuration object. - * - * @param config - */ - public static void init(JProxyConfig config) - { - JProxyDefaultImpl.initStatic((JProxyConfigImpl)config); - } - - - - /** - * Creates a proxy object using java.lang.reflect.Proxy based on the provided Java object and the class of the implemented Java interface. - * - *

This method is a simplification for a single interface (the most common case) of {@link #create(Object,Class[])} .

- * - * @param the interface implemented by the original object and proxy object returned. - * @param obj the original object to proxy. - * @param clasz the class of the interface implemented by the original object and proxy object returned. - * @return the java.lang.reflect.Proxy object associated or the original object when GProxy is disabled. - */ - public static T create(T obj,Class clasz) - { - return JProxyDefaultImpl.createStatic(obj, clasz); - } - - /** - * Creates a proxy object using java.lang.reflect.Proxy based on the provided Java object and the classes of the implemented Java interfaces. - * - *

If JProxy has been configured and is enabled this method returns a java.lang.reflect.Proxy object implementing instead of - * the original object provided. Methods called in proxy object are received by JProxy and forwarded to the original object, if source code - * managed by JProxy has been changed, the class of the original object is reloaded based on the new source and the original object - * is recreated with the new class and fields are re-set in the new object, then the method is called on the new original object.

- * - *

If JProxy is disabled returns the original object provided with no performance penalty.

- * - * @param obj the original object to proxy. - * @param classes the classes of the interfaces implemented by the original object and proxy object returned. - * @return the java.lang.reflect.Proxy object associated or the original object when JProxy is disabled. - */ - public static Object create(Object obj,Class[] classes) - { - return JProxyDefaultImpl.createStatic(obj, classes); - } - - /** - * Informs whether JProxy is configured and enabled. - * - * @return true if enabled. - */ - public static boolean isEnabled() - { - return JProxyDefaultImpl.isEnabledStatic(); - } - - /** - * Informs whether JProxy is enabled and started (timed checking for changes). - * - * @return true if running. - */ - public static boolean isRunning() - { - return JProxyDefaultImpl.isRunningStatic(); - } - - /** - * Stops source code periodic change detection. - * - *

Periodicity of change detection is defined by {@link JProxyConfig#setScanPeriod(long)}

- * - * @return true if source change detection has been stopped, false if it is already stopped or JProxy is not enabled or initialized. - * @see #stop() - */ - public static boolean stop() - { - return JProxyDefaultImpl.stopStatic(); - } - - /** - * Starts source code periodic change detection. - * - *

Periodicity of change detection is defined by {@link JProxyConfig#setScanPeriod(long)}.

- * - *

By default when JProxy is initialized and enabled.

- * - * @return true if source change detection has been started again, false if it is already started or cannot start because JProxy is not enabled or initialized or scan period is not positive. - * @see #start() - */ - public static boolean start() - { - return JProxyDefaultImpl.startStatic(); - } -} + +package com.innowhere.relproxy.jproxy; + +import com.innowhere.relproxy.impl.jproxy.JProxyConfigImpl; +import com.innowhere.relproxy.impl.jproxy.JProxyDefaultImpl; + +/** + * Is the class to create Java proxy objects based on Java objects and keep track of source code changes reloading classes when detected. + * + * @author Jose Maria Arranz Santamaria + */ +public class JProxy +{ + /** + * Creates a {@link JProxyConfig} object to be used to configure JProxy and {@link JProxyScriptEngineFactory}. + * + * @return a new configuration object. + * @see #init(JProxyConfig) + */ + public static JProxyConfig createJProxyConfig() + { + return JProxyDefaultImpl.createJProxyConfig(); + } + + /** + * Initializes JProxy with the provided configuration object. + * + * @param config the configuration + */ + public static void init(JProxyConfig config) + { + JProxyDefaultImpl.initStatic((JProxyConfigImpl)config); + } + + + + /** + * Creates a proxy object using java.lang.reflect.Proxy based on the provided Java object and the class of the implemented Java interface. + * + *

This method is a simplification for a single interface (the most common case) of {@link #create(Object,Class[])} .

+ * + * @param the interface implemented by the original object and proxy object returned. + * @param obj the original object to proxy. + * @param clasz the class of the interface implemented by the original object and proxy object returned. + * @return the java.lang.reflect.Proxy object associated or the original object when GProxy is disabled. + */ + public static T create(T obj,Class clasz) + { + return JProxyDefaultImpl.createStatic(obj, clasz); + } + + /** + * Creates a proxy object using java.lang.reflect.Proxy based on the provided Java object and the classes of the implemented Java interfaces. + * + *

If JProxy has been configured and is enabled this method returns a java.lang.reflect.Proxy object implementing instead of + * the original object provided. Methods called in proxy object are received by JProxy and forwarded to the original object, if source code + * managed by JProxy has been changed, the class of the original object is reloaded based on the new source and the original object + * is recreated with the new class and fields are re-set in the new object, then the method is called on the new original object.

+ * + *

If JProxy is disabled returns the original object provided with no performance penalty.

+ * + * @param obj the original object to proxy. + * @param classes the classes of the interfaces implemented by the original object and proxy object returned. + * @return the java.lang.reflect.Proxy object associated or the original object when JProxy is disabled. + */ + public static Object create(Object obj,Class[] classes) + { + return JProxyDefaultImpl.createStatic(obj, classes); + } + + /** + * Informs whether JProxy is configured and enabled. + * + * @return true if enabled. + */ + public static boolean isEnabled() + { + return JProxyDefaultImpl.isEnabledStatic(); + } + + /** + * Informs whether JProxy is enabled and started (timed checking for changes). + * + * @return true if running. + */ + public static boolean isRunning() + { + return JProxyDefaultImpl.isRunningStatic(); + } + + /** + * Stops source code periodic change detection. + * + *

Periodicity of change detection is defined by {@link JProxyConfig#setScanPeriod(long)}

+ * + * @return true if source change detection has been stopped, false if it is already stopped or JProxy is not enabled or initialized. + * @see #stop() + */ + public static boolean stop() + { + return JProxyDefaultImpl.stopStatic(); + } + + /** + * Starts source code periodic change detection. + * + *

Periodicity of change detection is defined by {@link JProxyConfig#setScanPeriod(long)}.

+ * + *

By default when JProxy is initialized and enabled.

+ * + * @return true if source change detection has been started again, false if it is already started or cannot start because JProxy is not enabled or initialized or scan period is not positive. + * @see #start() + */ + public static boolean start() + { + return JProxyDefaultImpl.startStatic(); + } +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/jproxy/JProxyCompilerListener.java b/src/main/java/com/innowhere/relproxy/jproxy/JProxyCompilerListener.java similarity index 96% rename from relproxy/src/main/java/com/innowhere/relproxy/jproxy/JProxyCompilerListener.java rename to src/main/java/com/innowhere/relproxy/jproxy/JProxyCompilerListener.java index 397a907..b4fbcde 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/jproxy/JProxyCompilerListener.java +++ b/src/main/java/com/innowhere/relproxy/jproxy/JProxyCompilerListener.java @@ -1,15 +1,15 @@ -package com.innowhere.relproxy.jproxy; - -import java.io.File; - -/** - * Is the interface to monitor the files being compiled. - * - * @see JProxyConfig#setJProxyCompilerListener(JProxyCompilerListener) - * @author Jose Maria Arranz Santamaria - */ -public interface JProxyCompilerListener -{ - public void beforeCompile(File file); - public void afterCompile(File file); -} +package com.innowhere.relproxy.jproxy; + +import java.io.File; + +/** + * Is the interface to monitor the files being compiled. + * + * @see JProxyConfig#setJProxyCompilerListener(JProxyCompilerListener) + * @author Jose Maria Arranz Santamaria + */ +public interface JProxyCompilerListener +{ + public void beforeCompile(File file); + public void afterCompile(File file); +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/jproxy/JProxyConfig.java b/src/main/java/com/innowhere/relproxy/jproxy/JProxyConfig.java similarity index 93% rename from relproxy/src/main/java/com/innowhere/relproxy/jproxy/JProxyConfig.java rename to src/main/java/com/innowhere/relproxy/jproxy/JProxyConfig.java index 52d5b93..88dc6be 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/jproxy/JProxyConfig.java +++ b/src/main/java/com/innowhere/relproxy/jproxy/JProxyConfig.java @@ -1,164 +1,164 @@ - -package com.innowhere.relproxy.jproxy; - -import com.innowhere.relproxy.RelProxyOnReloadListener; - -/** - * Interface implemented by the configuration object needed to initialize JProxy and {@link JProxyScriptEngineFactory}. - * - * @see JProxy#init(JProxyConfig) - * @see JProxyScriptEngine#init(JProxyConfig) - * @author Jose Maria Arranz Santamaria - */ -public interface JProxyConfig -{ - /** - * Sets whether automatic detection of source code changes is enabled. - * - *

If set to false other configuration parameters are ignored, there is no automatic source code change detection/reload and original objects are returned - * instead of proxies, performance penalty is zero. Setting to false is recommended in production whether source code change detection/reload is not required.

- * - * @param enabled whether automatic source code change detection and reload is enabled. By default is true. - * @return this object for flow API use. - */ - public JProxyConfig setEnabled(boolean enabled); - - /** - * Sets the class reload listener. - * - * @param relListener the class reload listener. By default is null. - * @return this object for flow API use. - */ - public JProxyConfig setRelProxyOnReloadListener(RelProxyOnReloadListener relListener); - - /** - * Defines the folder root to locate source code Java files. - * - *

Structure of the source tree must be the same as a JavaSE application, the only difference is shell scripts, shell scripts must be - * located on the top level of the source tree (default package) and file extension is not required .

- * - *

Setting some input path is required.

- * - * @param inputPath the folder root to locate source code Java files. - * @return this object for flow API use. - * @see #setInputPaths(java.lang.String[]) - */ - public JProxyConfig setInputPath(String inputPath); - - /** - * Defines the folder roots to locate source code Java files. - * - *

Structure of the source tree must be the same as a JavaSE application, the only difference is shell scripts, shell scripts must be - * located on the top level of the source tree (default package).

- * - *

Setting some input path is required.

- * - * @param inputPaths the folder roots to locate source code Java files. - * @return this object for flow API use. - * @see #setJProxyInputSourceFileExcludedListener(JProxyInputSourceFileExcludedListener) - * @see #setRequiredExtraJarPaths(String[]) - */ - public JProxyConfig setInputPaths(String[] inputPaths); - - /** - * Defines the extra required jars providing the absolute paths to them. - * - *

In some circunstances RelProxy is not able to find some required classes by the compiler because the jar containing them is not found in spite of existing in classpath, - * the reason may be due some conflictive configuration of META-INF/MANIFEST.MF of the jar. This problem can be fixed modifying accordingly the META-INF/MANIFEST.MF - * file, or alternatively providing the paths to the conflictive jars calling to this method, in this case RelProxy will find the required classes searching on them by using brute force - * avoiding the jar modification (not recommended). - *

- * - * @param inputJarPaths the paths of the required extra jars. - * @return this object for flow API use. - * @see #setInputPaths(String[]) - */ - public JProxyConfig setRequiredExtraJarPaths(String[] inputJarPaths); - - /** - * Registers the listener implementing excluding rules to filter source files not to be part of the hot reloading system in spite of included in input paths. - * - * @param listener the listener. By default is null. - * @return this object for flow API use. - */ - public JProxyConfig setJProxyInputSourceFileExcludedListener(JProxyInputSourceFileExcludedListener listener); - - /** - * Registers the listener for monitoring files being compiled. - * - * @param listener the listener. By default is null. - * @return this object for flow API use. - */ - public JProxyConfig setJProxyCompilerListener(JProxyCompilerListener listener); - - - /** - * Sets the folder where to save .class files result of recompiling source code changed. - * - *

This setting is optional and the folder must be included in Java classpath because the objective is to avoid recompiling.

- * - *

Be careful when executing several Java scripts in the same time and source code has been changed, some file write collisions may happen.

- * - * @param classFolder the folder where to save .class files. By default is null (not defined, .class files are not saved). - * @return this object for flow API use. - */ - public JProxyConfig setClassFolder(String classFolder); - - /** - * Sets the delay between source code change checking. - * - *

If this value is set to 0 or negative, no periodic source code change detection is executed and only compilation on the fly happens in load time, - * this is valid for one shot scripts but it has no sense when using proxies. - * - * @param scanPeriod the delay between source code change checking. - * @return this object for flow API use. - */ - public JProxyConfig setScanPeriod(long scanPeriod); - - /** - * Sets the compilation options to be provided to the compiler built-in in JDK like JavaCompiler.getTask() method and the same you would provide to javac. - * - *

Example of compilation options:

- *

Iterable compilationOptions = Arrays.asList(new String[]{"-source","1.6","-target","1.6"});

- * - * @param compilationOptions compilation options passed to the internal compiler. By default is null (default compiler settings). - * @return this object for flow API use. - */ - public JProxyConfig setCompilationOptions(Iterable compilationOptions); - - /** - * Sets the diagnostic listener to capture compilation errors and warnings thrown by the internal compiler. - * - *

The following is an example similar to the default behavior when this listener is not specified:

- * -
-        JProxyDiagnosticsListener diagnosticsListener = new JProxyDiagnosticsListener()
-        {
-            {@code @}Override
-            public void onDiagnostics(DiagnosticCollector{@code <}JavaFileObject> diagnostics)
-            {
-                List{@code <}Diagnostic{@code <}? extends JavaFileObject>> diagList = diagnostics.getDiagnostics();                
-                int i = 1;
-                for (Diagnostic diagnostic : diagList)
-                {
-                   System.err.println("Diagnostic " + i);
-                   System.err.println("  code: " + diagnostic.getCode());
-                   System.err.println("  kind: " + diagnostic.getKind());
-                   System.err.println("  line number: " + diagnostic.getLineNumber());                   
-                   System.err.println("  column number: " + diagnostic.getColumnNumber());
-                   System.err.println("  start position: " + diagnostic.getStartPosition());
-                   System.err.println("  position: " + diagnostic.getPosition());                   
-                   System.err.println("  end position: " + diagnostic.getEndPosition());
-                   System.err.println("  source: " + diagnostic.getSource());
-                   System.err.println("  message: " + diagnostic.getMessage(null));
-                   i++;
-                }
-            }
-        };   
-     
- * - * @param diagnosticsListener the diagnostic listener to capture compilation errors and warnings. By default is null, an internal listener is used logging to System.err. - * @return this object for flow API use. - */ - public JProxyConfig setJProxyDiagnosticsListener(JProxyDiagnosticsListener diagnosticsListener); -} + +package com.innowhere.relproxy.jproxy; + +import com.innowhere.relproxy.RelProxyOnReloadListener; + +/** + * Interface implemented by the configuration object needed to initialize JProxy and {@link JProxyScriptEngineFactory}. + * + * @see JProxy#init(JProxyConfig) + * @see JProxyScriptEngine#init(JProxyConfig) + * @author Jose Maria Arranz Santamaria + */ +public interface JProxyConfig +{ + /** + * Sets whether automatic detection of source code changes is enabled. + * + *

If set to false other configuration parameters are ignored, there is no automatic source code change detection/reload and original objects are returned + * instead of proxies, performance penalty is zero. Setting to false is recommended in production whether source code change detection/reload is not required.

+ * + * @param enabled whether automatic source code change detection and reload is enabled. By default is true. + * @return this object for flow API use. + */ + public JProxyConfig setEnabled(boolean enabled); + + /** + * Sets the class reload listener. + * + * @param relListener the class reload listener. By default is null. + * @return this object for flow API use. + */ + public JProxyConfig setRelProxyOnReloadListener(RelProxyOnReloadListener relListener); + + /** + * Defines the folder root to locate source code Java files. + * + *

Structure of the source tree must be the same as a JavaSE application, the only difference is shell scripts, shell scripts must be + * located on the top level of the source tree (default package) and file extension is not required .

+ * + *

Setting some input path is required.

+ * + * @param inputPath the folder root to locate source code Java files. + * @return this object for flow API use. + * @see #setInputPaths(java.lang.String[]) + */ + public JProxyConfig setInputPath(String inputPath); + + /** + * Defines the folder roots to locate source code Java files. + * + *

Structure of the source tree must be the same as a JavaSE application, the only difference is shell scripts, shell scripts must be + * located on the top level of the source tree (default package).

+ * + *

Setting some input path is required.

+ * + * @param inputPaths the folder roots to locate source code Java files. + * @return this object for flow API use. + * @see #setJProxyInputSourceFileExcludedListener(JProxyInputSourceFileExcludedListener) + * @see #setRequiredExtraJarPaths(String[]) + */ + public JProxyConfig setInputPaths(String[] inputPaths); + + /** + * Defines the extra required jars providing the absolute paths to them. + * + *

In some circunstances RelProxy is not able to find some required classes by the compiler because the jar containing them is not found in spite of existing in classpath, + * the reason may be due some conflictive configuration of META-INF/MANIFEST.MF of the jar. This problem can be fixed modifying accordingly the META-INF/MANIFEST.MF + * file, or alternatively providing the paths to the conflictive jars calling to this method, in this case RelProxy will find the required classes searching on them by using brute force + * avoiding the jar modification (not recommended). + *

+ * + * @param inputJarPaths the paths of the required extra jars. + * @return this object for flow API use. + * @see #setInputPaths(String[]) + */ + public JProxyConfig setRequiredExtraJarPaths(String[] inputJarPaths); + + /** + * Registers the listener implementing excluding rules to filter source files not to be part of the hot reloading system in spite of included in input paths. + * + * @param listener the listener. By default is null. + * @return this object for flow API use. + */ + public JProxyConfig setJProxyInputSourceFileExcludedListener(JProxyInputSourceFileExcludedListener listener); + + /** + * Registers the listener for monitoring files being compiled. + * + * @param listener the listener. By default is null. + * @return this object for flow API use. + */ + public JProxyConfig setJProxyCompilerListener(JProxyCompilerListener listener); + + + /** + * Sets the folder where to save .class files result of recompiling source code changed. + * + *

This setting is optional and the folder must be included in Java classpath because the objective is to avoid recompiling.

+ * + *

Be careful when executing several Java scripts in the same time and source code has been changed, some file write collisions may happen.

+ * + * @param classFolder the folder where to save .class files. By default is null (not defined, .class files are not saved). + * @return this object for flow API use. + */ + public JProxyConfig setClassFolder(String classFolder); + + /** + * Sets the delay between source code change checking. + * + *

If this value is set to 0 or negative, no periodic source code change detection is executed and only compilation on the fly happens in load time, + * this is valid for one shot scripts but it has no sense when using proxies. + * + * @param scanPeriod the delay between source code change checking. + * @return this object for flow API use. + */ + public JProxyConfig setScanPeriod(long scanPeriod); + + /** + * Sets the compilation options to be provided to the compiler built-in in JDK like JavaCompiler.getTask() method and the same you would provide to javac. + * + *

Example of compilation options:

+ *

Iterable<String> compilationOptions = Arrays.asList(new String[]{"-source","1.6","-target","1.6"});

+ * + * @param compilationOptions compilation options passed to the internal compiler. By default is null (default compiler settings). + * @return this object for flow API use. + */ + public JProxyConfig setCompilationOptions(Iterable compilationOptions); + + /** + * Sets the diagnostic listener to capture compilation errors and warnings thrown by the internal compiler. + * + *

The following is an example similar to the default behavior when this listener is not specified:

+ * +
+        JProxyDiagnosticsListener diagnosticsListener = new JProxyDiagnosticsListener()
+        {
+            {@code @}Override
+            public void onDiagnostics(DiagnosticCollector<JavaFileObject> diagnostics)
+            {
+                List<Diagnostic<? extends JavaFileObject>> diagList = diagnostics.getDiagnostics();
+                int i = 1;
+                for (Diagnostic diagnostic : diagList)
+                {
+                   System.err.println("Diagnostic " + i);
+                   System.err.println("  code: " + diagnostic.getCode());
+                   System.err.println("  kind: " + diagnostic.getKind());
+                   System.err.println("  line number: " + diagnostic.getLineNumber());                   
+                   System.err.println("  column number: " + diagnostic.getColumnNumber());
+                   System.err.println("  start position: " + diagnostic.getStartPosition());
+                   System.err.println("  position: " + diagnostic.getPosition());                   
+                   System.err.println("  end position: " + diagnostic.getEndPosition());
+                   System.err.println("  source: " + diagnostic.getSource());
+                   System.err.println("  message: " + diagnostic.getMessage(null));
+                   i++;
+                }
+            }
+        };   
+     
+ * + * @param diagnosticsListener the diagnostic listener to capture compilation errors and warnings. By default is null, an internal listener is used logging to System.err. + * @return this object for flow API use. + */ + public JProxyConfig setJProxyDiagnosticsListener(JProxyDiagnosticsListener diagnosticsListener); +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/jproxy/JProxyDiagnosticsListener.java b/src/main/java/com/innowhere/relproxy/jproxy/JProxyDiagnosticsListener.java similarity index 96% rename from relproxy/src/main/java/com/innowhere/relproxy/jproxy/JProxyDiagnosticsListener.java rename to src/main/java/com/innowhere/relproxy/jproxy/JProxyDiagnosticsListener.java index 9b0ea1f..bfc6663 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/jproxy/JProxyDiagnosticsListener.java +++ b/src/main/java/com/innowhere/relproxy/jproxy/JProxyDiagnosticsListener.java @@ -1,20 +1,20 @@ -package com.innowhere.relproxy.jproxy; - -import javax.tools.DiagnosticCollector; -import javax.tools.JavaFileObject; - -/** - * Is the interface to implement diagnostic listeners to capture compilation errors and warnings. - * - * @see JProxyConfig#setJProxyDiagnosticsListener(JProxyDiagnosticsListener) - * @author Jose Maria Arranz Santamaria - */ -public interface JProxyDiagnosticsListener -{ - /** - * This method is called when compilation Java code has generated diagnostics. - * - * @param diagnostics the list of diagnostics. - */ - public void onDiagnostics(DiagnosticCollector diagnostics); -} +package com.innowhere.relproxy.jproxy; + +import javax.tools.DiagnosticCollector; +import javax.tools.JavaFileObject; + +/** + * Is the interface to implement diagnostic listeners to capture compilation errors and warnings. + * + * @see JProxyConfig#setJProxyDiagnosticsListener(JProxyDiagnosticsListener) + * @author Jose Maria Arranz Santamaria + */ +public interface JProxyDiagnosticsListener +{ + /** + * This method is called when compilation Java code has generated diagnostics. + * + * @param diagnostics the list of diagnostics. + */ + public void onDiagnostics(DiagnosticCollector diagnostics); +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java b/src/main/java/com/innowhere/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java similarity index 97% rename from relproxy/src/main/java/com/innowhere/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java rename to src/main/java/com/innowhere/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java index 196bfb9..2602645 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java +++ b/src/main/java/com/innowhere/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java @@ -1,21 +1,21 @@ -package com.innowhere.relproxy.jproxy; - -import java.io.File; - -/** - * This interface is provided to developers to implement excluding rules to filter source files not to be part of the hot reloading system in spite of included in input paths - * - * @see JProxyConfig#setJProxyInputSourceFileExcludedListener(JProxyInputSourceFileExcludedListener) - * @author Jose Maria Arranz Santamaria - */ -public interface JProxyInputSourceFileExcludedListener -{ - /** - * This method is called per file when going to be managed by the hot reloading system. - * - * @param file the file to be managed. - * @param rootFolderOfSources the folder root of sources where this file is located. - * @return true whether the file must be ignored. - */ - public boolean isExcluded(File file,File rootFolderOfSources); -} +package com.innowhere.relproxy.jproxy; + +import java.io.File; + +/** + * This interface is provided to developers to implement excluding rules to filter source files not to be part of the hot reloading system in spite of included in input paths + * + * @see JProxyConfig#setJProxyInputSourceFileExcludedListener(JProxyInputSourceFileExcludedListener) + * @author Jose Maria Arranz Santamaria + */ +public interface JProxyInputSourceFileExcludedListener +{ + /** + * This method is called per file when going to be managed by the hot reloading system. + * + * @param file the file to be managed. + * @param rootFolderOfSources the folder root of sources where this file is located. + * @return true whether the file must be ignored. + */ + public boolean isExcluded(File file,File rootFolderOfSources); +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/jproxy/JProxyScriptEngine.java b/src/main/java/com/innowhere/relproxy/jproxy/JProxyScriptEngine.java similarity index 100% rename from relproxy/src/main/java/com/innowhere/relproxy/jproxy/JProxyScriptEngine.java rename to src/main/java/com/innowhere/relproxy/jproxy/JProxyScriptEngine.java diff --git a/relproxy/src/main/java/com/innowhere/relproxy/jproxy/JProxyScriptEngineFactory.java b/src/main/java/com/innowhere/relproxy/jproxy/JProxyScriptEngineFactory.java similarity index 96% rename from relproxy/src/main/java/com/innowhere/relproxy/jproxy/JProxyScriptEngineFactory.java rename to src/main/java/com/innowhere/relproxy/jproxy/JProxyScriptEngineFactory.java index c04e34a..434aad9 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/jproxy/JProxyScriptEngineFactory.java +++ b/src/main/java/com/innowhere/relproxy/jproxy/JProxyScriptEngineFactory.java @@ -1,22 +1,22 @@ -package com.innowhere.relproxy.jproxy; - -import com.innowhere.relproxy.impl.jproxy.screngine.JProxyScriptEngineFactoryImpl; -import javax.script.ScriptEngineFactory; - -/** - * Is the root class of JSR-223 Java Scripting API support. - * - * @author Jose Maria Arranz Santamaria - */ -public abstract class JProxyScriptEngineFactory implements ScriptEngineFactory -{ - /** - * Factory method to create a JProxyScriptEngineFactory implementing ScriptEngineFactory. - * - * @return the new factory. - */ - public static JProxyScriptEngineFactory create() - { - return JProxyScriptEngineFactoryImpl.create(); - } -} +package com.innowhere.relproxy.jproxy; + +import com.innowhere.relproxy.impl.jproxy.screngine.JProxyScriptEngineFactoryImpl; +import javax.script.ScriptEngineFactory; + +/** + * Is the root class of JSR-223 Java Scripting API support. + * + * @author Jose Maria Arranz Santamaria + */ +public abstract class JProxyScriptEngineFactory implements ScriptEngineFactory +{ + /** + * Factory method to create a JProxyScriptEngineFactory implementing ScriptEngineFactory. + * + * @return the new factory. + */ + public static JProxyScriptEngineFactory create() + { + return JProxyScriptEngineFactoryImpl.create(); + } +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/jproxy/JProxyShell.java b/src/main/java/com/innowhere/relproxy/jproxy/JProxyShell.java similarity index 96% rename from relproxy/src/main/java/com/innowhere/relproxy/jproxy/JProxyShell.java rename to src/main/java/com/innowhere/relproxy/jproxy/JProxyShell.java index ec1ee09..baa3a66 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/jproxy/JProxyShell.java +++ b/src/main/java/com/innowhere/relproxy/jproxy/JProxyShell.java @@ -1,23 +1,23 @@ -package com.innowhere.relproxy.jproxy; - -import com.innowhere.relproxy.impl.jproxy.shell.JProxyShellImpl; - -/** - * Is the main class to execute shell scripting based on Java. - * - *

You are not going to use directly this class, use instead jproxysh command line.

- * - * @author Jose Maria Arranz Santamaria - */ -public class JProxyShell -{ - /** - * The main method. - * - * @param args arguments with the necessary data to initialize and executing the provided script. - */ - public static void main(String[] args) - { - JProxyShellImpl.main(args); - } -} +package com.innowhere.relproxy.jproxy; + +import com.innowhere.relproxy.impl.jproxy.shell.JProxyShellImpl; + +/** + * Is the main class to execute shell scripting based on Java. + * + *

You are not going to use directly this class, use instead jproxysh command line.

+ * + * @author Jose Maria Arranz Santamaria + */ +public class JProxyShell +{ + /** + * The main method. + * + * @param args arguments with the necessary data to initialize and executing the provided script. + */ + public static void main(String[] args) + { + JProxyShellImpl.main(args); + } +} diff --git a/relproxy/src/main/java/com/innowhere/relproxy/jproxy/package.html b/src/main/java/com/innowhere/relproxy/jproxy/package.html similarity index 95% rename from relproxy/src/main/java/com/innowhere/relproxy/jproxy/package.html rename to src/main/java/com/innowhere/relproxy/jproxy/package.html index 372b30f..3a1f2ab 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/jproxy/package.html +++ b/src/main/java/com/innowhere/relproxy/jproxy/package.html @@ -1,13 +1,13 @@ - - - - - - - -Contains the classes related with Java support of RelProxy. - - - + + + + + + + +Contains the classes related with Java support of RelProxy. + + + diff --git a/relproxy/src/main/java/com/innowhere/relproxy/package.html b/src/main/java/com/innowhere/relproxy/package.html similarity index 96% rename from relproxy/src/main/java/com/innowhere/relproxy/package.html rename to src/main/java/com/innowhere/relproxy/package.html index 1ede5ea..d8f25f0 100644 --- a/relproxy/src/main/java/com/innowhere/relproxy/package.html +++ b/src/main/java/com/innowhere/relproxy/package.html @@ -1,13 +1,13 @@ - - - - - - - -Contains the root and shared interfaces and classes of RelProxy, shared between all different language based utilities. - - - + + + + + + + +Contains the root and shared interfaces and classes of RelProxy, shared between all different language based utilities. + + + From 8e31e2950bcaa2539501f8ef884724e22bcfae14 Mon Sep 17 00:00:00 2001 From: neilellis Date: Fri, 7 Jul 2017 15:37:41 +0100 Subject: [PATCH 002/135] Moving over to Maven --- README.md => README.tmpl.md | 0 circle.yml | 51 +++++++++++++++++++++++++++++++++++++ relproxy/distribute.xml | 2 +- 3 files changed, 52 insertions(+), 1 deletion(-) rename README.md => README.tmpl.md (100%) create mode 100644 circle.yml diff --git a/README.md b/README.tmpl.md similarity index 100% rename from README.md rename to README.tmpl.md diff --git a/circle.yml b/circle.yml new file mode 100644 index 0000000..8cc01e2 --- /dev/null +++ b/circle.yml @@ -0,0 +1,51 @@ +machine: + environment: + MAJOR_VERSION: 0.9 + MAVEN_OPTS: "-Xmx1g -DbuildNumber=${CIRCLE_BUILD_NUM} -Dorg.xml.sax.driver='com.sun.org.apache.xerces.internal.parsers.SAXParser' " + java: + version: oraclejdk8 + +general: + branches: + ignore: + - gh-pages + + +dependencies: + cache_directories: + - ~/.gnupg + pre: + - cd ~ && git clone https://github.com/dollar-org/build-utils.git && chmod a+x ~/build-utils/*.sh + - "[[ ${CIRCLE_BRANCH} != 'master' ]] || ( mvn versions:set -DnewVersion=$(cat .release) && mvn versions:resolve-ranges && mvn versions:lock-snapshots )" + - mvn install -e -q -Drat.skip -Dsource.skip=true -DgenerateReports=false -Dmaven.javadoc.skip=true -Dmaven.test.skip + + +test: + override: + - sudo ln -fs /usr/share/zoneinfo/Europe/London /etc/localtime + - "mvn -q -T 1C -Drat.skip -Dsource.skip=true -DgenerateReports=false -Dmaven.javadoc.skip=true integration-test": + timeout: 600 + +deployment: + + staging: + branch: staging + commands: + - ~/build-utils/promote_from_staging.sh + + production: + branch: master + commands: + - git config --global user.email "hello@neilellis.me" + - git config --global user.name "Neil Ellis" + - mvn versions:set -DnewVersion=$(cat .release) + - mvn versions:resolve-ranges + - mvn versions:lock-snapshots + - mvn -T 1C -Dmaven.test.skip=true -Drat.skip=true -DskipEnforcer -Dmaven.javadoc.skip=true -DgenerateReports=false package + - mvn -T 2C -Dorg.xml.sax.driver=com.sun.org.apache.xerces.internal.parsers.SAXParser -Dmaven.test.skip=true -Drat.skip=true -DskipEnforcer -Dmaven.javadoc.skip=true -DgenerateReports=false deploy + + + development: + branch: dev + commands: + - echo "dev" diff --git a/relproxy/distribute.xml b/relproxy/distribute.xml index afe6c42..75ef5e6 100644 --- a/relproxy/distribute.xml +++ b/relproxy/distribute.xml @@ -19,7 +19,7 @@ - + From 642b55254650e2a01d9c583cfd56ad5e204a6233 Mon Sep 17 00:00:00 2001 From: neilellis Date: Fri, 7 Jul 2017 15:42:36 +0100 Subject: [PATCH 003/135] Moving over to Maven --- README.tmpl.md | 59 +++++++++++++++++++++++--------------------------- pom.xml | 2 +- 2 files changed, 28 insertions(+), 33 deletions(-) diff --git a/README.tmpl.md b/README.tmpl.md index 07a9119..934900c 100644 --- a/README.tmpl.md +++ b/README.tmpl.md @@ -2,37 +2,14 @@ RelProxy ======== RelProxy is a simple Java and Groovy hot class reloader for Java and Groovy providing transparent compilation and class reload on the fly, and scripting support and shell of pure Java code. -News ------- - -- 2016-3-16 v0.8.8 Released. Support of static final fields in reloadable proxies. [Release Notes](https://github.com/jmarranz/relproxy/blob/master/relproxy/CHANGES.txt) -- 2015-10-6 DZone article: [Improve Productivity With RelProxy for Java](https://dzone.com/articles/embedding-relproxy-in-your-java-framework-to-provi). About embedding RelProxy in your own Java framework. -- 2015-10-1 v0.8.7 Released. Some improvement needed when embedding RelProxy Java using the scripting API. [Release Notes](https://github.com/jmarranz/relproxy/blob/master/relproxy/CHANGES.txt) -- 2015-6-12 v0.8.6 Released. Support of class reloading of inner classes including anonymous. [Release Notes](https://github.com/jmarranz/relproxy/blob/master/relproxy/CHANGES.txt) -- 2015-6-12 v0.8.5 Released. Improved performance when checking source changes and no change is detected. [Release Notes](https://github.com/jmarranz/relproxy/blob/master/relproxy/CHANGES.txt) -- 2015-2-17 v0.8.4 Released. Added workaround to support Liferay (6.2 tested) [Release Notes](https://github.com/jmarranz/relproxy/blob/master/relproxy/CHANGES.txt). - New [Liferay 6.2 example](https://github.com/jmarranz/relproxy_examples/tree/master/relproxy_ex_liferay-portlet) using RelProxy. -- 2015-1-23 v0.8.3 Released. First release in JCenter and Maven Central [Release Notes](https://github.com/jmarranz/relproxy/blob/master/relproxy/CHANGES.txt) -- 2015-2-5 [Java Hot Class Reloading with RelProxy in Development Mode, a GWT Example](http://java.dzone.com/articles/java-hot-class-reloading) JavaLobby article -- 2015-1-30 [Slides](http://www.slideshare.net/jmarranz/relproxy-class-reload-and-easy-java-scripting) in English and [video](http://autentia.com/2015/01/30/relproxy-easy-class-reload-and-scripting-with-java-por-jose-maria-arranz/#) in Spanish of the RelProxy presentation in MadridJUG on January 28! - - -Download Binaries and Docs ------- - -[Download](https://sourceforge.net/projects/relproxy/files/) - -Distribution file includes binaries, examples, manual and javadocs. - -Artefacts are uploaded to [JCenter](https://bintray.com/jmarranz/maven/relproxy/view) ([direct](https://jcenter.bintray.com/com/innowhere/relproxy/)) and [Maven Central](http://mvnrepository.com/artifact/com.innowhere/relproxy) ([direct](https://oss.sonatype.org/content/repositories/releases/com/innowhere/relproxy/)) repositories - -Maven: ```xml -com.innowhere + +com.sillelien.dollar relproxy -(version) +${RELEASE} jar + ``` Overview @@ -60,9 +37,6 @@ to other normal Java files. Optionally .class can be saved in a cache to provide In case of Java "scripting", there is no a new language, is pure Java code with compilation on the fly. -In spite of RelProxy is a general purpose tool it was conceived for [ItsNat web framework](http://www.itsnat.org) to provide hot class reload in development time... -and if you want also in production. RelProxy is standalone and has no dependency on ItsNat. - RelProxy Manual explains how to configure and use RelProxy in NetBeans and Eclipse avoiding class reloading (of course other IDEs are possible). There are several examples of how to use RelProxy with most popular Java web frameworks ready to run into [RelProxy Examples](https://github.com/jmarranz/relproxy_examples) @@ -87,6 +61,16 @@ By using this API you can embed Java as any other scripting language in your Jav Yes, Java is also a dynamic scripting language with no need of manual compilation, and it is extremely fast and robust. + +Bug Reporting +------ + +Use this GitHub project. + + +Historical Details +================== + Online Docs Last Version ------ @@ -104,10 +88,21 @@ Questions and discussions There is a [Google Group](https://groups.google.com/forum/#!forum/relproxy) for RelProxy. -Bug Reporting + +News ------ -Use this GitHub project. +- 2016-3-16 v0.8.8 Released. Support of static final fields in reloadable proxies. [Release Notes](https://github.com/jmarranz/relproxy/blob/master/relproxy/CHANGES.txt) +- 2015-10-6 DZone article: [Improve Productivity With RelProxy for Java](https://dzone.com/articles/embedding-relproxy-in-your-java-framework-to-provi). About embedding RelProxy in your own Java framework. +- 2015-10-1 v0.8.7 Released. Some improvement needed when embedding RelProxy Java using the scripting API. [Release Notes](https://github.com/jmarranz/relproxy/blob/master/relproxy/CHANGES.txt) +- 2015-6-12 v0.8.6 Released. Support of class reloading of inner classes including anonymous. [Release Notes](https://github.com/jmarranz/relproxy/blob/master/relproxy/CHANGES.txt) +- 2015-6-12 v0.8.5 Released. Improved performance when checking source changes and no change is detected. [Release Notes](https://github.com/jmarranz/relproxy/blob/master/relproxy/CHANGES.txt) +- 2015-2-17 v0.8.4 Released. Added workaround to support Liferay (6.2 tested) [Release Notes](https://github.com/jmarranz/relproxy/blob/master/relproxy/CHANGES.txt). + New [Liferay 6.2 example](https://github.com/jmarranz/relproxy_examples/tree/master/relproxy_ex_liferay-portlet) using RelProxy. +- 2015-1-23 v0.8.3 Released. First release in JCenter and Maven Central [Release Notes](https://github.com/jmarranz/relproxy/blob/master/relproxy/CHANGES.txt) +- 2015-2-5 [Java Hot Class Reloading with RelProxy in Development Mode, a GWT Example](http://java.dzone.com/articles/java-hot-class-reloading) JavaLobby article +- 2015-1-30 [Slides](http://www.slideshare.net/jmarranz/relproxy-class-reload-and-easy-java-scripting) in English and [video](http://autentia.com/2015/01/30/relproxy-easy-class-reload-and-scripting-with-java-por-jose-maria-arranz/#) in Spanish of the RelProxy presentation in MadridJUG on January 28! + Articles/Blogs/Presentations diff --git a/pom.xml b/pom.xml index 09c6838..edd1d18 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.sillelien.dollar relproxy - LATEST + 0 2.0.2 From fb47a3851a44f84752db10fd2cb89bbff9c98a94 Mon Sep 17 00:00:00 2001 From: "hello@neilellis.me" Date: Fri, 7 Jul 2017 15:52:59 +0100 Subject: [PATCH 004/135] Release 0.9.5 [5/642b55254650e2a01d9c583cfd56ad5e204a6233] (often-dotal-manna) --- .release | 1 + .release.details | 1 + 2 files changed, 2 insertions(+) create mode 100644 .release create mode 100644 .release.details diff --git a/.release b/.release new file mode 100644 index 0000000..b0bb878 --- /dev/null +++ b/.release @@ -0,0 +1 @@ +0.9.5 diff --git a/.release.details b/.release.details new file mode 100644 index 0000000..6d44865 --- /dev/null +++ b/.release.details @@ -0,0 +1 @@ +0.9.5 5 642b55254650e2a01d9c583cfd56ad5e204a6233 often-dotal-manna From 87e81f13b1ad084f95fcd3cca45cdcd542f23a3b Mon Sep 17 00:00:00 2001 From: neilellis Date: Fri, 7 Jul 2017 16:03:53 +0100 Subject: [PATCH 005/135] Refactoring for Dollar project --- pom.xml | 71 ++++++++++++++++--- relproxy/pom.xml | 2 +- relproxy/src/main/asciidoc/manual.asciidoc | 56 +++++++-------- .../JProxyCodeSnippetCompleteClassTest.java | 2 +- .../jproxy/JProxyCodeSnippetTest.java | 2 +- .../JProxyJavaScriptEngineNoManagerTest.java | 8 +-- .../jproxy/JProxyJavaScriptEngineTest.java | 8 +-- .../JProxyJavaShellCompleteClassTest.java | 4 +- .../JProxyJavaShellInteractiveTest.java | 2 +- .../JProxyJavaShellNormalClassTest.java | 4 +- .../relproxy/jproxy/JProxyJavaShellTest.java | 7 +- .../relproxy/jproxy/util/JProxyTestUtil.java | 4 +- .../javashellex/JProxyShellExample.java | 2 +- .../example/groovyex/ItsNatGroovyServlet.java | 6 +- .../example/javaex/JProxyExampleServlet.java | 2 +- .../javaex/JProxyServletContextListener.java | 21 +++--- .../groovyex/groovy_servlet_init.groovy | 12 ++-- .../example/javaex/JProxyExampleDocument.java | 3 +- .../relproxy/RelProxy.java | 2 +- .../relproxy/RelProxyException.java | 2 +- .../relproxy/RelProxyOnReloadListener.java | 6 +- .../relproxy/gproxy/GProxy.java | 6 +- .../relproxy/gproxy/GProxyConfig.java | 4 +- .../gproxy/GProxyGroovyScriptEngine.java | 2 +- .../relproxy/gproxy/package.html | 0 .../relproxy/impl/FileExt.java | 4 +- .../impl/GenericProxyConfigBaseImpl.java | 4 +- .../relproxy/impl/GenericProxyImpl.java | 6 +- .../impl/GenericProxyInvocationHandler.java | 4 +- .../impl/GenericProxyVersionedObject.java | 6 +- .../impl/gproxy/GProxyConfigImpl.java | 10 +-- .../impl/gproxy/GProxyDefaultImpl.java | 6 +- .../relproxy/impl/gproxy/core/GProxyImpl.java | 10 +-- .../gproxy/core/GProxyInvocationHandler.java | 6 +- .../gproxy/core/GProxyVersionedObject.java | 6 +- .../impl/jproxy/JProxyConfigImpl.java | 18 ++--- .../impl/jproxy/JProxyDefaultImpl.java | 6 +- .../relproxy/impl/jproxy/JProxyUtil.java | 4 +- .../relproxy/impl/jproxy/core/JProxyImpl.java | 22 +++--- .../jproxy/core/JProxyInvocationHandler.java | 6 +- .../jproxy/core/JProxyVersionedObject.java | 8 +-- .../jproxy/core/clsmgr/FolderSourceList.java | 6 +- .../jproxy/core/clsmgr/JProxyClassLoader.java | 8 +-- .../impl/jproxy/core/clsmgr/JProxyEngine.java | 22 +++--- ...JProxyEngineChangeDetectorAndCompiler.java | 34 ++++----- .../jproxy/core/clsmgr/JavaSourcesSearch.java | 28 ++++---- .../core/clsmgr/cldesc/ClassDescriptor.java | 2 +- .../clsmgr/cldesc/ClassDescriptorInner.java | 2 +- .../cldesc/ClassDescriptorSourceFileJava.java | 8 +-- .../ClassDescriptorSourceFileRegistry.java | 2 +- .../cldesc/ClassDescriptorSourceScript.java | 10 +-- .../cldesc/ClassDescriptorSourceUnit.java | 10 +-- .../comp/JProxyCompilationException.java | 6 +- .../clsmgr/comp/JProxyCompilerContext.java | 6 +- .../clsmgr/comp/JProxyCompilerInMemory.java | 26 +++---- .../clsmgr/comp/JavaFileManagerInMemory.java | 18 ++--- ...leObjectInputClassFinderByClassLoader.java | 20 +++--- .../comp/jfo/JProxyJavaFileObjectInput.java | 2 +- .../jfo/JavaFileObjectInputClassInFile.java | 5 +- .../JavaFileObjectInputClassInFileSystem.java | 2 +- .../jfo/JavaFileObjectInputClassInJar.java | 4 +- .../jfo/JavaFileObjectInputClassInMemory.java | 2 +- .../jfo/JavaFileObjectInputSourceBase.java | 4 +- .../jfo/JavaFileObjectInputSourceInFile.java | 4 +- .../JavaFileObjectInputSourceInMemory.java | 2 +- .../comp/jfo/JavaFileObjectOutputClass.java | 4 +- .../clsmgr/srcunit/SourceFileJavaNormal.java | 4 +- .../core/clsmgr/srcunit/SourceScriptRoot.java | 2 +- .../clsmgr/srcunit/SourceScriptRootFile.java | 8 +-- .../srcunit/SourceScriptRootFileJavaExt.java | 8 +-- .../srcunit/SourceScriptRootFileOtherExt.java | 8 +-- .../srcunit/SourceScriptRootInMemory.java | 2 +- .../core/clsmgr/srcunit/SourceUnit.java | 6 +- .../impl/jproxy/screngine/BindingsImpl.java | 2 +- .../JProxyScriptEngineDelegateImpl.java | 20 +++--- .../JProxyScriptEngineFactoryImpl.java | 6 +- .../screngine/JProxyScriptEngineImpl.java | 14 ++-- .../jproxy/shell/JProxyShellClassLoader.java | 6 +- .../shell/JProxyShellCodeSnippetImpl.java | 14 ++-- .../impl/jproxy/shell/JProxyShellImpl.java | 18 ++--- .../shell/JProxyShellInteractiveImpl.java | 16 ++--- .../shell/JProxyShellScriptFileImpl.java | 18 ++--- .../impl/jproxy/shell/inter/Command.java | 2 +- .../shell/inter/CommandCodeChangerBase.java | 2 +- .../jproxy/shell/inter/CommandDelete.java | 2 +- .../impl/jproxy/shell/inter/CommandEdit.java | 2 +- .../impl/jproxy/shell/inter/CommandError.java | 2 +- .../jproxy/shell/inter/CommandInsert.java | 2 +- .../impl/jproxy/shell/inter/CommandLoad.java | 4 +- .../impl/jproxy/shell/inter/CommandOther.java | 4 +- .../impl/jproxy/shell/inter/CommandSave.java | 4 +- .../shell/inter/JProxyShellProcessor.java | 14 ++-- .../impl/jproxy/shell/inter/Keyboard.java | 2 +- .../inter/KeyboardNotUsingClipboard.java | 4 +- .../shell/inter/KeyboardUsingClipboard.java | 4 +- .../shell/inter/LinuxUnicodeKeyboard.java | 4 +- .../shell/inter/MacOSXUnicodeKeyboard.java | 4 +- .../shell/inter/WindowUnicodeKeyboard.java | 4 +- .../relproxy/jproxy/JProxy.java | 6 +- .../jproxy/JProxyCompilerListener.java | 2 +- .../relproxy/jproxy/JProxyConfig.java | 4 +- .../jproxy/JProxyDiagnosticsListener.java | 2 +- ...JProxyInputSourceFileExcludedListener.java | 2 +- .../relproxy/jproxy/JProxyScriptEngine.java | 2 +- .../jproxy/JProxyScriptEngineFactory.java | 4 +- .../relproxy/jproxy/JProxyShell.java | 4 +- .../relproxy/jproxy/package.html | 0 .../relproxy/package.html | 0 108 files changed, 442 insertions(+), 397 deletions(-) rename src/main/java/com/{innowhere => sillelien}/relproxy/RelProxy.java (90%) rename src/main/java/com/{innowhere => sillelien}/relproxy/RelProxyException.java (97%) rename src/main/java/com/{innowhere => sillelien}/relproxy/RelProxyOnReloadListener.java (79%) rename src/main/java/com/{innowhere => sillelien}/relproxy/gproxy/GProxy.java (94%) rename src/main/java/com/{innowhere => sillelien}/relproxy/gproxy/GProxyConfig.java (94%) rename src/main/java/com/{innowhere => sillelien}/relproxy/gproxy/GProxyGroovyScriptEngine.java (97%) rename src/main/java/com/{innowhere => sillelien}/relproxy/gproxy/package.html (100%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/FileExt.java (89%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/GenericProxyConfigBaseImpl.java (78%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/GenericProxyImpl.java (91%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/GenericProxyInvocationHandler.java (96%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/GenericProxyVersionedObject.java (97%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/gproxy/GProxyConfigImpl.java (72%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/gproxy/GProxyDefaultImpl.java (86%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/gproxy/core/GProxyImpl.java (68%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/gproxy/core/GProxyInvocationHandler.java (75%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/gproxy/core/GProxyVersionedObject.java (87%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/JProxyConfigImpl.java (88%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/JProxyDefaultImpl.java (92%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/JProxyUtil.java (97%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/JProxyImpl.java (78%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/JProxyInvocationHandler.java (75%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/JProxyVersionedObject.java (83%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java (95%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java (96%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java (94%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java (93%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java (92%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java (98%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java (89%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java (70%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java (98%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java (96%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java (92%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java (72%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java (93%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java (92%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java (92%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java (95%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JProxyJavaFileObjectInput.java (64%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java (85%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java (97%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java (92%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java (95%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java (93%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java (86%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java (91%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java (92%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java (83%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRoot.java (80%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java (82%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java (68%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java (80%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootInMemory.java (96%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java (81%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/screngine/BindingsImpl.java (76%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java (85%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java (96%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java (87%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java (88%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java (81%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/JProxyShellImpl.java (91%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java (84%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java (83%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/inter/Command.java (98%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java (97%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/inter/CommandDelete.java (97%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/inter/CommandEdit.java (97%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/inter/CommandError.java (84%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/inter/CommandInsert.java (97%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/inter/CommandLoad.java (94%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/inter/CommandOther.java (97%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/inter/CommandSave.java (92%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java (94%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/inter/Keyboard.java (90%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java (99%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java (94%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/inter/LinuxUnicodeKeyboard.java (96%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/inter/MacOSXUnicodeKeyboard.java (95%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/inter/WindowUnicodeKeyboard.java (95%) rename src/main/java/com/{innowhere => sillelien}/relproxy/jproxy/JProxy.java (96%) rename src/main/java/com/{innowhere => sillelien}/relproxy/jproxy/JProxyCompilerListener.java (89%) rename src/main/java/com/{innowhere => sillelien}/relproxy/jproxy/JProxyConfig.java (98%) rename src/main/java/com/{innowhere => sillelien}/relproxy/jproxy/JProxyDiagnosticsListener.java (93%) rename src/main/java/com/{innowhere => sillelien}/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java (95%) rename src/main/java/com/{innowhere => sillelien}/relproxy/jproxy/JProxyScriptEngine.java (98%) rename src/main/java/com/{innowhere => sillelien}/relproxy/jproxy/JProxyScriptEngineFactory.java (84%) rename src/main/java/com/{innowhere => sillelien}/relproxy/jproxy/JProxyShell.java (83%) rename src/main/java/com/{innowhere => sillelien}/relproxy/jproxy/package.html (100%) rename src/main/java/com/{innowhere => sillelien}/relproxy/package.html (100%) diff --git a/pom.xml b/pom.xml index edd1d18..e1e5557 100644 --- a/pom.xml +++ b/pom.xml @@ -8,6 +8,57 @@ relproxy 0 + relproxy + + Simple Java and Groovy hot class reloader,and Java based shell and scripting used by Dollar project, original project is https://github.com/jmarranz/relproxy + + https://github.com/dollar-org/relproxy + + + The Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + + + + + Jose Maria Arranz + jmarranz@innowhere.com + Innowhere Software + http://www.innowhere.com + + Original Author + + + + + + + Daniel López (greeneyed) + + + https://github.com/Verdoso + + Original Contributor + + + + Michael Vorburger + mike@vorburger.ch + Vorburger.CH + http://www.vorburger.ch + + Original Contributor + + + + + + scm:git:git@github.com:dollar-org/relproxy.git + scm:git:git@github.com:dollar-org/relproxy.git + git@github.com:dollar-org/relproxy.git + + + 2.0.2 2.4 @@ -22,16 +73,16 @@ - - com.versioneye - versioneye-maven-plugin - 3.11.4 - - 0c797be864338a3649f0 - neilellis_orga - Owners - - + + + + + + + + + + org.apache.rat diff --git a/relproxy/pom.xml b/relproxy/pom.xml index 369a555..9ca34a3 100644 --- a/relproxy/pom.xml +++ b/relproxy/pom.xml @@ -147,7 +147,7 @@ RelProxy v${project.version} RelProxy v${project.version} - com.innowhere.relproxy.impl + com.sillelien.relproxy.impl diff --git a/relproxy/src/main/asciidoc/manual.asciidoc b/relproxy/src/main/asciidoc/manual.asciidoc index 3552f6a..005049c 100644 --- a/relproxy/src/main/asciidoc/manual.asciidoc +++ b/relproxy/src/main/asciidoc/manual.asciidoc @@ -630,7 +630,7 @@ Both types of web applications, publishing source code to war and direct access == GProxy or how to be able to reload Groovy classes on the Java environment -`com.innowhere.relproxy.gproxy.GProxy` is the main Java class of RelProxy to provide this feature, with `GProxy` you can create Java proxies for Groovy objects because +`GProxy` is the main Java class of RelProxy to provide this feature, with `GProxy` you can create Java proxies for Groovy objects because a `java.lang.reflect.Proxy` wrapper is passed instead of the original Groovy object, the original Groovy object is retained under the hood and method calls to the proxy are redirected to the real object calling the corresponding method using reflection. When the source code of the Groovy class changes GProxy automatically reloads the Groovy class and creates a new object to replace the old one, the fields of the original object are got and re-set to the new object to keep the state (number of fields and types @@ -651,10 +651,10 @@ import org.itsnat.core.tmpl.ItsNatDocumentTemplate; import org.itsnat.core.event.ItsNatServletRequestListener; import groovy.util.GroovyScriptEngine; import java.lang.reflect.Method; -import com.innowhere.relproxy.RelProxyOnReloadListener; -import com.innowhere.relproxy.gproxy.GProxy; -import com.innowhere.relproxy.gproxy.GProxyGroovyScriptEngine; -import com.innowhere.relproxy.gproxy.GProxyConfig; +import RelProxyOnReloadListener; +import GProxy; +import GProxyGroovyScriptEngine; +import GProxyConfig; GroovyScriptEngine groovyEngine = servlet.getGroovyScriptEngine(); @@ -825,7 +825,7 @@ Finally we have been able to reload Groovy classes mixed in a Java environment. Java hot reloadable proxies are very similar to Groovy support of RelProxy, in this case the task of detecting source changes, recompiling and reloading is fully done by RelProxy (in case of Groovy provided `groovy.util.GroovyScriptEngine` does most of this work). -`com.innowhere.relproxy.jproxy.JProxy` is the main Java class of RelProxy for hot reload of pure Java, with `JProxy` you can create Java `java.lang.reflect.Proxy` proxies wrapping +`JProxy` is the main Java class of RelProxy for hot reload of pure Java, with `JProxy` you can create Java `java.lang.reflect.Proxy` proxies wrapping your original objects to be passed to listeners, the original object is retained under the hood and method calls to the proxy are redirected to the real object calling the corresponding method using reflection. When the source code of a monitored Java file is changed, it is automatically recompiled in memory. When the `processRequest` method of the proxied `JProxyExampleLoadListener` object is called because an end user is reloading the related web page, `JProxy` detects something has changed and reload all monitored @@ -860,12 +860,12 @@ import javax.tools.JavaFileObject; import org.itsnat.core.event.ItsNatServletRequestListener; import org.itsnat.core.http.HttpServletWrapper; import org.itsnat.core.tmpl.ItsNatDocumentTemplate; -import com.innowhere.relproxy.RelProxyOnReloadListener; -import com.innowhere.relproxy.jproxy.JProxy; -import com.innowhere.relproxy.jproxy.JProxyCompilerListener; -import com.innowhere.relproxy.jproxy.JProxyConfig; -import com.innowhere.relproxy.jproxy.JProxyDiagnosticsListener; -import com.innowhere.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import RelProxyOnReloadListener; +import JProxy; +import JProxyCompilerListener; +import JProxyConfig; +import JProxyDiagnosticsListener; +import JProxyInputSourceFileExcludedListener; /** @@ -1304,12 +1304,12 @@ import javax.tools.DiagnosticCollector; import javax.tools.JavaFileObject; import com.google.gwt.user.server.rpc.RemoteServiceServlet; -import com.innowhere.relproxy.RelProxyOnReloadListener; -import com.innowhere.relproxy.jproxy.JProxy; -import com.innowhere.relproxy.jproxy.JProxyConfig; -import com.innowhere.relproxy.jproxy.JProxyDiagnosticsListener; -import com.innowhere.relproxy.jproxy.JProxyInputSourceFileExcludedListener; -import com.innowhere.relproxy.jproxy.JProxyCompilerListener; +import RelProxyOnReloadListener; +import JProxy; +import JProxyConfig; +import JProxyDiagnosticsListener; +import JProxyInputSourceFileExcludedListener; +import JProxyCompilerListener; import com.innowhere.relproxyexgwt.client.GreetingService; /** @@ -2121,7 +2121,7 @@ public class RelProxyBuiltinRoot ---- package com.innowhere.relproxy_builtin_ex; -import com.innowhere.relproxy.jproxy.JProxyScriptEngine; +import JProxyScriptEngine; import java.io.InputStream; import java.io.PrintStream; @@ -2174,8 +2174,8 @@ Now the implementation details, this class shows how simple is to built-in RelPr ---- package com.innowhere.relproxy_builtin_ex.impl; -import com.innowhere.relproxy.jproxy.JProxyScriptEngine; -import com.innowhere.relproxy.jproxy.JProxyScriptEngineFactory; +import JProxyScriptEngine; +import JProxyScriptEngineFactory; import com.innowhere.relproxy_builtin_ex.CommandListener; import com.innowhere.relproxy_builtin_ex.OutputListener; import com.innowhere.relproxy_builtin_ex.RelProxyBuiltin; @@ -2332,13 +2332,13 @@ This is the example code of this console based program (names are inspired on JU ---- package com.innowhere.relproxy_builtin_ex_main; -import com.innowhere.relproxy.RelProxyOnReloadListener; -import com.innowhere.relproxy.jproxy.JProxy; -import com.innowhere.relproxy.jproxy.JProxyCompilerListener; -import com.innowhere.relproxy.jproxy.JProxyConfig; -import com.innowhere.relproxy.jproxy.JProxyDiagnosticsListener; -import com.innowhere.relproxy.jproxy.JProxyInputSourceFileExcludedListener; -import com.innowhere.relproxy.jproxy.JProxyScriptEngine; +import RelProxyOnReloadListener; +import JProxy; +import JProxyCompilerListener; +import JProxyConfig; +import JProxyDiagnosticsListener; +import JProxyInputSourceFileExcludedListener; +import JProxyScriptEngine; import com.innowhere.relproxy_builtin_ex.CommandListener; import com.innowhere.relproxy_builtin_ex.RelProxyBuiltin; import com.innowhere.relproxy_builtin_ex.RelProxyBuiltinRoot; diff --git a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyCodeSnippetCompleteClassTest.java b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyCodeSnippetCompleteClassTest.java index 2dd7a06..4f40057 100644 --- a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyCodeSnippetCompleteClassTest.java +++ b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyCodeSnippetCompleteClassTest.java @@ -4,7 +4,7 @@ * and open the template in the editor. */ -package com.innowhere.relproxy.jproxy; +package com.sillelien.relproxy.jproxy; import org.junit.After; import org.junit.AfterClass; diff --git a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyCodeSnippetTest.java b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyCodeSnippetTest.java index b692a63..5435fff 100644 --- a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyCodeSnippetTest.java +++ b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyCodeSnippetTest.java @@ -4,7 +4,7 @@ * and open the template in the editor. */ -package com.innowhere.relproxy.jproxy; +package com.sillelien.relproxy.jproxy; import org.junit.After; import org.junit.AfterClass; diff --git a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaScriptEngineNoManagerTest.java b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaScriptEngineNoManagerTest.java index 9ad97a7..dcddcfe 100644 --- a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaScriptEngineNoManagerTest.java +++ b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaScriptEngineNoManagerTest.java @@ -1,8 +1,8 @@ -package com.innowhere.relproxy.jproxy; +package com.sillelien.relproxy.jproxy; -import com.innowhere.relproxy.RelProxyOnReloadListener; -import static com.innowhere.relproxy.jproxy.util.JProxyTestUtil.RESOURCES_FOLDER; -import static com.innowhere.relproxy.jproxy.util.JProxyTestUtil.getProjectFolder; +import com.sillelien.relproxy.RelProxyOnReloadListener; +import static com.sillelien.relproxy.jproxy.util.JProxyTestUtil.RESOURCES_FOLDER; +import static com.sillelien.relproxy.jproxy.util.JProxyTestUtil.getProjectFolder; import java.io.File; diff --git a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaScriptEngineTest.java b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaScriptEngineTest.java index d9812b6..6ff0c01 100644 --- a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaScriptEngineTest.java +++ b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaScriptEngineTest.java @@ -1,8 +1,8 @@ -package com.innowhere.relproxy.jproxy; +package com.sillelien.relproxy.jproxy; -import com.innowhere.relproxy.RelProxyOnReloadListener; -import static com.innowhere.relproxy.jproxy.util.JProxyTestUtil.RESOURCES_FOLDER; -import static com.innowhere.relproxy.jproxy.util.JProxyTestUtil.getProjectFolder; +import com.sillelien.relproxy.RelProxyOnReloadListener; +import static com.sillelien.relproxy.jproxy.util.JProxyTestUtil.RESOURCES_FOLDER; +import static com.sillelien.relproxy.jproxy.util.JProxyTestUtil.getProjectFolder; import java.io.File; diff --git a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellCompleteClassTest.java b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellCompleteClassTest.java index 91fdbbe..d0de94b 100644 --- a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellCompleteClassTest.java +++ b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellCompleteClassTest.java @@ -1,6 +1,6 @@ -package com.innowhere.relproxy.jproxy; +package com.sillelien.relproxy.jproxy; -import com.innowhere.relproxy.jproxy.util.JProxyTestUtil; +import com.sillelien.relproxy.jproxy.util.JProxyTestUtil; import java.io.File; import org.junit.After; import org.junit.AfterClass; diff --git a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellInteractiveTest.java b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellInteractiveTest.java index 92fc5d9..5d18b4b 100644 --- a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellInteractiveTest.java +++ b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellInteractiveTest.java @@ -4,7 +4,7 @@ * and open the template in the editor. */ -package com.innowhere.relproxy.jproxy; +package com.sillelien.relproxy.jproxy; import org.junit.After; import org.junit.AfterClass; diff --git a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellNormalClassTest.java b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellNormalClassTest.java index 31c819c..1673a26 100644 --- a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellNormalClassTest.java +++ b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellNormalClassTest.java @@ -1,6 +1,6 @@ -package com.innowhere.relproxy.jproxy; +package com.sillelien.relproxy.jproxy; -import com.innowhere.relproxy.jproxy.util.JProxyTestUtil; +import com.sillelien.relproxy.jproxy.util.JProxyTestUtil; import java.io.File; import org.junit.After; import org.junit.AfterClass; diff --git a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellTest.java b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellTest.java index 05b8f11..4461b7c 100644 --- a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellTest.java +++ b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellTest.java @@ -1,13 +1,14 @@ -package com.innowhere.relproxy.jproxy; +package com.sillelien.relproxy.jproxy; -import com.innowhere.relproxy.jproxy.util.JProxyTestUtil; -import java.io.File; +import com.sillelien.relproxy.jproxy.util.JProxyTestUtil; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; +import java.io.File; + /** * * @author jmarranz diff --git a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/util/JProxyTestUtil.java b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/util/JProxyTestUtil.java index 51dc64d..eed55b9 100644 --- a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/util/JProxyTestUtil.java +++ b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/util/JProxyTestUtil.java @@ -1,5 +1,5 @@ -package com.innowhere.relproxy.jproxy.util; +package com.sillelien.relproxy.jproxy.util; import java.io.File; import java.net.URL; @@ -15,7 +15,7 @@ public class JProxyTestUtil public static File getProjectFolder() { - String className = JProxyTestUtil.class.getName(); // com.innowhere.relproxy.jproxy.util.JProxyTestUtil + String className = JProxyTestUtil.class.getName(); // com.sillelien.relproxy.jproxy.util.JProxyTestUtil URL urlClass = JProxyTestUtil.class.getClassLoader().getResource(className.replace('.','/') + ".class"); File fileClass = new File(urlClass.getPath()); File projectFolder = fileClass.getParentFile(); diff --git a/relproxy/src/test/resources/example/javashellex/JProxyShellExample.java b/relproxy/src/test/resources/example/javashellex/JProxyShellExample.java index f538370..92de1f4 100644 --- a/relproxy/src/test/resources/example/javashellex/JProxyShellExample.java +++ b/relproxy/src/test/resources/example/javashellex/JProxyShellExample.java @@ -1,7 +1,7 @@ package example.javashellex; import javax.script.ScriptEngine; -import com.innowhere.relproxy.jproxy.JProxyScriptEngine; +import com.sillelien.relproxy.jproxy.JProxyScriptEngine; /** * diff --git a/relproxy_test_itsnat/src/main/java/example/groovyex/ItsNatGroovyServlet.java b/relproxy_test_itsnat/src/main/java/example/groovyex/ItsNatGroovyServlet.java index 3d84c78..c8216b0 100644 --- a/relproxy_test_itsnat/src/main/java/example/groovyex/ItsNatGroovyServlet.java +++ b/relproxy_test_itsnat/src/main/java/example/groovyex/ItsNatGroovyServlet.java @@ -82,9 +82,9 @@ public void init(ServletConfig config) throws ServletException binding.setVariable("context", getServletContext()); binding.setVariable("application", getServletContext()); - com.innowhere.relproxy.gproxy.GProxyGroovyScriptEngine.class.getName(); - com.innowhere.relproxy.gproxy.GProxyConfig.class.getName(); - com.innowhere.relproxy.gproxy.GProxy.class.getName(); + com.sillelien.relproxy.gproxy.GProxyGroovyScriptEngine.class.getName(); + com.sillelien.relproxy.gproxy.GProxyConfig.class.getName(); + com.sillelien.relproxy.gproxy.GProxy.class.getName(); execGroovyScript(initScript,binding); } diff --git a/relproxy_test_itsnat/src/main/java/example/javaex/JProxyExampleServlet.java b/relproxy_test_itsnat/src/main/java/example/javaex/JProxyExampleServlet.java index 9bc7397..e845d30 100644 --- a/relproxy_test_itsnat/src/main/java/example/javaex/JProxyExampleServlet.java +++ b/relproxy_test_itsnat/src/main/java/example/javaex/JProxyExampleServlet.java @@ -1,7 +1,7 @@ package example.javaex; -import com.innowhere.relproxy.jproxy.JProxy; +import com.sillelien.relproxy.jproxy.JProxy; import javax.servlet.ServletConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; diff --git a/relproxy_test_itsnat/src/main/java/example/javaex/JProxyServletContextListener.java b/relproxy_test_itsnat/src/main/java/example/javaex/JProxyServletContextListener.java index e8b00f3..58fadd2 100644 --- a/relproxy_test_itsnat/src/main/java/example/javaex/JProxyServletContextListener.java +++ b/relproxy_test_itsnat/src/main/java/example/javaex/JProxyServletContextListener.java @@ -1,21 +1,22 @@ package example.javaex; -import com.innowhere.relproxy.RelProxyOnReloadListener; -import com.innowhere.relproxy.jproxy.JProxy; -import com.innowhere.relproxy.jproxy.JProxyCompilerListener; -import com.innowhere.relproxy.jproxy.JProxyConfig; -import com.innowhere.relproxy.jproxy.JProxyDiagnosticsListener; -import com.innowhere.relproxy.jproxy.JProxyInputSourceFileExcludedListener; -import java.io.File; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.List; +import com.sillelien.relproxy.RelProxyOnReloadListener; +import com.sillelien.relproxy.jproxy.JProxy; +import com.sillelien.relproxy.jproxy.JProxyCompilerListener; +import com.sillelien.relproxy.jproxy.JProxyConfig; +import com.sillelien.relproxy.jproxy.JProxyDiagnosticsListener; +import com.sillelien.relproxy.jproxy.JProxyInputSourceFileExcludedListener; + import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.tools.Diagnostic; import javax.tools.DiagnosticCollector; import javax.tools.JavaFileObject; +import java.io.File; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.List; /** * diff --git a/relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/code/example/groovyex/groovy_servlet_init.groovy b/relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/code/example/groovyex/groovy_servlet_init.groovy index c0b94bb..cdf3128 100644 --- a/relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/code/example/groovyex/groovy_servlet_init.groovy +++ b/relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/code/example/groovyex/groovy_servlet_init.groovy @@ -1,16 +1,12 @@ -package example.groovyex; +package example.groovyex -import org.itsnat.core.http.ItsNatHttpServlet; -import org.itsnat.core.tmpl.ItsNatDocumentTemplate; import org.itsnat.core.event.ItsNatServletRequestListener; import groovy.util.GroovyScriptEngine; import java.lang.reflect.Method; -import com.innowhere.relproxy.RelProxyOnReloadListener; -import com.innowhere.relproxy.gproxy.GProxy; -import com.innowhere.relproxy.gproxy.GProxyGroovyScriptEngine; -import com.innowhere.relproxy.gproxy.GProxyConfig; - +import com.sillelien.relproxy.RelProxyOnReloadListener; +import com.sillelien.relproxy.gproxy.GProxy; +import com.sillelien.relproxy.gproxy.GProxyGroovyScriptEngine GroovyScriptEngine groovyEngine = servlet.getGroovyScriptEngine(); diff --git a/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleDocument.java b/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleDocument.java index 903e65a..221a465 100644 --- a/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleDocument.java +++ b/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleDocument.java @@ -1,13 +1,12 @@ package example.javaex; -import com.innowhere.relproxy.jproxy.JProxy; +import com.sillelien.relproxy.jproxy.JProxy; import example.javaex.hotreload.JProxyExampleAux2; import example.javaex.nothotreload.JProxyExampleAuxIgnored2; import example.javaex.nothotreload.JProxyExampleAuxIgnored3; import org.itsnat.comp.ItsNatComponentManager; import org.itsnat.comp.text.ItsNatHTMLInputText; import org.itsnat.core.ItsNatServletRequest; -import org.itsnat.core.event.ItsNatServletRequestListener; import org.itsnat.core.html.ItsNatHTMLDocument; import org.w3c.dom.Element; import org.w3c.dom.events.Event; diff --git a/src/main/java/com/innowhere/relproxy/RelProxy.java b/src/main/java/com/sillelien/relproxy/RelProxy.java similarity index 90% rename from src/main/java/com/innowhere/relproxy/RelProxy.java rename to src/main/java/com/sillelien/relproxy/RelProxy.java index 2209333..c63cea3 100644 --- a/src/main/java/com/innowhere/relproxy/RelProxy.java +++ b/src/main/java/com/sillelien/relproxy/RelProxy.java @@ -1,4 +1,4 @@ -package com.innowhere.relproxy; +package com.sillelien.relproxy; /** * Is the root of RelProxy diff --git a/src/main/java/com/innowhere/relproxy/RelProxyException.java b/src/main/java/com/sillelien/relproxy/RelProxyException.java similarity index 97% rename from src/main/java/com/innowhere/relproxy/RelProxyException.java rename to src/main/java/com/sillelien/relproxy/RelProxyException.java index aeafaad..8b16207 100644 --- a/src/main/java/com/innowhere/relproxy/RelProxyException.java +++ b/src/main/java/com/sillelien/relproxy/RelProxyException.java @@ -1,4 +1,4 @@ -package com.innowhere.relproxy; +package com.sillelien.relproxy; /** * Internal checked exceptions thrown by RelProxy and library specific errors are wrapped into this exception class. diff --git a/src/main/java/com/innowhere/relproxy/RelProxyOnReloadListener.java b/src/main/java/com/sillelien/relproxy/RelProxyOnReloadListener.java similarity index 79% rename from src/main/java/com/innowhere/relproxy/RelProxyOnReloadListener.java rename to src/main/java/com/sillelien/relproxy/RelProxyOnReloadListener.java index faf1c62..acad475 100644 --- a/src/main/java/com/innowhere/relproxy/RelProxyOnReloadListener.java +++ b/src/main/java/com/sillelien/relproxy/RelProxyOnReloadListener.java @@ -1,4 +1,4 @@ -package com.innowhere.relproxy; +package com.sillelien.relproxy; import java.lang.reflect.Method; @@ -10,8 +10,8 @@ *

* * - * @see com.innowhere.relproxy.jproxy.JProxyConfig#setRelProxyOnReloadListener(com.innowhere.relproxy.RelProxyOnReloadListener) - * @see com.innowhere.relproxy.gproxy.GProxyConfig#setRelProxyOnReloadListener(com.innowhere.relproxy.RelProxyOnReloadListener) + * @see com.sillelien.relproxy.jproxy.JProxyConfig#setRelProxyOnReloadListener(com.sillelien.relproxy.RelProxyOnReloadListener) + * @see com.sillelien.relproxy.gproxy.GProxyConfig#setRelProxyOnReloadListener(com.sillelien.relproxy.RelProxyOnReloadListener) * @author Jose Maria Arranz Santamaria */ public interface RelProxyOnReloadListener diff --git a/src/main/java/com/innowhere/relproxy/gproxy/GProxy.java b/src/main/java/com/sillelien/relproxy/gproxy/GProxy.java similarity index 94% rename from src/main/java/com/innowhere/relproxy/gproxy/GProxy.java rename to src/main/java/com/sillelien/relproxy/gproxy/GProxy.java index 942b56e..5c74686 100644 --- a/src/main/java/com/innowhere/relproxy/gproxy/GProxy.java +++ b/src/main/java/com/sillelien/relproxy/gproxy/GProxy.java @@ -1,8 +1,8 @@ -package com.innowhere.relproxy.gproxy; +package com.sillelien.relproxy.gproxy; -import com.innowhere.relproxy.impl.gproxy.GProxyConfigImpl; -import com.innowhere.relproxy.impl.gproxy.GProxyDefaultImpl; +import com.sillelien.relproxy.impl.gproxy.GProxyConfigImpl; +import com.sillelien.relproxy.impl.gproxy.GProxyDefaultImpl; /** * Is the class to create Java proxy objects based on Groovy objects and keep track of Groovy source code changes reloading Groovy classes when detected. diff --git a/src/main/java/com/innowhere/relproxy/gproxy/GProxyConfig.java b/src/main/java/com/sillelien/relproxy/gproxy/GProxyConfig.java similarity index 94% rename from src/main/java/com/innowhere/relproxy/gproxy/GProxyConfig.java rename to src/main/java/com/sillelien/relproxy/gproxy/GProxyConfig.java index 4e517fa..14cb90c 100644 --- a/src/main/java/com/innowhere/relproxy/gproxy/GProxyConfig.java +++ b/src/main/java/com/sillelien/relproxy/gproxy/GProxyConfig.java @@ -1,7 +1,7 @@ -package com.innowhere.relproxy.gproxy; +package com.sillelien.relproxy.gproxy; -import com.innowhere.relproxy.RelProxyOnReloadListener; +import com.sillelien.relproxy.RelProxyOnReloadListener; /** * Interface implemented by the configuration object needed to initialize GProxy. diff --git a/src/main/java/com/innowhere/relproxy/gproxy/GProxyGroovyScriptEngine.java b/src/main/java/com/sillelien/relproxy/gproxy/GProxyGroovyScriptEngine.java similarity index 97% rename from src/main/java/com/innowhere/relproxy/gproxy/GProxyGroovyScriptEngine.java rename to src/main/java/com/sillelien/relproxy/gproxy/GProxyGroovyScriptEngine.java index 47d09d7..4025e04 100644 --- a/src/main/java/com/innowhere/relproxy/gproxy/GProxyGroovyScriptEngine.java +++ b/src/main/java/com/sillelien/relproxy/gproxy/GProxyGroovyScriptEngine.java @@ -1,4 +1,4 @@ -package com.innowhere.relproxy.gproxy; +package com.sillelien.relproxy.gproxy; /** * Interface to implement the object implementing the GroovyScriptEngine wrapper used to reload Groovy classes. diff --git a/src/main/java/com/innowhere/relproxy/gproxy/package.html b/src/main/java/com/sillelien/relproxy/gproxy/package.html similarity index 100% rename from src/main/java/com/innowhere/relproxy/gproxy/package.html rename to src/main/java/com/sillelien/relproxy/gproxy/package.html diff --git a/src/main/java/com/innowhere/relproxy/impl/FileExt.java b/src/main/java/com/sillelien/relproxy/impl/FileExt.java similarity index 89% rename from src/main/java/com/innowhere/relproxy/impl/FileExt.java rename to src/main/java/com/sillelien/relproxy/impl/FileExt.java index bc3fa3d..d9d3d3c 100644 --- a/src/main/java/com/innowhere/relproxy/impl/FileExt.java +++ b/src/main/java/com/sillelien/relproxy/impl/FileExt.java @@ -1,6 +1,6 @@ -package com.innowhere.relproxy.impl; +package com.sillelien.relproxy.impl; -import com.innowhere.relproxy.RelProxyException; +import com.sillelien.relproxy.RelProxyException; import java.io.File; import java.io.IOException; diff --git a/src/main/java/com/innowhere/relproxy/impl/GenericProxyConfigBaseImpl.java b/src/main/java/com/sillelien/relproxy/impl/GenericProxyConfigBaseImpl.java similarity index 78% rename from src/main/java/com/innowhere/relproxy/impl/GenericProxyConfigBaseImpl.java rename to src/main/java/com/sillelien/relproxy/impl/GenericProxyConfigBaseImpl.java index f1fda6d..f46404e 100644 --- a/src/main/java/com/innowhere/relproxy/impl/GenericProxyConfigBaseImpl.java +++ b/src/main/java/com/sillelien/relproxy/impl/GenericProxyConfigBaseImpl.java @@ -1,6 +1,6 @@ -package com.innowhere.relproxy.impl; +package com.sillelien.relproxy.impl; -import com.innowhere.relproxy.RelProxyOnReloadListener; +import com.sillelien.relproxy.RelProxyOnReloadListener; /** * diff --git a/src/main/java/com/innowhere/relproxy/impl/GenericProxyImpl.java b/src/main/java/com/sillelien/relproxy/impl/GenericProxyImpl.java similarity index 91% rename from src/main/java/com/innowhere/relproxy/impl/GenericProxyImpl.java rename to src/main/java/com/sillelien/relproxy/impl/GenericProxyImpl.java index a24ba38..ca7a397 100644 --- a/src/main/java/com/innowhere/relproxy/impl/GenericProxyImpl.java +++ b/src/main/java/com/sillelien/relproxy/impl/GenericProxyImpl.java @@ -1,7 +1,7 @@ -package com.innowhere.relproxy.impl; +package com.sillelien.relproxy.impl; -import com.innowhere.relproxy.RelProxyException; -import com.innowhere.relproxy.RelProxyOnReloadListener; +import com.sillelien.relproxy.RelProxyException; +import com.sillelien.relproxy.RelProxyOnReloadListener; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; diff --git a/src/main/java/com/innowhere/relproxy/impl/GenericProxyInvocationHandler.java b/src/main/java/com/sillelien/relproxy/impl/GenericProxyInvocationHandler.java similarity index 96% rename from src/main/java/com/innowhere/relproxy/impl/GenericProxyInvocationHandler.java rename to src/main/java/com/sillelien/relproxy/impl/GenericProxyInvocationHandler.java index e9fba8c..ad6d6f9 100644 --- a/src/main/java/com/innowhere/relproxy/impl/GenericProxyInvocationHandler.java +++ b/src/main/java/com/sillelien/relproxy/impl/GenericProxyInvocationHandler.java @@ -1,6 +1,6 @@ -package com.innowhere.relproxy.impl; +package com.sillelien.relproxy.impl; -import com.innowhere.relproxy.RelProxyOnReloadListener; +import com.sillelien.relproxy.RelProxyOnReloadListener; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; diff --git a/src/main/java/com/innowhere/relproxy/impl/GenericProxyVersionedObject.java b/src/main/java/com/sillelien/relproxy/impl/GenericProxyVersionedObject.java similarity index 97% rename from src/main/java/com/innowhere/relproxy/impl/GenericProxyVersionedObject.java rename to src/main/java/com/sillelien/relproxy/impl/GenericProxyVersionedObject.java index f7165a6..c23db15 100644 --- a/src/main/java/com/innowhere/relproxy/impl/GenericProxyVersionedObject.java +++ b/src/main/java/com/sillelien/relproxy/impl/GenericProxyVersionedObject.java @@ -1,13 +1,11 @@ -package com.innowhere.relproxy.impl; +package com.sillelien.relproxy.impl; -import com.innowhere.relproxy.RelProxyException; +import com.sillelien.relproxy.RelProxyException; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Modifier; import java.util.ArrayList; -import java.util.logging.Level; -import java.util.logging.Logger; /** * diff --git a/src/main/java/com/innowhere/relproxy/impl/gproxy/GProxyConfigImpl.java b/src/main/java/com/sillelien/relproxy/impl/gproxy/GProxyConfigImpl.java similarity index 72% rename from src/main/java/com/innowhere/relproxy/impl/gproxy/GProxyConfigImpl.java rename to src/main/java/com/sillelien/relproxy/impl/gproxy/GProxyConfigImpl.java index 247cc6d..d57bc86 100644 --- a/src/main/java/com/innowhere/relproxy/impl/gproxy/GProxyConfigImpl.java +++ b/src/main/java/com/sillelien/relproxy/impl/gproxy/GProxyConfigImpl.java @@ -1,9 +1,9 @@ -package com.innowhere.relproxy.impl.gproxy; +package com.sillelien.relproxy.impl.gproxy; -import com.innowhere.relproxy.RelProxyOnReloadListener; -import com.innowhere.relproxy.gproxy.GProxyConfig; -import com.innowhere.relproxy.gproxy.GProxyGroovyScriptEngine; -import com.innowhere.relproxy.impl.GenericProxyConfigBaseImpl; +import com.sillelien.relproxy.RelProxyOnReloadListener; +import com.sillelien.relproxy.gproxy.GProxyConfig; +import com.sillelien.relproxy.gproxy.GProxyGroovyScriptEngine; +import com.sillelien.relproxy.impl.GenericProxyConfigBaseImpl; /** * diff --git a/src/main/java/com/innowhere/relproxy/impl/gproxy/GProxyDefaultImpl.java b/src/main/java/com/sillelien/relproxy/impl/gproxy/GProxyDefaultImpl.java similarity index 86% rename from src/main/java/com/innowhere/relproxy/impl/gproxy/GProxyDefaultImpl.java rename to src/main/java/com/sillelien/relproxy/impl/gproxy/GProxyDefaultImpl.java index 2c8b0dd..6c8fe50 100644 --- a/src/main/java/com/innowhere/relproxy/impl/gproxy/GProxyDefaultImpl.java +++ b/src/main/java/com/sillelien/relproxy/impl/gproxy/GProxyDefaultImpl.java @@ -1,7 +1,7 @@ -package com.innowhere.relproxy.impl.gproxy; +package com.sillelien.relproxy.impl.gproxy; -import com.innowhere.relproxy.gproxy.GProxyConfig; -import com.innowhere.relproxy.impl.gproxy.core.GProxyImpl; +import com.sillelien.relproxy.gproxy.GProxyConfig; +import com.sillelien.relproxy.impl.gproxy.core.GProxyImpl; /** * diff --git a/src/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyImpl.java b/src/main/java/com/sillelien/relproxy/impl/gproxy/core/GProxyImpl.java similarity index 68% rename from src/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyImpl.java rename to src/main/java/com/sillelien/relproxy/impl/gproxy/core/GProxyImpl.java index c20285b..ca00943 100644 --- a/src/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyImpl.java +++ b/src/main/java/com/sillelien/relproxy/impl/gproxy/core/GProxyImpl.java @@ -1,9 +1,9 @@ -package com.innowhere.relproxy.impl.gproxy.core; +package com.sillelien.relproxy.impl.gproxy.core; -import com.innowhere.relproxy.impl.gproxy.GProxyConfigImpl; -import com.innowhere.relproxy.gproxy.GProxyGroovyScriptEngine; -import com.innowhere.relproxy.impl.GenericProxyImpl; -import com.innowhere.relproxy.impl.GenericProxyInvocationHandler; +import com.sillelien.relproxy.impl.gproxy.GProxyConfigImpl; +import com.sillelien.relproxy.gproxy.GProxyGroovyScriptEngine; +import com.sillelien.relproxy.impl.GenericProxyImpl; +import com.sillelien.relproxy.impl.GenericProxyInvocationHandler; /** diff --git a/src/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyInvocationHandler.java b/src/main/java/com/sillelien/relproxy/impl/gproxy/core/GProxyInvocationHandler.java similarity index 75% rename from src/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyInvocationHandler.java rename to src/main/java/com/sillelien/relproxy/impl/gproxy/core/GProxyInvocationHandler.java index 6bacae7..f362a27 100644 --- a/src/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyInvocationHandler.java +++ b/src/main/java/com/sillelien/relproxy/impl/gproxy/core/GProxyInvocationHandler.java @@ -1,6 +1,6 @@ -package com.innowhere.relproxy.impl.gproxy.core; +package com.sillelien.relproxy.impl.gproxy.core; -import com.innowhere.relproxy.impl.GenericProxyInvocationHandler; +import com.sillelien.relproxy.impl.GenericProxyInvocationHandler; /** * @@ -19,4 +19,4 @@ public GProxyImpl getGProxyImpl() return (GProxyImpl)root; } -} \ No newline at end of file +} diff --git a/src/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyVersionedObject.java b/src/main/java/com/sillelien/relproxy/impl/gproxy/core/GProxyVersionedObject.java similarity index 87% rename from src/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyVersionedObject.java rename to src/main/java/com/sillelien/relproxy/impl/gproxy/core/GProxyVersionedObject.java index 38f574c..f57bf53 100644 --- a/src/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyVersionedObject.java +++ b/src/main/java/com/sillelien/relproxy/impl/gproxy/core/GProxyVersionedObject.java @@ -1,7 +1,7 @@ -package com.innowhere.relproxy.impl.gproxy.core; +package com.sillelien.relproxy.impl.gproxy.core; -import com.innowhere.relproxy.gproxy.GProxyGroovyScriptEngine; -import com.innowhere.relproxy.impl.GenericProxyVersionedObject; +import com.sillelien.relproxy.gproxy.GProxyGroovyScriptEngine; +import com.sillelien.relproxy.impl.GenericProxyVersionedObject; import java.lang.reflect.Field; /** diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/JProxyConfigImpl.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/JProxyConfigImpl.java similarity index 88% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/JProxyConfigImpl.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/JProxyConfigImpl.java index 8dc72f0..cc095a2 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/JProxyConfigImpl.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/JProxyConfigImpl.java @@ -1,13 +1,13 @@ -package com.innowhere.relproxy.impl.jproxy; +package com.sillelien.relproxy.impl.jproxy; -import com.innowhere.relproxy.RelProxyException; -import com.innowhere.relproxy.RelProxyOnReloadListener; -import com.innowhere.relproxy.impl.GenericProxyConfigBaseImpl; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; -import com.innowhere.relproxy.jproxy.JProxyCompilerListener; -import com.innowhere.relproxy.jproxy.JProxyConfig; -import com.innowhere.relproxy.jproxy.JProxyDiagnosticsListener; -import com.innowhere.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import com.sillelien.relproxy.RelProxyException; +import com.sillelien.relproxy.RelProxyOnReloadListener; +import com.sillelien.relproxy.impl.GenericProxyConfigBaseImpl; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import com.sillelien.relproxy.jproxy.JProxyCompilerListener; +import com.sillelien.relproxy.jproxy.JProxyConfig; +import com.sillelien.relproxy.jproxy.JProxyDiagnosticsListener; +import com.sillelien.relproxy.jproxy.JProxyInputSourceFileExcludedListener; import java.io.File; /** diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/JProxyDefaultImpl.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/JProxyDefaultImpl.java similarity index 92% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/JProxyDefaultImpl.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/JProxyDefaultImpl.java index 5b9d6d0..92ab460 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/JProxyDefaultImpl.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/JProxyDefaultImpl.java @@ -1,7 +1,7 @@ -package com.innowhere.relproxy.impl.jproxy; +package com.sillelien.relproxy.impl.jproxy; -import com.innowhere.relproxy.impl.jproxy.core.JProxyImpl; -import com.innowhere.relproxy.jproxy.JProxyConfig; +import com.sillelien.relproxy.impl.jproxy.core.JProxyImpl; +import com.sillelien.relproxy.jproxy.JProxyConfig; /** * diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/JProxyUtil.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/JProxyUtil.java similarity index 97% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/JProxyUtil.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/JProxyUtil.java index d8e46e3..b63a961 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/JProxyUtil.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/JProxyUtil.java @@ -1,6 +1,6 @@ -package com.innowhere.relproxy.impl.jproxy; +package com.sillelien.relproxy.impl.jproxy; -import com.innowhere.relproxy.RelProxyException; +import com.sillelien.relproxy.RelProxyException; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.File; diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyImpl.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/JProxyImpl.java similarity index 78% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyImpl.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/JProxyImpl.java index b9ea4da..1690794 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyImpl.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/JProxyImpl.java @@ -1,15 +1,15 @@ -package com.innowhere.relproxy.impl.jproxy.core; +package com.sillelien.relproxy.impl.jproxy.core; -import com.innowhere.relproxy.impl.GenericProxyImpl; -import com.innowhere.relproxy.impl.GenericProxyInvocationHandler; -import com.innowhere.relproxy.impl.jproxy.JProxyConfigImpl; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; -import com.innowhere.relproxy.jproxy.JProxyCompilerListener; -import com.innowhere.relproxy.jproxy.JProxyDiagnosticsListener; -import com.innowhere.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import com.sillelien.relproxy.impl.GenericProxyImpl; +import com.sillelien.relproxy.impl.GenericProxyInvocationHandler; +import com.sillelien.relproxy.impl.jproxy.JProxyConfigImpl; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.sillelien.relproxy.jproxy.JProxyCompilerListener; +import com.sillelien.relproxy.jproxy.JProxyDiagnosticsListener; +import com.sillelien.relproxy.jproxy.JProxyInputSourceFileExcludedListener; /** * diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyInvocationHandler.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/JProxyInvocationHandler.java similarity index 75% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyInvocationHandler.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/JProxyInvocationHandler.java index ebef741..ef748f4 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyInvocationHandler.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/JProxyInvocationHandler.java @@ -1,7 +1,7 @@ -package com.innowhere.relproxy.impl.jproxy.core; +package com.sillelien.relproxy.impl.jproxy.core; -import com.innowhere.relproxy.impl.GenericProxyInvocationHandler; +import com.sillelien.relproxy.impl.GenericProxyInvocationHandler; /** * @@ -20,4 +20,4 @@ public JProxyImpl getJProxyImpl() return (JProxyImpl)root; } -} \ No newline at end of file +} diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyVersionedObject.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/JProxyVersionedObject.java similarity index 83% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyVersionedObject.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/JProxyVersionedObject.java index ded542f..bb20998 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyVersionedObject.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/JProxyVersionedObject.java @@ -1,7 +1,7 @@ -package com.innowhere.relproxy.impl.jproxy.core; +package com.sillelien.relproxy.impl.jproxy.core; -import com.innowhere.relproxy.impl.GenericProxyVersionedObject; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; +import com.sillelien.relproxy.impl.GenericProxyVersionedObject; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; import java.lang.reflect.Field; /** @@ -36,4 +36,4 @@ protected boolean ignoreField(Field field) { return false; // Todos cuentan (útil en Groovy no en Java) } -} \ No newline at end of file +} diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java similarity index 95% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java index 248a714..31c7dd7 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java @@ -1,7 +1,7 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr; +package com.sillelien.relproxy.impl.jproxy.core.clsmgr; -import com.innowhere.relproxy.RelProxyException; -import com.innowhere.relproxy.impl.FileExt; +import com.sillelien.relproxy.RelProxyException; +import com.sillelien.relproxy.impl.FileExt; import java.io.File; /** diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java similarity index 96% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java index 19c7b33..b27dfb4 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java @@ -1,8 +1,8 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr; +package com.sillelien.relproxy.impl.jproxy.core.clsmgr; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; -import com.innowhere.relproxy.impl.jproxy.JProxyUtil; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; +import com.sillelien.relproxy.impl.jproxy.JProxyUtil; import java.net.URL; /** diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java similarity index 94% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java index e662177..61fef71 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java @@ -1,15 +1,15 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr; +package com.sillelien.relproxy.impl.jproxy.core.clsmgr; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorInner; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.innowhere.relproxy.impl.jproxy.core.JProxyImpl; -import com.innowhere.relproxy.jproxy.JProxyCompilerListener; -import com.innowhere.relproxy.jproxy.JProxyDiagnosticsListener; -import com.innowhere.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorInner; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.sillelien.relproxy.impl.jproxy.core.JProxyImpl; +import com.sillelien.relproxy.jproxy.JProxyCompilerListener; +import com.sillelien.relproxy.jproxy.JProxyDiagnosticsListener; +import com.sillelien.relproxy.jproxy.JProxyInputSourceFileExcludedListener; import java.util.LinkedList; import java.util.Timer; import java.util.TimerTask; diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java similarity index 93% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java index e58b76b..1cd6537 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java @@ -1,21 +1,21 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr; +package com.sillelien.relproxy.impl.jproxy.core.clsmgr; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootInMemory; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceUnit; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootFile; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorInner; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.innowhere.relproxy.impl.jproxy.JProxyUtil; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.JProxyCompilerContext; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.JProxyCompilerInMemory; -import com.innowhere.relproxy.jproxy.JProxyCompilerListener; -import com.innowhere.relproxy.jproxy.JProxyDiagnosticsListener; -import com.innowhere.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootInMemory; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceUnit; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootFile; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorInner; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.sillelien.relproxy.impl.jproxy.JProxyUtil; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.JProxyCompilerContext; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.JProxyCompilerInMemory; +import com.sillelien.relproxy.jproxy.JProxyCompilerListener; +import com.sillelien.relproxy.jproxy.JProxyDiagnosticsListener; +import com.sillelien.relproxy.jproxy.JProxyInputSourceFileExcludedListener; import java.io.File; import java.util.ArrayList; import java.util.LinkedList; diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java similarity index 92% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java index d6d8a6a..d680220 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java @@ -1,18 +1,18 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr; +package com.sillelien.relproxy.impl.jproxy.core.clsmgr; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootFileJavaExt; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceUnit; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileJava; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.innowhere.relproxy.RelProxyException; -import com.innowhere.relproxy.impl.FileExt; -import com.innowhere.relproxy.impl.jproxy.JProxyUtil; -import com.innowhere.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootFileJavaExt; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceUnit; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileJava; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.sillelien.relproxy.RelProxyException; +import com.sillelien.relproxy.impl.FileExt; +import com.sillelien.relproxy.impl.jproxy.JProxyUtil; +import com.sillelien.relproxy.jproxy.JProxyInputSourceFileExcludedListener; import java.io.File; import java.net.URL; import java.util.LinkedList; diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java similarity index 98% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java index 11c443d..659a846 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java @@ -1,4 +1,4 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc; +package com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc; import java.io.File; diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java similarity index 89% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java index d78d72b..30d5f23 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java @@ -1,4 +1,4 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc; +package com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc; /** * diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java similarity index 70% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java index 0586c19..3fe12c8 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java @@ -1,8 +1,8 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc; +package com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc; -import com.innowhere.relproxy.impl.FileExt; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; +import com.sillelien.relproxy.impl.FileExt; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; /** * diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java similarity index 98% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java index ba2e1d7..6728995 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java @@ -1,4 +1,4 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc; +package com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc; import java.util.Collection; import java.util.HashMap; diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java similarity index 96% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java index 780c575..2a69b59 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java @@ -1,9 +1,9 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc; +package com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc; -import com.innowhere.relproxy.RelProxyException; -import com.innowhere.relproxy.impl.jproxy.core.JProxyImpl; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.sillelien.relproxy.RelProxyException; +import com.sillelien.relproxy.impl.jproxy.core.JProxyImpl; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.LinkedList; diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java similarity index 92% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java index 3e2c858..931378f 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java @@ -1,9 +1,9 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc; +package com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceUnit; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceUnit; import java.util.LinkedList; /** diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java similarity index 72% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java index 7bf171a..90c2d23 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java @@ -1,8 +1,8 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp; +package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp; -import com.innowhere.relproxy.RelProxyException; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; +import com.sillelien.relproxy.RelProxyException; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; /** * diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java similarity index 93% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java index ab483ec..9b9d9b3 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java @@ -1,7 +1,7 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp; +package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp; -import com.innowhere.relproxy.RelProxyException; -import com.innowhere.relproxy.jproxy.JProxyDiagnosticsListener; +import com.sillelien.relproxy.RelProxyException; +import com.sillelien.relproxy.jproxy.JProxyDiagnosticsListener; import java.io.IOException; import java.util.List; import javax.tools.Diagnostic; diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java similarity index 92% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java index b00df77..90a3946 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java @@ -1,17 +1,17 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp; +package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputSourceInMemory; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectOutputClass; -import com.innowhere.relproxy.RelProxyException; -import com.innowhere.relproxy.impl.FileExt; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorInner; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileJava; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.JProxyEngineChangeDetectorAndCompiler; -import com.innowhere.relproxy.jproxy.JProxyDiagnosticsListener; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputSourceInMemory; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectOutputClass; +import com.sillelien.relproxy.RelProxyException; +import com.sillelien.relproxy.impl.FileExt; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorInner; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileJava; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.JProxyEngineChangeDetectorAndCompiler; +import com.sillelien.relproxy.jproxy.JProxyDiagnosticsListener; import java.io.File; import java.util.ArrayList; import java.util.LinkedList; diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java similarity index 92% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java index d1f39bd..46c6e43 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java @@ -1,12 +1,12 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp; +package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JProxyJavaFileObjectInput; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInMemory; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInFileSystem; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectOutputClass; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JProxyJavaFileObjectInput; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInMemory; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInFileSystem; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectOutputClass; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; import java.io.IOException; import java.util.Collection; import java.util.Collections; @@ -126,4 +126,4 @@ public String inferBinaryName(Location location, JavaFileObject file) return super.inferBinaryName(location, file); } -} \ No newline at end of file +} diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java similarity index 95% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java index fab17f4..e88c91e 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java @@ -1,12 +1,12 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp; - -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInFile; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInFileSystem; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInJar; -import com.innowhere.relproxy.RelProxyException; -import com.innowhere.relproxy.impl.FileExt; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp; + +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInFile; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInFileSystem; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInJar; +import com.sillelien.relproxy.RelProxyException; +import com.sillelien.relproxy.impl.FileExt; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; @@ -211,4 +211,4 @@ private void listUnderJarCustom(String packagePath,FileExt jarFile,CollectionJProxy and {@link JProxyScriptEngineFactory}. diff --git a/src/main/java/com/innowhere/relproxy/jproxy/JProxyDiagnosticsListener.java b/src/main/java/com/sillelien/relproxy/jproxy/JProxyDiagnosticsListener.java similarity index 93% rename from src/main/java/com/innowhere/relproxy/jproxy/JProxyDiagnosticsListener.java rename to src/main/java/com/sillelien/relproxy/jproxy/JProxyDiagnosticsListener.java index bfc6663..563ebf5 100644 --- a/src/main/java/com/innowhere/relproxy/jproxy/JProxyDiagnosticsListener.java +++ b/src/main/java/com/sillelien/relproxy/jproxy/JProxyDiagnosticsListener.java @@ -1,4 +1,4 @@ -package com.innowhere.relproxy.jproxy; +package com.sillelien.relproxy.jproxy; import javax.tools.DiagnosticCollector; import javax.tools.JavaFileObject; diff --git a/src/main/java/com/innowhere/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java b/src/main/java/com/sillelien/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java similarity index 95% rename from src/main/java/com/innowhere/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java rename to src/main/java/com/sillelien/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java index 2602645..0fb92d4 100644 --- a/src/main/java/com/innowhere/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java +++ b/src/main/java/com/sillelien/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java @@ -1,4 +1,4 @@ -package com.innowhere.relproxy.jproxy; +package com.sillelien.relproxy.jproxy; import java.io.File; diff --git a/src/main/java/com/innowhere/relproxy/jproxy/JProxyScriptEngine.java b/src/main/java/com/sillelien/relproxy/jproxy/JProxyScriptEngine.java similarity index 98% rename from src/main/java/com/innowhere/relproxy/jproxy/JProxyScriptEngine.java rename to src/main/java/com/sillelien/relproxy/jproxy/JProxyScriptEngine.java index 10a5ef7..3fd5806 100644 --- a/src/main/java/com/innowhere/relproxy/jproxy/JProxyScriptEngine.java +++ b/src/main/java/com/sillelien/relproxy/jproxy/JProxyScriptEngine.java @@ -1,4 +1,4 @@ -package com.innowhere.relproxy.jproxy; +package com.sillelien.relproxy.jproxy; import javax.script.ScriptEngine; diff --git a/src/main/java/com/innowhere/relproxy/jproxy/JProxyScriptEngineFactory.java b/src/main/java/com/sillelien/relproxy/jproxy/JProxyScriptEngineFactory.java similarity index 84% rename from src/main/java/com/innowhere/relproxy/jproxy/JProxyScriptEngineFactory.java rename to src/main/java/com/sillelien/relproxy/jproxy/JProxyScriptEngineFactory.java index 434aad9..036f218 100644 --- a/src/main/java/com/innowhere/relproxy/jproxy/JProxyScriptEngineFactory.java +++ b/src/main/java/com/sillelien/relproxy/jproxy/JProxyScriptEngineFactory.java @@ -1,6 +1,6 @@ -package com.innowhere.relproxy.jproxy; +package com.sillelien.relproxy.jproxy; -import com.innowhere.relproxy.impl.jproxy.screngine.JProxyScriptEngineFactoryImpl; +import com.sillelien.relproxy.impl.jproxy.screngine.JProxyScriptEngineFactoryImpl; import javax.script.ScriptEngineFactory; /** diff --git a/src/main/java/com/innowhere/relproxy/jproxy/JProxyShell.java b/src/main/java/com/sillelien/relproxy/jproxy/JProxyShell.java similarity index 83% rename from src/main/java/com/innowhere/relproxy/jproxy/JProxyShell.java rename to src/main/java/com/sillelien/relproxy/jproxy/JProxyShell.java index baa3a66..d0e1024 100644 --- a/src/main/java/com/innowhere/relproxy/jproxy/JProxyShell.java +++ b/src/main/java/com/sillelien/relproxy/jproxy/JProxyShell.java @@ -1,6 +1,6 @@ -package com.innowhere.relproxy.jproxy; +package com.sillelien.relproxy.jproxy; -import com.innowhere.relproxy.impl.jproxy.shell.JProxyShellImpl; +import com.sillelien.relproxy.impl.jproxy.shell.JProxyShellImpl; /** * Is the main class to execute shell scripting based on Java. diff --git a/src/main/java/com/innowhere/relproxy/jproxy/package.html b/src/main/java/com/sillelien/relproxy/jproxy/package.html similarity index 100% rename from src/main/java/com/innowhere/relproxy/jproxy/package.html rename to src/main/java/com/sillelien/relproxy/jproxy/package.html diff --git a/src/main/java/com/innowhere/relproxy/package.html b/src/main/java/com/sillelien/relproxy/package.html similarity index 100% rename from src/main/java/com/innowhere/relproxy/package.html rename to src/main/java/com/sillelien/relproxy/package.html From 9a870a471ac0fac5d9bcbab3ed760e3930528110 Mon Sep 17 00:00:00 2001 From: Neil Ellis Date: Fri, 7 Jul 2017 16:05:24 +0100 Subject: [PATCH 006/135] Create README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..3681ee6 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# relproxy +Simple Java and Groovy hot class reloader and Java based shell and scripting From 894505520d5956c9efbc3694834d88149b123258 Mon Sep 17 00:00:00 2001 From: neilellis Date: Fri, 7 Jul 2017 16:03:53 +0100 Subject: [PATCH 007/135] Refactoring for Dollar project --- pom.xml | 71 ++++++++++++++++--- relproxy/pom.xml | 2 +- relproxy/src/main/asciidoc/manual.asciidoc | 56 +++++++-------- .../JProxyCodeSnippetCompleteClassTest.java | 2 +- .../jproxy/JProxyCodeSnippetTest.java | 2 +- .../JProxyJavaScriptEngineNoManagerTest.java | 8 +-- .../jproxy/JProxyJavaScriptEngineTest.java | 8 +-- .../JProxyJavaShellCompleteClassTest.java | 4 +- .../JProxyJavaShellInteractiveTest.java | 2 +- .../JProxyJavaShellNormalClassTest.java | 4 +- .../relproxy/jproxy/JProxyJavaShellTest.java | 7 +- .../relproxy/jproxy/util/JProxyTestUtil.java | 4 +- .../javashellex/JProxyShellExample.java | 2 +- .../example/groovyex/ItsNatGroovyServlet.java | 6 +- .../example/javaex/JProxyExampleServlet.java | 2 +- .../javaex/JProxyServletContextListener.java | 21 +++--- .../groovyex/groovy_servlet_init.groovy | 12 ++-- .../example/javaex/JProxyExampleDocument.java | 3 +- .../relproxy/RelProxy.java | 2 +- .../relproxy/RelProxyException.java | 2 +- .../relproxy/RelProxyOnReloadListener.java | 6 +- .../relproxy/gproxy/GProxy.java | 6 +- .../relproxy/gproxy/GProxyConfig.java | 4 +- .../gproxy/GProxyGroovyScriptEngine.java | 2 +- .../relproxy/gproxy/package.html | 0 .../relproxy/impl/FileExt.java | 4 +- .../impl/GenericProxyConfigBaseImpl.java | 4 +- .../relproxy/impl/GenericProxyImpl.java | 6 +- .../impl/GenericProxyInvocationHandler.java | 4 +- .../impl/GenericProxyVersionedObject.java | 6 +- .../impl/gproxy/GProxyConfigImpl.java | 10 +-- .../impl/gproxy/GProxyDefaultImpl.java | 6 +- .../relproxy/impl/gproxy/core/GProxyImpl.java | 10 +-- .../gproxy/core/GProxyInvocationHandler.java | 6 +- .../gproxy/core/GProxyVersionedObject.java | 6 +- .../impl/jproxy/JProxyConfigImpl.java | 18 ++--- .../impl/jproxy/JProxyDefaultImpl.java | 6 +- .../relproxy/impl/jproxy/JProxyUtil.java | 4 +- .../relproxy/impl/jproxy/core/JProxyImpl.java | 22 +++--- .../jproxy/core/JProxyInvocationHandler.java | 6 +- .../jproxy/core/JProxyVersionedObject.java | 8 +-- .../jproxy/core/clsmgr/FolderSourceList.java | 6 +- .../jproxy/core/clsmgr/JProxyClassLoader.java | 8 +-- .../impl/jproxy/core/clsmgr/JProxyEngine.java | 22 +++--- ...JProxyEngineChangeDetectorAndCompiler.java | 34 ++++----- .../jproxy/core/clsmgr/JavaSourcesSearch.java | 28 ++++---- .../core/clsmgr/cldesc/ClassDescriptor.java | 2 +- .../clsmgr/cldesc/ClassDescriptorInner.java | 2 +- .../cldesc/ClassDescriptorSourceFileJava.java | 8 +-- .../ClassDescriptorSourceFileRegistry.java | 2 +- .../cldesc/ClassDescriptorSourceScript.java | 10 +-- .../cldesc/ClassDescriptorSourceUnit.java | 10 +-- .../comp/JProxyCompilationException.java | 6 +- .../clsmgr/comp/JProxyCompilerContext.java | 6 +- .../clsmgr/comp/JProxyCompilerInMemory.java | 26 +++---- .../clsmgr/comp/JavaFileManagerInMemory.java | 18 ++--- ...leObjectInputClassFinderByClassLoader.java | 20 +++--- .../comp/jfo/JProxyJavaFileObjectInput.java | 2 +- .../jfo/JavaFileObjectInputClassInFile.java | 5 +- .../JavaFileObjectInputClassInFileSystem.java | 2 +- .../jfo/JavaFileObjectInputClassInJar.java | 4 +- .../jfo/JavaFileObjectInputClassInMemory.java | 2 +- .../jfo/JavaFileObjectInputSourceBase.java | 4 +- .../jfo/JavaFileObjectInputSourceInFile.java | 4 +- .../JavaFileObjectInputSourceInMemory.java | 2 +- .../comp/jfo/JavaFileObjectOutputClass.java | 4 +- .../clsmgr/srcunit/SourceFileJavaNormal.java | 4 +- .../core/clsmgr/srcunit/SourceScriptRoot.java | 2 +- .../clsmgr/srcunit/SourceScriptRootFile.java | 8 +-- .../srcunit/SourceScriptRootFileJavaExt.java | 8 +-- .../srcunit/SourceScriptRootFileOtherExt.java | 8 +-- .../srcunit/SourceScriptRootInMemory.java | 2 +- .../core/clsmgr/srcunit/SourceUnit.java | 6 +- .../impl/jproxy/screngine/BindingsImpl.java | 2 +- .../JProxyScriptEngineDelegateImpl.java | 20 +++--- .../JProxyScriptEngineFactoryImpl.java | 6 +- .../screngine/JProxyScriptEngineImpl.java | 14 ++-- .../jproxy/shell/JProxyShellClassLoader.java | 6 +- .../shell/JProxyShellCodeSnippetImpl.java | 14 ++-- .../impl/jproxy/shell/JProxyShellImpl.java | 18 ++--- .../shell/JProxyShellInteractiveImpl.java | 16 ++--- .../shell/JProxyShellScriptFileImpl.java | 18 ++--- .../impl/jproxy/shell/inter/Command.java | 2 +- .../shell/inter/CommandCodeChangerBase.java | 2 +- .../jproxy/shell/inter/CommandDelete.java | 2 +- .../impl/jproxy/shell/inter/CommandEdit.java | 2 +- .../impl/jproxy/shell/inter/CommandError.java | 2 +- .../jproxy/shell/inter/CommandInsert.java | 2 +- .../impl/jproxy/shell/inter/CommandLoad.java | 4 +- .../impl/jproxy/shell/inter/CommandOther.java | 4 +- .../impl/jproxy/shell/inter/CommandSave.java | 4 +- .../shell/inter/JProxyShellProcessor.java | 14 ++-- .../impl/jproxy/shell/inter/Keyboard.java | 2 +- .../inter/KeyboardNotUsingClipboard.java | 4 +- .../shell/inter/KeyboardUsingClipboard.java | 4 +- .../shell/inter/LinuxUnicodeKeyboard.java | 4 +- .../shell/inter/MacOSXUnicodeKeyboard.java | 4 +- .../shell/inter/WindowUnicodeKeyboard.java | 4 +- .../relproxy/jproxy/JProxy.java | 6 +- .../jproxy/JProxyCompilerListener.java | 2 +- .../relproxy/jproxy/JProxyConfig.java | 4 +- .../jproxy/JProxyDiagnosticsListener.java | 2 +- ...JProxyInputSourceFileExcludedListener.java | 2 +- .../relproxy/jproxy/JProxyScriptEngine.java | 2 +- .../jproxy/JProxyScriptEngineFactory.java | 4 +- .../relproxy/jproxy/JProxyShell.java | 4 +- .../relproxy/jproxy/package.html | 0 .../relproxy/package.html | 0 108 files changed, 442 insertions(+), 397 deletions(-) rename src/main/java/com/{innowhere => sillelien}/relproxy/RelProxy.java (90%) rename src/main/java/com/{innowhere => sillelien}/relproxy/RelProxyException.java (97%) rename src/main/java/com/{innowhere => sillelien}/relproxy/RelProxyOnReloadListener.java (79%) rename src/main/java/com/{innowhere => sillelien}/relproxy/gproxy/GProxy.java (94%) rename src/main/java/com/{innowhere => sillelien}/relproxy/gproxy/GProxyConfig.java (94%) rename src/main/java/com/{innowhere => sillelien}/relproxy/gproxy/GProxyGroovyScriptEngine.java (97%) rename src/main/java/com/{innowhere => sillelien}/relproxy/gproxy/package.html (100%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/FileExt.java (89%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/GenericProxyConfigBaseImpl.java (78%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/GenericProxyImpl.java (91%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/GenericProxyInvocationHandler.java (96%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/GenericProxyVersionedObject.java (97%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/gproxy/GProxyConfigImpl.java (72%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/gproxy/GProxyDefaultImpl.java (86%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/gproxy/core/GProxyImpl.java (68%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/gproxy/core/GProxyInvocationHandler.java (75%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/gproxy/core/GProxyVersionedObject.java (87%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/JProxyConfigImpl.java (88%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/JProxyDefaultImpl.java (92%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/JProxyUtil.java (97%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/JProxyImpl.java (78%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/JProxyInvocationHandler.java (75%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/JProxyVersionedObject.java (83%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java (95%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java (96%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java (94%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java (93%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java (92%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java (98%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java (89%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java (70%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java (98%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java (96%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java (92%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java (72%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java (93%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java (92%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java (92%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java (95%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JProxyJavaFileObjectInput.java (64%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java (85%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java (97%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java (92%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java (95%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java (93%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java (86%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java (91%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java (92%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java (83%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRoot.java (80%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java (82%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java (68%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java (80%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootInMemory.java (96%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java (81%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/screngine/BindingsImpl.java (76%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java (85%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java (96%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java (87%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java (88%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java (81%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/JProxyShellImpl.java (91%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java (84%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java (83%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/inter/Command.java (98%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java (97%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/inter/CommandDelete.java (97%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/inter/CommandEdit.java (97%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/inter/CommandError.java (84%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/inter/CommandInsert.java (97%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/inter/CommandLoad.java (94%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/inter/CommandOther.java (97%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/inter/CommandSave.java (92%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java (94%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/inter/Keyboard.java (90%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java (99%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java (94%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/inter/LinuxUnicodeKeyboard.java (96%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/inter/MacOSXUnicodeKeyboard.java (95%) rename src/main/java/com/{innowhere => sillelien}/relproxy/impl/jproxy/shell/inter/WindowUnicodeKeyboard.java (95%) rename src/main/java/com/{innowhere => sillelien}/relproxy/jproxy/JProxy.java (96%) rename src/main/java/com/{innowhere => sillelien}/relproxy/jproxy/JProxyCompilerListener.java (89%) rename src/main/java/com/{innowhere => sillelien}/relproxy/jproxy/JProxyConfig.java (98%) rename src/main/java/com/{innowhere => sillelien}/relproxy/jproxy/JProxyDiagnosticsListener.java (93%) rename src/main/java/com/{innowhere => sillelien}/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java (95%) rename src/main/java/com/{innowhere => sillelien}/relproxy/jproxy/JProxyScriptEngine.java (98%) rename src/main/java/com/{innowhere => sillelien}/relproxy/jproxy/JProxyScriptEngineFactory.java (84%) rename src/main/java/com/{innowhere => sillelien}/relproxy/jproxy/JProxyShell.java (83%) rename src/main/java/com/{innowhere => sillelien}/relproxy/jproxy/package.html (100%) rename src/main/java/com/{innowhere => sillelien}/relproxy/package.html (100%) diff --git a/pom.xml b/pom.xml index edd1d18..e1e5557 100644 --- a/pom.xml +++ b/pom.xml @@ -8,6 +8,57 @@ relproxy 0 + relproxy + + Simple Java and Groovy hot class reloader,and Java based shell and scripting used by Dollar project, original project is https://github.com/jmarranz/relproxy + + https://github.com/dollar-org/relproxy + + + The Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + + + + + Jose Maria Arranz + jmarranz@innowhere.com + Innowhere Software + http://www.innowhere.com + + Original Author + + + + + + + Daniel López (greeneyed) + + + https://github.com/Verdoso + + Original Contributor + + + + Michael Vorburger + mike@vorburger.ch + Vorburger.CH + http://www.vorburger.ch + + Original Contributor + + + + + + scm:git:git@github.com:dollar-org/relproxy.git + scm:git:git@github.com:dollar-org/relproxy.git + git@github.com:dollar-org/relproxy.git + + + 2.0.2 2.4 @@ -22,16 +73,16 @@ - - com.versioneye - versioneye-maven-plugin - 3.11.4 - - 0c797be864338a3649f0 - neilellis_orga - Owners - - + + + + + + + + + + org.apache.rat diff --git a/relproxy/pom.xml b/relproxy/pom.xml index 369a555..9ca34a3 100644 --- a/relproxy/pom.xml +++ b/relproxy/pom.xml @@ -147,7 +147,7 @@ RelProxy v${project.version} RelProxy v${project.version} - com.innowhere.relproxy.impl + com.sillelien.relproxy.impl diff --git a/relproxy/src/main/asciidoc/manual.asciidoc b/relproxy/src/main/asciidoc/manual.asciidoc index 3552f6a..005049c 100644 --- a/relproxy/src/main/asciidoc/manual.asciidoc +++ b/relproxy/src/main/asciidoc/manual.asciidoc @@ -630,7 +630,7 @@ Both types of web applications, publishing source code to war and direct access == GProxy or how to be able to reload Groovy classes on the Java environment -`com.innowhere.relproxy.gproxy.GProxy` is the main Java class of RelProxy to provide this feature, with `GProxy` you can create Java proxies for Groovy objects because +`GProxy` is the main Java class of RelProxy to provide this feature, with `GProxy` you can create Java proxies for Groovy objects because a `java.lang.reflect.Proxy` wrapper is passed instead of the original Groovy object, the original Groovy object is retained under the hood and method calls to the proxy are redirected to the real object calling the corresponding method using reflection. When the source code of the Groovy class changes GProxy automatically reloads the Groovy class and creates a new object to replace the old one, the fields of the original object are got and re-set to the new object to keep the state (number of fields and types @@ -651,10 +651,10 @@ import org.itsnat.core.tmpl.ItsNatDocumentTemplate; import org.itsnat.core.event.ItsNatServletRequestListener; import groovy.util.GroovyScriptEngine; import java.lang.reflect.Method; -import com.innowhere.relproxy.RelProxyOnReloadListener; -import com.innowhere.relproxy.gproxy.GProxy; -import com.innowhere.relproxy.gproxy.GProxyGroovyScriptEngine; -import com.innowhere.relproxy.gproxy.GProxyConfig; +import RelProxyOnReloadListener; +import GProxy; +import GProxyGroovyScriptEngine; +import GProxyConfig; GroovyScriptEngine groovyEngine = servlet.getGroovyScriptEngine(); @@ -825,7 +825,7 @@ Finally we have been able to reload Groovy classes mixed in a Java environment. Java hot reloadable proxies are very similar to Groovy support of RelProxy, in this case the task of detecting source changes, recompiling and reloading is fully done by RelProxy (in case of Groovy provided `groovy.util.GroovyScriptEngine` does most of this work). -`com.innowhere.relproxy.jproxy.JProxy` is the main Java class of RelProxy for hot reload of pure Java, with `JProxy` you can create Java `java.lang.reflect.Proxy` proxies wrapping +`JProxy` is the main Java class of RelProxy for hot reload of pure Java, with `JProxy` you can create Java `java.lang.reflect.Proxy` proxies wrapping your original objects to be passed to listeners, the original object is retained under the hood and method calls to the proxy are redirected to the real object calling the corresponding method using reflection. When the source code of a monitored Java file is changed, it is automatically recompiled in memory. When the `processRequest` method of the proxied `JProxyExampleLoadListener` object is called because an end user is reloading the related web page, `JProxy` detects something has changed and reload all monitored @@ -860,12 +860,12 @@ import javax.tools.JavaFileObject; import org.itsnat.core.event.ItsNatServletRequestListener; import org.itsnat.core.http.HttpServletWrapper; import org.itsnat.core.tmpl.ItsNatDocumentTemplate; -import com.innowhere.relproxy.RelProxyOnReloadListener; -import com.innowhere.relproxy.jproxy.JProxy; -import com.innowhere.relproxy.jproxy.JProxyCompilerListener; -import com.innowhere.relproxy.jproxy.JProxyConfig; -import com.innowhere.relproxy.jproxy.JProxyDiagnosticsListener; -import com.innowhere.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import RelProxyOnReloadListener; +import JProxy; +import JProxyCompilerListener; +import JProxyConfig; +import JProxyDiagnosticsListener; +import JProxyInputSourceFileExcludedListener; /** @@ -1304,12 +1304,12 @@ import javax.tools.DiagnosticCollector; import javax.tools.JavaFileObject; import com.google.gwt.user.server.rpc.RemoteServiceServlet; -import com.innowhere.relproxy.RelProxyOnReloadListener; -import com.innowhere.relproxy.jproxy.JProxy; -import com.innowhere.relproxy.jproxy.JProxyConfig; -import com.innowhere.relproxy.jproxy.JProxyDiagnosticsListener; -import com.innowhere.relproxy.jproxy.JProxyInputSourceFileExcludedListener; -import com.innowhere.relproxy.jproxy.JProxyCompilerListener; +import RelProxyOnReloadListener; +import JProxy; +import JProxyConfig; +import JProxyDiagnosticsListener; +import JProxyInputSourceFileExcludedListener; +import JProxyCompilerListener; import com.innowhere.relproxyexgwt.client.GreetingService; /** @@ -2121,7 +2121,7 @@ public class RelProxyBuiltinRoot ---- package com.innowhere.relproxy_builtin_ex; -import com.innowhere.relproxy.jproxy.JProxyScriptEngine; +import JProxyScriptEngine; import java.io.InputStream; import java.io.PrintStream; @@ -2174,8 +2174,8 @@ Now the implementation details, this class shows how simple is to built-in RelPr ---- package com.innowhere.relproxy_builtin_ex.impl; -import com.innowhere.relproxy.jproxy.JProxyScriptEngine; -import com.innowhere.relproxy.jproxy.JProxyScriptEngineFactory; +import JProxyScriptEngine; +import JProxyScriptEngineFactory; import com.innowhere.relproxy_builtin_ex.CommandListener; import com.innowhere.relproxy_builtin_ex.OutputListener; import com.innowhere.relproxy_builtin_ex.RelProxyBuiltin; @@ -2332,13 +2332,13 @@ This is the example code of this console based program (names are inspired on JU ---- package com.innowhere.relproxy_builtin_ex_main; -import com.innowhere.relproxy.RelProxyOnReloadListener; -import com.innowhere.relproxy.jproxy.JProxy; -import com.innowhere.relproxy.jproxy.JProxyCompilerListener; -import com.innowhere.relproxy.jproxy.JProxyConfig; -import com.innowhere.relproxy.jproxy.JProxyDiagnosticsListener; -import com.innowhere.relproxy.jproxy.JProxyInputSourceFileExcludedListener; -import com.innowhere.relproxy.jproxy.JProxyScriptEngine; +import RelProxyOnReloadListener; +import JProxy; +import JProxyCompilerListener; +import JProxyConfig; +import JProxyDiagnosticsListener; +import JProxyInputSourceFileExcludedListener; +import JProxyScriptEngine; import com.innowhere.relproxy_builtin_ex.CommandListener; import com.innowhere.relproxy_builtin_ex.RelProxyBuiltin; import com.innowhere.relproxy_builtin_ex.RelProxyBuiltinRoot; diff --git a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyCodeSnippetCompleteClassTest.java b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyCodeSnippetCompleteClassTest.java index 2dd7a06..4f40057 100644 --- a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyCodeSnippetCompleteClassTest.java +++ b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyCodeSnippetCompleteClassTest.java @@ -4,7 +4,7 @@ * and open the template in the editor. */ -package com.innowhere.relproxy.jproxy; +package com.sillelien.relproxy.jproxy; import org.junit.After; import org.junit.AfterClass; diff --git a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyCodeSnippetTest.java b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyCodeSnippetTest.java index b692a63..5435fff 100644 --- a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyCodeSnippetTest.java +++ b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyCodeSnippetTest.java @@ -4,7 +4,7 @@ * and open the template in the editor. */ -package com.innowhere.relproxy.jproxy; +package com.sillelien.relproxy.jproxy; import org.junit.After; import org.junit.AfterClass; diff --git a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaScriptEngineNoManagerTest.java b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaScriptEngineNoManagerTest.java index 9ad97a7..dcddcfe 100644 --- a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaScriptEngineNoManagerTest.java +++ b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaScriptEngineNoManagerTest.java @@ -1,8 +1,8 @@ -package com.innowhere.relproxy.jproxy; +package com.sillelien.relproxy.jproxy; -import com.innowhere.relproxy.RelProxyOnReloadListener; -import static com.innowhere.relproxy.jproxy.util.JProxyTestUtil.RESOURCES_FOLDER; -import static com.innowhere.relproxy.jproxy.util.JProxyTestUtil.getProjectFolder; +import com.sillelien.relproxy.RelProxyOnReloadListener; +import static com.sillelien.relproxy.jproxy.util.JProxyTestUtil.RESOURCES_FOLDER; +import static com.sillelien.relproxy.jproxy.util.JProxyTestUtil.getProjectFolder; import java.io.File; diff --git a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaScriptEngineTest.java b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaScriptEngineTest.java index d9812b6..6ff0c01 100644 --- a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaScriptEngineTest.java +++ b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaScriptEngineTest.java @@ -1,8 +1,8 @@ -package com.innowhere.relproxy.jproxy; +package com.sillelien.relproxy.jproxy; -import com.innowhere.relproxy.RelProxyOnReloadListener; -import static com.innowhere.relproxy.jproxy.util.JProxyTestUtil.RESOURCES_FOLDER; -import static com.innowhere.relproxy.jproxy.util.JProxyTestUtil.getProjectFolder; +import com.sillelien.relproxy.RelProxyOnReloadListener; +import static com.sillelien.relproxy.jproxy.util.JProxyTestUtil.RESOURCES_FOLDER; +import static com.sillelien.relproxy.jproxy.util.JProxyTestUtil.getProjectFolder; import java.io.File; diff --git a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellCompleteClassTest.java b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellCompleteClassTest.java index 91fdbbe..d0de94b 100644 --- a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellCompleteClassTest.java +++ b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellCompleteClassTest.java @@ -1,6 +1,6 @@ -package com.innowhere.relproxy.jproxy; +package com.sillelien.relproxy.jproxy; -import com.innowhere.relproxy.jproxy.util.JProxyTestUtil; +import com.sillelien.relproxy.jproxy.util.JProxyTestUtil; import java.io.File; import org.junit.After; import org.junit.AfterClass; diff --git a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellInteractiveTest.java b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellInteractiveTest.java index 92fc5d9..5d18b4b 100644 --- a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellInteractiveTest.java +++ b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellInteractiveTest.java @@ -4,7 +4,7 @@ * and open the template in the editor. */ -package com.innowhere.relproxy.jproxy; +package com.sillelien.relproxy.jproxy; import org.junit.After; import org.junit.AfterClass; diff --git a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellNormalClassTest.java b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellNormalClassTest.java index 31c819c..1673a26 100644 --- a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellNormalClassTest.java +++ b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellNormalClassTest.java @@ -1,6 +1,6 @@ -package com.innowhere.relproxy.jproxy; +package com.sillelien.relproxy.jproxy; -import com.innowhere.relproxy.jproxy.util.JProxyTestUtil; +import com.sillelien.relproxy.jproxy.util.JProxyTestUtil; import java.io.File; import org.junit.After; import org.junit.AfterClass; diff --git a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellTest.java b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellTest.java index 05b8f11..4461b7c 100644 --- a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellTest.java +++ b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellTest.java @@ -1,13 +1,14 @@ -package com.innowhere.relproxy.jproxy; +package com.sillelien.relproxy.jproxy; -import com.innowhere.relproxy.jproxy.util.JProxyTestUtil; -import java.io.File; +import com.sillelien.relproxy.jproxy.util.JProxyTestUtil; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; +import java.io.File; + /** * * @author jmarranz diff --git a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/util/JProxyTestUtil.java b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/util/JProxyTestUtil.java index 51dc64d..eed55b9 100644 --- a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/util/JProxyTestUtil.java +++ b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/util/JProxyTestUtil.java @@ -1,5 +1,5 @@ -package com.innowhere.relproxy.jproxy.util; +package com.sillelien.relproxy.jproxy.util; import java.io.File; import java.net.URL; @@ -15,7 +15,7 @@ public class JProxyTestUtil public static File getProjectFolder() { - String className = JProxyTestUtil.class.getName(); // com.innowhere.relproxy.jproxy.util.JProxyTestUtil + String className = JProxyTestUtil.class.getName(); // com.sillelien.relproxy.jproxy.util.JProxyTestUtil URL urlClass = JProxyTestUtil.class.getClassLoader().getResource(className.replace('.','/') + ".class"); File fileClass = new File(urlClass.getPath()); File projectFolder = fileClass.getParentFile(); diff --git a/relproxy/src/test/resources/example/javashellex/JProxyShellExample.java b/relproxy/src/test/resources/example/javashellex/JProxyShellExample.java index f538370..92de1f4 100644 --- a/relproxy/src/test/resources/example/javashellex/JProxyShellExample.java +++ b/relproxy/src/test/resources/example/javashellex/JProxyShellExample.java @@ -1,7 +1,7 @@ package example.javashellex; import javax.script.ScriptEngine; -import com.innowhere.relproxy.jproxy.JProxyScriptEngine; +import com.sillelien.relproxy.jproxy.JProxyScriptEngine; /** * diff --git a/relproxy_test_itsnat/src/main/java/example/groovyex/ItsNatGroovyServlet.java b/relproxy_test_itsnat/src/main/java/example/groovyex/ItsNatGroovyServlet.java index 3d84c78..c8216b0 100644 --- a/relproxy_test_itsnat/src/main/java/example/groovyex/ItsNatGroovyServlet.java +++ b/relproxy_test_itsnat/src/main/java/example/groovyex/ItsNatGroovyServlet.java @@ -82,9 +82,9 @@ public void init(ServletConfig config) throws ServletException binding.setVariable("context", getServletContext()); binding.setVariable("application", getServletContext()); - com.innowhere.relproxy.gproxy.GProxyGroovyScriptEngine.class.getName(); - com.innowhere.relproxy.gproxy.GProxyConfig.class.getName(); - com.innowhere.relproxy.gproxy.GProxy.class.getName(); + com.sillelien.relproxy.gproxy.GProxyGroovyScriptEngine.class.getName(); + com.sillelien.relproxy.gproxy.GProxyConfig.class.getName(); + com.sillelien.relproxy.gproxy.GProxy.class.getName(); execGroovyScript(initScript,binding); } diff --git a/relproxy_test_itsnat/src/main/java/example/javaex/JProxyExampleServlet.java b/relproxy_test_itsnat/src/main/java/example/javaex/JProxyExampleServlet.java index 9bc7397..e845d30 100644 --- a/relproxy_test_itsnat/src/main/java/example/javaex/JProxyExampleServlet.java +++ b/relproxy_test_itsnat/src/main/java/example/javaex/JProxyExampleServlet.java @@ -1,7 +1,7 @@ package example.javaex; -import com.innowhere.relproxy.jproxy.JProxy; +import com.sillelien.relproxy.jproxy.JProxy; import javax.servlet.ServletConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; diff --git a/relproxy_test_itsnat/src/main/java/example/javaex/JProxyServletContextListener.java b/relproxy_test_itsnat/src/main/java/example/javaex/JProxyServletContextListener.java index e8b00f3..58fadd2 100644 --- a/relproxy_test_itsnat/src/main/java/example/javaex/JProxyServletContextListener.java +++ b/relproxy_test_itsnat/src/main/java/example/javaex/JProxyServletContextListener.java @@ -1,21 +1,22 @@ package example.javaex; -import com.innowhere.relproxy.RelProxyOnReloadListener; -import com.innowhere.relproxy.jproxy.JProxy; -import com.innowhere.relproxy.jproxy.JProxyCompilerListener; -import com.innowhere.relproxy.jproxy.JProxyConfig; -import com.innowhere.relproxy.jproxy.JProxyDiagnosticsListener; -import com.innowhere.relproxy.jproxy.JProxyInputSourceFileExcludedListener; -import java.io.File; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.List; +import com.sillelien.relproxy.RelProxyOnReloadListener; +import com.sillelien.relproxy.jproxy.JProxy; +import com.sillelien.relproxy.jproxy.JProxyCompilerListener; +import com.sillelien.relproxy.jproxy.JProxyConfig; +import com.sillelien.relproxy.jproxy.JProxyDiagnosticsListener; +import com.sillelien.relproxy.jproxy.JProxyInputSourceFileExcludedListener; + import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.tools.Diagnostic; import javax.tools.DiagnosticCollector; import javax.tools.JavaFileObject; +import java.io.File; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.List; /** * diff --git a/relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/code/example/groovyex/groovy_servlet_init.groovy b/relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/code/example/groovyex/groovy_servlet_init.groovy index c0b94bb..cdf3128 100644 --- a/relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/code/example/groovyex/groovy_servlet_init.groovy +++ b/relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/code/example/groovyex/groovy_servlet_init.groovy @@ -1,16 +1,12 @@ -package example.groovyex; +package example.groovyex -import org.itsnat.core.http.ItsNatHttpServlet; -import org.itsnat.core.tmpl.ItsNatDocumentTemplate; import org.itsnat.core.event.ItsNatServletRequestListener; import groovy.util.GroovyScriptEngine; import java.lang.reflect.Method; -import com.innowhere.relproxy.RelProxyOnReloadListener; -import com.innowhere.relproxy.gproxy.GProxy; -import com.innowhere.relproxy.gproxy.GProxyGroovyScriptEngine; -import com.innowhere.relproxy.gproxy.GProxyConfig; - +import com.sillelien.relproxy.RelProxyOnReloadListener; +import com.sillelien.relproxy.gproxy.GProxy; +import com.sillelien.relproxy.gproxy.GProxyGroovyScriptEngine GroovyScriptEngine groovyEngine = servlet.getGroovyScriptEngine(); diff --git a/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleDocument.java b/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleDocument.java index 903e65a..221a465 100644 --- a/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleDocument.java +++ b/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleDocument.java @@ -1,13 +1,12 @@ package example.javaex; -import com.innowhere.relproxy.jproxy.JProxy; +import com.sillelien.relproxy.jproxy.JProxy; import example.javaex.hotreload.JProxyExampleAux2; import example.javaex.nothotreload.JProxyExampleAuxIgnored2; import example.javaex.nothotreload.JProxyExampleAuxIgnored3; import org.itsnat.comp.ItsNatComponentManager; import org.itsnat.comp.text.ItsNatHTMLInputText; import org.itsnat.core.ItsNatServletRequest; -import org.itsnat.core.event.ItsNatServletRequestListener; import org.itsnat.core.html.ItsNatHTMLDocument; import org.w3c.dom.Element; import org.w3c.dom.events.Event; diff --git a/src/main/java/com/innowhere/relproxy/RelProxy.java b/src/main/java/com/sillelien/relproxy/RelProxy.java similarity index 90% rename from src/main/java/com/innowhere/relproxy/RelProxy.java rename to src/main/java/com/sillelien/relproxy/RelProxy.java index 2209333..c63cea3 100644 --- a/src/main/java/com/innowhere/relproxy/RelProxy.java +++ b/src/main/java/com/sillelien/relproxy/RelProxy.java @@ -1,4 +1,4 @@ -package com.innowhere.relproxy; +package com.sillelien.relproxy; /** * Is the root of RelProxy diff --git a/src/main/java/com/innowhere/relproxy/RelProxyException.java b/src/main/java/com/sillelien/relproxy/RelProxyException.java similarity index 97% rename from src/main/java/com/innowhere/relproxy/RelProxyException.java rename to src/main/java/com/sillelien/relproxy/RelProxyException.java index aeafaad..8b16207 100644 --- a/src/main/java/com/innowhere/relproxy/RelProxyException.java +++ b/src/main/java/com/sillelien/relproxy/RelProxyException.java @@ -1,4 +1,4 @@ -package com.innowhere.relproxy; +package com.sillelien.relproxy; /** * Internal checked exceptions thrown by RelProxy and library specific errors are wrapped into this exception class. diff --git a/src/main/java/com/innowhere/relproxy/RelProxyOnReloadListener.java b/src/main/java/com/sillelien/relproxy/RelProxyOnReloadListener.java similarity index 79% rename from src/main/java/com/innowhere/relproxy/RelProxyOnReloadListener.java rename to src/main/java/com/sillelien/relproxy/RelProxyOnReloadListener.java index faf1c62..acad475 100644 --- a/src/main/java/com/innowhere/relproxy/RelProxyOnReloadListener.java +++ b/src/main/java/com/sillelien/relproxy/RelProxyOnReloadListener.java @@ -1,4 +1,4 @@ -package com.innowhere.relproxy; +package com.sillelien.relproxy; import java.lang.reflect.Method; @@ -10,8 +10,8 @@ *

* * - * @see com.innowhere.relproxy.jproxy.JProxyConfig#setRelProxyOnReloadListener(com.innowhere.relproxy.RelProxyOnReloadListener) - * @see com.innowhere.relproxy.gproxy.GProxyConfig#setRelProxyOnReloadListener(com.innowhere.relproxy.RelProxyOnReloadListener) + * @see com.sillelien.relproxy.jproxy.JProxyConfig#setRelProxyOnReloadListener(com.sillelien.relproxy.RelProxyOnReloadListener) + * @see com.sillelien.relproxy.gproxy.GProxyConfig#setRelProxyOnReloadListener(com.sillelien.relproxy.RelProxyOnReloadListener) * @author Jose Maria Arranz Santamaria */ public interface RelProxyOnReloadListener diff --git a/src/main/java/com/innowhere/relproxy/gproxy/GProxy.java b/src/main/java/com/sillelien/relproxy/gproxy/GProxy.java similarity index 94% rename from src/main/java/com/innowhere/relproxy/gproxy/GProxy.java rename to src/main/java/com/sillelien/relproxy/gproxy/GProxy.java index 942b56e..5c74686 100644 --- a/src/main/java/com/innowhere/relproxy/gproxy/GProxy.java +++ b/src/main/java/com/sillelien/relproxy/gproxy/GProxy.java @@ -1,8 +1,8 @@ -package com.innowhere.relproxy.gproxy; +package com.sillelien.relproxy.gproxy; -import com.innowhere.relproxy.impl.gproxy.GProxyConfigImpl; -import com.innowhere.relproxy.impl.gproxy.GProxyDefaultImpl; +import com.sillelien.relproxy.impl.gproxy.GProxyConfigImpl; +import com.sillelien.relproxy.impl.gproxy.GProxyDefaultImpl; /** * Is the class to create Java proxy objects based on Groovy objects and keep track of Groovy source code changes reloading Groovy classes when detected. diff --git a/src/main/java/com/innowhere/relproxy/gproxy/GProxyConfig.java b/src/main/java/com/sillelien/relproxy/gproxy/GProxyConfig.java similarity index 94% rename from src/main/java/com/innowhere/relproxy/gproxy/GProxyConfig.java rename to src/main/java/com/sillelien/relproxy/gproxy/GProxyConfig.java index 4e517fa..14cb90c 100644 --- a/src/main/java/com/innowhere/relproxy/gproxy/GProxyConfig.java +++ b/src/main/java/com/sillelien/relproxy/gproxy/GProxyConfig.java @@ -1,7 +1,7 @@ -package com.innowhere.relproxy.gproxy; +package com.sillelien.relproxy.gproxy; -import com.innowhere.relproxy.RelProxyOnReloadListener; +import com.sillelien.relproxy.RelProxyOnReloadListener; /** * Interface implemented by the configuration object needed to initialize GProxy. diff --git a/src/main/java/com/innowhere/relproxy/gproxy/GProxyGroovyScriptEngine.java b/src/main/java/com/sillelien/relproxy/gproxy/GProxyGroovyScriptEngine.java similarity index 97% rename from src/main/java/com/innowhere/relproxy/gproxy/GProxyGroovyScriptEngine.java rename to src/main/java/com/sillelien/relproxy/gproxy/GProxyGroovyScriptEngine.java index 47d09d7..4025e04 100644 --- a/src/main/java/com/innowhere/relproxy/gproxy/GProxyGroovyScriptEngine.java +++ b/src/main/java/com/sillelien/relproxy/gproxy/GProxyGroovyScriptEngine.java @@ -1,4 +1,4 @@ -package com.innowhere.relproxy.gproxy; +package com.sillelien.relproxy.gproxy; /** * Interface to implement the object implementing the GroovyScriptEngine wrapper used to reload Groovy classes. diff --git a/src/main/java/com/innowhere/relproxy/gproxy/package.html b/src/main/java/com/sillelien/relproxy/gproxy/package.html similarity index 100% rename from src/main/java/com/innowhere/relproxy/gproxy/package.html rename to src/main/java/com/sillelien/relproxy/gproxy/package.html diff --git a/src/main/java/com/innowhere/relproxy/impl/FileExt.java b/src/main/java/com/sillelien/relproxy/impl/FileExt.java similarity index 89% rename from src/main/java/com/innowhere/relproxy/impl/FileExt.java rename to src/main/java/com/sillelien/relproxy/impl/FileExt.java index bc3fa3d..d9d3d3c 100644 --- a/src/main/java/com/innowhere/relproxy/impl/FileExt.java +++ b/src/main/java/com/sillelien/relproxy/impl/FileExt.java @@ -1,6 +1,6 @@ -package com.innowhere.relproxy.impl; +package com.sillelien.relproxy.impl; -import com.innowhere.relproxy.RelProxyException; +import com.sillelien.relproxy.RelProxyException; import java.io.File; import java.io.IOException; diff --git a/src/main/java/com/innowhere/relproxy/impl/GenericProxyConfigBaseImpl.java b/src/main/java/com/sillelien/relproxy/impl/GenericProxyConfigBaseImpl.java similarity index 78% rename from src/main/java/com/innowhere/relproxy/impl/GenericProxyConfigBaseImpl.java rename to src/main/java/com/sillelien/relproxy/impl/GenericProxyConfigBaseImpl.java index f1fda6d..f46404e 100644 --- a/src/main/java/com/innowhere/relproxy/impl/GenericProxyConfigBaseImpl.java +++ b/src/main/java/com/sillelien/relproxy/impl/GenericProxyConfigBaseImpl.java @@ -1,6 +1,6 @@ -package com.innowhere.relproxy.impl; +package com.sillelien.relproxy.impl; -import com.innowhere.relproxy.RelProxyOnReloadListener; +import com.sillelien.relproxy.RelProxyOnReloadListener; /** * diff --git a/src/main/java/com/innowhere/relproxy/impl/GenericProxyImpl.java b/src/main/java/com/sillelien/relproxy/impl/GenericProxyImpl.java similarity index 91% rename from src/main/java/com/innowhere/relproxy/impl/GenericProxyImpl.java rename to src/main/java/com/sillelien/relproxy/impl/GenericProxyImpl.java index a24ba38..ca7a397 100644 --- a/src/main/java/com/innowhere/relproxy/impl/GenericProxyImpl.java +++ b/src/main/java/com/sillelien/relproxy/impl/GenericProxyImpl.java @@ -1,7 +1,7 @@ -package com.innowhere.relproxy.impl; +package com.sillelien.relproxy.impl; -import com.innowhere.relproxy.RelProxyException; -import com.innowhere.relproxy.RelProxyOnReloadListener; +import com.sillelien.relproxy.RelProxyException; +import com.sillelien.relproxy.RelProxyOnReloadListener; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; diff --git a/src/main/java/com/innowhere/relproxy/impl/GenericProxyInvocationHandler.java b/src/main/java/com/sillelien/relproxy/impl/GenericProxyInvocationHandler.java similarity index 96% rename from src/main/java/com/innowhere/relproxy/impl/GenericProxyInvocationHandler.java rename to src/main/java/com/sillelien/relproxy/impl/GenericProxyInvocationHandler.java index e9fba8c..ad6d6f9 100644 --- a/src/main/java/com/innowhere/relproxy/impl/GenericProxyInvocationHandler.java +++ b/src/main/java/com/sillelien/relproxy/impl/GenericProxyInvocationHandler.java @@ -1,6 +1,6 @@ -package com.innowhere.relproxy.impl; +package com.sillelien.relproxy.impl; -import com.innowhere.relproxy.RelProxyOnReloadListener; +import com.sillelien.relproxy.RelProxyOnReloadListener; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; diff --git a/src/main/java/com/innowhere/relproxy/impl/GenericProxyVersionedObject.java b/src/main/java/com/sillelien/relproxy/impl/GenericProxyVersionedObject.java similarity index 97% rename from src/main/java/com/innowhere/relproxy/impl/GenericProxyVersionedObject.java rename to src/main/java/com/sillelien/relproxy/impl/GenericProxyVersionedObject.java index f7165a6..c23db15 100644 --- a/src/main/java/com/innowhere/relproxy/impl/GenericProxyVersionedObject.java +++ b/src/main/java/com/sillelien/relproxy/impl/GenericProxyVersionedObject.java @@ -1,13 +1,11 @@ -package com.innowhere.relproxy.impl; +package com.sillelien.relproxy.impl; -import com.innowhere.relproxy.RelProxyException; +import com.sillelien.relproxy.RelProxyException; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Modifier; import java.util.ArrayList; -import java.util.logging.Level; -import java.util.logging.Logger; /** * diff --git a/src/main/java/com/innowhere/relproxy/impl/gproxy/GProxyConfigImpl.java b/src/main/java/com/sillelien/relproxy/impl/gproxy/GProxyConfigImpl.java similarity index 72% rename from src/main/java/com/innowhere/relproxy/impl/gproxy/GProxyConfigImpl.java rename to src/main/java/com/sillelien/relproxy/impl/gproxy/GProxyConfigImpl.java index 247cc6d..d57bc86 100644 --- a/src/main/java/com/innowhere/relproxy/impl/gproxy/GProxyConfigImpl.java +++ b/src/main/java/com/sillelien/relproxy/impl/gproxy/GProxyConfigImpl.java @@ -1,9 +1,9 @@ -package com.innowhere.relproxy.impl.gproxy; +package com.sillelien.relproxy.impl.gproxy; -import com.innowhere.relproxy.RelProxyOnReloadListener; -import com.innowhere.relproxy.gproxy.GProxyConfig; -import com.innowhere.relproxy.gproxy.GProxyGroovyScriptEngine; -import com.innowhere.relproxy.impl.GenericProxyConfigBaseImpl; +import com.sillelien.relproxy.RelProxyOnReloadListener; +import com.sillelien.relproxy.gproxy.GProxyConfig; +import com.sillelien.relproxy.gproxy.GProxyGroovyScriptEngine; +import com.sillelien.relproxy.impl.GenericProxyConfigBaseImpl; /** * diff --git a/src/main/java/com/innowhere/relproxy/impl/gproxy/GProxyDefaultImpl.java b/src/main/java/com/sillelien/relproxy/impl/gproxy/GProxyDefaultImpl.java similarity index 86% rename from src/main/java/com/innowhere/relproxy/impl/gproxy/GProxyDefaultImpl.java rename to src/main/java/com/sillelien/relproxy/impl/gproxy/GProxyDefaultImpl.java index 2c8b0dd..6c8fe50 100644 --- a/src/main/java/com/innowhere/relproxy/impl/gproxy/GProxyDefaultImpl.java +++ b/src/main/java/com/sillelien/relproxy/impl/gproxy/GProxyDefaultImpl.java @@ -1,7 +1,7 @@ -package com.innowhere.relproxy.impl.gproxy; +package com.sillelien.relproxy.impl.gproxy; -import com.innowhere.relproxy.gproxy.GProxyConfig; -import com.innowhere.relproxy.impl.gproxy.core.GProxyImpl; +import com.sillelien.relproxy.gproxy.GProxyConfig; +import com.sillelien.relproxy.impl.gproxy.core.GProxyImpl; /** * diff --git a/src/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyImpl.java b/src/main/java/com/sillelien/relproxy/impl/gproxy/core/GProxyImpl.java similarity index 68% rename from src/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyImpl.java rename to src/main/java/com/sillelien/relproxy/impl/gproxy/core/GProxyImpl.java index c20285b..ca00943 100644 --- a/src/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyImpl.java +++ b/src/main/java/com/sillelien/relproxy/impl/gproxy/core/GProxyImpl.java @@ -1,9 +1,9 @@ -package com.innowhere.relproxy.impl.gproxy.core; +package com.sillelien.relproxy.impl.gproxy.core; -import com.innowhere.relproxy.impl.gproxy.GProxyConfigImpl; -import com.innowhere.relproxy.gproxy.GProxyGroovyScriptEngine; -import com.innowhere.relproxy.impl.GenericProxyImpl; -import com.innowhere.relproxy.impl.GenericProxyInvocationHandler; +import com.sillelien.relproxy.impl.gproxy.GProxyConfigImpl; +import com.sillelien.relproxy.gproxy.GProxyGroovyScriptEngine; +import com.sillelien.relproxy.impl.GenericProxyImpl; +import com.sillelien.relproxy.impl.GenericProxyInvocationHandler; /** diff --git a/src/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyInvocationHandler.java b/src/main/java/com/sillelien/relproxy/impl/gproxy/core/GProxyInvocationHandler.java similarity index 75% rename from src/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyInvocationHandler.java rename to src/main/java/com/sillelien/relproxy/impl/gproxy/core/GProxyInvocationHandler.java index 6bacae7..f362a27 100644 --- a/src/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyInvocationHandler.java +++ b/src/main/java/com/sillelien/relproxy/impl/gproxy/core/GProxyInvocationHandler.java @@ -1,6 +1,6 @@ -package com.innowhere.relproxy.impl.gproxy.core; +package com.sillelien.relproxy.impl.gproxy.core; -import com.innowhere.relproxy.impl.GenericProxyInvocationHandler; +import com.sillelien.relproxy.impl.GenericProxyInvocationHandler; /** * @@ -19,4 +19,4 @@ public GProxyImpl getGProxyImpl() return (GProxyImpl)root; } -} \ No newline at end of file +} diff --git a/src/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyVersionedObject.java b/src/main/java/com/sillelien/relproxy/impl/gproxy/core/GProxyVersionedObject.java similarity index 87% rename from src/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyVersionedObject.java rename to src/main/java/com/sillelien/relproxy/impl/gproxy/core/GProxyVersionedObject.java index 38f574c..f57bf53 100644 --- a/src/main/java/com/innowhere/relproxy/impl/gproxy/core/GProxyVersionedObject.java +++ b/src/main/java/com/sillelien/relproxy/impl/gproxy/core/GProxyVersionedObject.java @@ -1,7 +1,7 @@ -package com.innowhere.relproxy.impl.gproxy.core; +package com.sillelien.relproxy.impl.gproxy.core; -import com.innowhere.relproxy.gproxy.GProxyGroovyScriptEngine; -import com.innowhere.relproxy.impl.GenericProxyVersionedObject; +import com.sillelien.relproxy.gproxy.GProxyGroovyScriptEngine; +import com.sillelien.relproxy.impl.GenericProxyVersionedObject; import java.lang.reflect.Field; /** diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/JProxyConfigImpl.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/JProxyConfigImpl.java similarity index 88% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/JProxyConfigImpl.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/JProxyConfigImpl.java index 8dc72f0..cc095a2 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/JProxyConfigImpl.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/JProxyConfigImpl.java @@ -1,13 +1,13 @@ -package com.innowhere.relproxy.impl.jproxy; +package com.sillelien.relproxy.impl.jproxy; -import com.innowhere.relproxy.RelProxyException; -import com.innowhere.relproxy.RelProxyOnReloadListener; -import com.innowhere.relproxy.impl.GenericProxyConfigBaseImpl; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; -import com.innowhere.relproxy.jproxy.JProxyCompilerListener; -import com.innowhere.relproxy.jproxy.JProxyConfig; -import com.innowhere.relproxy.jproxy.JProxyDiagnosticsListener; -import com.innowhere.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import com.sillelien.relproxy.RelProxyException; +import com.sillelien.relproxy.RelProxyOnReloadListener; +import com.sillelien.relproxy.impl.GenericProxyConfigBaseImpl; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import com.sillelien.relproxy.jproxy.JProxyCompilerListener; +import com.sillelien.relproxy.jproxy.JProxyConfig; +import com.sillelien.relproxy.jproxy.JProxyDiagnosticsListener; +import com.sillelien.relproxy.jproxy.JProxyInputSourceFileExcludedListener; import java.io.File; /** diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/JProxyDefaultImpl.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/JProxyDefaultImpl.java similarity index 92% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/JProxyDefaultImpl.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/JProxyDefaultImpl.java index 5b9d6d0..92ab460 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/JProxyDefaultImpl.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/JProxyDefaultImpl.java @@ -1,7 +1,7 @@ -package com.innowhere.relproxy.impl.jproxy; +package com.sillelien.relproxy.impl.jproxy; -import com.innowhere.relproxy.impl.jproxy.core.JProxyImpl; -import com.innowhere.relproxy.jproxy.JProxyConfig; +import com.sillelien.relproxy.impl.jproxy.core.JProxyImpl; +import com.sillelien.relproxy.jproxy.JProxyConfig; /** * diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/JProxyUtil.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/JProxyUtil.java similarity index 97% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/JProxyUtil.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/JProxyUtil.java index d8e46e3..b63a961 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/JProxyUtil.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/JProxyUtil.java @@ -1,6 +1,6 @@ -package com.innowhere.relproxy.impl.jproxy; +package com.sillelien.relproxy.impl.jproxy; -import com.innowhere.relproxy.RelProxyException; +import com.sillelien.relproxy.RelProxyException; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.File; diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyImpl.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/JProxyImpl.java similarity index 78% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyImpl.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/JProxyImpl.java index b9ea4da..1690794 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyImpl.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/JProxyImpl.java @@ -1,15 +1,15 @@ -package com.innowhere.relproxy.impl.jproxy.core; +package com.sillelien.relproxy.impl.jproxy.core; -import com.innowhere.relproxy.impl.GenericProxyImpl; -import com.innowhere.relproxy.impl.GenericProxyInvocationHandler; -import com.innowhere.relproxy.impl.jproxy.JProxyConfigImpl; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; -import com.innowhere.relproxy.jproxy.JProxyCompilerListener; -import com.innowhere.relproxy.jproxy.JProxyDiagnosticsListener; -import com.innowhere.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import com.sillelien.relproxy.impl.GenericProxyImpl; +import com.sillelien.relproxy.impl.GenericProxyInvocationHandler; +import com.sillelien.relproxy.impl.jproxy.JProxyConfigImpl; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.sillelien.relproxy.jproxy.JProxyCompilerListener; +import com.sillelien.relproxy.jproxy.JProxyDiagnosticsListener; +import com.sillelien.relproxy.jproxy.JProxyInputSourceFileExcludedListener; /** * diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyInvocationHandler.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/JProxyInvocationHandler.java similarity index 75% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyInvocationHandler.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/JProxyInvocationHandler.java index ebef741..ef748f4 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyInvocationHandler.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/JProxyInvocationHandler.java @@ -1,7 +1,7 @@ -package com.innowhere.relproxy.impl.jproxy.core; +package com.sillelien.relproxy.impl.jproxy.core; -import com.innowhere.relproxy.impl.GenericProxyInvocationHandler; +import com.sillelien.relproxy.impl.GenericProxyInvocationHandler; /** * @@ -20,4 +20,4 @@ public JProxyImpl getJProxyImpl() return (JProxyImpl)root; } -} \ No newline at end of file +} diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyVersionedObject.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/JProxyVersionedObject.java similarity index 83% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyVersionedObject.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/JProxyVersionedObject.java index ded542f..bb20998 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyVersionedObject.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/JProxyVersionedObject.java @@ -1,7 +1,7 @@ -package com.innowhere.relproxy.impl.jproxy.core; +package com.sillelien.relproxy.impl.jproxy.core; -import com.innowhere.relproxy.impl.GenericProxyVersionedObject; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; +import com.sillelien.relproxy.impl.GenericProxyVersionedObject; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; import java.lang.reflect.Field; /** @@ -36,4 +36,4 @@ protected boolean ignoreField(Field field) { return false; // Todos cuentan (útil en Groovy no en Java) } -} \ No newline at end of file +} diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java similarity index 95% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java index 248a714..31c7dd7 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java @@ -1,7 +1,7 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr; +package com.sillelien.relproxy.impl.jproxy.core.clsmgr; -import com.innowhere.relproxy.RelProxyException; -import com.innowhere.relproxy.impl.FileExt; +import com.sillelien.relproxy.RelProxyException; +import com.sillelien.relproxy.impl.FileExt; import java.io.File; /** diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java similarity index 96% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java index 19c7b33..b27dfb4 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java @@ -1,8 +1,8 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr; +package com.sillelien.relproxy.impl.jproxy.core.clsmgr; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; -import com.innowhere.relproxy.impl.jproxy.JProxyUtil; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; +import com.sillelien.relproxy.impl.jproxy.JProxyUtil; import java.net.URL; /** diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java similarity index 94% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java index e662177..61fef71 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java @@ -1,15 +1,15 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr; +package com.sillelien.relproxy.impl.jproxy.core.clsmgr; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorInner; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.innowhere.relproxy.impl.jproxy.core.JProxyImpl; -import com.innowhere.relproxy.jproxy.JProxyCompilerListener; -import com.innowhere.relproxy.jproxy.JProxyDiagnosticsListener; -import com.innowhere.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorInner; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.sillelien.relproxy.impl.jproxy.core.JProxyImpl; +import com.sillelien.relproxy.jproxy.JProxyCompilerListener; +import com.sillelien.relproxy.jproxy.JProxyDiagnosticsListener; +import com.sillelien.relproxy.jproxy.JProxyInputSourceFileExcludedListener; import java.util.LinkedList; import java.util.Timer; import java.util.TimerTask; diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java similarity index 93% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java index e58b76b..1cd6537 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java @@ -1,21 +1,21 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr; +package com.sillelien.relproxy.impl.jproxy.core.clsmgr; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootInMemory; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceUnit; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootFile; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorInner; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.innowhere.relproxy.impl.jproxy.JProxyUtil; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.JProxyCompilerContext; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.JProxyCompilerInMemory; -import com.innowhere.relproxy.jproxy.JProxyCompilerListener; -import com.innowhere.relproxy.jproxy.JProxyDiagnosticsListener; -import com.innowhere.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootInMemory; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceUnit; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootFile; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorInner; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.sillelien.relproxy.impl.jproxy.JProxyUtil; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.JProxyCompilerContext; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.JProxyCompilerInMemory; +import com.sillelien.relproxy.jproxy.JProxyCompilerListener; +import com.sillelien.relproxy.jproxy.JProxyDiagnosticsListener; +import com.sillelien.relproxy.jproxy.JProxyInputSourceFileExcludedListener; import java.io.File; import java.util.ArrayList; import java.util.LinkedList; diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java similarity index 92% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java index d6d8a6a..d680220 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java @@ -1,18 +1,18 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr; +package com.sillelien.relproxy.impl.jproxy.core.clsmgr; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootFileJavaExt; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceUnit; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileJava; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.innowhere.relproxy.RelProxyException; -import com.innowhere.relproxy.impl.FileExt; -import com.innowhere.relproxy.impl.jproxy.JProxyUtil; -import com.innowhere.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootFileJavaExt; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceUnit; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileJava; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.sillelien.relproxy.RelProxyException; +import com.sillelien.relproxy.impl.FileExt; +import com.sillelien.relproxy.impl.jproxy.JProxyUtil; +import com.sillelien.relproxy.jproxy.JProxyInputSourceFileExcludedListener; import java.io.File; import java.net.URL; import java.util.LinkedList; diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java similarity index 98% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java index 11c443d..659a846 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java @@ -1,4 +1,4 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc; +package com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc; import java.io.File; diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java similarity index 89% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java index d78d72b..30d5f23 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java @@ -1,4 +1,4 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc; +package com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc; /** * diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java similarity index 70% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java index 0586c19..3fe12c8 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java @@ -1,8 +1,8 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc; +package com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc; -import com.innowhere.relproxy.impl.FileExt; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; +import com.sillelien.relproxy.impl.FileExt; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; /** * diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java similarity index 98% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java index ba2e1d7..6728995 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java @@ -1,4 +1,4 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc; +package com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc; import java.util.Collection; import java.util.HashMap; diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java similarity index 96% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java index 780c575..2a69b59 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java @@ -1,9 +1,9 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc; +package com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc; -import com.innowhere.relproxy.RelProxyException; -import com.innowhere.relproxy.impl.jproxy.core.JProxyImpl; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.sillelien.relproxy.RelProxyException; +import com.sillelien.relproxy.impl.jproxy.core.JProxyImpl; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.LinkedList; diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java similarity index 92% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java index 3e2c858..931378f 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java @@ -1,9 +1,9 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc; +package com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceUnit; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceUnit; import java.util.LinkedList; /** diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java similarity index 72% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java index 7bf171a..90c2d23 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java @@ -1,8 +1,8 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp; +package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp; -import com.innowhere.relproxy.RelProxyException; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; +import com.sillelien.relproxy.RelProxyException; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; /** * diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java similarity index 93% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java index ab483ec..9b9d9b3 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java @@ -1,7 +1,7 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp; +package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp; -import com.innowhere.relproxy.RelProxyException; -import com.innowhere.relproxy.jproxy.JProxyDiagnosticsListener; +import com.sillelien.relproxy.RelProxyException; +import com.sillelien.relproxy.jproxy.JProxyDiagnosticsListener; import java.io.IOException; import java.util.List; import javax.tools.Diagnostic; diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java similarity index 92% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java index b00df77..90a3946 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java @@ -1,17 +1,17 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp; +package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputSourceInMemory; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectOutputClass; -import com.innowhere.relproxy.RelProxyException; -import com.innowhere.relproxy.impl.FileExt; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorInner; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileJava; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.JProxyEngineChangeDetectorAndCompiler; -import com.innowhere.relproxy.jproxy.JProxyDiagnosticsListener; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputSourceInMemory; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectOutputClass; +import com.sillelien.relproxy.RelProxyException; +import com.sillelien.relproxy.impl.FileExt; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorInner; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileJava; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.JProxyEngineChangeDetectorAndCompiler; +import com.sillelien.relproxy.jproxy.JProxyDiagnosticsListener; import java.io.File; import java.util.ArrayList; import java.util.LinkedList; diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java similarity index 92% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java index d1f39bd..46c6e43 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java @@ -1,12 +1,12 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp; +package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JProxyJavaFileObjectInput; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInMemory; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInFileSystem; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectOutputClass; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JProxyJavaFileObjectInput; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInMemory; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInFileSystem; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectOutputClass; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; import java.io.IOException; import java.util.Collection; import java.util.Collections; @@ -126,4 +126,4 @@ public String inferBinaryName(Location location, JavaFileObject file) return super.inferBinaryName(location, file); } -} \ No newline at end of file +} diff --git a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java similarity index 95% rename from src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java rename to src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java index fab17f4..e88c91e 100644 --- a/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java +++ b/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java @@ -1,12 +1,12 @@ -package com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp; - -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInFile; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInFileSystem; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInJar; -import com.innowhere.relproxy.RelProxyException; -import com.innowhere.relproxy.impl.FileExt; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; -import com.innowhere.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp; + +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInFile; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInFileSystem; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInJar; +import com.sillelien.relproxy.RelProxyException; +import com.sillelien.relproxy.impl.FileExt; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; +import com.sillelien.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; @@ -211,4 +211,4 @@ private void listUnderJarCustom(String packagePath,FileExt jarFile,CollectionJProxy and {@link JProxyScriptEngineFactory}. diff --git a/src/main/java/com/innowhere/relproxy/jproxy/JProxyDiagnosticsListener.java b/src/main/java/com/sillelien/relproxy/jproxy/JProxyDiagnosticsListener.java similarity index 93% rename from src/main/java/com/innowhere/relproxy/jproxy/JProxyDiagnosticsListener.java rename to src/main/java/com/sillelien/relproxy/jproxy/JProxyDiagnosticsListener.java index bfc6663..563ebf5 100644 --- a/src/main/java/com/innowhere/relproxy/jproxy/JProxyDiagnosticsListener.java +++ b/src/main/java/com/sillelien/relproxy/jproxy/JProxyDiagnosticsListener.java @@ -1,4 +1,4 @@ -package com.innowhere.relproxy.jproxy; +package com.sillelien.relproxy.jproxy; import javax.tools.DiagnosticCollector; import javax.tools.JavaFileObject; diff --git a/src/main/java/com/innowhere/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java b/src/main/java/com/sillelien/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java similarity index 95% rename from src/main/java/com/innowhere/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java rename to src/main/java/com/sillelien/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java index 2602645..0fb92d4 100644 --- a/src/main/java/com/innowhere/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java +++ b/src/main/java/com/sillelien/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java @@ -1,4 +1,4 @@ -package com.innowhere.relproxy.jproxy; +package com.sillelien.relproxy.jproxy; import java.io.File; diff --git a/src/main/java/com/innowhere/relproxy/jproxy/JProxyScriptEngine.java b/src/main/java/com/sillelien/relproxy/jproxy/JProxyScriptEngine.java similarity index 98% rename from src/main/java/com/innowhere/relproxy/jproxy/JProxyScriptEngine.java rename to src/main/java/com/sillelien/relproxy/jproxy/JProxyScriptEngine.java index 10a5ef7..3fd5806 100644 --- a/src/main/java/com/innowhere/relproxy/jproxy/JProxyScriptEngine.java +++ b/src/main/java/com/sillelien/relproxy/jproxy/JProxyScriptEngine.java @@ -1,4 +1,4 @@ -package com.innowhere.relproxy.jproxy; +package com.sillelien.relproxy.jproxy; import javax.script.ScriptEngine; diff --git a/src/main/java/com/innowhere/relproxy/jproxy/JProxyScriptEngineFactory.java b/src/main/java/com/sillelien/relproxy/jproxy/JProxyScriptEngineFactory.java similarity index 84% rename from src/main/java/com/innowhere/relproxy/jproxy/JProxyScriptEngineFactory.java rename to src/main/java/com/sillelien/relproxy/jproxy/JProxyScriptEngineFactory.java index 434aad9..036f218 100644 --- a/src/main/java/com/innowhere/relproxy/jproxy/JProxyScriptEngineFactory.java +++ b/src/main/java/com/sillelien/relproxy/jproxy/JProxyScriptEngineFactory.java @@ -1,6 +1,6 @@ -package com.innowhere.relproxy.jproxy; +package com.sillelien.relproxy.jproxy; -import com.innowhere.relproxy.impl.jproxy.screngine.JProxyScriptEngineFactoryImpl; +import com.sillelien.relproxy.impl.jproxy.screngine.JProxyScriptEngineFactoryImpl; import javax.script.ScriptEngineFactory; /** diff --git a/src/main/java/com/innowhere/relproxy/jproxy/JProxyShell.java b/src/main/java/com/sillelien/relproxy/jproxy/JProxyShell.java similarity index 83% rename from src/main/java/com/innowhere/relproxy/jproxy/JProxyShell.java rename to src/main/java/com/sillelien/relproxy/jproxy/JProxyShell.java index baa3a66..d0e1024 100644 --- a/src/main/java/com/innowhere/relproxy/jproxy/JProxyShell.java +++ b/src/main/java/com/sillelien/relproxy/jproxy/JProxyShell.java @@ -1,6 +1,6 @@ -package com.innowhere.relproxy.jproxy; +package com.sillelien.relproxy.jproxy; -import com.innowhere.relproxy.impl.jproxy.shell.JProxyShellImpl; +import com.sillelien.relproxy.impl.jproxy.shell.JProxyShellImpl; /** * Is the main class to execute shell scripting based on Java. diff --git a/src/main/java/com/innowhere/relproxy/jproxy/package.html b/src/main/java/com/sillelien/relproxy/jproxy/package.html similarity index 100% rename from src/main/java/com/innowhere/relproxy/jproxy/package.html rename to src/main/java/com/sillelien/relproxy/jproxy/package.html diff --git a/src/main/java/com/innowhere/relproxy/package.html b/src/main/java/com/sillelien/relproxy/package.html similarity index 100% rename from src/main/java/com/innowhere/relproxy/package.html rename to src/main/java/com/sillelien/relproxy/package.html From 60373ea2a3e8e4dd4d5058e3f5eea914882b08cb Mon Sep 17 00:00:00 2001 From: "hello@neilellis.me" Date: Fri, 7 Jul 2017 16:06:07 +0100 Subject: [PATCH 008/135] Release 0.9.7 [7/87e81f13b1ad084f95fcd3cca45cdcd542f23a3b] (direly-ablush-second) --- .release | 2 +- .release.details | 2 +- README.md | 126 ++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 126 insertions(+), 4 deletions(-) diff --git a/.release b/.release index b0bb878..c81aa44 100644 --- a/.release +++ b/.release @@ -1 +1 @@ -0.9.5 +0.9.7 diff --git a/.release.details b/.release.details index 6d44865..41b3640 100644 --- a/.release.details +++ b/.release.details @@ -1 +1 @@ -0.9.5 5 642b55254650e2a01d9c583cfd56ad5e204a6233 often-dotal-manna +0.9.7 7 87e81f13b1ad084f95fcd3cca45cdcd542f23a3b direly-ablush-second diff --git a/README.md b/README.md index 3681ee6..be83703 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,124 @@ -# relproxy -Simple Java and Groovy hot class reloader and Java based shell and scripting +RelProxy +======== +RelProxy is a simple Java and Groovy hot class reloader for Java and Groovy providing transparent compilation and class reload on the fly, and scripting support and shell of pure Java code. + + +```xml + +com.sillelien.dollar +relproxy +0.9.7 +jar + +``` + +Overview +------ + +RelProxy is a simple Java and Groovy hot class reloader for Java and Groovy providing transparent compilation and class reload on the fly, and scripting support and shell of pure +Java code. + +RelProxy is: + +1) A simple Java and Groovy hot class reloader for Java and Groovy providing transparent compilation and class reload on the fly with no need of a bootstrap class loader agent and +avoiding context reloading. Reloading happens only in memory. Class reloading can be used in development phase and optionally in production (if source code can be uploaded to +production). + +2) A scripting environment to execute Java code snippets the same as a shell script. There is no new language, is Java compiled on the fly, code in the initial archive can call +to other normal Java files. Optionally .class can be saved in a cache to provide the fastest "scripting" language of the world. + +3) Execution of Java code snippets in command line (no need of packaging into an archive). + +4) A simple shell to code, edit and execute code snippets in Java interactively. + +5) JSR 223 Scripting API implementation for "Java" as the target scripting language. You can embed and execute Java code as scripting into your Java program. + + + +In case of Java "scripting", there is no a new language, is pure Java code with compilation on the fly. + +RelProxy Manual explains how to configure and use RelProxy in NetBeans and Eclipse avoiding class reloading (of course other IDEs are possible). + +There are several examples of how to use RelProxy with most popular Java web frameworks ready to run into [RelProxy Examples](https://github.com/jmarranz/relproxy_examples) +repository. Also [ItsNat Experiments](https://github.com/jmarranz/itsnat/tree/master/inexperiments) includes an ItsNat example using NetBeans with Ant, to reload Java and Groovy code. +The most complex example is [relproxy_test_itsnat](https://github.com/jmarranz/relproxy/tree/master/relproxy_test_itsnat) created for internal testing. + +Besides fast and custom Java (and Groovy) class reloading, RelProxy provides a Java shell scripting environment to execute: + +1) A pure Java archive packaged like a shell script file with no need of previous compilation, compilation is done on the fly and optionally .class can be saved in a +cache to provide the fastest "scripting" language of the world. Code in the initial archive can call to other normal Java files, again with compilation on the fly +and optional compilation caching as .class files. [Example 1](https://github.com/jmarranz/relproxy/blob/master/relproxy/src/test/resources/example_java_shell) +and [example 2](https://github.com/jmarranz/relproxy/blob/master/relproxy/src/test/resources/example_java_shell_complete_class) or just +a conventional [Java source file](https://github.com/jmarranz/relproxy/blob/master/relproxy/src/test/resources/example_normal_class.java) (yes you can execute a conventional +JavaSE application from source code). + +2) Execution of Java code snippets in command line (no need of packaging in an archive). [Example](https://github.com/jmarranz/relproxy/blob/master/relproxy/test_cmd/test_java_shell_snippet_launcher.sh). + +3) Interactive console to edit and execute Java code (ever compilation on the fly). [Example of launcher](https://github.com/jmarranz/relproxy/blob/master/relproxy/test_cmd/test_java_shell_interactive_launcher.sh) + +Finally RelProxy implements the official JSR-223 [Java Scripting API](http://docs.oracle.com/javase/6/docs/technotes/guides/scripting/programmer_guide/index.html) as found in Java 1.6 for "Java" language. +By using this API you can embed Java as any other scripting language in your Java code. + +Yes, Java is also a dynamic scripting language with no need of manual compilation, and it is extremely fast and robust. + + +Bug Reporting +------ + +Use this GitHub project. + + +Historical Details +================== + +Online Docs Last Version +------ + +[Manual](http://relproxy.sourceforge.net/docs/manual/manual.html) + +[JavaDocs](http://relproxy.sourceforge.net/docs/javadoc/) + +Examples +------ + +See the GitHub repository [RelProxy Examples](https://github.com/jmarranz/relproxy_examples) + +Questions and discussions +------ + +There is a [Google Group](https://groups.google.com/forum/#!forum/relproxy) for RelProxy. + + +News +------ + +- 2016-3-16 v0.8.8 Released. Support of static final fields in reloadable proxies. [Release Notes](https://github.com/jmarranz/relproxy/blob/master/relproxy/CHANGES.txt) +- 2015-10-6 DZone article: [Improve Productivity With RelProxy for Java](https://dzone.com/articles/embedding-relproxy-in-your-java-framework-to-provi). About embedding RelProxy in your own Java framework. +- 2015-10-1 v0.8.7 Released. Some improvement needed when embedding RelProxy Java using the scripting API. [Release Notes](https://github.com/jmarranz/relproxy/blob/master/relproxy/CHANGES.txt) +- 2015-6-12 v0.8.6 Released. Support of class reloading of inner classes including anonymous. [Release Notes](https://github.com/jmarranz/relproxy/blob/master/relproxy/CHANGES.txt) +- 2015-6-12 v0.8.5 Released. Improved performance when checking source changes and no change is detected. [Release Notes](https://github.com/jmarranz/relproxy/blob/master/relproxy/CHANGES.txt) +- 2015-2-17 v0.8.4 Released. Added workaround to support Liferay (6.2 tested) [Release Notes](https://github.com/jmarranz/relproxy/blob/master/relproxy/CHANGES.txt). + New [Liferay 6.2 example](https://github.com/jmarranz/relproxy_examples/tree/master/relproxy_ex_liferay-portlet) using RelProxy. +- 2015-1-23 v0.8.3 Released. First release in JCenter and Maven Central [Release Notes](https://github.com/jmarranz/relproxy/blob/master/relproxy/CHANGES.txt) +- 2015-2-5 [Java Hot Class Reloading with RelProxy in Development Mode, a GWT Example](http://java.dzone.com/articles/java-hot-class-reloading) JavaLobby article +- 2015-1-30 [Slides](http://www.slideshare.net/jmarranz/relproxy-class-reload-and-easy-java-scripting) in English and [video](http://autentia.com/2015/01/30/relproxy-easy-class-reload-and-scripting-with-java-por-jose-maria-arranz/#) in Spanish of the RelProxy presentation in MadridJUG on January 28! + + + +Articles/Blogs/Presentations +------ + +- Oct 6,2015 [Improve Productivity With RelProxy for Java](https://dzone.com/articles/embedding-relproxy-in-your-java-framework-to-provi). About embedding RelProxy in your own Java framework. + +- Feb 19,2015 [No longer virgin, uploaded my first jar to Maven Central, and it was not nice](http://jmarranz.blogspot.com.es/2015/02/no-longer-virgin-uploaded-my-first-jar.html). [JavaLobby](http://java.dzone.com/articles/no-longer-virgin-uploaded-my). [Bintray Quote](http://blog.bintray.com/2015/02/19/another-one-bites-the-maven-central-dust-and-saved-by-bintray/). + +- Feb 5,2015 [Java Hot Class Reloading with RelProxy in Development Mode, a GWT Example](http://java.dzone.com/articles/java-hot-class-reloading) + +- Jan 28,2015 [Slides](http://www.slideshare.net/jmarranz/relproxy-class-reload-and-easy-java-scripting) in English and [video](http://autentia.com/2015/01/30/relproxy-easy-class-reload-and-scripting-with-java-por-jose-maria-arranz/#) ([youtube](https://www.youtube.com/watch?v=dyUhX6t5t-Y)) in Spanish of the RelProxy presentation in MadridJUG + +- Dec 31,2014 [RelProxy v0.8.1 reduce el numero de redeploys en GWT-RPC y otros Java web frameworks](http://www.javahispano.org/portada/2014/12/31/relproxy-v081-reduce-el-numero-de-redeploys-en-gwt-rpc-y-otr.html) Published at javaHispano + +- Feb 15,2014 [v0.8 announce at JavaLobby](http://java.dzone.com/articles/presenting-relproxy-hot-class) + +- Feb 12,2014 [v0.8 announce at javaHispano](http://www.javahispano.org/portada/2014/2/12/publicado-relproxy-v08-hot-class-reloader-y-scripting-para-j.html) + From d4f977f85a53fb90921532728ea86e77c1be6e02 Mon Sep 17 00:00:00 2001 From: neilellis Date: Fri, 7 Jul 2017 16:10:39 +0100 Subject: [PATCH 009/135] Refactoring for Dollar project --- README.tmpl.md | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/README.tmpl.md b/README.tmpl.md index 934900c..b4ca0b4 100644 --- a/README.tmpl.md +++ b/README.tmpl.md @@ -1,6 +1,8 @@ -RelProxy +${HEADER} + +RelProxy ${STATE_ALPHA} ======== -RelProxy is a simple Java and Groovy hot class reloader for Java and Groovy providing transparent compilation and class reload on the fly, and scripting support and shell of pure Java code. +RelProxy is a simple Java and Groovy hot class reloader for Java and Groovy providing transparent compilation and class reload on the fly, and scripting support and shell of pure Java code. This version is a fork of [the original project](https://github.com/jmarranz/relproxy) (see the Historical Section below). ```xml @@ -12,6 +14,8 @@ RelProxy is a simple Java and Groovy hot class reloader for Java and Groovy prov ``` +${BLURB} + Overview ------ @@ -68,6 +72,18 @@ Bug Reporting Use this GitHub project. +${FOOTER} + + + + + + + + + + + Historical Details ================== From e3e2f910f69566e2e6b4975c5f42077d83613163 Mon Sep 17 00:00:00 2001 From: neilellis Date: Fri, 7 Jul 2017 16:12:42 +0100 Subject: [PATCH 010/135] Refactoring for Dollar project --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index e1e5557..1d2f216 100644 --- a/pom.xml +++ b/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - com.sillelien.dollar - relproxy + com.sillelien + dollar-relproxy 0 relproxy From 729a3a5adca77e41e15d4ee0ff88bc398712a2f5 Mon Sep 17 00:00:00 2001 From: neilellis Date: Fri, 7 Jul 2017 16:10:39 +0100 Subject: [PATCH 011/135] Refactoring for Dollar project --- README.tmpl.md | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/README.tmpl.md b/README.tmpl.md index 934900c..b4ca0b4 100644 --- a/README.tmpl.md +++ b/README.tmpl.md @@ -1,6 +1,8 @@ -RelProxy +${HEADER} + +RelProxy ${STATE_ALPHA} ======== -RelProxy is a simple Java and Groovy hot class reloader for Java and Groovy providing transparent compilation and class reload on the fly, and scripting support and shell of pure Java code. +RelProxy is a simple Java and Groovy hot class reloader for Java and Groovy providing transparent compilation and class reload on the fly, and scripting support and shell of pure Java code. This version is a fork of [the original project](https://github.com/jmarranz/relproxy) (see the Historical Section below). ```xml @@ -12,6 +14,8 @@ RelProxy is a simple Java and Groovy hot class reloader for Java and Groovy prov ``` +${BLURB} + Overview ------ @@ -68,6 +72,18 @@ Bug Reporting Use this GitHub project. +${FOOTER} + + + + + + + + + + + Historical Details ================== From 3fb9d0263b3ebd61bb5c80ba4929257e65bad224 Mon Sep 17 00:00:00 2001 From: "hello@neilellis.me" Date: Fri, 7 Jul 2017 16:12:46 +0100 Subject: [PATCH 012/135] Release 0.9.11 [11/d4f977f85a53fb90921532728ea86e77c1be6e02] (calmly-ocher-towhee) --- .release | 2 +- .release.details | 2 +- README.md | 51 +++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 50 insertions(+), 5 deletions(-) diff --git a/.release b/.release index c81aa44..8225a4b 100644 --- a/.release +++ b/.release @@ -1 +1 @@ -0.9.7 +0.9.11 diff --git a/.release.details b/.release.details index 41b3640..c58c14d 100644 --- a/.release.details +++ b/.release.details @@ -1 +1 @@ -0.9.7 7 87e81f13b1ad084f95fcd3cca45cdcd542f23a3b direly-ablush-second +0.9.11 11 d4f977f85a53fb90921532728ea86e77c1be6e02 calmly-ocher-towhee diff --git a/README.md b/README.md index be83703..c133019 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,30 @@ -RelProxy + + +RelProxy [![Alpha](https://img.shields.io/badge/Status-Alpha-yellowgreen.svg?style=flat)](http://github.com/dollar-org/relproxy) ======== -RelProxy is a simple Java and Groovy hot class reloader for Java and Groovy providing transparent compilation and class reload on the fly, and scripting support and shell of pure Java code. +RelProxy is a simple Java and Groovy hot class reloader for Java and Groovy providing transparent compilation and class reload on the fly, and scripting support and shell of pure Java code. This version is a fork of [the original project](https://github.com/jmarranz/relproxy) (see the Historical Section below). ```xml com.sillelien.dollar relproxy -0.9.7 +0.9.11 jar ``` +------- + +** If you use this project please consider giving us a star on [GitHub](http://github.com/dollar-org/relproxy). ** + +Please contact me through Gitter (chat) or through GitHub Issues. + +[![GitHub Issues](https://img.shields.io/github/issues/dollar-org/relproxy.svg)](https://github.com/dollar-org/relproxy/issues) [![Join the chat at https://gitter.im/dollar-org/relproxy](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/dollar-org/relproxy?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +For commercial support please contact me directly. +------- + Overview ------ @@ -68,6 +81,38 @@ Bug Reporting Use this GitHub project. +-------- + +# Referral Links + +This is an open source project, which means that we are giving our time to you for free. However like yourselves, we do have bills to pay. Please consider visiting some of these excellent services, they are not junk we can assure you, all services we would or do use ourselves. + +[Really Excellent Dedicated Servers from Limestone Networks](http://www.limestonenetworks.com/?utm_campaign=rwreferrer&utm_medium=affiliate&utm_source=RFR16798) - fantastic service, great price. + +[Low Cost and High Quality Cloud Hosting from Digital Ocean](https://www.digitalocean.com/?refcode=7b4639fc8194) - truly awesome service. + +# Copyright and License + +[![GitHub License](https://img.shields.io/github/license/dollar-org/relproxy.svg)](https://raw.githubusercontent.com/dollar-org/relproxy/master/LICENSE) + +(c) 2015-2017 Neil Ellis all rights reserved. Please see [LICENSE](https://raw.githubusercontent.com/dollar-org/relproxy/master/LICENSE) for license details of this project. Please visit http://neilellis.me for help and raise issues on [GitHub](https://github.com/dollar-org/relproxy/issues). + +For commercial support please contact me directly. + +
+ +
+ + + + + + + + + + + Historical Details ================== From 67b65bb2a3dc5de2ea6cba30b50c7946b77d23d4 Mon Sep 17 00:00:00 2001 From: neilellis Date: Fri, 7 Jul 2017 16:13:02 +0100 Subject: [PATCH 013/135] Refactoring for Dollar project --- README.tmpl.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.tmpl.md b/README.tmpl.md index b4ca0b4..907af65 100644 --- a/README.tmpl.md +++ b/README.tmpl.md @@ -7,8 +7,8 @@ RelProxy is a simple Java and Groovy hot class reloader for Java and Groovy prov ```xml -com.sillelien.dollar -relproxy +com.sillelien +dollar-relproxy ${RELEASE} jar From 325825b54fad7e79f10adc6260a3201a01973d30 Mon Sep 17 00:00:00 2001 From: neilellis Date: Fri, 7 Jul 2017 16:12:42 +0100 Subject: [PATCH 014/135] Refactoring for Dollar project --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index e1e5557..1d2f216 100644 --- a/pom.xml +++ b/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - com.sillelien.dollar - relproxy + com.sillelien + dollar-relproxy 0 relproxy From f51ab0519f1f702b07e12e740fbd7cbb4ec9dc79 Mon Sep 17 00:00:00 2001 From: "hello@neilellis.me" Date: Fri, 7 Jul 2017 16:14:42 +0100 Subject: [PATCH 015/135] Release 0.9.12 [12/e3e2f910f69566e2e6b4975c5f42077d83613163] (hourly-bare-draw) --- .release | 2 +- .release.details | 2 +- README.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release b/.release index 8225a4b..583b27a 100644 --- a/.release +++ b/.release @@ -1 +1 @@ -0.9.11 +0.9.12 diff --git a/.release.details b/.release.details index c58c14d..c97735f 100644 --- a/.release.details +++ b/.release.details @@ -1 +1 @@ -0.9.11 11 d4f977f85a53fb90921532728ea86e77c1be6e02 calmly-ocher-towhee +0.9.12 12 e3e2f910f69566e2e6b4975c5f42077d83613163 hourly-bare-draw diff --git a/README.md b/README.md index c133019..5657db3 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ RelProxy is a simple Java and Groovy hot class reloader for Java and Groovy prov com.sillelien.dollar relproxy -0.9.11 +0.9.12 jar ``` From c0c3e05e4fd5c816e62e16bf7d555380efeb2585 Mon Sep 17 00:00:00 2001 From: neilellis Date: Fri, 7 Jul 2017 16:13:02 +0100 Subject: [PATCH 016/135] Refactoring for Dollar project --- README.tmpl.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.tmpl.md b/README.tmpl.md index b4ca0b4..907af65 100644 --- a/README.tmpl.md +++ b/README.tmpl.md @@ -7,8 +7,8 @@ RelProxy is a simple Java and Groovy hot class reloader for Java and Groovy prov ```xml -com.sillelien.dollar -relproxy +com.sillelien +dollar-relproxy ${RELEASE} jar From cb967a7dd4c438f8faa1a883cf8fd6b1f15165a8 Mon Sep 17 00:00:00 2001 From: "hello@neilellis.me" Date: Fri, 7 Jul 2017 16:15:15 +0100 Subject: [PATCH 017/135] Release 0.9.15 [15/67b65bb2a3dc5de2ea6cba30b50c7946b77d23d4] (dully-then-lieu) --- .release | 2 +- .release.details | 2 +- README.md | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.release b/.release index 583b27a..5d11b14 100644 --- a/.release +++ b/.release @@ -1 +1 @@ -0.9.12 +0.9.15 diff --git a/.release.details b/.release.details index c97735f..8e5cd22 100644 --- a/.release.details +++ b/.release.details @@ -1 +1 @@ -0.9.12 12 e3e2f910f69566e2e6b4975c5f42077d83613163 hourly-bare-draw +0.9.15 15 67b65bb2a3dc5de2ea6cba30b50c7946b77d23d4 dully-then-lieu diff --git a/README.md b/README.md index 5657db3..bbeb216 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,9 @@ RelProxy is a simple Java and Groovy hot class reloader for Java and Groovy prov ```xml -com.sillelien.dollar -relproxy -0.9.12 +com.sillelien +dollar-relproxy +0.9.15 jar ``` From 6565bf3d1f7b1ea1ee03b5ed32f85bc18db23e4f Mon Sep 17 00:00:00 2001 From: neilellis Date: Fri, 7 Jul 2017 16:17:36 +0100 Subject: [PATCH 018/135] Refactoring for Dollar project --- relproxy/LICENSE-2.0.txt => LICENSE-2.0.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename relproxy/LICENSE-2.0.txt => LICENSE-2.0.txt (100%) diff --git a/relproxy/LICENSE-2.0.txt b/LICENSE-2.0.txt similarity index 100% rename from relproxy/LICENSE-2.0.txt rename to LICENSE-2.0.txt From 73d88fe35b6c630a138f9ed7cb68ff7a2e92cfa3 Mon Sep 17 00:00:00 2001 From: neilellis Date: Fri, 7 Jul 2017 16:17:36 +0100 Subject: [PATCH 019/135] Refactoring for Dollar project --- relproxy/LICENSE-2.0.txt => LICENSE-2.0.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename relproxy/LICENSE-2.0.txt => LICENSE-2.0.txt (100%) diff --git a/relproxy/LICENSE-2.0.txt b/LICENSE-2.0.txt similarity index 100% rename from relproxy/LICENSE-2.0.txt rename to LICENSE-2.0.txt From 5c42c31cf5a827cefb9bb147b4565db0a6f059ce Mon Sep 17 00:00:00 2001 From: "hello@neilellis.me" Date: Fri, 7 Jul 2017 16:21:16 +0100 Subject: [PATCH 020/135] Release 0.9.20 [20/6565bf3d1f7b1ea1ee03b5ed32f85bc18db23e4f] (sure-legit-rales) --- .release | 2 +- .release.details | 2 +- README.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release b/.release index 5d11b14..bd758c9 100644 --- a/.release +++ b/.release @@ -1 +1 @@ -0.9.15 +0.9.20 diff --git a/.release.details b/.release.details index 8e5cd22..c8f4163 100644 --- a/.release.details +++ b/.release.details @@ -1 +1 @@ -0.9.15 15 67b65bb2a3dc5de2ea6cba30b50c7946b77d23d4 dully-then-lieu +0.9.20 20 6565bf3d1f7b1ea1ee03b5ed32f85bc18db23e4f sure-legit-rales diff --git a/README.md b/README.md index bbeb216..e9a113a 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ RelProxy is a simple Java and Groovy hot class reloader for Java and Groovy prov com.sillelien dollar-relproxy -0.9.15 +0.9.20 jar ``` From c98b76b6a1df15f1c33d2e1a06925b6687692966 Mon Sep 17 00:00:00 2001 From: neilellis Date: Fri, 7 Jul 2017 16:21:48 +0100 Subject: [PATCH 021/135] Refactoring for Dollar project --- relproxy/pom.xml | 2 +- .../JProxyCodeSnippetCompleteClassTest.java | 2 +- .../jproxy/JProxyCodeSnippetTest.java | 2 +- .../JProxyJavaScriptEngineNoManagerTest.java | 8 ++--- .../jproxy/JProxyJavaScriptEngineTest.java | 8 ++--- .../JProxyJavaShellCompleteClassTest.java | 4 +-- .../JProxyJavaShellInteractiveTest.java | 2 +- .../JProxyJavaShellNormalClassTest.java | 4 +-- .../relproxy/jproxy/JProxyJavaShellTest.java | 4 +-- .../relproxy/jproxy/util/JProxyTestUtil.java | 4 +-- .../javashellex/JProxyShellExample.java | 2 +- .../example/groovyex/ItsNatGroovyServlet.java | 6 ++-- .../example/javaex/JProxyExampleServlet.java | 2 +- .../javaex/JProxyServletContextListener.java | 12 +++---- .../groovyex/groovy_servlet_init.groovy | 6 ++-- .../example/javaex/JProxyExampleDocument.java | 2 +- .../{ => dollar}/relproxy/RelProxy.java | 2 +- .../relproxy/RelProxyException.java | 2 +- .../relproxy/RelProxyOnReloadListener.java | 6 ++-- .../{ => dollar}/relproxy/gproxy/GProxy.java | 6 ++-- .../relproxy/gproxy/GProxyConfig.java | 4 +-- .../gproxy/GProxyGroovyScriptEngine.java | 2 +- .../{ => dollar}/relproxy/gproxy/package.html | 0 .../{ => dollar}/relproxy/impl/FileExt.java | 4 +-- .../impl/GenericProxyConfigBaseImpl.java | 4 +-- .../relproxy/impl/GenericProxyImpl.java | 6 ++-- .../impl/GenericProxyInvocationHandler.java | 4 +-- .../impl/GenericProxyVersionedObject.java | 4 +-- .../impl/gproxy/GProxyConfigImpl.java | 10 +++--- .../impl/gproxy/GProxyDefaultImpl.java | 6 ++-- .../relproxy/impl/gproxy/core/GProxyImpl.java | 10 +++--- .../gproxy/core/GProxyInvocationHandler.java | 4 +-- .../gproxy/core/GProxyVersionedObject.java | 6 ++-- .../impl/jproxy/JProxyConfigImpl.java | 18 +++++----- .../impl/jproxy/JProxyDefaultImpl.java | 6 ++-- .../relproxy/impl/jproxy/JProxyUtil.java | 4 +-- .../relproxy/impl/jproxy/core/JProxyImpl.java | 22 ++++++------ .../jproxy/core/JProxyInvocationHandler.java | 4 +-- .../jproxy/core/JProxyVersionedObject.java | 6 ++-- .../jproxy/core/clsmgr/FolderSourceList.java | 6 ++-- .../jproxy/core/clsmgr/JProxyClassLoader.java | 8 ++--- .../impl/jproxy/core/clsmgr/JProxyEngine.java | 22 ++++++------ ...JProxyEngineChangeDetectorAndCompiler.java | 34 +++++++++---------- .../jproxy/core/clsmgr/JavaSourcesSearch.java | 28 +++++++-------- .../core/clsmgr/cldesc/ClassDescriptor.java | 2 +- .../clsmgr/cldesc/ClassDescriptorInner.java | 2 +- .../cldesc/ClassDescriptorSourceFileJava.java | 8 ++--- .../ClassDescriptorSourceFileRegistry.java | 2 +- .../cldesc/ClassDescriptorSourceScript.java | 10 +++--- .../cldesc/ClassDescriptorSourceUnit.java | 10 +++--- .../comp/JProxyCompilationException.java | 6 ++-- .../clsmgr/comp/JProxyCompilerContext.java | 6 ++-- .../clsmgr/comp/JProxyCompilerInMemory.java | 26 +++++++------- .../clsmgr/comp/JavaFileManagerInMemory.java | 16 ++++----- ...leObjectInputClassFinderByClassLoader.java | 18 +++++----- .../comp/jfo/JProxyJavaFileObjectInput.java | 2 +- .../jfo/JavaFileObjectInputClassInFile.java | 2 +- .../JavaFileObjectInputClassInFileSystem.java | 2 +- .../jfo/JavaFileObjectInputClassInJar.java | 2 +- .../jfo/JavaFileObjectInputClassInMemory.java | 2 +- .../jfo/JavaFileObjectInputSourceBase.java | 4 +-- .../jfo/JavaFileObjectInputSourceInFile.java | 4 +-- .../JavaFileObjectInputSourceInMemory.java | 2 +- .../comp/jfo/JavaFileObjectOutputClass.java | 4 +-- .../clsmgr/srcunit/SourceFileJavaNormal.java | 4 +-- .../core/clsmgr/srcunit/SourceScriptRoot.java | 2 +- .../clsmgr/srcunit/SourceScriptRootFile.java | 8 ++--- .../srcunit/SourceScriptRootFileJavaExt.java | 8 ++--- .../srcunit/SourceScriptRootFileOtherExt.java | 8 ++--- .../srcunit/SourceScriptRootInMemory.java | 2 +- .../core/clsmgr/srcunit/SourceUnit.java | 6 ++-- .../impl/jproxy/screngine/BindingsImpl.java | 2 +- .../JProxyScriptEngineDelegateImpl.java | 20 +++++------ .../JProxyScriptEngineFactoryImpl.java | 6 ++-- .../screngine/JProxyScriptEngineImpl.java | 14 ++++---- .../jproxy/shell/JProxyShellClassLoader.java | 6 ++-- .../shell/JProxyShellCodeSnippetImpl.java | 14 ++++---- .../impl/jproxy/shell/JProxyShellImpl.java | 18 +++++----- .../shell/JProxyShellInteractiveImpl.java | 16 ++++----- .../shell/JProxyShellScriptFileImpl.java | 18 +++++----- .../impl/jproxy/shell/inter/Command.java | 2 +- .../shell/inter/CommandCodeChangerBase.java | 2 +- .../jproxy/shell/inter/CommandDelete.java | 2 +- .../impl/jproxy/shell/inter/CommandEdit.java | 2 +- .../impl/jproxy/shell/inter/CommandError.java | 2 +- .../jproxy/shell/inter/CommandInsert.java | 2 +- .../impl/jproxy/shell/inter/CommandLoad.java | 4 +-- .../impl/jproxy/shell/inter/CommandOther.java | 4 +-- .../impl/jproxy/shell/inter/CommandSave.java | 4 +-- .../shell/inter/JProxyShellProcessor.java | 14 ++++---- .../impl/jproxy/shell/inter/Keyboard.java | 2 +- .../inter/KeyboardNotUsingClipboard.java | 4 +-- .../shell/inter/KeyboardUsingClipboard.java | 4 +-- .../shell/inter/LinuxUnicodeKeyboard.java | 2 +- .../shell/inter/MacOSXUnicodeKeyboard.java | 2 +- .../shell/inter/WindowUnicodeKeyboard.java | 2 +- .../{ => dollar}/relproxy/jproxy/JProxy.java | 6 ++-- .../jproxy/JProxyCompilerListener.java | 2 +- .../relproxy/jproxy/JProxyConfig.java | 4 +-- .../jproxy/JProxyDiagnosticsListener.java | 2 +- ...JProxyInputSourceFileExcludedListener.java | 2 +- .../relproxy/jproxy/JProxyScriptEngine.java | 2 +- .../jproxy/JProxyScriptEngineFactory.java | 4 +-- .../relproxy/jproxy/JProxyShell.java | 4 +-- .../{ => dollar}/relproxy/jproxy/package.html | 0 .../{ => dollar}/relproxy/package.html | 0 106 files changed, 335 insertions(+), 335 deletions(-) rename src/main/java/com/sillelien/{ => dollar}/relproxy/RelProxy.java (88%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/RelProxyException.java (96%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/RelProxyOnReloadListener.java (77%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/gproxy/GProxy.java (94%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/gproxy/GProxyConfig.java (93%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/gproxy/GProxyGroovyScriptEngine.java (96%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/gproxy/package.html (100%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/FileExt.java (87%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/GenericProxyConfigBaseImpl.java (76%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/GenericProxyImpl.java (90%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/GenericProxyInvocationHandler.java (95%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/GenericProxyVersionedObject.java (98%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/gproxy/GProxyConfigImpl.java (70%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/gproxy/GProxyDefaultImpl.java (84%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/gproxy/core/GProxyImpl.java (65%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/gproxy/core/GProxyInvocationHandler.java (73%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/gproxy/core/GProxyVersionedObject.java (85%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/JProxyConfigImpl.java (86%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/JProxyDefaultImpl.java (91%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/JProxyUtil.java (97%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/JProxyImpl.java (74%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/JProxyInvocationHandler.java (73%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/JProxyVersionedObject.java (81%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java (94%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java (95%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java (92%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java (90%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java (89%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java (98%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java (87%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java (65%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java (97%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java (95%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java (91%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java (66%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java (92%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java (89%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java (89%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java (93%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JProxyJavaFileObjectInput.java (61%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java (93%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java (96%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java (91%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java (94%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java (92%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java (84%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java (90%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java (91%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java (81%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRoot.java (78%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java (80%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java (65%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java (78%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootInMemory.java (95%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java (79%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/screngine/BindingsImpl.java (73%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java (81%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java (96%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java (86%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java (85%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java (76%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/JProxyShellImpl.java (89%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java (79%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java (79%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/inter/Command.java (97%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java (96%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/inter/CommandDelete.java (96%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/inter/CommandEdit.java (97%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/inter/CommandError.java (83%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/inter/CommandInsert.java (96%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/inter/CommandLoad.java (93%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/inter/CommandOther.java (96%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/inter/CommandSave.java (91%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java (93%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/inter/Keyboard.java (89%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java (98%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java (93%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/inter/LinuxUnicodeKeyboard.java (96%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/inter/MacOSXUnicodeKeyboard.java (95%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/inter/WindowUnicodeKeyboard.java (95%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/jproxy/JProxy.java (96%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/jproxy/JProxyCompilerListener.java (87%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/jproxy/JProxyConfig.java (98%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/jproxy/JProxyDiagnosticsListener.java (92%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java (94%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/jproxy/JProxyScriptEngine.java (98%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/jproxy/JProxyScriptEngineFactory.java (79%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/jproxy/JProxyShell.java (80%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/jproxy/package.html (100%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/package.html (100%) diff --git a/relproxy/pom.xml b/relproxy/pom.xml index 9ca34a3..e39ffb1 100644 --- a/relproxy/pom.xml +++ b/relproxy/pom.xml @@ -147,7 +147,7 @@ RelProxy v${project.version} RelProxy v${project.version} - com.sillelien.relproxy.impl + com.sillelien.dollar.relproxy.impl diff --git a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyCodeSnippetCompleteClassTest.java b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyCodeSnippetCompleteClassTest.java index 4f40057..d74e03c 100644 --- a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyCodeSnippetCompleteClassTest.java +++ b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyCodeSnippetCompleteClassTest.java @@ -4,7 +4,7 @@ * and open the template in the editor. */ -package com.sillelien.relproxy.jproxy; +package com.sillelien.dollar.relproxy.jproxy; import org.junit.After; import org.junit.AfterClass; diff --git a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyCodeSnippetTest.java b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyCodeSnippetTest.java index 5435fff..353d50e 100644 --- a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyCodeSnippetTest.java +++ b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyCodeSnippetTest.java @@ -4,7 +4,7 @@ * and open the template in the editor. */ -package com.sillelien.relproxy.jproxy; +package com.sillelien.dollar.relproxy.jproxy; import org.junit.After; import org.junit.AfterClass; diff --git a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaScriptEngineNoManagerTest.java b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaScriptEngineNoManagerTest.java index dcddcfe..3f65f86 100644 --- a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaScriptEngineNoManagerTest.java +++ b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaScriptEngineNoManagerTest.java @@ -1,8 +1,8 @@ -package com.sillelien.relproxy.jproxy; +package com.sillelien.dollar.relproxy.jproxy; -import com.sillelien.relproxy.RelProxyOnReloadListener; -import static com.sillelien.relproxy.jproxy.util.JProxyTestUtil.RESOURCES_FOLDER; -import static com.sillelien.relproxy.jproxy.util.JProxyTestUtil.getProjectFolder; +import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; +import static com.sillelien.dollar.relproxy.jproxy.util.JProxyTestUtil.RESOURCES_FOLDER; +import static com.sillelien.dollar.relproxy.jproxy.util.JProxyTestUtil.getProjectFolder; import java.io.File; diff --git a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaScriptEngineTest.java b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaScriptEngineTest.java index 6ff0c01..5ae666f 100644 --- a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaScriptEngineTest.java +++ b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaScriptEngineTest.java @@ -1,8 +1,8 @@ -package com.sillelien.relproxy.jproxy; +package com.sillelien.dollar.relproxy.jproxy; -import com.sillelien.relproxy.RelProxyOnReloadListener; -import static com.sillelien.relproxy.jproxy.util.JProxyTestUtil.RESOURCES_FOLDER; -import static com.sillelien.relproxy.jproxy.util.JProxyTestUtil.getProjectFolder; +import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; +import static com.sillelien.dollar.relproxy.jproxy.util.JProxyTestUtil.RESOURCES_FOLDER; +import static com.sillelien.dollar.relproxy.jproxy.util.JProxyTestUtil.getProjectFolder; import java.io.File; diff --git a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellCompleteClassTest.java b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellCompleteClassTest.java index d0de94b..e4598d6 100644 --- a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellCompleteClassTest.java +++ b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellCompleteClassTest.java @@ -1,6 +1,6 @@ -package com.sillelien.relproxy.jproxy; +package com.sillelien.dollar.relproxy.jproxy; -import com.sillelien.relproxy.jproxy.util.JProxyTestUtil; +import com.sillelien.dollar.relproxy.jproxy.util.JProxyTestUtil; import java.io.File; import org.junit.After; import org.junit.AfterClass; diff --git a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellInteractiveTest.java b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellInteractiveTest.java index 5d18b4b..86c15a8 100644 --- a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellInteractiveTest.java +++ b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellInteractiveTest.java @@ -4,7 +4,7 @@ * and open the template in the editor. */ -package com.sillelien.relproxy.jproxy; +package com.sillelien.dollar.relproxy.jproxy; import org.junit.After; import org.junit.AfterClass; diff --git a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellNormalClassTest.java b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellNormalClassTest.java index 1673a26..8b7f8f2 100644 --- a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellNormalClassTest.java +++ b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellNormalClassTest.java @@ -1,6 +1,6 @@ -package com.sillelien.relproxy.jproxy; +package com.sillelien.dollar.relproxy.jproxy; -import com.sillelien.relproxy.jproxy.util.JProxyTestUtil; +import com.sillelien.dollar.relproxy.jproxy.util.JProxyTestUtil; import java.io.File; import org.junit.After; import org.junit.AfterClass; diff --git a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellTest.java b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellTest.java index 4461b7c..6a74548 100644 --- a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellTest.java +++ b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellTest.java @@ -1,6 +1,6 @@ -package com.sillelien.relproxy.jproxy; +package com.sillelien.dollar.relproxy.jproxy; -import com.sillelien.relproxy.jproxy.util.JProxyTestUtil; +import com.sillelien.dollar.relproxy.jproxy.util.JProxyTestUtil; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; diff --git a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/util/JProxyTestUtil.java b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/util/JProxyTestUtil.java index eed55b9..679f8c6 100644 --- a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/util/JProxyTestUtil.java +++ b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/util/JProxyTestUtil.java @@ -1,5 +1,5 @@ -package com.sillelien.relproxy.jproxy.util; +package com.sillelien.dollar.relproxy.jproxy.util; import java.io.File; import java.net.URL; @@ -15,7 +15,7 @@ public class JProxyTestUtil public static File getProjectFolder() { - String className = JProxyTestUtil.class.getName(); // com.sillelien.relproxy.jproxy.util.JProxyTestUtil + String className = JProxyTestUtil.class.getName(); // com.sillelien.dollar.relproxy.jproxy.util.JProxyTestUtil URL urlClass = JProxyTestUtil.class.getClassLoader().getResource(className.replace('.','/') + ".class"); File fileClass = new File(urlClass.getPath()); File projectFolder = fileClass.getParentFile(); diff --git a/relproxy/src/test/resources/example/javashellex/JProxyShellExample.java b/relproxy/src/test/resources/example/javashellex/JProxyShellExample.java index 92de1f4..b0b5dcf 100644 --- a/relproxy/src/test/resources/example/javashellex/JProxyShellExample.java +++ b/relproxy/src/test/resources/example/javashellex/JProxyShellExample.java @@ -1,7 +1,7 @@ package example.javashellex; import javax.script.ScriptEngine; -import com.sillelien.relproxy.jproxy.JProxyScriptEngine; +import com.sillelien.dollar.relproxy.jproxy.JProxyScriptEngine; /** * diff --git a/relproxy_test_itsnat/src/main/java/example/groovyex/ItsNatGroovyServlet.java b/relproxy_test_itsnat/src/main/java/example/groovyex/ItsNatGroovyServlet.java index c8216b0..5a46c71 100644 --- a/relproxy_test_itsnat/src/main/java/example/groovyex/ItsNatGroovyServlet.java +++ b/relproxy_test_itsnat/src/main/java/example/groovyex/ItsNatGroovyServlet.java @@ -82,9 +82,9 @@ public void init(ServletConfig config) throws ServletException binding.setVariable("context", getServletContext()); binding.setVariable("application", getServletContext()); - com.sillelien.relproxy.gproxy.GProxyGroovyScriptEngine.class.getName(); - com.sillelien.relproxy.gproxy.GProxyConfig.class.getName(); - com.sillelien.relproxy.gproxy.GProxy.class.getName(); + com.sillelien.dollar.relproxy.gproxy.GProxyGroovyScriptEngine.class.getName(); + com.sillelien.dollar.relproxy.gproxy.GProxyConfig.class.getName(); + com.sillelien.dollar.relproxy.gproxy.GProxy.class.getName(); execGroovyScript(initScript,binding); } diff --git a/relproxy_test_itsnat/src/main/java/example/javaex/JProxyExampleServlet.java b/relproxy_test_itsnat/src/main/java/example/javaex/JProxyExampleServlet.java index e845d30..86ac5f4 100644 --- a/relproxy_test_itsnat/src/main/java/example/javaex/JProxyExampleServlet.java +++ b/relproxy_test_itsnat/src/main/java/example/javaex/JProxyExampleServlet.java @@ -1,7 +1,7 @@ package example.javaex; -import com.sillelien.relproxy.jproxy.JProxy; +import com.sillelien.dollar.relproxy.jproxy.JProxy; import javax.servlet.ServletConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; diff --git a/relproxy_test_itsnat/src/main/java/example/javaex/JProxyServletContextListener.java b/relproxy_test_itsnat/src/main/java/example/javaex/JProxyServletContextListener.java index 58fadd2..5f6fa74 100644 --- a/relproxy_test_itsnat/src/main/java/example/javaex/JProxyServletContextListener.java +++ b/relproxy_test_itsnat/src/main/java/example/javaex/JProxyServletContextListener.java @@ -1,11 +1,11 @@ package example.javaex; -import com.sillelien.relproxy.RelProxyOnReloadListener; -import com.sillelien.relproxy.jproxy.JProxy; -import com.sillelien.relproxy.jproxy.JProxyCompilerListener; -import com.sillelien.relproxy.jproxy.JProxyConfig; -import com.sillelien.relproxy.jproxy.JProxyDiagnosticsListener; -import com.sillelien.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; +import com.sillelien.dollar.relproxy.jproxy.JProxy; +import com.sillelien.dollar.relproxy.jproxy.JProxyCompilerListener; +import com.sillelien.dollar.relproxy.jproxy.JProxyConfig; +import com.sillelien.dollar.relproxy.jproxy.JProxyDiagnosticsListener; +import com.sillelien.dollar.relproxy.jproxy.JProxyInputSourceFileExcludedListener; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; diff --git a/relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/code/example/groovyex/groovy_servlet_init.groovy b/relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/code/example/groovyex/groovy_servlet_init.groovy index cdf3128..de148d7 100644 --- a/relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/code/example/groovyex/groovy_servlet_init.groovy +++ b/relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/code/example/groovyex/groovy_servlet_init.groovy @@ -4,9 +4,9 @@ package example.groovyex import org.itsnat.core.event.ItsNatServletRequestListener; import groovy.util.GroovyScriptEngine; import java.lang.reflect.Method; -import com.sillelien.relproxy.RelProxyOnReloadListener; -import com.sillelien.relproxy.gproxy.GProxy; -import com.sillelien.relproxy.gproxy.GProxyGroovyScriptEngine +import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; +import com.sillelien.dollar.relproxy.gproxy.GProxy; +import com.sillelien.dollar.relproxy.gproxy.GProxyGroovyScriptEngine GroovyScriptEngine groovyEngine = servlet.getGroovyScriptEngine(); diff --git a/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleDocument.java b/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleDocument.java index 221a465..f09bde7 100644 --- a/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleDocument.java +++ b/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleDocument.java @@ -1,6 +1,6 @@ package example.javaex; -import com.sillelien.relproxy.jproxy.JProxy; +import com.sillelien.dollar.relproxy.jproxy.JProxy; import example.javaex.hotreload.JProxyExampleAux2; import example.javaex.nothotreload.JProxyExampleAuxIgnored2; import example.javaex.nothotreload.JProxyExampleAuxIgnored3; diff --git a/src/main/java/com/sillelien/relproxy/RelProxy.java b/src/main/java/com/sillelien/dollar/relproxy/RelProxy.java similarity index 88% rename from src/main/java/com/sillelien/relproxy/RelProxy.java rename to src/main/java/com/sillelien/dollar/relproxy/RelProxy.java index c63cea3..8b2ee78 100644 --- a/src/main/java/com/sillelien/relproxy/RelProxy.java +++ b/src/main/java/com/sillelien/dollar/relproxy/RelProxy.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy; +package com.sillelien.dollar.relproxy; /** * Is the root of RelProxy diff --git a/src/main/java/com/sillelien/relproxy/RelProxyException.java b/src/main/java/com/sillelien/dollar/relproxy/RelProxyException.java similarity index 96% rename from src/main/java/com/sillelien/relproxy/RelProxyException.java rename to src/main/java/com/sillelien/dollar/relproxy/RelProxyException.java index 8b16207..1d0e5d4 100644 --- a/src/main/java/com/sillelien/relproxy/RelProxyException.java +++ b/src/main/java/com/sillelien/dollar/relproxy/RelProxyException.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy; +package com.sillelien.dollar.relproxy; /** * Internal checked exceptions thrown by RelProxy and library specific errors are wrapped into this exception class. diff --git a/src/main/java/com/sillelien/relproxy/RelProxyOnReloadListener.java b/src/main/java/com/sillelien/dollar/relproxy/RelProxyOnReloadListener.java similarity index 77% rename from src/main/java/com/sillelien/relproxy/RelProxyOnReloadListener.java rename to src/main/java/com/sillelien/dollar/relproxy/RelProxyOnReloadListener.java index acad475..1750bf3 100644 --- a/src/main/java/com/sillelien/relproxy/RelProxyOnReloadListener.java +++ b/src/main/java/com/sillelien/dollar/relproxy/RelProxyOnReloadListener.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy; +package com.sillelien.dollar.relproxy; import java.lang.reflect.Method; @@ -10,8 +10,8 @@ *

* * - * @see com.sillelien.relproxy.jproxy.JProxyConfig#setRelProxyOnReloadListener(com.sillelien.relproxy.RelProxyOnReloadListener) - * @see com.sillelien.relproxy.gproxy.GProxyConfig#setRelProxyOnReloadListener(com.sillelien.relproxy.RelProxyOnReloadListener) + * @see com.sillelien.dollar.relproxy.jproxy.JProxyConfig#setRelProxyOnReloadListener(com.sillelien.dollar.relproxy.RelProxyOnReloadListener) + * @see com.sillelien.dollar.relproxy.gproxy.GProxyConfig#setRelProxyOnReloadListener(com.sillelien.dollar.relproxy.RelProxyOnReloadListener) * @author Jose Maria Arranz Santamaria */ public interface RelProxyOnReloadListener diff --git a/src/main/java/com/sillelien/relproxy/gproxy/GProxy.java b/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxy.java similarity index 94% rename from src/main/java/com/sillelien/relproxy/gproxy/GProxy.java rename to src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxy.java index 5c74686..6fb5120 100644 --- a/src/main/java/com/sillelien/relproxy/gproxy/GProxy.java +++ b/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxy.java @@ -1,8 +1,8 @@ -package com.sillelien.relproxy.gproxy; +package com.sillelien.dollar.relproxy.gproxy; -import com.sillelien.relproxy.impl.gproxy.GProxyConfigImpl; -import com.sillelien.relproxy.impl.gproxy.GProxyDefaultImpl; +import com.sillelien.dollar.relproxy.impl.gproxy.GProxyConfigImpl; +import com.sillelien.dollar.relproxy.impl.gproxy.GProxyDefaultImpl; /** * Is the class to create Java proxy objects based on Groovy objects and keep track of Groovy source code changes reloading Groovy classes when detected. diff --git a/src/main/java/com/sillelien/relproxy/gproxy/GProxyConfig.java b/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyConfig.java similarity index 93% rename from src/main/java/com/sillelien/relproxy/gproxy/GProxyConfig.java rename to src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyConfig.java index 14cb90c..ea57bcd 100644 --- a/src/main/java/com/sillelien/relproxy/gproxy/GProxyConfig.java +++ b/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyConfig.java @@ -1,7 +1,7 @@ -package com.sillelien.relproxy.gproxy; +package com.sillelien.dollar.relproxy.gproxy; -import com.sillelien.relproxy.RelProxyOnReloadListener; +import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; /** * Interface implemented by the configuration object needed to initialize GProxy. diff --git a/src/main/java/com/sillelien/relproxy/gproxy/GProxyGroovyScriptEngine.java b/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyGroovyScriptEngine.java similarity index 96% rename from src/main/java/com/sillelien/relproxy/gproxy/GProxyGroovyScriptEngine.java rename to src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyGroovyScriptEngine.java index 4025e04..53957a5 100644 --- a/src/main/java/com/sillelien/relproxy/gproxy/GProxyGroovyScriptEngine.java +++ b/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyGroovyScriptEngine.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.gproxy; +package com.sillelien.dollar.relproxy.gproxy; /** * Interface to implement the object implementing the GroovyScriptEngine wrapper used to reload Groovy classes. diff --git a/src/main/java/com/sillelien/relproxy/gproxy/package.html b/src/main/java/com/sillelien/dollar/relproxy/gproxy/package.html similarity index 100% rename from src/main/java/com/sillelien/relproxy/gproxy/package.html rename to src/main/java/com/sillelien/dollar/relproxy/gproxy/package.html diff --git a/src/main/java/com/sillelien/relproxy/impl/FileExt.java b/src/main/java/com/sillelien/dollar/relproxy/impl/FileExt.java similarity index 87% rename from src/main/java/com/sillelien/relproxy/impl/FileExt.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/FileExt.java index d9d3d3c..e3ab333 100644 --- a/src/main/java/com/sillelien/relproxy/impl/FileExt.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/FileExt.java @@ -1,6 +1,6 @@ -package com.sillelien.relproxy.impl; +package com.sillelien.dollar.relproxy.impl; -import com.sillelien.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.RelProxyException; import java.io.File; import java.io.IOException; diff --git a/src/main/java/com/sillelien/relproxy/impl/GenericProxyConfigBaseImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyConfigBaseImpl.java similarity index 76% rename from src/main/java/com/sillelien/relproxy/impl/GenericProxyConfigBaseImpl.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyConfigBaseImpl.java index f46404e..2dd406d 100644 --- a/src/main/java/com/sillelien/relproxy/impl/GenericProxyConfigBaseImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyConfigBaseImpl.java @@ -1,6 +1,6 @@ -package com.sillelien.relproxy.impl; +package com.sillelien.dollar.relproxy.impl; -import com.sillelien.relproxy.RelProxyOnReloadListener; +import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/GenericProxyImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyImpl.java similarity index 90% rename from src/main/java/com/sillelien/relproxy/impl/GenericProxyImpl.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyImpl.java index ca7a397..53a8b3c 100644 --- a/src/main/java/com/sillelien/relproxy/impl/GenericProxyImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyImpl.java @@ -1,7 +1,7 @@ -package com.sillelien.relproxy.impl; +package com.sillelien.dollar.relproxy.impl; -import com.sillelien.relproxy.RelProxyException; -import com.sillelien.relproxy.RelProxyOnReloadListener; +import com.sillelien.dollar.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; diff --git a/src/main/java/com/sillelien/relproxy/impl/GenericProxyInvocationHandler.java b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyInvocationHandler.java similarity index 95% rename from src/main/java/com/sillelien/relproxy/impl/GenericProxyInvocationHandler.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyInvocationHandler.java index ad6d6f9..76bf545 100644 --- a/src/main/java/com/sillelien/relproxy/impl/GenericProxyInvocationHandler.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyInvocationHandler.java @@ -1,6 +1,6 @@ -package com.sillelien.relproxy.impl; +package com.sillelien.dollar.relproxy.impl; -import com.sillelien.relproxy.RelProxyOnReloadListener; +import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; diff --git a/src/main/java/com/sillelien/relproxy/impl/GenericProxyVersionedObject.java b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyVersionedObject.java similarity index 98% rename from src/main/java/com/sillelien/relproxy/impl/GenericProxyVersionedObject.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyVersionedObject.java index c23db15..b941169 100644 --- a/src/main/java/com/sillelien/relproxy/impl/GenericProxyVersionedObject.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyVersionedObject.java @@ -1,6 +1,6 @@ -package com.sillelien.relproxy.impl; +package com.sillelien.dollar.relproxy.impl; -import com.sillelien.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.RelProxyException; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; diff --git a/src/main/java/com/sillelien/relproxy/impl/gproxy/GProxyConfigImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyConfigImpl.java similarity index 70% rename from src/main/java/com/sillelien/relproxy/impl/gproxy/GProxyConfigImpl.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyConfigImpl.java index d57bc86..d549078 100644 --- a/src/main/java/com/sillelien/relproxy/impl/gproxy/GProxyConfigImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyConfigImpl.java @@ -1,9 +1,9 @@ -package com.sillelien.relproxy.impl.gproxy; +package com.sillelien.dollar.relproxy.impl.gproxy; -import com.sillelien.relproxy.RelProxyOnReloadListener; -import com.sillelien.relproxy.gproxy.GProxyConfig; -import com.sillelien.relproxy.gproxy.GProxyGroovyScriptEngine; -import com.sillelien.relproxy.impl.GenericProxyConfigBaseImpl; +import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; +import com.sillelien.dollar.relproxy.gproxy.GProxyConfig; +import com.sillelien.dollar.relproxy.gproxy.GProxyGroovyScriptEngine; +import com.sillelien.dollar.relproxy.impl.GenericProxyConfigBaseImpl; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/gproxy/GProxyDefaultImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyDefaultImpl.java similarity index 84% rename from src/main/java/com/sillelien/relproxy/impl/gproxy/GProxyDefaultImpl.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyDefaultImpl.java index 6c8fe50..03735ef 100644 --- a/src/main/java/com/sillelien/relproxy/impl/gproxy/GProxyDefaultImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyDefaultImpl.java @@ -1,7 +1,7 @@ -package com.sillelien.relproxy.impl.gproxy; +package com.sillelien.dollar.relproxy.impl.gproxy; -import com.sillelien.relproxy.gproxy.GProxyConfig; -import com.sillelien.relproxy.impl.gproxy.core.GProxyImpl; +import com.sillelien.dollar.relproxy.gproxy.GProxyConfig; +import com.sillelien.dollar.relproxy.impl.gproxy.core.GProxyImpl; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/gproxy/core/GProxyImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyImpl.java similarity index 65% rename from src/main/java/com/sillelien/relproxy/impl/gproxy/core/GProxyImpl.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyImpl.java index ca00943..40ab707 100644 --- a/src/main/java/com/sillelien/relproxy/impl/gproxy/core/GProxyImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyImpl.java @@ -1,9 +1,9 @@ -package com.sillelien.relproxy.impl.gproxy.core; +package com.sillelien.dollar.relproxy.impl.gproxy.core; -import com.sillelien.relproxy.impl.gproxy.GProxyConfigImpl; -import com.sillelien.relproxy.gproxy.GProxyGroovyScriptEngine; -import com.sillelien.relproxy.impl.GenericProxyImpl; -import com.sillelien.relproxy.impl.GenericProxyInvocationHandler; +import com.sillelien.dollar.relproxy.impl.gproxy.GProxyConfigImpl; +import com.sillelien.dollar.relproxy.gproxy.GProxyGroovyScriptEngine; +import com.sillelien.dollar.relproxy.impl.GenericProxyImpl; +import com.sillelien.dollar.relproxy.impl.GenericProxyInvocationHandler; /** diff --git a/src/main/java/com/sillelien/relproxy/impl/gproxy/core/GProxyInvocationHandler.java b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyInvocationHandler.java similarity index 73% rename from src/main/java/com/sillelien/relproxy/impl/gproxy/core/GProxyInvocationHandler.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyInvocationHandler.java index f362a27..0bff93a 100644 --- a/src/main/java/com/sillelien/relproxy/impl/gproxy/core/GProxyInvocationHandler.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyInvocationHandler.java @@ -1,6 +1,6 @@ -package com.sillelien.relproxy.impl.gproxy.core; +package com.sillelien.dollar.relproxy.impl.gproxy.core; -import com.sillelien.relproxy.impl.GenericProxyInvocationHandler; +import com.sillelien.dollar.relproxy.impl.GenericProxyInvocationHandler; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/gproxy/core/GProxyVersionedObject.java b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyVersionedObject.java similarity index 85% rename from src/main/java/com/sillelien/relproxy/impl/gproxy/core/GProxyVersionedObject.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyVersionedObject.java index f57bf53..c4edf28 100644 --- a/src/main/java/com/sillelien/relproxy/impl/gproxy/core/GProxyVersionedObject.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyVersionedObject.java @@ -1,7 +1,7 @@ -package com.sillelien.relproxy.impl.gproxy.core; +package com.sillelien.dollar.relproxy.impl.gproxy.core; -import com.sillelien.relproxy.gproxy.GProxyGroovyScriptEngine; -import com.sillelien.relproxy.impl.GenericProxyVersionedObject; +import com.sillelien.dollar.relproxy.gproxy.GProxyGroovyScriptEngine; +import com.sillelien.dollar.relproxy.impl.GenericProxyVersionedObject; import java.lang.reflect.Field; /** diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/JProxyConfigImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyConfigImpl.java similarity index 86% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/JProxyConfigImpl.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyConfigImpl.java index cc095a2..bd1fe4c 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/JProxyConfigImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyConfigImpl.java @@ -1,13 +1,13 @@ -package com.sillelien.relproxy.impl.jproxy; +package com.sillelien.dollar.relproxy.impl.jproxy; -import com.sillelien.relproxy.RelProxyException; -import com.sillelien.relproxy.RelProxyOnReloadListener; -import com.sillelien.relproxy.impl.GenericProxyConfigBaseImpl; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; -import com.sillelien.relproxy.jproxy.JProxyCompilerListener; -import com.sillelien.relproxy.jproxy.JProxyConfig; -import com.sillelien.relproxy.jproxy.JProxyDiagnosticsListener; -import com.sillelien.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import com.sillelien.dollar.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; +import com.sillelien.dollar.relproxy.impl.GenericProxyConfigBaseImpl; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import com.sillelien.dollar.relproxy.jproxy.JProxyCompilerListener; +import com.sillelien.dollar.relproxy.jproxy.JProxyConfig; +import com.sillelien.dollar.relproxy.jproxy.JProxyDiagnosticsListener; +import com.sillelien.dollar.relproxy.jproxy.JProxyInputSourceFileExcludedListener; import java.io.File; /** diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/JProxyDefaultImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyDefaultImpl.java similarity index 91% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/JProxyDefaultImpl.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyDefaultImpl.java index 92ab460..a4ed4f5 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/JProxyDefaultImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyDefaultImpl.java @@ -1,7 +1,7 @@ -package com.sillelien.relproxy.impl.jproxy; +package com.sillelien.dollar.relproxy.impl.jproxy; -import com.sillelien.relproxy.impl.jproxy.core.JProxyImpl; -import com.sillelien.relproxy.jproxy.JProxyConfig; +import com.sillelien.dollar.relproxy.impl.jproxy.core.JProxyImpl; +import com.sillelien.dollar.relproxy.jproxy.JProxyConfig; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/JProxyUtil.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyUtil.java similarity index 97% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/JProxyUtil.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyUtil.java index b63a961..86b3716 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/JProxyUtil.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyUtil.java @@ -1,6 +1,6 @@ -package com.sillelien.relproxy.impl.jproxy; +package com.sillelien.dollar.relproxy.impl.jproxy; -import com.sillelien.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.RelProxyException; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.File; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/JProxyImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyImpl.java similarity index 74% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/JProxyImpl.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyImpl.java index 1690794..93c9fb9 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/JProxyImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyImpl.java @@ -1,15 +1,15 @@ -package com.sillelien.relproxy.impl.jproxy.core; +package com.sillelien.dollar.relproxy.impl.jproxy.core; -import com.sillelien.relproxy.impl.GenericProxyImpl; -import com.sillelien.relproxy.impl.GenericProxyInvocationHandler; -import com.sillelien.relproxy.impl.jproxy.JProxyConfigImpl; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; -import com.sillelien.relproxy.jproxy.JProxyCompilerListener; -import com.sillelien.relproxy.jproxy.JProxyDiagnosticsListener; -import com.sillelien.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import com.sillelien.dollar.relproxy.impl.GenericProxyImpl; +import com.sillelien.dollar.relproxy.impl.GenericProxyInvocationHandler; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyConfigImpl; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.sillelien.dollar.relproxy.jproxy.JProxyCompilerListener; +import com.sillelien.dollar.relproxy.jproxy.JProxyDiagnosticsListener; +import com.sillelien.dollar.relproxy.jproxy.JProxyInputSourceFileExcludedListener; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/JProxyInvocationHandler.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyInvocationHandler.java similarity index 73% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/JProxyInvocationHandler.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyInvocationHandler.java index ef748f4..2cb390e 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/JProxyInvocationHandler.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyInvocationHandler.java @@ -1,7 +1,7 @@ -package com.sillelien.relproxy.impl.jproxy.core; +package com.sillelien.dollar.relproxy.impl.jproxy.core; -import com.sillelien.relproxy.impl.GenericProxyInvocationHandler; +import com.sillelien.dollar.relproxy.impl.GenericProxyInvocationHandler; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/JProxyVersionedObject.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyVersionedObject.java similarity index 81% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/JProxyVersionedObject.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyVersionedObject.java index bb20998..d3b07ca 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/JProxyVersionedObject.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyVersionedObject.java @@ -1,7 +1,7 @@ -package com.sillelien.relproxy.impl.jproxy.core; +package com.sillelien.dollar.relproxy.impl.jproxy.core; -import com.sillelien.relproxy.impl.GenericProxyVersionedObject; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; +import com.sillelien.dollar.relproxy.impl.GenericProxyVersionedObject; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; import java.lang.reflect.Field; /** diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java similarity index 94% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java index 31c7dd7..d9b48e7 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java @@ -1,7 +1,7 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr; -import com.sillelien.relproxy.RelProxyException; -import com.sillelien.relproxy.impl.FileExt; +import com.sillelien.dollar.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.impl.FileExt; import java.io.File; /** diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java similarity index 95% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java index b27dfb4..328b1b9 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java @@ -1,8 +1,8 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; -import com.sillelien.relproxy.impl.jproxy.JProxyUtil; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; import java.net.URL; /** diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java similarity index 92% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java index 61fef71..8fc57ad 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java @@ -1,15 +1,15 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorInner; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.sillelien.relproxy.impl.jproxy.core.JProxyImpl; -import com.sillelien.relproxy.jproxy.JProxyCompilerListener; -import com.sillelien.relproxy.jproxy.JProxyDiagnosticsListener; -import com.sillelien.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorInner; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.sillelien.dollar.relproxy.impl.jproxy.core.JProxyImpl; +import com.sillelien.dollar.relproxy.jproxy.JProxyCompilerListener; +import com.sillelien.dollar.relproxy.jproxy.JProxyDiagnosticsListener; +import com.sillelien.dollar.relproxy.jproxy.JProxyInputSourceFileExcludedListener; import java.util.LinkedList; import java.util.Timer; import java.util.TimerTask; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java similarity index 90% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java index 1cd6537..4460e33 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java @@ -1,21 +1,21 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootInMemory; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceUnit; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootFile; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorInner; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.sillelien.relproxy.impl.jproxy.JProxyUtil; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.JProxyCompilerContext; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.JProxyCompilerInMemory; -import com.sillelien.relproxy.jproxy.JProxyCompilerListener; -import com.sillelien.relproxy.jproxy.JProxyDiagnosticsListener; -import com.sillelien.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootInMemory; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceUnit; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootFile; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorInner; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.JProxyCompilerContext; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.JProxyCompilerInMemory; +import com.sillelien.dollar.relproxy.jproxy.JProxyCompilerListener; +import com.sillelien.dollar.relproxy.jproxy.JProxyDiagnosticsListener; +import com.sillelien.dollar.relproxy.jproxy.JProxyInputSourceFileExcludedListener; import java.io.File; import java.util.ArrayList; import java.util.LinkedList; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java similarity index 89% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java index d680220..536113b 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java @@ -1,18 +1,18 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootFileJavaExt; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceUnit; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileJava; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.sillelien.relproxy.RelProxyException; -import com.sillelien.relproxy.impl.FileExt; -import com.sillelien.relproxy.impl.jproxy.JProxyUtil; -import com.sillelien.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootFileJavaExt; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceUnit; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileJava; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.sillelien.dollar.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.impl.FileExt; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; +import com.sillelien.dollar.relproxy.jproxy.JProxyInputSourceFileExcludedListener; import java.io.File; import java.net.URL; import java.util.LinkedList; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java similarity index 98% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java index 659a846..99bc7ac 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc; import java.io.File; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java similarity index 87% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java index 30d5f23..7190866 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java similarity index 65% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java index 3fe12c8..1300fea 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java @@ -1,8 +1,8 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc; -import com.sillelien.relproxy.impl.FileExt; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; +import com.sillelien.dollar.relproxy.impl.FileExt; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java similarity index 97% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java index 6728995..bf0b64b 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc; import java.util.Collection; import java.util.HashMap; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java similarity index 95% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java index 2a69b59..0dda05d 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java @@ -1,9 +1,9 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc; -import com.sillelien.relproxy.RelProxyException; -import com.sillelien.relproxy.impl.jproxy.core.JProxyImpl; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.sillelien.dollar.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.impl.jproxy.core.JProxyImpl; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.LinkedList; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java similarity index 91% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java index 931378f..4896ee1 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java @@ -1,9 +1,9 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceUnit; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceUnit; import java.util.LinkedList; /** diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java similarity index 66% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java index 90c2d23..dd43381 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java @@ -1,8 +1,8 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp; -import com.sillelien.relproxy.RelProxyException; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; +import com.sillelien.dollar.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java similarity index 92% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java index 9b9d9b3..2ad1bd7 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java @@ -1,7 +1,7 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp; -import com.sillelien.relproxy.RelProxyException; -import com.sillelien.relproxy.jproxy.JProxyDiagnosticsListener; +import com.sillelien.dollar.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.jproxy.JProxyDiagnosticsListener; import java.io.IOException; import java.util.List; import javax.tools.Diagnostic; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java similarity index 89% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java index 90a3946..c8b20c8 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java @@ -1,17 +1,17 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputSourceInMemory; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectOutputClass; -import com.sillelien.relproxy.RelProxyException; -import com.sillelien.relproxy.impl.FileExt; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorInner; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileJava; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.JProxyEngineChangeDetectorAndCompiler; -import com.sillelien.relproxy.jproxy.JProxyDiagnosticsListener; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputSourceInMemory; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectOutputClass; +import com.sillelien.dollar.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.impl.FileExt; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorInner; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileJava; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.JProxyEngineChangeDetectorAndCompiler; +import com.sillelien.dollar.relproxy.jproxy.JProxyDiagnosticsListener; import java.io.File; import java.util.ArrayList; import java.util.LinkedList; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java similarity index 89% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java index 46c6e43..7de7a8e 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java @@ -1,12 +1,12 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JProxyJavaFileObjectInput; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInMemory; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInFileSystem; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectOutputClass; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JProxyJavaFileObjectInput; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInMemory; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInFileSystem; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectOutputClass; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; import java.io.IOException; import java.util.Collection; import java.util.Collections; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java similarity index 93% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java index e88c91e..62f950f 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java @@ -1,12 +1,12 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp; - -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInFile; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInFileSystem; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInJar; -import com.sillelien.relproxy.RelProxyException; -import com.sillelien.relproxy.impl.FileExt; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp; + +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInFile; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInFileSystem; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInJar; +import com.sillelien.dollar.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.impl.FileExt; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JProxyJavaFileObjectInput.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JProxyJavaFileObjectInput.java similarity index 61% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JProxyJavaFileObjectInput.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JProxyJavaFileObjectInput.java index 570933f..8faf5a6 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JProxyJavaFileObjectInput.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JProxyJavaFileObjectInput.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java similarity index 93% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java index 5f3a3e3..eeb1b23 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo; import java.io.BufferedInputStream; import java.io.File; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java similarity index 96% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java index 87f2230..62bf61e 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo; import java.io.IOException; import java.io.OutputStream; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java similarity index 91% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java index 2e62f66..4dee882 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo; import java.io.IOException; import java.io.InputStream; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java similarity index 94% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java index 5694fab..d4d764c 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo; import java.io.ByteArrayInputStream; import java.io.IOException; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java similarity index 92% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java index 8a9569c..cf40ca1 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java @@ -1,6 +1,6 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo; -import com.sillelien.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.RelProxyException; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java similarity index 84% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java index ebddf24..8683f69 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java @@ -1,6 +1,6 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo; -import com.sillelien.relproxy.impl.jproxy.JProxyUtil; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; import java.io.File; /** diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java similarity index 90% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java index f01bb30..dca46cd 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo; /** * http://www.javablogging.com/dynamic-in-memory-compilation/ diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java similarity index 91% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java index aa62e0b..6fa68d0 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java @@ -1,6 +1,6 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo; -import com.sillelien.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.RelProxyException; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java similarity index 81% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java index 91e72ff..b4432cf 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java @@ -1,6 +1,6 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit; -import com.sillelien.relproxy.impl.FileExt; +import com.sillelien.dollar.relproxy.impl.FileExt; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRoot.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRoot.java similarity index 78% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRoot.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRoot.java index a8ab184..5d81119 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRoot.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRoot.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java similarity index 80% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java index 153aef1..60b46bb 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java @@ -1,8 +1,8 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit; -import com.sillelien.relproxy.impl.FileExt; -import com.sillelien.relproxy.impl.jproxy.JProxyUtil; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import com.sillelien.dollar.relproxy.impl.FileExt; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java similarity index 65% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java index cf0450d..4aeb091 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java @@ -1,8 +1,8 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit; -import com.sillelien.relproxy.impl.FileExt; -import com.sillelien.relproxy.impl.jproxy.JProxyUtil; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import com.sillelien.dollar.relproxy.impl.FileExt; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java similarity index 78% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java index bcc19ba..154b757 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java @@ -1,8 +1,8 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit; -import com.sillelien.relproxy.impl.FileExt; -import com.sillelien.relproxy.impl.jproxy.JProxyUtil; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import com.sillelien.dollar.relproxy.impl.FileExt; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootInMemory.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootInMemory.java similarity index 95% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootInMemory.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootInMemory.java index e4e401c..9ad61e0 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootInMemory.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootInMemory.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java similarity index 79% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java index cf216a1..f0b55e2 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java @@ -1,7 +1,7 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit; -import com.sillelien.relproxy.impl.FileExt; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import com.sillelien.dollar.relproxy.impl.FileExt; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/screngine/BindingsImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/BindingsImpl.java similarity index 73% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/screngine/BindingsImpl.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/BindingsImpl.java index 8c646af..e960b2a 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/screngine/BindingsImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/BindingsImpl.java @@ -1,5 +1,5 @@ -package com.sillelien.relproxy.impl.jproxy.screngine; +package com.sillelien.dollar.relproxy.impl.jproxy.screngine; import java.util.HashMap; import javax.script.Bindings; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java similarity index 81% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java index a197c2f..461c2d5 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java @@ -1,14 +1,14 @@ -package com.sillelien.relproxy.impl.jproxy.screngine; +package com.sillelien.dollar.relproxy.impl.jproxy.screngine; -import com.sillelien.relproxy.RelProxyException; -import com.sillelien.relproxy.impl.jproxy.JProxyConfigImpl; -import com.sillelien.relproxy.impl.jproxy.core.JProxyImpl; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootInMemory; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.JProxyCompilationException; -import com.sillelien.relproxy.impl.jproxy.shell.JProxyShellClassLoader; +import com.sillelien.dollar.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyConfigImpl; +import com.sillelien.dollar.relproxy.impl.jproxy.core.JProxyImpl; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootInMemory; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.JProxyCompilationException; +import com.sillelien.dollar.relproxy.impl.jproxy.shell.JProxyShellClassLoader; import java.io.File; import javax.script.ScriptContext; import javax.script.ScriptException; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java similarity index 96% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java index 725bbb3..aab0f23 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java @@ -1,7 +1,7 @@ -package com.sillelien.relproxy.impl.jproxy.screngine; +package com.sillelien.dollar.relproxy.impl.jproxy.screngine; -import com.sillelien.relproxy.RelProxy; -import com.sillelien.relproxy.jproxy.JProxyScriptEngineFactory; +import com.sillelien.dollar.relproxy.RelProxy; +import com.sillelien.dollar.relproxy.jproxy.JProxyScriptEngineFactory; import java.util.ArrayList; import java.util.Collections; import java.util.List; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java similarity index 86% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java index 4431df8..eab9862 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java @@ -1,11 +1,11 @@ -package com.sillelien.relproxy.impl.jproxy.screngine; +package com.sillelien.dollar.relproxy.impl.jproxy.screngine; -import com.sillelien.relproxy.RelProxyException; -import com.sillelien.relproxy.impl.GenericProxyImpl; -import com.sillelien.relproxy.impl.jproxy.JProxyConfigImpl; -import com.sillelien.relproxy.impl.jproxy.JProxyUtil; -import com.sillelien.relproxy.jproxy.JProxyConfig; -import com.sillelien.relproxy.jproxy.JProxyScriptEngine; +import com.sillelien.dollar.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.impl.GenericProxyImpl; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyConfigImpl; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; +import com.sillelien.dollar.relproxy.jproxy.JProxyConfig; +import com.sillelien.dollar.relproxy.jproxy.JProxyScriptEngine; import java.io.Reader; import javax.script.AbstractScriptEngine; import javax.script.Bindings; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java similarity index 85% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java index a6d7cc3..1941300 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java @@ -1,7 +1,7 @@ -package com.sillelien.relproxy.impl.jproxy.shell; +package com.sillelien.dollar.relproxy.impl.jproxy.shell; -import com.sillelien.relproxy.RelProxyException; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; +import com.sillelien.dollar.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; import java.io.File; import java.net.MalformedURLException; import java.net.URL; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java similarity index 76% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java index c59a4b9..220909a 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java @@ -1,11 +1,11 @@ -package com.sillelien.relproxy.impl.jproxy.shell; +package com.sillelien.dollar.relproxy.impl.jproxy.shell; -import com.sillelien.relproxy.RelProxyException; -import com.sillelien.relproxy.impl.jproxy.JProxyConfigImpl; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootInMemory; +import com.sillelien.dollar.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyConfigImpl; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootInMemory; import java.util.LinkedList; /** diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/JProxyShellImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellImpl.java similarity index 89% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/JProxyShellImpl.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellImpl.java index d89c1f5..adba4a7 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/JProxyShellImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellImpl.java @@ -1,12 +1,12 @@ -package com.sillelien.relproxy.impl.jproxy.shell; +package com.sillelien.dollar.relproxy.impl.jproxy.shell; -import com.sillelien.relproxy.RelProxyException; -import com.sillelien.relproxy.RelProxyOnReloadListener; -import com.sillelien.relproxy.impl.jproxy.JProxyConfigImpl; -import com.sillelien.relproxy.impl.jproxy.core.JProxyImpl; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.sillelien.dollar.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyConfigImpl; +import com.sillelien.dollar.relproxy.impl.jproxy.core.JProxyImpl; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; import java.lang.reflect.Method; import java.util.LinkedList; @@ -22,7 +22,7 @@ public static void main(String[] args) { if (args[0].isEmpty()) { - // Esto tiene explicación: cuando invocamos jproxysh sin parámetros (o espacios da igual) invocamos dentro jproxysh con com.sillelien.relproxy.jproxy.JProxyShell "$@" + // Esto tiene explicación: cuando invocamos jproxysh sin parámetros (o espacios da igual) invocamos dentro jproxysh con com.sillelien.dollar.relproxy.jproxy.JProxyShell "$@" // el parámetro "$@" se convierte en "" que es un parámetro de verdad que recibimos pero de cadena vacía, lo cual nos viene GENIAL para distinguir el caso shell interactive SINGLETON = new JProxyShellInteractiveImpl(); ((JProxyShellInteractiveImpl)SINGLETON).init(args); diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java similarity index 79% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java index d740fd4..1a72f62 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java @@ -1,12 +1,12 @@ -package com.sillelien.relproxy.impl.jproxy.shell; +package com.sillelien.dollar.relproxy.impl.jproxy.shell; -import com.sillelien.relproxy.RelProxyException; -import com.sillelien.relproxy.impl.jproxy.JProxyConfigImpl; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootInMemory; -import com.sillelien.relproxy.impl.jproxy.shell.inter.JProxyShellProcessor; +import com.sillelien.dollar.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyConfigImpl; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootInMemory; +import com.sillelien.dollar.relproxy.impl.jproxy.shell.inter.JProxyShellProcessor; import java.util.LinkedList; /** diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java similarity index 79% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java index abdea1c..b19d3bb 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java @@ -1,13 +1,13 @@ -package com.sillelien.relproxy.impl.jproxy.shell; +package com.sillelien.dollar.relproxy.impl.jproxy.shell; -import com.sillelien.relproxy.RelProxyException; -import com.sillelien.relproxy.impl.FileExt; -import com.sillelien.relproxy.impl.jproxy.JProxyConfigImpl; -import com.sillelien.relproxy.impl.jproxy.JProxyUtil; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootFile; +import com.sillelien.dollar.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.impl.FileExt; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyConfigImpl; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootFile; import java.io.File; import java.util.LinkedList; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/Command.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/Command.java similarity index 97% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/Command.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/Command.java index a15999b..b41f3bb 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/Command.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/Command.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.shell.inter; +package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java similarity index 96% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java index c1e277f..5884b0c 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.shell.inter; +package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; /** diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandDelete.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandDelete.java similarity index 96% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandDelete.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandDelete.java index 797a6a6..f4d6b29 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandDelete.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandDelete.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.shell.inter; +package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; /** diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandEdit.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandEdit.java similarity index 97% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandEdit.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandEdit.java index 1440c09..d86f854 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandEdit.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandEdit.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.shell.inter; +package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; /** diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandError.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandError.java similarity index 83% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandError.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandError.java index db9299f..2c7480e 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandError.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandError.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.shell.inter; +package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandInsert.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandInsert.java similarity index 96% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandInsert.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandInsert.java index f372131..cf36e4f 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandInsert.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandInsert.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.shell.inter; +package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; /** diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandLoad.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandLoad.java similarity index 93% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandLoad.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandLoad.java index 8333dfa..cf4e7b8 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandLoad.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandLoad.java @@ -1,6 +1,6 @@ -package com.sillelien.relproxy.impl.jproxy.shell.inter; +package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; -import com.sillelien.relproxy.impl.jproxy.JProxyUtil; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; import java.io.File; import java.net.URI; import java.net.URL; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandOther.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandOther.java similarity index 96% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandOther.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandOther.java index a4fb614..e93c5e4 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandOther.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandOther.java @@ -1,7 +1,7 @@ -package com.sillelien.relproxy.impl.jproxy.shell.inter; +package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; -import com.sillelien.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.RelProxyException; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandSave.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandSave.java similarity index 91% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandSave.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandSave.java index 9e34990..b19f83c 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandSave.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandSave.java @@ -1,6 +1,6 @@ -package com.sillelien.relproxy.impl.jproxy.shell.inter; +package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; -import com.sillelien.relproxy.impl.jproxy.JProxyUtil; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; import java.io.File; import java.util.List; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java similarity index 93% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java index d0f96db..4f14985 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java @@ -1,11 +1,11 @@ -package com.sillelien.relproxy.impl.jproxy.shell.inter; +package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; -import com.sillelien.relproxy.RelProxy; -import com.sillelien.relproxy.RelProxyException; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.JProxyCompilationException; -import com.sillelien.relproxy.impl.jproxy.shell.JProxyShellInteractiveImpl; +import com.sillelien.dollar.relproxy.RelProxy; +import com.sillelien.dollar.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.JProxyCompilationException; +import com.sillelien.dollar.relproxy.impl.jproxy.shell.JProxyShellInteractiveImpl; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collections; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/Keyboard.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/Keyboard.java similarity index 89% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/Keyboard.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/Keyboard.java index 50b4f05..b1cb22a 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/Keyboard.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/Keyboard.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.shell.inter; +package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; import java.nio.charset.Charset; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java similarity index 98% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java index 1207ba8..bef7800 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java @@ -1,7 +1,7 @@ -package com.sillelien.relproxy.impl.jproxy.shell.inter; +package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; -import com.sillelien.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.RelProxyException; import java.awt.AWTException; import java.awt.Robot; import static java.awt.event.KeyEvent.VK_0; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java similarity index 93% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java index d4d39a9..0f42d3b 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java @@ -1,7 +1,7 @@ -package com.sillelien.relproxy.impl.jproxy.shell.inter; +package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; -import com.sillelien.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.RelProxyException; import java.awt.AWTException; import java.awt.Robot; import java.awt.Toolkit; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/LinuxUnicodeKeyboard.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/LinuxUnicodeKeyboard.java similarity index 96% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/LinuxUnicodeKeyboard.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/LinuxUnicodeKeyboard.java index 760172a..b11f86b 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/LinuxUnicodeKeyboard.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/LinuxUnicodeKeyboard.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.shell.inter; +package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; import static java.awt.event.KeyEvent.VK_CONTROL; import static java.awt.event.KeyEvent.VK_SHIFT; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/MacOSXUnicodeKeyboard.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/MacOSXUnicodeKeyboard.java similarity index 95% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/MacOSXUnicodeKeyboard.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/MacOSXUnicodeKeyboard.java index 990cd8a..7a1caf5 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/MacOSXUnicodeKeyboard.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/MacOSXUnicodeKeyboard.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.shell.inter; +package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; import static java.awt.Event.ALT_MASK; import java.nio.charset.Charset; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/WindowUnicodeKeyboard.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/WindowUnicodeKeyboard.java similarity index 95% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/WindowUnicodeKeyboard.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/WindowUnicodeKeyboard.java index 26de732..35d4a47 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/WindowUnicodeKeyboard.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/WindowUnicodeKeyboard.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.shell.inter; +package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; import static java.awt.event.KeyEvent.VK_ALT; import java.nio.charset.Charset; diff --git a/src/main/java/com/sillelien/relproxy/jproxy/JProxy.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxy.java similarity index 96% rename from src/main/java/com/sillelien/relproxy/jproxy/JProxy.java rename to src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxy.java index 13d6c0c..a101b83 100644 --- a/src/main/java/com/sillelien/relproxy/jproxy/JProxy.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxy.java @@ -1,8 +1,8 @@ -package com.sillelien.relproxy.jproxy; +package com.sillelien.dollar.relproxy.jproxy; -import com.sillelien.relproxy.impl.jproxy.JProxyConfigImpl; -import com.sillelien.relproxy.impl.jproxy.JProxyDefaultImpl; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyConfigImpl; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyDefaultImpl; /** * Is the class to create Java proxy objects based on Java objects and keep track of source code changes reloading classes when detected. diff --git a/src/main/java/com/sillelien/relproxy/jproxy/JProxyCompilerListener.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyCompilerListener.java similarity index 87% rename from src/main/java/com/sillelien/relproxy/jproxy/JProxyCompilerListener.java rename to src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyCompilerListener.java index 4c581c9..218f16e 100644 --- a/src/main/java/com/sillelien/relproxy/jproxy/JProxyCompilerListener.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyCompilerListener.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.jproxy; +package com.sillelien.dollar.relproxy.jproxy; import java.io.File; diff --git a/src/main/java/com/sillelien/relproxy/jproxy/JProxyConfig.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyConfig.java similarity index 98% rename from src/main/java/com/sillelien/relproxy/jproxy/JProxyConfig.java rename to src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyConfig.java index 6cc88ca..1c8a235 100644 --- a/src/main/java/com/sillelien/relproxy/jproxy/JProxyConfig.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyConfig.java @@ -1,7 +1,7 @@ -package com.sillelien.relproxy.jproxy; +package com.sillelien.dollar.relproxy.jproxy; -import com.sillelien.relproxy.RelProxyOnReloadListener; +import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; /** * Interface implemented by the configuration object needed to initialize JProxy and {@link JProxyScriptEngineFactory}. diff --git a/src/main/java/com/sillelien/relproxy/jproxy/JProxyDiagnosticsListener.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyDiagnosticsListener.java similarity index 92% rename from src/main/java/com/sillelien/relproxy/jproxy/JProxyDiagnosticsListener.java rename to src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyDiagnosticsListener.java index 563ebf5..6de8b26 100644 --- a/src/main/java/com/sillelien/relproxy/jproxy/JProxyDiagnosticsListener.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyDiagnosticsListener.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.jproxy; +package com.sillelien.dollar.relproxy.jproxy; import javax.tools.DiagnosticCollector; import javax.tools.JavaFileObject; diff --git a/src/main/java/com/sillelien/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java similarity index 94% rename from src/main/java/com/sillelien/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java rename to src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java index 0fb92d4..def541e 100644 --- a/src/main/java/com/sillelien/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.jproxy; +package com.sillelien.dollar.relproxy.jproxy; import java.io.File; diff --git a/src/main/java/com/sillelien/relproxy/jproxy/JProxyScriptEngine.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyScriptEngine.java similarity index 98% rename from src/main/java/com/sillelien/relproxy/jproxy/JProxyScriptEngine.java rename to src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyScriptEngine.java index 3fd5806..ea1ae96 100644 --- a/src/main/java/com/sillelien/relproxy/jproxy/JProxyScriptEngine.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyScriptEngine.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.jproxy; +package com.sillelien.dollar.relproxy.jproxy; import javax.script.ScriptEngine; diff --git a/src/main/java/com/sillelien/relproxy/jproxy/JProxyScriptEngineFactory.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyScriptEngineFactory.java similarity index 79% rename from src/main/java/com/sillelien/relproxy/jproxy/JProxyScriptEngineFactory.java rename to src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyScriptEngineFactory.java index 036f218..175b320 100644 --- a/src/main/java/com/sillelien/relproxy/jproxy/JProxyScriptEngineFactory.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyScriptEngineFactory.java @@ -1,6 +1,6 @@ -package com.sillelien.relproxy.jproxy; +package com.sillelien.dollar.relproxy.jproxy; -import com.sillelien.relproxy.impl.jproxy.screngine.JProxyScriptEngineFactoryImpl; +import com.sillelien.dollar.relproxy.impl.jproxy.screngine.JProxyScriptEngineFactoryImpl; import javax.script.ScriptEngineFactory; /** diff --git a/src/main/java/com/sillelien/relproxy/jproxy/JProxyShell.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyShell.java similarity index 80% rename from src/main/java/com/sillelien/relproxy/jproxy/JProxyShell.java rename to src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyShell.java index d0e1024..0afa40a 100644 --- a/src/main/java/com/sillelien/relproxy/jproxy/JProxyShell.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyShell.java @@ -1,6 +1,6 @@ -package com.sillelien.relproxy.jproxy; +package com.sillelien.dollar.relproxy.jproxy; -import com.sillelien.relproxy.impl.jproxy.shell.JProxyShellImpl; +import com.sillelien.dollar.relproxy.impl.jproxy.shell.JProxyShellImpl; /** * Is the main class to execute shell scripting based on Java. diff --git a/src/main/java/com/sillelien/relproxy/jproxy/package.html b/src/main/java/com/sillelien/dollar/relproxy/jproxy/package.html similarity index 100% rename from src/main/java/com/sillelien/relproxy/jproxy/package.html rename to src/main/java/com/sillelien/dollar/relproxy/jproxy/package.html diff --git a/src/main/java/com/sillelien/relproxy/package.html b/src/main/java/com/sillelien/dollar/relproxy/package.html similarity index 100% rename from src/main/java/com/sillelien/relproxy/package.html rename to src/main/java/com/sillelien/dollar/relproxy/package.html From c37ff8e0226b87c5bd3ef544978e49e16b9684ad Mon Sep 17 00:00:00 2001 From: neilellis Date: Fri, 7 Jul 2017 16:21:48 +0100 Subject: [PATCH 022/135] Refactoring for Dollar project --- relproxy/pom.xml | 2 +- .../JProxyCodeSnippetCompleteClassTest.java | 2 +- .../jproxy/JProxyCodeSnippetTest.java | 2 +- .../JProxyJavaScriptEngineNoManagerTest.java | 8 ++--- .../jproxy/JProxyJavaScriptEngineTest.java | 8 ++--- .../JProxyJavaShellCompleteClassTest.java | 4 +-- .../JProxyJavaShellInteractiveTest.java | 2 +- .../JProxyJavaShellNormalClassTest.java | 4 +-- .../relproxy/jproxy/JProxyJavaShellTest.java | 4 +-- .../relproxy/jproxy/util/JProxyTestUtil.java | 4 +-- .../javashellex/JProxyShellExample.java | 2 +- .../example/groovyex/ItsNatGroovyServlet.java | 6 ++-- .../example/javaex/JProxyExampleServlet.java | 2 +- .../javaex/JProxyServletContextListener.java | 12 +++---- .../groovyex/groovy_servlet_init.groovy | 6 ++-- .../example/javaex/JProxyExampleDocument.java | 2 +- .../{ => dollar}/relproxy/RelProxy.java | 2 +- .../relproxy/RelProxyException.java | 2 +- .../relproxy/RelProxyOnReloadListener.java | 6 ++-- .../{ => dollar}/relproxy/gproxy/GProxy.java | 6 ++-- .../relproxy/gproxy/GProxyConfig.java | 4 +-- .../gproxy/GProxyGroovyScriptEngine.java | 2 +- .../{ => dollar}/relproxy/gproxy/package.html | 0 .../{ => dollar}/relproxy/impl/FileExt.java | 4 +-- .../impl/GenericProxyConfigBaseImpl.java | 4 +-- .../relproxy/impl/GenericProxyImpl.java | 6 ++-- .../impl/GenericProxyInvocationHandler.java | 4 +-- .../impl/GenericProxyVersionedObject.java | 4 +-- .../impl/gproxy/GProxyConfigImpl.java | 10 +++--- .../impl/gproxy/GProxyDefaultImpl.java | 6 ++-- .../relproxy/impl/gproxy/core/GProxyImpl.java | 10 +++--- .../gproxy/core/GProxyInvocationHandler.java | 4 +-- .../gproxy/core/GProxyVersionedObject.java | 6 ++-- .../impl/jproxy/JProxyConfigImpl.java | 18 +++++----- .../impl/jproxy/JProxyDefaultImpl.java | 6 ++-- .../relproxy/impl/jproxy/JProxyUtil.java | 4 +-- .../relproxy/impl/jproxy/core/JProxyImpl.java | 22 ++++++------ .../jproxy/core/JProxyInvocationHandler.java | 4 +-- .../jproxy/core/JProxyVersionedObject.java | 6 ++-- .../jproxy/core/clsmgr/FolderSourceList.java | 6 ++-- .../jproxy/core/clsmgr/JProxyClassLoader.java | 8 ++--- .../impl/jproxy/core/clsmgr/JProxyEngine.java | 22 ++++++------ ...JProxyEngineChangeDetectorAndCompiler.java | 34 +++++++++---------- .../jproxy/core/clsmgr/JavaSourcesSearch.java | 28 +++++++-------- .../core/clsmgr/cldesc/ClassDescriptor.java | 2 +- .../clsmgr/cldesc/ClassDescriptorInner.java | 2 +- .../cldesc/ClassDescriptorSourceFileJava.java | 8 ++--- .../ClassDescriptorSourceFileRegistry.java | 2 +- .../cldesc/ClassDescriptorSourceScript.java | 10 +++--- .../cldesc/ClassDescriptorSourceUnit.java | 10 +++--- .../comp/JProxyCompilationException.java | 6 ++-- .../clsmgr/comp/JProxyCompilerContext.java | 6 ++-- .../clsmgr/comp/JProxyCompilerInMemory.java | 26 +++++++------- .../clsmgr/comp/JavaFileManagerInMemory.java | 16 ++++----- ...leObjectInputClassFinderByClassLoader.java | 18 +++++----- .../comp/jfo/JProxyJavaFileObjectInput.java | 2 +- .../jfo/JavaFileObjectInputClassInFile.java | 2 +- .../JavaFileObjectInputClassInFileSystem.java | 2 +- .../jfo/JavaFileObjectInputClassInJar.java | 2 +- .../jfo/JavaFileObjectInputClassInMemory.java | 2 +- .../jfo/JavaFileObjectInputSourceBase.java | 4 +-- .../jfo/JavaFileObjectInputSourceInFile.java | 4 +-- .../JavaFileObjectInputSourceInMemory.java | 2 +- .../comp/jfo/JavaFileObjectOutputClass.java | 4 +-- .../clsmgr/srcunit/SourceFileJavaNormal.java | 4 +-- .../core/clsmgr/srcunit/SourceScriptRoot.java | 2 +- .../clsmgr/srcunit/SourceScriptRootFile.java | 8 ++--- .../srcunit/SourceScriptRootFileJavaExt.java | 8 ++--- .../srcunit/SourceScriptRootFileOtherExt.java | 8 ++--- .../srcunit/SourceScriptRootInMemory.java | 2 +- .../core/clsmgr/srcunit/SourceUnit.java | 6 ++-- .../impl/jproxy/screngine/BindingsImpl.java | 2 +- .../JProxyScriptEngineDelegateImpl.java | 20 +++++------ .../JProxyScriptEngineFactoryImpl.java | 6 ++-- .../screngine/JProxyScriptEngineImpl.java | 14 ++++---- .../jproxy/shell/JProxyShellClassLoader.java | 6 ++-- .../shell/JProxyShellCodeSnippetImpl.java | 14 ++++---- .../impl/jproxy/shell/JProxyShellImpl.java | 18 +++++----- .../shell/JProxyShellInteractiveImpl.java | 16 ++++----- .../shell/JProxyShellScriptFileImpl.java | 18 +++++----- .../impl/jproxy/shell/inter/Command.java | 2 +- .../shell/inter/CommandCodeChangerBase.java | 2 +- .../jproxy/shell/inter/CommandDelete.java | 2 +- .../impl/jproxy/shell/inter/CommandEdit.java | 2 +- .../impl/jproxy/shell/inter/CommandError.java | 2 +- .../jproxy/shell/inter/CommandInsert.java | 2 +- .../impl/jproxy/shell/inter/CommandLoad.java | 4 +-- .../impl/jproxy/shell/inter/CommandOther.java | 4 +-- .../impl/jproxy/shell/inter/CommandSave.java | 4 +-- .../shell/inter/JProxyShellProcessor.java | 14 ++++---- .../impl/jproxy/shell/inter/Keyboard.java | 2 +- .../inter/KeyboardNotUsingClipboard.java | 4 +-- .../shell/inter/KeyboardUsingClipboard.java | 4 +-- .../shell/inter/LinuxUnicodeKeyboard.java | 2 +- .../shell/inter/MacOSXUnicodeKeyboard.java | 2 +- .../shell/inter/WindowUnicodeKeyboard.java | 2 +- .../{ => dollar}/relproxy/jproxy/JProxy.java | 6 ++-- .../jproxy/JProxyCompilerListener.java | 2 +- .../relproxy/jproxy/JProxyConfig.java | 4 +-- .../jproxy/JProxyDiagnosticsListener.java | 2 +- ...JProxyInputSourceFileExcludedListener.java | 2 +- .../relproxy/jproxy/JProxyScriptEngine.java | 2 +- .../jproxy/JProxyScriptEngineFactory.java | 4 +-- .../relproxy/jproxy/JProxyShell.java | 4 +-- .../{ => dollar}/relproxy/jproxy/package.html | 0 .../{ => dollar}/relproxy/package.html | 0 106 files changed, 335 insertions(+), 335 deletions(-) rename src/main/java/com/sillelien/{ => dollar}/relproxy/RelProxy.java (88%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/RelProxyException.java (96%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/RelProxyOnReloadListener.java (77%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/gproxy/GProxy.java (94%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/gproxy/GProxyConfig.java (93%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/gproxy/GProxyGroovyScriptEngine.java (96%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/gproxy/package.html (100%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/FileExt.java (87%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/GenericProxyConfigBaseImpl.java (76%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/GenericProxyImpl.java (90%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/GenericProxyInvocationHandler.java (95%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/GenericProxyVersionedObject.java (98%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/gproxy/GProxyConfigImpl.java (70%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/gproxy/GProxyDefaultImpl.java (84%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/gproxy/core/GProxyImpl.java (65%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/gproxy/core/GProxyInvocationHandler.java (73%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/gproxy/core/GProxyVersionedObject.java (85%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/JProxyConfigImpl.java (86%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/JProxyDefaultImpl.java (91%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/JProxyUtil.java (97%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/JProxyImpl.java (74%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/JProxyInvocationHandler.java (73%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/JProxyVersionedObject.java (81%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java (94%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java (95%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java (92%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java (90%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java (89%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java (98%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java (87%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java (65%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java (97%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java (95%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java (91%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java (66%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java (92%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java (89%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java (89%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java (93%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JProxyJavaFileObjectInput.java (61%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java (93%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java (96%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java (91%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java (94%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java (92%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java (84%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java (90%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java (91%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java (81%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRoot.java (78%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java (80%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java (65%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java (78%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootInMemory.java (95%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java (79%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/screngine/BindingsImpl.java (73%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java (81%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java (96%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java (86%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java (85%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java (76%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/JProxyShellImpl.java (89%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java (79%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java (79%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/inter/Command.java (97%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java (96%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/inter/CommandDelete.java (96%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/inter/CommandEdit.java (97%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/inter/CommandError.java (83%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/inter/CommandInsert.java (96%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/inter/CommandLoad.java (93%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/inter/CommandOther.java (96%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/inter/CommandSave.java (91%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java (93%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/inter/Keyboard.java (89%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java (98%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java (93%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/inter/LinuxUnicodeKeyboard.java (96%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/inter/MacOSXUnicodeKeyboard.java (95%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/impl/jproxy/shell/inter/WindowUnicodeKeyboard.java (95%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/jproxy/JProxy.java (96%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/jproxy/JProxyCompilerListener.java (87%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/jproxy/JProxyConfig.java (98%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/jproxy/JProxyDiagnosticsListener.java (92%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java (94%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/jproxy/JProxyScriptEngine.java (98%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/jproxy/JProxyScriptEngineFactory.java (79%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/jproxy/JProxyShell.java (80%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/jproxy/package.html (100%) rename src/main/java/com/sillelien/{ => dollar}/relproxy/package.html (100%) diff --git a/relproxy/pom.xml b/relproxy/pom.xml index 9ca34a3..e39ffb1 100644 --- a/relproxy/pom.xml +++ b/relproxy/pom.xml @@ -147,7 +147,7 @@ RelProxy v${project.version} RelProxy v${project.version} - com.sillelien.relproxy.impl + com.sillelien.dollar.relproxy.impl diff --git a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyCodeSnippetCompleteClassTest.java b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyCodeSnippetCompleteClassTest.java index 4f40057..d74e03c 100644 --- a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyCodeSnippetCompleteClassTest.java +++ b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyCodeSnippetCompleteClassTest.java @@ -4,7 +4,7 @@ * and open the template in the editor. */ -package com.sillelien.relproxy.jproxy; +package com.sillelien.dollar.relproxy.jproxy; import org.junit.After; import org.junit.AfterClass; diff --git a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyCodeSnippetTest.java b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyCodeSnippetTest.java index 5435fff..353d50e 100644 --- a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyCodeSnippetTest.java +++ b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyCodeSnippetTest.java @@ -4,7 +4,7 @@ * and open the template in the editor. */ -package com.sillelien.relproxy.jproxy; +package com.sillelien.dollar.relproxy.jproxy; import org.junit.After; import org.junit.AfterClass; diff --git a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaScriptEngineNoManagerTest.java b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaScriptEngineNoManagerTest.java index dcddcfe..3f65f86 100644 --- a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaScriptEngineNoManagerTest.java +++ b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaScriptEngineNoManagerTest.java @@ -1,8 +1,8 @@ -package com.sillelien.relproxy.jproxy; +package com.sillelien.dollar.relproxy.jproxy; -import com.sillelien.relproxy.RelProxyOnReloadListener; -import static com.sillelien.relproxy.jproxy.util.JProxyTestUtil.RESOURCES_FOLDER; -import static com.sillelien.relproxy.jproxy.util.JProxyTestUtil.getProjectFolder; +import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; +import static com.sillelien.dollar.relproxy.jproxy.util.JProxyTestUtil.RESOURCES_FOLDER; +import static com.sillelien.dollar.relproxy.jproxy.util.JProxyTestUtil.getProjectFolder; import java.io.File; diff --git a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaScriptEngineTest.java b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaScriptEngineTest.java index 6ff0c01..5ae666f 100644 --- a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaScriptEngineTest.java +++ b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaScriptEngineTest.java @@ -1,8 +1,8 @@ -package com.sillelien.relproxy.jproxy; +package com.sillelien.dollar.relproxy.jproxy; -import com.sillelien.relproxy.RelProxyOnReloadListener; -import static com.sillelien.relproxy.jproxy.util.JProxyTestUtil.RESOURCES_FOLDER; -import static com.sillelien.relproxy.jproxy.util.JProxyTestUtil.getProjectFolder; +import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; +import static com.sillelien.dollar.relproxy.jproxy.util.JProxyTestUtil.RESOURCES_FOLDER; +import static com.sillelien.dollar.relproxy.jproxy.util.JProxyTestUtil.getProjectFolder; import java.io.File; diff --git a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellCompleteClassTest.java b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellCompleteClassTest.java index d0de94b..e4598d6 100644 --- a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellCompleteClassTest.java +++ b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellCompleteClassTest.java @@ -1,6 +1,6 @@ -package com.sillelien.relproxy.jproxy; +package com.sillelien.dollar.relproxy.jproxy; -import com.sillelien.relproxy.jproxy.util.JProxyTestUtil; +import com.sillelien.dollar.relproxy.jproxy.util.JProxyTestUtil; import java.io.File; import org.junit.After; import org.junit.AfterClass; diff --git a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellInteractiveTest.java b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellInteractiveTest.java index 5d18b4b..86c15a8 100644 --- a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellInteractiveTest.java +++ b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellInteractiveTest.java @@ -4,7 +4,7 @@ * and open the template in the editor. */ -package com.sillelien.relproxy.jproxy; +package com.sillelien.dollar.relproxy.jproxy; import org.junit.After; import org.junit.AfterClass; diff --git a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellNormalClassTest.java b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellNormalClassTest.java index 1673a26..8b7f8f2 100644 --- a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellNormalClassTest.java +++ b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellNormalClassTest.java @@ -1,6 +1,6 @@ -package com.sillelien.relproxy.jproxy; +package com.sillelien.dollar.relproxy.jproxy; -import com.sillelien.relproxy.jproxy.util.JProxyTestUtil; +import com.sillelien.dollar.relproxy.jproxy.util.JProxyTestUtil; import java.io.File; import org.junit.After; import org.junit.AfterClass; diff --git a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellTest.java b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellTest.java index 4461b7c..6a74548 100644 --- a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellTest.java +++ b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellTest.java @@ -1,6 +1,6 @@ -package com.sillelien.relproxy.jproxy; +package com.sillelien.dollar.relproxy.jproxy; -import com.sillelien.relproxy.jproxy.util.JProxyTestUtil; +import com.sillelien.dollar.relproxy.jproxy.util.JProxyTestUtil; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; diff --git a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/util/JProxyTestUtil.java b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/util/JProxyTestUtil.java index eed55b9..679f8c6 100644 --- a/relproxy/src/test/java/com/innowhere/relproxy/jproxy/util/JProxyTestUtil.java +++ b/relproxy/src/test/java/com/innowhere/relproxy/jproxy/util/JProxyTestUtil.java @@ -1,5 +1,5 @@ -package com.sillelien.relproxy.jproxy.util; +package com.sillelien.dollar.relproxy.jproxy.util; import java.io.File; import java.net.URL; @@ -15,7 +15,7 @@ public class JProxyTestUtil public static File getProjectFolder() { - String className = JProxyTestUtil.class.getName(); // com.sillelien.relproxy.jproxy.util.JProxyTestUtil + String className = JProxyTestUtil.class.getName(); // com.sillelien.dollar.relproxy.jproxy.util.JProxyTestUtil URL urlClass = JProxyTestUtil.class.getClassLoader().getResource(className.replace('.','/') + ".class"); File fileClass = new File(urlClass.getPath()); File projectFolder = fileClass.getParentFile(); diff --git a/relproxy/src/test/resources/example/javashellex/JProxyShellExample.java b/relproxy/src/test/resources/example/javashellex/JProxyShellExample.java index 92de1f4..b0b5dcf 100644 --- a/relproxy/src/test/resources/example/javashellex/JProxyShellExample.java +++ b/relproxy/src/test/resources/example/javashellex/JProxyShellExample.java @@ -1,7 +1,7 @@ package example.javashellex; import javax.script.ScriptEngine; -import com.sillelien.relproxy.jproxy.JProxyScriptEngine; +import com.sillelien.dollar.relproxy.jproxy.JProxyScriptEngine; /** * diff --git a/relproxy_test_itsnat/src/main/java/example/groovyex/ItsNatGroovyServlet.java b/relproxy_test_itsnat/src/main/java/example/groovyex/ItsNatGroovyServlet.java index c8216b0..5a46c71 100644 --- a/relproxy_test_itsnat/src/main/java/example/groovyex/ItsNatGroovyServlet.java +++ b/relproxy_test_itsnat/src/main/java/example/groovyex/ItsNatGroovyServlet.java @@ -82,9 +82,9 @@ public void init(ServletConfig config) throws ServletException binding.setVariable("context", getServletContext()); binding.setVariable("application", getServletContext()); - com.sillelien.relproxy.gproxy.GProxyGroovyScriptEngine.class.getName(); - com.sillelien.relproxy.gproxy.GProxyConfig.class.getName(); - com.sillelien.relproxy.gproxy.GProxy.class.getName(); + com.sillelien.dollar.relproxy.gproxy.GProxyGroovyScriptEngine.class.getName(); + com.sillelien.dollar.relproxy.gproxy.GProxyConfig.class.getName(); + com.sillelien.dollar.relproxy.gproxy.GProxy.class.getName(); execGroovyScript(initScript,binding); } diff --git a/relproxy_test_itsnat/src/main/java/example/javaex/JProxyExampleServlet.java b/relproxy_test_itsnat/src/main/java/example/javaex/JProxyExampleServlet.java index e845d30..86ac5f4 100644 --- a/relproxy_test_itsnat/src/main/java/example/javaex/JProxyExampleServlet.java +++ b/relproxy_test_itsnat/src/main/java/example/javaex/JProxyExampleServlet.java @@ -1,7 +1,7 @@ package example.javaex; -import com.sillelien.relproxy.jproxy.JProxy; +import com.sillelien.dollar.relproxy.jproxy.JProxy; import javax.servlet.ServletConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; diff --git a/relproxy_test_itsnat/src/main/java/example/javaex/JProxyServletContextListener.java b/relproxy_test_itsnat/src/main/java/example/javaex/JProxyServletContextListener.java index 58fadd2..5f6fa74 100644 --- a/relproxy_test_itsnat/src/main/java/example/javaex/JProxyServletContextListener.java +++ b/relproxy_test_itsnat/src/main/java/example/javaex/JProxyServletContextListener.java @@ -1,11 +1,11 @@ package example.javaex; -import com.sillelien.relproxy.RelProxyOnReloadListener; -import com.sillelien.relproxy.jproxy.JProxy; -import com.sillelien.relproxy.jproxy.JProxyCompilerListener; -import com.sillelien.relproxy.jproxy.JProxyConfig; -import com.sillelien.relproxy.jproxy.JProxyDiagnosticsListener; -import com.sillelien.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; +import com.sillelien.dollar.relproxy.jproxy.JProxy; +import com.sillelien.dollar.relproxy.jproxy.JProxyCompilerListener; +import com.sillelien.dollar.relproxy.jproxy.JProxyConfig; +import com.sillelien.dollar.relproxy.jproxy.JProxyDiagnosticsListener; +import com.sillelien.dollar.relproxy.jproxy.JProxyInputSourceFileExcludedListener; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; diff --git a/relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/code/example/groovyex/groovy_servlet_init.groovy b/relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/code/example/groovyex/groovy_servlet_init.groovy index cdf3128..de148d7 100644 --- a/relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/code/example/groovyex/groovy_servlet_init.groovy +++ b/relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/code/example/groovyex/groovy_servlet_init.groovy @@ -4,9 +4,9 @@ package example.groovyex import org.itsnat.core.event.ItsNatServletRequestListener; import groovy.util.GroovyScriptEngine; import java.lang.reflect.Method; -import com.sillelien.relproxy.RelProxyOnReloadListener; -import com.sillelien.relproxy.gproxy.GProxy; -import com.sillelien.relproxy.gproxy.GProxyGroovyScriptEngine +import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; +import com.sillelien.dollar.relproxy.gproxy.GProxy; +import com.sillelien.dollar.relproxy.gproxy.GProxyGroovyScriptEngine GroovyScriptEngine groovyEngine = servlet.getGroovyScriptEngine(); diff --git a/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleDocument.java b/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleDocument.java index 221a465..f09bde7 100644 --- a/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleDocument.java +++ b/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleDocument.java @@ -1,6 +1,6 @@ package example.javaex; -import com.sillelien.relproxy.jproxy.JProxy; +import com.sillelien.dollar.relproxy.jproxy.JProxy; import example.javaex.hotreload.JProxyExampleAux2; import example.javaex.nothotreload.JProxyExampleAuxIgnored2; import example.javaex.nothotreload.JProxyExampleAuxIgnored3; diff --git a/src/main/java/com/sillelien/relproxy/RelProxy.java b/src/main/java/com/sillelien/dollar/relproxy/RelProxy.java similarity index 88% rename from src/main/java/com/sillelien/relproxy/RelProxy.java rename to src/main/java/com/sillelien/dollar/relproxy/RelProxy.java index c63cea3..8b2ee78 100644 --- a/src/main/java/com/sillelien/relproxy/RelProxy.java +++ b/src/main/java/com/sillelien/dollar/relproxy/RelProxy.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy; +package com.sillelien.dollar.relproxy; /** * Is the root of RelProxy diff --git a/src/main/java/com/sillelien/relproxy/RelProxyException.java b/src/main/java/com/sillelien/dollar/relproxy/RelProxyException.java similarity index 96% rename from src/main/java/com/sillelien/relproxy/RelProxyException.java rename to src/main/java/com/sillelien/dollar/relproxy/RelProxyException.java index 8b16207..1d0e5d4 100644 --- a/src/main/java/com/sillelien/relproxy/RelProxyException.java +++ b/src/main/java/com/sillelien/dollar/relproxy/RelProxyException.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy; +package com.sillelien.dollar.relproxy; /** * Internal checked exceptions thrown by RelProxy and library specific errors are wrapped into this exception class. diff --git a/src/main/java/com/sillelien/relproxy/RelProxyOnReloadListener.java b/src/main/java/com/sillelien/dollar/relproxy/RelProxyOnReloadListener.java similarity index 77% rename from src/main/java/com/sillelien/relproxy/RelProxyOnReloadListener.java rename to src/main/java/com/sillelien/dollar/relproxy/RelProxyOnReloadListener.java index acad475..1750bf3 100644 --- a/src/main/java/com/sillelien/relproxy/RelProxyOnReloadListener.java +++ b/src/main/java/com/sillelien/dollar/relproxy/RelProxyOnReloadListener.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy; +package com.sillelien.dollar.relproxy; import java.lang.reflect.Method; @@ -10,8 +10,8 @@ *

* * - * @see com.sillelien.relproxy.jproxy.JProxyConfig#setRelProxyOnReloadListener(com.sillelien.relproxy.RelProxyOnReloadListener) - * @see com.sillelien.relproxy.gproxy.GProxyConfig#setRelProxyOnReloadListener(com.sillelien.relproxy.RelProxyOnReloadListener) + * @see com.sillelien.dollar.relproxy.jproxy.JProxyConfig#setRelProxyOnReloadListener(com.sillelien.dollar.relproxy.RelProxyOnReloadListener) + * @see com.sillelien.dollar.relproxy.gproxy.GProxyConfig#setRelProxyOnReloadListener(com.sillelien.dollar.relproxy.RelProxyOnReloadListener) * @author Jose Maria Arranz Santamaria */ public interface RelProxyOnReloadListener diff --git a/src/main/java/com/sillelien/relproxy/gproxy/GProxy.java b/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxy.java similarity index 94% rename from src/main/java/com/sillelien/relproxy/gproxy/GProxy.java rename to src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxy.java index 5c74686..6fb5120 100644 --- a/src/main/java/com/sillelien/relproxy/gproxy/GProxy.java +++ b/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxy.java @@ -1,8 +1,8 @@ -package com.sillelien.relproxy.gproxy; +package com.sillelien.dollar.relproxy.gproxy; -import com.sillelien.relproxy.impl.gproxy.GProxyConfigImpl; -import com.sillelien.relproxy.impl.gproxy.GProxyDefaultImpl; +import com.sillelien.dollar.relproxy.impl.gproxy.GProxyConfigImpl; +import com.sillelien.dollar.relproxy.impl.gproxy.GProxyDefaultImpl; /** * Is the class to create Java proxy objects based on Groovy objects and keep track of Groovy source code changes reloading Groovy classes when detected. diff --git a/src/main/java/com/sillelien/relproxy/gproxy/GProxyConfig.java b/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyConfig.java similarity index 93% rename from src/main/java/com/sillelien/relproxy/gproxy/GProxyConfig.java rename to src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyConfig.java index 14cb90c..ea57bcd 100644 --- a/src/main/java/com/sillelien/relproxy/gproxy/GProxyConfig.java +++ b/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyConfig.java @@ -1,7 +1,7 @@ -package com.sillelien.relproxy.gproxy; +package com.sillelien.dollar.relproxy.gproxy; -import com.sillelien.relproxy.RelProxyOnReloadListener; +import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; /** * Interface implemented by the configuration object needed to initialize GProxy. diff --git a/src/main/java/com/sillelien/relproxy/gproxy/GProxyGroovyScriptEngine.java b/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyGroovyScriptEngine.java similarity index 96% rename from src/main/java/com/sillelien/relproxy/gproxy/GProxyGroovyScriptEngine.java rename to src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyGroovyScriptEngine.java index 4025e04..53957a5 100644 --- a/src/main/java/com/sillelien/relproxy/gproxy/GProxyGroovyScriptEngine.java +++ b/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyGroovyScriptEngine.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.gproxy; +package com.sillelien.dollar.relproxy.gproxy; /** * Interface to implement the object implementing the GroovyScriptEngine wrapper used to reload Groovy classes. diff --git a/src/main/java/com/sillelien/relproxy/gproxy/package.html b/src/main/java/com/sillelien/dollar/relproxy/gproxy/package.html similarity index 100% rename from src/main/java/com/sillelien/relproxy/gproxy/package.html rename to src/main/java/com/sillelien/dollar/relproxy/gproxy/package.html diff --git a/src/main/java/com/sillelien/relproxy/impl/FileExt.java b/src/main/java/com/sillelien/dollar/relproxy/impl/FileExt.java similarity index 87% rename from src/main/java/com/sillelien/relproxy/impl/FileExt.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/FileExt.java index d9d3d3c..e3ab333 100644 --- a/src/main/java/com/sillelien/relproxy/impl/FileExt.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/FileExt.java @@ -1,6 +1,6 @@ -package com.sillelien.relproxy.impl; +package com.sillelien.dollar.relproxy.impl; -import com.sillelien.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.RelProxyException; import java.io.File; import java.io.IOException; diff --git a/src/main/java/com/sillelien/relproxy/impl/GenericProxyConfigBaseImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyConfigBaseImpl.java similarity index 76% rename from src/main/java/com/sillelien/relproxy/impl/GenericProxyConfigBaseImpl.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyConfigBaseImpl.java index f46404e..2dd406d 100644 --- a/src/main/java/com/sillelien/relproxy/impl/GenericProxyConfigBaseImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyConfigBaseImpl.java @@ -1,6 +1,6 @@ -package com.sillelien.relproxy.impl; +package com.sillelien.dollar.relproxy.impl; -import com.sillelien.relproxy.RelProxyOnReloadListener; +import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/GenericProxyImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyImpl.java similarity index 90% rename from src/main/java/com/sillelien/relproxy/impl/GenericProxyImpl.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyImpl.java index ca7a397..53a8b3c 100644 --- a/src/main/java/com/sillelien/relproxy/impl/GenericProxyImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyImpl.java @@ -1,7 +1,7 @@ -package com.sillelien.relproxy.impl; +package com.sillelien.dollar.relproxy.impl; -import com.sillelien.relproxy.RelProxyException; -import com.sillelien.relproxy.RelProxyOnReloadListener; +import com.sillelien.dollar.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; diff --git a/src/main/java/com/sillelien/relproxy/impl/GenericProxyInvocationHandler.java b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyInvocationHandler.java similarity index 95% rename from src/main/java/com/sillelien/relproxy/impl/GenericProxyInvocationHandler.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyInvocationHandler.java index ad6d6f9..76bf545 100644 --- a/src/main/java/com/sillelien/relproxy/impl/GenericProxyInvocationHandler.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyInvocationHandler.java @@ -1,6 +1,6 @@ -package com.sillelien.relproxy.impl; +package com.sillelien.dollar.relproxy.impl; -import com.sillelien.relproxy.RelProxyOnReloadListener; +import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; diff --git a/src/main/java/com/sillelien/relproxy/impl/GenericProxyVersionedObject.java b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyVersionedObject.java similarity index 98% rename from src/main/java/com/sillelien/relproxy/impl/GenericProxyVersionedObject.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyVersionedObject.java index c23db15..b941169 100644 --- a/src/main/java/com/sillelien/relproxy/impl/GenericProxyVersionedObject.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyVersionedObject.java @@ -1,6 +1,6 @@ -package com.sillelien.relproxy.impl; +package com.sillelien.dollar.relproxy.impl; -import com.sillelien.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.RelProxyException; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; diff --git a/src/main/java/com/sillelien/relproxy/impl/gproxy/GProxyConfigImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyConfigImpl.java similarity index 70% rename from src/main/java/com/sillelien/relproxy/impl/gproxy/GProxyConfigImpl.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyConfigImpl.java index d57bc86..d549078 100644 --- a/src/main/java/com/sillelien/relproxy/impl/gproxy/GProxyConfigImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyConfigImpl.java @@ -1,9 +1,9 @@ -package com.sillelien.relproxy.impl.gproxy; +package com.sillelien.dollar.relproxy.impl.gproxy; -import com.sillelien.relproxy.RelProxyOnReloadListener; -import com.sillelien.relproxy.gproxy.GProxyConfig; -import com.sillelien.relproxy.gproxy.GProxyGroovyScriptEngine; -import com.sillelien.relproxy.impl.GenericProxyConfigBaseImpl; +import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; +import com.sillelien.dollar.relproxy.gproxy.GProxyConfig; +import com.sillelien.dollar.relproxy.gproxy.GProxyGroovyScriptEngine; +import com.sillelien.dollar.relproxy.impl.GenericProxyConfigBaseImpl; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/gproxy/GProxyDefaultImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyDefaultImpl.java similarity index 84% rename from src/main/java/com/sillelien/relproxy/impl/gproxy/GProxyDefaultImpl.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyDefaultImpl.java index 6c8fe50..03735ef 100644 --- a/src/main/java/com/sillelien/relproxy/impl/gproxy/GProxyDefaultImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyDefaultImpl.java @@ -1,7 +1,7 @@ -package com.sillelien.relproxy.impl.gproxy; +package com.sillelien.dollar.relproxy.impl.gproxy; -import com.sillelien.relproxy.gproxy.GProxyConfig; -import com.sillelien.relproxy.impl.gproxy.core.GProxyImpl; +import com.sillelien.dollar.relproxy.gproxy.GProxyConfig; +import com.sillelien.dollar.relproxy.impl.gproxy.core.GProxyImpl; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/gproxy/core/GProxyImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyImpl.java similarity index 65% rename from src/main/java/com/sillelien/relproxy/impl/gproxy/core/GProxyImpl.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyImpl.java index ca00943..40ab707 100644 --- a/src/main/java/com/sillelien/relproxy/impl/gproxy/core/GProxyImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyImpl.java @@ -1,9 +1,9 @@ -package com.sillelien.relproxy.impl.gproxy.core; +package com.sillelien.dollar.relproxy.impl.gproxy.core; -import com.sillelien.relproxy.impl.gproxy.GProxyConfigImpl; -import com.sillelien.relproxy.gproxy.GProxyGroovyScriptEngine; -import com.sillelien.relproxy.impl.GenericProxyImpl; -import com.sillelien.relproxy.impl.GenericProxyInvocationHandler; +import com.sillelien.dollar.relproxy.impl.gproxy.GProxyConfigImpl; +import com.sillelien.dollar.relproxy.gproxy.GProxyGroovyScriptEngine; +import com.sillelien.dollar.relproxy.impl.GenericProxyImpl; +import com.sillelien.dollar.relproxy.impl.GenericProxyInvocationHandler; /** diff --git a/src/main/java/com/sillelien/relproxy/impl/gproxy/core/GProxyInvocationHandler.java b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyInvocationHandler.java similarity index 73% rename from src/main/java/com/sillelien/relproxy/impl/gproxy/core/GProxyInvocationHandler.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyInvocationHandler.java index f362a27..0bff93a 100644 --- a/src/main/java/com/sillelien/relproxy/impl/gproxy/core/GProxyInvocationHandler.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyInvocationHandler.java @@ -1,6 +1,6 @@ -package com.sillelien.relproxy.impl.gproxy.core; +package com.sillelien.dollar.relproxy.impl.gproxy.core; -import com.sillelien.relproxy.impl.GenericProxyInvocationHandler; +import com.sillelien.dollar.relproxy.impl.GenericProxyInvocationHandler; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/gproxy/core/GProxyVersionedObject.java b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyVersionedObject.java similarity index 85% rename from src/main/java/com/sillelien/relproxy/impl/gproxy/core/GProxyVersionedObject.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyVersionedObject.java index f57bf53..c4edf28 100644 --- a/src/main/java/com/sillelien/relproxy/impl/gproxy/core/GProxyVersionedObject.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyVersionedObject.java @@ -1,7 +1,7 @@ -package com.sillelien.relproxy.impl.gproxy.core; +package com.sillelien.dollar.relproxy.impl.gproxy.core; -import com.sillelien.relproxy.gproxy.GProxyGroovyScriptEngine; -import com.sillelien.relproxy.impl.GenericProxyVersionedObject; +import com.sillelien.dollar.relproxy.gproxy.GProxyGroovyScriptEngine; +import com.sillelien.dollar.relproxy.impl.GenericProxyVersionedObject; import java.lang.reflect.Field; /** diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/JProxyConfigImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyConfigImpl.java similarity index 86% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/JProxyConfigImpl.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyConfigImpl.java index cc095a2..bd1fe4c 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/JProxyConfigImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyConfigImpl.java @@ -1,13 +1,13 @@ -package com.sillelien.relproxy.impl.jproxy; +package com.sillelien.dollar.relproxy.impl.jproxy; -import com.sillelien.relproxy.RelProxyException; -import com.sillelien.relproxy.RelProxyOnReloadListener; -import com.sillelien.relproxy.impl.GenericProxyConfigBaseImpl; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; -import com.sillelien.relproxy.jproxy.JProxyCompilerListener; -import com.sillelien.relproxy.jproxy.JProxyConfig; -import com.sillelien.relproxy.jproxy.JProxyDiagnosticsListener; -import com.sillelien.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import com.sillelien.dollar.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; +import com.sillelien.dollar.relproxy.impl.GenericProxyConfigBaseImpl; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import com.sillelien.dollar.relproxy.jproxy.JProxyCompilerListener; +import com.sillelien.dollar.relproxy.jproxy.JProxyConfig; +import com.sillelien.dollar.relproxy.jproxy.JProxyDiagnosticsListener; +import com.sillelien.dollar.relproxy.jproxy.JProxyInputSourceFileExcludedListener; import java.io.File; /** diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/JProxyDefaultImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyDefaultImpl.java similarity index 91% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/JProxyDefaultImpl.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyDefaultImpl.java index 92ab460..a4ed4f5 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/JProxyDefaultImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyDefaultImpl.java @@ -1,7 +1,7 @@ -package com.sillelien.relproxy.impl.jproxy; +package com.sillelien.dollar.relproxy.impl.jproxy; -import com.sillelien.relproxy.impl.jproxy.core.JProxyImpl; -import com.sillelien.relproxy.jproxy.JProxyConfig; +import com.sillelien.dollar.relproxy.impl.jproxy.core.JProxyImpl; +import com.sillelien.dollar.relproxy.jproxy.JProxyConfig; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/JProxyUtil.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyUtil.java similarity index 97% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/JProxyUtil.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyUtil.java index b63a961..86b3716 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/JProxyUtil.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyUtil.java @@ -1,6 +1,6 @@ -package com.sillelien.relproxy.impl.jproxy; +package com.sillelien.dollar.relproxy.impl.jproxy; -import com.sillelien.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.RelProxyException; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.File; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/JProxyImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyImpl.java similarity index 74% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/JProxyImpl.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyImpl.java index 1690794..93c9fb9 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/JProxyImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyImpl.java @@ -1,15 +1,15 @@ -package com.sillelien.relproxy.impl.jproxy.core; +package com.sillelien.dollar.relproxy.impl.jproxy.core; -import com.sillelien.relproxy.impl.GenericProxyImpl; -import com.sillelien.relproxy.impl.GenericProxyInvocationHandler; -import com.sillelien.relproxy.impl.jproxy.JProxyConfigImpl; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; -import com.sillelien.relproxy.jproxy.JProxyCompilerListener; -import com.sillelien.relproxy.jproxy.JProxyDiagnosticsListener; -import com.sillelien.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import com.sillelien.dollar.relproxy.impl.GenericProxyImpl; +import com.sillelien.dollar.relproxy.impl.GenericProxyInvocationHandler; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyConfigImpl; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.sillelien.dollar.relproxy.jproxy.JProxyCompilerListener; +import com.sillelien.dollar.relproxy.jproxy.JProxyDiagnosticsListener; +import com.sillelien.dollar.relproxy.jproxy.JProxyInputSourceFileExcludedListener; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/JProxyInvocationHandler.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyInvocationHandler.java similarity index 73% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/JProxyInvocationHandler.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyInvocationHandler.java index ef748f4..2cb390e 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/JProxyInvocationHandler.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyInvocationHandler.java @@ -1,7 +1,7 @@ -package com.sillelien.relproxy.impl.jproxy.core; +package com.sillelien.dollar.relproxy.impl.jproxy.core; -import com.sillelien.relproxy.impl.GenericProxyInvocationHandler; +import com.sillelien.dollar.relproxy.impl.GenericProxyInvocationHandler; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/JProxyVersionedObject.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyVersionedObject.java similarity index 81% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/JProxyVersionedObject.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyVersionedObject.java index bb20998..d3b07ca 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/JProxyVersionedObject.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyVersionedObject.java @@ -1,7 +1,7 @@ -package com.sillelien.relproxy.impl.jproxy.core; +package com.sillelien.dollar.relproxy.impl.jproxy.core; -import com.sillelien.relproxy.impl.GenericProxyVersionedObject; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; +import com.sillelien.dollar.relproxy.impl.GenericProxyVersionedObject; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; import java.lang.reflect.Field; /** diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java similarity index 94% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java index 31c7dd7..d9b48e7 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java @@ -1,7 +1,7 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr; -import com.sillelien.relproxy.RelProxyException; -import com.sillelien.relproxy.impl.FileExt; +import com.sillelien.dollar.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.impl.FileExt; import java.io.File; /** diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java similarity index 95% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java index b27dfb4..328b1b9 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java @@ -1,8 +1,8 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; -import com.sillelien.relproxy.impl.jproxy.JProxyUtil; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; import java.net.URL; /** diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java similarity index 92% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java index 61fef71..8fc57ad 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java @@ -1,15 +1,15 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorInner; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.sillelien.relproxy.impl.jproxy.core.JProxyImpl; -import com.sillelien.relproxy.jproxy.JProxyCompilerListener; -import com.sillelien.relproxy.jproxy.JProxyDiagnosticsListener; -import com.sillelien.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorInner; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.sillelien.dollar.relproxy.impl.jproxy.core.JProxyImpl; +import com.sillelien.dollar.relproxy.jproxy.JProxyCompilerListener; +import com.sillelien.dollar.relproxy.jproxy.JProxyDiagnosticsListener; +import com.sillelien.dollar.relproxy.jproxy.JProxyInputSourceFileExcludedListener; import java.util.LinkedList; import java.util.Timer; import java.util.TimerTask; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java similarity index 90% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java index 1cd6537..4460e33 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java @@ -1,21 +1,21 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootInMemory; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceUnit; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootFile; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorInner; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.sillelien.relproxy.impl.jproxy.JProxyUtil; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.JProxyCompilerContext; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.JProxyCompilerInMemory; -import com.sillelien.relproxy.jproxy.JProxyCompilerListener; -import com.sillelien.relproxy.jproxy.JProxyDiagnosticsListener; -import com.sillelien.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootInMemory; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceUnit; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootFile; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorInner; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.JProxyCompilerContext; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.JProxyCompilerInMemory; +import com.sillelien.dollar.relproxy.jproxy.JProxyCompilerListener; +import com.sillelien.dollar.relproxy.jproxy.JProxyDiagnosticsListener; +import com.sillelien.dollar.relproxy.jproxy.JProxyInputSourceFileExcludedListener; import java.io.File; import java.util.ArrayList; import java.util.LinkedList; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java similarity index 89% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java index d680220..536113b 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java @@ -1,18 +1,18 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootFileJavaExt; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceUnit; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileJava; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.sillelien.relproxy.RelProxyException; -import com.sillelien.relproxy.impl.FileExt; -import com.sillelien.relproxy.impl.jproxy.JProxyUtil; -import com.sillelien.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootFileJavaExt; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceUnit; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileJava; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.sillelien.dollar.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.impl.FileExt; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; +import com.sillelien.dollar.relproxy.jproxy.JProxyInputSourceFileExcludedListener; import java.io.File; import java.net.URL; import java.util.LinkedList; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java similarity index 98% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java index 659a846..99bc7ac 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc; import java.io.File; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java similarity index 87% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java index 30d5f23..7190866 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java similarity index 65% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java index 3fe12c8..1300fea 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java @@ -1,8 +1,8 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc; -import com.sillelien.relproxy.impl.FileExt; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; +import com.sillelien.dollar.relproxy.impl.FileExt; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java similarity index 97% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java index 6728995..bf0b64b 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc; import java.util.Collection; import java.util.HashMap; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java similarity index 95% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java index 2a69b59..0dda05d 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java @@ -1,9 +1,9 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc; -import com.sillelien.relproxy.RelProxyException; -import com.sillelien.relproxy.impl.jproxy.core.JProxyImpl; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.sillelien.dollar.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.impl.jproxy.core.JProxyImpl; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.LinkedList; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java similarity index 91% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java index 931378f..4896ee1 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java @@ -1,9 +1,9 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceUnit; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceUnit; import java.util.LinkedList; /** diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java similarity index 66% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java index 90c2d23..dd43381 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java @@ -1,8 +1,8 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp; -import com.sillelien.relproxy.RelProxyException; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; +import com.sillelien.dollar.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java similarity index 92% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java index 9b9d9b3..2ad1bd7 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java @@ -1,7 +1,7 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp; -import com.sillelien.relproxy.RelProxyException; -import com.sillelien.relproxy.jproxy.JProxyDiagnosticsListener; +import com.sillelien.dollar.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.jproxy.JProxyDiagnosticsListener; import java.io.IOException; import java.util.List; import javax.tools.Diagnostic; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java similarity index 89% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java index 90a3946..c8b20c8 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java @@ -1,17 +1,17 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputSourceInMemory; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectOutputClass; -import com.sillelien.relproxy.RelProxyException; -import com.sillelien.relproxy.impl.FileExt; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorInner; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileJava; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.JProxyEngineChangeDetectorAndCompiler; -import com.sillelien.relproxy.jproxy.JProxyDiagnosticsListener; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputSourceInMemory; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectOutputClass; +import com.sillelien.dollar.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.impl.FileExt; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorInner; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileJava; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.JProxyEngineChangeDetectorAndCompiler; +import com.sillelien.dollar.relproxy.jproxy.JProxyDiagnosticsListener; import java.io.File; import java.util.ArrayList; import java.util.LinkedList; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java similarity index 89% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java index 46c6e43..7de7a8e 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java @@ -1,12 +1,12 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JProxyJavaFileObjectInput; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInMemory; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInFileSystem; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectOutputClass; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JProxyJavaFileObjectInput; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInMemory; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInFileSystem; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectOutputClass; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; import java.io.IOException; import java.util.Collection; import java.util.Collections; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java similarity index 93% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java index e88c91e..62f950f 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java @@ -1,12 +1,12 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp; - -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInFile; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInFileSystem; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInJar; -import com.sillelien.relproxy.RelProxyException; -import com.sillelien.relproxy.impl.FileExt; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp; + +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInFile; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInFileSystem; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo.JavaFileObjectInputClassInJar; +import com.sillelien.dollar.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.impl.FileExt; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JProxyJavaFileObjectInput.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JProxyJavaFileObjectInput.java similarity index 61% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JProxyJavaFileObjectInput.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JProxyJavaFileObjectInput.java index 570933f..8faf5a6 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JProxyJavaFileObjectInput.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JProxyJavaFileObjectInput.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java similarity index 93% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java index 5f3a3e3..eeb1b23 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo; import java.io.BufferedInputStream; import java.io.File; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java similarity index 96% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java index 87f2230..62bf61e 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo; import java.io.IOException; import java.io.OutputStream; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java similarity index 91% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java index 2e62f66..4dee882 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo; import java.io.IOException; import java.io.InputStream; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java similarity index 94% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java index 5694fab..d4d764c 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo; import java.io.ByteArrayInputStream; import java.io.IOException; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java similarity index 92% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java index 8a9569c..cf40ca1 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java @@ -1,6 +1,6 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo; -import com.sillelien.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.RelProxyException; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java similarity index 84% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java index ebddf24..8683f69 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java @@ -1,6 +1,6 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo; -import com.sillelien.relproxy.impl.jproxy.JProxyUtil; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; import java.io.File; /** diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java similarity index 90% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java index f01bb30..dca46cd 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo; /** * http://www.javablogging.com/dynamic-in-memory-compilation/ diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java similarity index 91% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java index aa62e0b..6fa68d0 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java @@ -1,6 +1,6 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.jfo; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo; -import com.sillelien.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.RelProxyException; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java similarity index 81% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java index 91e72ff..b4432cf 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java @@ -1,6 +1,6 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit; -import com.sillelien.relproxy.impl.FileExt; +import com.sillelien.dollar.relproxy.impl.FileExt; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRoot.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRoot.java similarity index 78% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRoot.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRoot.java index a8ab184..5d81119 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRoot.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRoot.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java similarity index 80% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java index 153aef1..60b46bb 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java @@ -1,8 +1,8 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit; -import com.sillelien.relproxy.impl.FileExt; -import com.sillelien.relproxy.impl.jproxy.JProxyUtil; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import com.sillelien.dollar.relproxy.impl.FileExt; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java similarity index 65% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java index cf0450d..4aeb091 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java @@ -1,8 +1,8 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit; -import com.sillelien.relproxy.impl.FileExt; -import com.sillelien.relproxy.impl.jproxy.JProxyUtil; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import com.sillelien.dollar.relproxy.impl.FileExt; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java similarity index 78% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java index bcc19ba..154b757 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java @@ -1,8 +1,8 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit; -import com.sillelien.relproxy.impl.FileExt; -import com.sillelien.relproxy.impl.jproxy.JProxyUtil; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import com.sillelien.dollar.relproxy.impl.FileExt; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootInMemory.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootInMemory.java similarity index 95% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootInMemory.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootInMemory.java index e4e401c..9ad61e0 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootInMemory.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootInMemory.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java similarity index 79% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java index cf216a1..f0b55e2 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java @@ -1,7 +1,7 @@ -package com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit; +package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit; -import com.sillelien.relproxy.impl.FileExt; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import com.sillelien.dollar.relproxy.impl.FileExt; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/screngine/BindingsImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/BindingsImpl.java similarity index 73% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/screngine/BindingsImpl.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/BindingsImpl.java index 8c646af..e960b2a 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/screngine/BindingsImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/BindingsImpl.java @@ -1,5 +1,5 @@ -package com.sillelien.relproxy.impl.jproxy.screngine; +package com.sillelien.dollar.relproxy.impl.jproxy.screngine; import java.util.HashMap; import javax.script.Bindings; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java similarity index 81% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java index a197c2f..461c2d5 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java @@ -1,14 +1,14 @@ -package com.sillelien.relproxy.impl.jproxy.screngine; +package com.sillelien.dollar.relproxy.impl.jproxy.screngine; -import com.sillelien.relproxy.RelProxyException; -import com.sillelien.relproxy.impl.jproxy.JProxyConfigImpl; -import com.sillelien.relproxy.impl.jproxy.core.JProxyImpl; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootInMemory; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.JProxyCompilationException; -import com.sillelien.relproxy.impl.jproxy.shell.JProxyShellClassLoader; +import com.sillelien.dollar.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyConfigImpl; +import com.sillelien.dollar.relproxy.impl.jproxy.core.JProxyImpl; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootInMemory; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.JProxyCompilationException; +import com.sillelien.dollar.relproxy.impl.jproxy.shell.JProxyShellClassLoader; import java.io.File; import javax.script.ScriptContext; import javax.script.ScriptException; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java similarity index 96% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java index 725bbb3..aab0f23 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java @@ -1,7 +1,7 @@ -package com.sillelien.relproxy.impl.jproxy.screngine; +package com.sillelien.dollar.relproxy.impl.jproxy.screngine; -import com.sillelien.relproxy.RelProxy; -import com.sillelien.relproxy.jproxy.JProxyScriptEngineFactory; +import com.sillelien.dollar.relproxy.RelProxy; +import com.sillelien.dollar.relproxy.jproxy.JProxyScriptEngineFactory; import java.util.ArrayList; import java.util.Collections; import java.util.List; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java similarity index 86% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java index 4431df8..eab9862 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java @@ -1,11 +1,11 @@ -package com.sillelien.relproxy.impl.jproxy.screngine; +package com.sillelien.dollar.relproxy.impl.jproxy.screngine; -import com.sillelien.relproxy.RelProxyException; -import com.sillelien.relproxy.impl.GenericProxyImpl; -import com.sillelien.relproxy.impl.jproxy.JProxyConfigImpl; -import com.sillelien.relproxy.impl.jproxy.JProxyUtil; -import com.sillelien.relproxy.jproxy.JProxyConfig; -import com.sillelien.relproxy.jproxy.JProxyScriptEngine; +import com.sillelien.dollar.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.impl.GenericProxyImpl; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyConfigImpl; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; +import com.sillelien.dollar.relproxy.jproxy.JProxyConfig; +import com.sillelien.dollar.relproxy.jproxy.JProxyScriptEngine; import java.io.Reader; import javax.script.AbstractScriptEngine; import javax.script.Bindings; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java similarity index 85% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java index a6d7cc3..1941300 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java @@ -1,7 +1,7 @@ -package com.sillelien.relproxy.impl.jproxy.shell; +package com.sillelien.dollar.relproxy.impl.jproxy.shell; -import com.sillelien.relproxy.RelProxyException; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; +import com.sillelien.dollar.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; import java.io.File; import java.net.MalformedURLException; import java.net.URL; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java similarity index 76% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java index c59a4b9..220909a 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java @@ -1,11 +1,11 @@ -package com.sillelien.relproxy.impl.jproxy.shell; +package com.sillelien.dollar.relproxy.impl.jproxy.shell; -import com.sillelien.relproxy.RelProxyException; -import com.sillelien.relproxy.impl.jproxy.JProxyConfigImpl; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootInMemory; +import com.sillelien.dollar.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyConfigImpl; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootInMemory; import java.util.LinkedList; /** diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/JProxyShellImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellImpl.java similarity index 89% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/JProxyShellImpl.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellImpl.java index d89c1f5..adba4a7 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/JProxyShellImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellImpl.java @@ -1,12 +1,12 @@ -package com.sillelien.relproxy.impl.jproxy.shell; +package com.sillelien.dollar.relproxy.impl.jproxy.shell; -import com.sillelien.relproxy.RelProxyException; -import com.sillelien.relproxy.RelProxyOnReloadListener; -import com.sillelien.relproxy.impl.jproxy.JProxyConfigImpl; -import com.sillelien.relproxy.impl.jproxy.core.JProxyImpl; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.sillelien.dollar.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyConfigImpl; +import com.sillelien.dollar.relproxy.impl.jproxy.core.JProxyImpl; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; import java.lang.reflect.Method; import java.util.LinkedList; @@ -22,7 +22,7 @@ public static void main(String[] args) { if (args[0].isEmpty()) { - // Esto tiene explicación: cuando invocamos jproxysh sin parámetros (o espacios da igual) invocamos dentro jproxysh con com.sillelien.relproxy.jproxy.JProxyShell "$@" + // Esto tiene explicación: cuando invocamos jproxysh sin parámetros (o espacios da igual) invocamos dentro jproxysh con com.sillelien.dollar.relproxy.jproxy.JProxyShell "$@" // el parámetro "$@" se convierte en "" que es un parámetro de verdad que recibimos pero de cadena vacía, lo cual nos viene GENIAL para distinguir el caso shell interactive SINGLETON = new JProxyShellInteractiveImpl(); ((JProxyShellInteractiveImpl)SINGLETON).init(args); diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java similarity index 79% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java index d740fd4..1a72f62 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java @@ -1,12 +1,12 @@ -package com.sillelien.relproxy.impl.jproxy.shell; +package com.sillelien.dollar.relproxy.impl.jproxy.shell; -import com.sillelien.relproxy.RelProxyException; -import com.sillelien.relproxy.impl.jproxy.JProxyConfigImpl; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootInMemory; -import com.sillelien.relproxy.impl.jproxy.shell.inter.JProxyShellProcessor; +import com.sillelien.dollar.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyConfigImpl; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootInMemory; +import com.sillelien.dollar.relproxy.impl.jproxy.shell.inter.JProxyShellProcessor; import java.util.LinkedList; /** diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java similarity index 79% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java index abdea1c..b19d3bb 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java @@ -1,13 +1,13 @@ -package com.sillelien.relproxy.impl.jproxy.shell; +package com.sillelien.dollar.relproxy.impl.jproxy.shell; -import com.sillelien.relproxy.RelProxyException; -import com.sillelien.relproxy.impl.FileExt; -import com.sillelien.relproxy.impl.jproxy.JProxyConfigImpl; -import com.sillelien.relproxy.impl.jproxy.JProxyUtil; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootFile; +import com.sillelien.dollar.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.impl.FileExt; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyConfigImpl; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootFile; import java.io.File; import java.util.LinkedList; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/Command.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/Command.java similarity index 97% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/Command.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/Command.java index a15999b..b41f3bb 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/Command.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/Command.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.shell.inter; +package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java similarity index 96% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java index c1e277f..5884b0c 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.shell.inter; +package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; /** diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandDelete.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandDelete.java similarity index 96% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandDelete.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandDelete.java index 797a6a6..f4d6b29 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandDelete.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandDelete.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.shell.inter; +package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; /** diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandEdit.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandEdit.java similarity index 97% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandEdit.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandEdit.java index 1440c09..d86f854 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandEdit.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandEdit.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.shell.inter; +package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; /** diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandError.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandError.java similarity index 83% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandError.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandError.java index db9299f..2c7480e 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandError.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandError.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.shell.inter; +package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandInsert.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandInsert.java similarity index 96% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandInsert.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandInsert.java index f372131..cf36e4f 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandInsert.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandInsert.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.shell.inter; +package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; /** diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandLoad.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandLoad.java similarity index 93% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandLoad.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandLoad.java index 8333dfa..cf4e7b8 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandLoad.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandLoad.java @@ -1,6 +1,6 @@ -package com.sillelien.relproxy.impl.jproxy.shell.inter; +package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; -import com.sillelien.relproxy.impl.jproxy.JProxyUtil; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; import java.io.File; import java.net.URI; import java.net.URL; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandOther.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandOther.java similarity index 96% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandOther.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandOther.java index a4fb614..e93c5e4 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandOther.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandOther.java @@ -1,7 +1,7 @@ -package com.sillelien.relproxy.impl.jproxy.shell.inter; +package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; -import com.sillelien.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.RelProxyException; /** * diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandSave.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandSave.java similarity index 91% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandSave.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandSave.java index 9e34990..b19f83c 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/CommandSave.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandSave.java @@ -1,6 +1,6 @@ -package com.sillelien.relproxy.impl.jproxy.shell.inter; +package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; -import com.sillelien.relproxy.impl.jproxy.JProxyUtil; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; import java.io.File; import java.util.List; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java similarity index 93% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java index d0f96db..4f14985 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java @@ -1,11 +1,11 @@ -package com.sillelien.relproxy.impl.jproxy.shell.inter; +package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; -import com.sillelien.relproxy.RelProxy; -import com.sillelien.relproxy.RelProxyException; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; -import com.sillelien.relproxy.impl.jproxy.core.clsmgr.comp.JProxyCompilationException; -import com.sillelien.relproxy.impl.jproxy.shell.JProxyShellInteractiveImpl; +import com.sillelien.dollar.relproxy.RelProxy; +import com.sillelien.dollar.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; +import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.JProxyCompilationException; +import com.sillelien.dollar.relproxy.impl.jproxy.shell.JProxyShellInteractiveImpl; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collections; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/Keyboard.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/Keyboard.java similarity index 89% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/Keyboard.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/Keyboard.java index 50b4f05..b1cb22a 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/Keyboard.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/Keyboard.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.shell.inter; +package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; import java.nio.charset.Charset; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java similarity index 98% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java index 1207ba8..bef7800 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java @@ -1,7 +1,7 @@ -package com.sillelien.relproxy.impl.jproxy.shell.inter; +package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; -import com.sillelien.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.RelProxyException; import java.awt.AWTException; import java.awt.Robot; import static java.awt.event.KeyEvent.VK_0; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java similarity index 93% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java index d4d39a9..0f42d3b 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java @@ -1,7 +1,7 @@ -package com.sillelien.relproxy.impl.jproxy.shell.inter; +package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; -import com.sillelien.relproxy.RelProxyException; +import com.sillelien.dollar.relproxy.RelProxyException; import java.awt.AWTException; import java.awt.Robot; import java.awt.Toolkit; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/LinuxUnicodeKeyboard.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/LinuxUnicodeKeyboard.java similarity index 96% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/LinuxUnicodeKeyboard.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/LinuxUnicodeKeyboard.java index 760172a..b11f86b 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/LinuxUnicodeKeyboard.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/LinuxUnicodeKeyboard.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.shell.inter; +package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; import static java.awt.event.KeyEvent.VK_CONTROL; import static java.awt.event.KeyEvent.VK_SHIFT; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/MacOSXUnicodeKeyboard.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/MacOSXUnicodeKeyboard.java similarity index 95% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/MacOSXUnicodeKeyboard.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/MacOSXUnicodeKeyboard.java index 990cd8a..7a1caf5 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/MacOSXUnicodeKeyboard.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/MacOSXUnicodeKeyboard.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.shell.inter; +package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; import static java.awt.Event.ALT_MASK; import java.nio.charset.Charset; diff --git a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/WindowUnicodeKeyboard.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/WindowUnicodeKeyboard.java similarity index 95% rename from src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/WindowUnicodeKeyboard.java rename to src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/WindowUnicodeKeyboard.java index 26de732..35d4a47 100644 --- a/src/main/java/com/sillelien/relproxy/impl/jproxy/shell/inter/WindowUnicodeKeyboard.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/WindowUnicodeKeyboard.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.impl.jproxy.shell.inter; +package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; import static java.awt.event.KeyEvent.VK_ALT; import java.nio.charset.Charset; diff --git a/src/main/java/com/sillelien/relproxy/jproxy/JProxy.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxy.java similarity index 96% rename from src/main/java/com/sillelien/relproxy/jproxy/JProxy.java rename to src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxy.java index 13d6c0c..a101b83 100644 --- a/src/main/java/com/sillelien/relproxy/jproxy/JProxy.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxy.java @@ -1,8 +1,8 @@ -package com.sillelien.relproxy.jproxy; +package com.sillelien.dollar.relproxy.jproxy; -import com.sillelien.relproxy.impl.jproxy.JProxyConfigImpl; -import com.sillelien.relproxy.impl.jproxy.JProxyDefaultImpl; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyConfigImpl; +import com.sillelien.dollar.relproxy.impl.jproxy.JProxyDefaultImpl; /** * Is the class to create Java proxy objects based on Java objects and keep track of source code changes reloading classes when detected. diff --git a/src/main/java/com/sillelien/relproxy/jproxy/JProxyCompilerListener.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyCompilerListener.java similarity index 87% rename from src/main/java/com/sillelien/relproxy/jproxy/JProxyCompilerListener.java rename to src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyCompilerListener.java index 4c581c9..218f16e 100644 --- a/src/main/java/com/sillelien/relproxy/jproxy/JProxyCompilerListener.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyCompilerListener.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.jproxy; +package com.sillelien.dollar.relproxy.jproxy; import java.io.File; diff --git a/src/main/java/com/sillelien/relproxy/jproxy/JProxyConfig.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyConfig.java similarity index 98% rename from src/main/java/com/sillelien/relproxy/jproxy/JProxyConfig.java rename to src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyConfig.java index 6cc88ca..1c8a235 100644 --- a/src/main/java/com/sillelien/relproxy/jproxy/JProxyConfig.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyConfig.java @@ -1,7 +1,7 @@ -package com.sillelien.relproxy.jproxy; +package com.sillelien.dollar.relproxy.jproxy; -import com.sillelien.relproxy.RelProxyOnReloadListener; +import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; /** * Interface implemented by the configuration object needed to initialize JProxy and {@link JProxyScriptEngineFactory}. diff --git a/src/main/java/com/sillelien/relproxy/jproxy/JProxyDiagnosticsListener.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyDiagnosticsListener.java similarity index 92% rename from src/main/java/com/sillelien/relproxy/jproxy/JProxyDiagnosticsListener.java rename to src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyDiagnosticsListener.java index 563ebf5..6de8b26 100644 --- a/src/main/java/com/sillelien/relproxy/jproxy/JProxyDiagnosticsListener.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyDiagnosticsListener.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.jproxy; +package com.sillelien.dollar.relproxy.jproxy; import javax.tools.DiagnosticCollector; import javax.tools.JavaFileObject; diff --git a/src/main/java/com/sillelien/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java similarity index 94% rename from src/main/java/com/sillelien/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java rename to src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java index 0fb92d4..def541e 100644 --- a/src/main/java/com/sillelien/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.jproxy; +package com.sillelien.dollar.relproxy.jproxy; import java.io.File; diff --git a/src/main/java/com/sillelien/relproxy/jproxy/JProxyScriptEngine.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyScriptEngine.java similarity index 98% rename from src/main/java/com/sillelien/relproxy/jproxy/JProxyScriptEngine.java rename to src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyScriptEngine.java index 3fd5806..ea1ae96 100644 --- a/src/main/java/com/sillelien/relproxy/jproxy/JProxyScriptEngine.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyScriptEngine.java @@ -1,4 +1,4 @@ -package com.sillelien.relproxy.jproxy; +package com.sillelien.dollar.relproxy.jproxy; import javax.script.ScriptEngine; diff --git a/src/main/java/com/sillelien/relproxy/jproxy/JProxyScriptEngineFactory.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyScriptEngineFactory.java similarity index 79% rename from src/main/java/com/sillelien/relproxy/jproxy/JProxyScriptEngineFactory.java rename to src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyScriptEngineFactory.java index 036f218..175b320 100644 --- a/src/main/java/com/sillelien/relproxy/jproxy/JProxyScriptEngineFactory.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyScriptEngineFactory.java @@ -1,6 +1,6 @@ -package com.sillelien.relproxy.jproxy; +package com.sillelien.dollar.relproxy.jproxy; -import com.sillelien.relproxy.impl.jproxy.screngine.JProxyScriptEngineFactoryImpl; +import com.sillelien.dollar.relproxy.impl.jproxy.screngine.JProxyScriptEngineFactoryImpl; import javax.script.ScriptEngineFactory; /** diff --git a/src/main/java/com/sillelien/relproxy/jproxy/JProxyShell.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyShell.java similarity index 80% rename from src/main/java/com/sillelien/relproxy/jproxy/JProxyShell.java rename to src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyShell.java index d0e1024..0afa40a 100644 --- a/src/main/java/com/sillelien/relproxy/jproxy/JProxyShell.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyShell.java @@ -1,6 +1,6 @@ -package com.sillelien.relproxy.jproxy; +package com.sillelien.dollar.relproxy.jproxy; -import com.sillelien.relproxy.impl.jproxy.shell.JProxyShellImpl; +import com.sillelien.dollar.relproxy.impl.jproxy.shell.JProxyShellImpl; /** * Is the main class to execute shell scripting based on Java. diff --git a/src/main/java/com/sillelien/relproxy/jproxy/package.html b/src/main/java/com/sillelien/dollar/relproxy/jproxy/package.html similarity index 100% rename from src/main/java/com/sillelien/relproxy/jproxy/package.html rename to src/main/java/com/sillelien/dollar/relproxy/jproxy/package.html diff --git a/src/main/java/com/sillelien/relproxy/package.html b/src/main/java/com/sillelien/dollar/relproxy/package.html similarity index 100% rename from src/main/java/com/sillelien/relproxy/package.html rename to src/main/java/com/sillelien/dollar/relproxy/package.html From f3b4ef985f279707f45a2e33fe8ec14d64cb6ba4 Mon Sep 17 00:00:00 2001 From: "hello@neilellis.me" Date: Fri, 7 Jul 2017 16:23:45 +0100 Subject: [PATCH 023/135] Release 0.9.23 [23/c98b76b6a1df15f1c33d2e1a06925b6687692966] (jimply-lawny-kef) --- .release | 2 +- .release.details | 2 +- README.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release b/.release index bd758c9..68a5945 100644 --- a/.release +++ b/.release @@ -1 +1 @@ -0.9.20 +0.9.23 diff --git a/.release.details b/.release.details index c8f4163..fd9c3c1 100644 --- a/.release.details +++ b/.release.details @@ -1 +1 @@ -0.9.20 20 6565bf3d1f7b1ea1ee03b5ed32f85bc18db23e4f sure-legit-rales +0.9.23 23 c98b76b6a1df15f1c33d2e1a06925b6687692966 jimply-lawny-kef diff --git a/README.md b/README.md index e9a113a..1adabca 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ RelProxy is a simple Java and Groovy hot class reloader for Java and Groovy prov com.sillelien dollar-relproxy -0.9.20 +0.9.23 jar ``` From 85d846629a8114e3e6634ae3b43f80e47f60d078 Mon Sep 17 00:00:00 2001 From: neilellis Date: Fri, 7 Jul 2017 17:20:16 +0100 Subject: [PATCH 024/135] Refactoring for Dollar project --- pom.xml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/pom.xml b/pom.xml index 1d2f216..51d3a7e 100644 --- a/pom.xml +++ b/pom.xml @@ -383,6 +383,32 @@ 0 + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.3 + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.4 + + + attach-sources + + jar + + + +
From 82c1dddba376ac18ad3cfd999665f28a357959a0 Mon Sep 17 00:00:00 2001 From: neilellis Date: Fri, 7 Jul 2017 17:20:16 +0100 Subject: [PATCH 025/135] Refactoring for Dollar project --- pom.xml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/pom.xml b/pom.xml index 1d2f216..51d3a7e 100644 --- a/pom.xml +++ b/pom.xml @@ -383,6 +383,32 @@ 0 + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.3 + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.4 + + + attach-sources + + jar + + + +
From 8ac02e96ebe71e3dde174e770b06564e798c3700 Mon Sep 17 00:00:00 2001 From: "hello@neilellis.me" Date: Fri, 7 Jul 2017 17:22:27 +0100 Subject: [PATCH 026/135] Release 0.9.26 [26/85d846629a8114e3e6634ae3b43f80e47f60d078] (bally-spoilt-flutes) --- .release | 2 +- .release.details | 2 +- README.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release b/.release index 68a5945..46e7a71 100644 --- a/.release +++ b/.release @@ -1 +1 @@ -0.9.23 +0.9.26 diff --git a/.release.details b/.release.details index fd9c3c1..d4ffea5 100644 --- a/.release.details +++ b/.release.details @@ -1 +1 @@ -0.9.23 23 c98b76b6a1df15f1c33d2e1a06925b6687692966 jimply-lawny-kef +0.9.26 26 85d846629a8114e3e6634ae3b43f80e47f60d078 bally-spoilt-flutes diff --git a/README.md b/README.md index 1adabca..b4e2b5f 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ RelProxy is a simple Java and Groovy hot class reloader for Java and Groovy prov com.sillelien dollar-relproxy -0.9.23 +0.9.26 jar ``` From 963bc5ff5e05bb4e56d0ad0d3a3482a39b0756a6 Mon Sep 17 00:00:00 2001 From: neilellis Date: Fri, 7 Jul 2017 22:14:35 +0100 Subject: [PATCH 027/135] Refactoring for Dollar project --- .idea/libraries/Maven__junit_junit_4_12.xml | 13 ++ .../Maven__org_hamcrest_hamcrest_core_1_3.xml | 13 ++ .../Maven__org_jetbrains_annotations_13_0.xml | 13 ++ .idea/libraries/annotations.xml | 9 + pom.xml | 23 +- .../example/javaex/JProxyExampleDocument.java | 5 +- .../javaex/JProxyExampleLoadListener.java | 4 +- .../dollar/relproxy/gproxy/GProxy.java | 8 +- .../dollar/relproxy/gproxy/GProxyConfig.java | 4 + .../gproxy/GProxyGroovyScriptEngine.java | 3 + .../dollar/relproxy/impl/FileExt.java | 8 +- .../relproxy/impl/GenericProxyImpl.java | 18 +- .../impl/GenericProxyInvocationHandler.java | 5 +- .../impl/GenericProxyVersionedObject.java | 12 +- .../impl/gproxy/GProxyConfigImpl.java | 4 + .../impl/gproxy/GProxyDefaultImpl.java | 10 +- .../relproxy/impl/gproxy/core/GProxyImpl.java | 6 +- .../gproxy/core/GProxyInvocationHandler.java | 4 +- .../gproxy/core/GProxyVersionedObject.java | 11 +- .../impl/jproxy/JProxyConfigImpl.java | 22 +- .../impl/jproxy/JProxyDefaultImpl.java | 13 +- .../relproxy/impl/jproxy/JProxyUtil.java | 22 +- .../relproxy/impl/jproxy/core/JProxyImpl.java | 12 +- .../jproxy/core/JProxyInvocationHandler.java | 4 +- .../jproxy/core/JProxyVersionedObject.java | 7 +- .../jproxy/core/clsmgr/FolderSourceList.java | 10 +- .../jproxy/core/clsmgr/JProxyClassLoader.java | 19 +- .../impl/jproxy/core/clsmgr/JProxyEngine.java | 22 +- ...JProxyEngineChangeDetectorAndCompiler.java | 19 +- .../jproxy/core/clsmgr/JavaSourcesSearch.java | 182 ++++++++-------- .../core/clsmgr/cldesc/ClassDescriptor.java | 23 +- .../clsmgr/cldesc/ClassDescriptorInner.java | 4 +- .../cldesc/ClassDescriptorSourceFileJava.java | 4 +- .../ClassDescriptorSourceFileRegistry.java | 15 +- .../cldesc/ClassDescriptorSourceScript.java | 17 +- .../cldesc/ClassDescriptorSourceUnit.java | 17 +- .../clsmgr/comp/JProxyCompilerInMemory.java | 11 +- .../clsmgr/comp/JavaFileManagerInMemory.java | 13 +- ...leObjectInputClassFinderByClassLoader.java | 13 +- .../jfo/JavaFileObjectInputClassInFile.java | 6 +- .../JavaFileObjectInputClassInFileSystem.java | 11 +- .../jfo/JavaFileObjectInputClassInJar.java | 5 +- .../jfo/JavaFileObjectInputClassInMemory.java | 6 +- .../jfo/JavaFileObjectInputSourceBase.java | 9 +- .../jfo/JavaFileObjectInputSourceInFile.java | 4 +- .../JavaFileObjectInputSourceInMemory.java | 4 +- .../comp/jfo/JavaFileObjectOutputClass.java | 5 +- .../clsmgr/srcunit/SourceFileJavaNormal.java | 5 +- .../clsmgr/srcunit/SourceScriptRootFile.java | 5 +- .../srcunit/SourceScriptRootFileJavaExt.java | 6 +- .../srcunit/SourceScriptRootFileOtherExt.java | 6 +- .../core/clsmgr/srcunit/SourceUnit.java | 8 +- .../JProxyScriptEngineDelegateImpl.java | 11 +- .../JProxyScriptEngineFactoryImpl.java | 23 +- .../screngine/JProxyScriptEngineImpl.java | 10 +- .../jproxy/shell/JProxyShellClassLoader.java | 8 +- .../shell/JProxyShellCodeSnippetImpl.java | 17 +- .../impl/jproxy/shell/JProxyShellImpl.java | 20 +- .../shell/JProxyShellInteractiveImpl.java | 20 +- .../shell/JProxyShellScriptFileImpl.java | 19 +- .../impl/jproxy/shell/inter/Command.java | 6 +- .../shell/inter/CommandCodeChangerBase.java | 4 +- .../jproxy/shell/inter/CommandDelete.java | 4 +- .../impl/jproxy/shell/inter/CommandEdit.java | 4 +- .../jproxy/shell/inter/CommandInsert.java | 4 +- .../impl/jproxy/shell/inter/CommandLoad.java | 4 +- .../impl/jproxy/shell/inter/CommandSave.java | 4 +- .../shell/inter/JProxyShellProcessor.java | 12 +- .../inter/KeyboardNotUsingClipboard.java | 13 +- .../shell/inter/KeyboardUsingClipboard.java | 5 +- .../dollar/relproxy/jproxy/JProxy.java | 8 +- .../dollar/relproxy/jproxy/JProxyConfig.java | 20 +- .../relproxy/jproxy/JProxyScriptEngine.java | 8 +- .../dollar/relproxy/jproxy/JProxyShell.java | 3 +- .../JProxyCodeSnippetCompleteClassTest.java | 74 +++++++ .../jproxy/JProxyCodeSnippetTest.java | 68 ++++++ .../JProxyJavaScriptEngineNoManagerTest.java | 183 ++++++++++++++++ .../jproxy/JProxyJavaScriptEngineTest.java | 201 ++++++++++++++++++ .../JProxyJavaShellCompleteClassTest.java | 72 +++++++ .../JProxyJavaShellInteractiveTest.java | 63 ++++++ .../JProxyJavaShellNormalClassTest.java | 69 ++++++ .../relproxy/jproxy/JProxyJavaShellTest.java | 74 +++++++ .../relproxy/jproxy/util/JProxyTestUtil.java | 16 ++ .../javashellex/JProxyShellExample.java | 44 ++-- .../test/resources/example_java_shell | 0 .../example_java_shell_complete_class | 0 .../test/resources/example_normal_class.java | 0 87 files changed, 1489 insertions(+), 304 deletions(-) create mode 100644 .idea/libraries/Maven__junit_junit_4_12.xml create mode 100644 .idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml create mode 100644 .idea/libraries/Maven__org_jetbrains_annotations_13_0.xml create mode 100644 .idea/libraries/annotations.xml create mode 100644 src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyCodeSnippetCompleteClassTest.java create mode 100644 src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyCodeSnippetTest.java create mode 100644 src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaScriptEngineNoManagerTest.java create mode 100644 src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaScriptEngineTest.java create mode 100644 src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaShellCompleteClassTest.java create mode 100644 src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaShellInteractiveTest.java create mode 100644 src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaShellNormalClassTest.java create mode 100644 src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaShellTest.java create mode 100644 src/test/java/com/sillelien/dollar/relproxy/jproxy/util/JProxyTestUtil.java rename {relproxy/src => src}/test/resources/example/javashellex/JProxyShellExample.java (96%) rename {relproxy/src => src}/test/resources/example_java_shell (100%) rename {relproxy/src => src}/test/resources/example_java_shell_complete_class (100%) rename {relproxy/src => src}/test/resources/example_normal_class.java (100%) diff --git a/.idea/libraries/Maven__junit_junit_4_12.xml b/.idea/libraries/Maven__junit_junit_4_12.xml new file mode 100644 index 0000000..d411041 --- /dev/null +++ b/.idea/libraries/Maven__junit_junit_4_12.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml b/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml new file mode 100644 index 0000000..f58bbc1 --- /dev/null +++ b/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_jetbrains_annotations_13_0.xml b/.idea/libraries/Maven__org_jetbrains_annotations_13_0.xml new file mode 100644 index 0000000..e2c8297 --- /dev/null +++ b/.idea/libraries/Maven__org_jetbrains_annotations_13_0.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/annotations.xml b/.idea/libraries/annotations.xml new file mode 100644 index 0000000..03e4ad1 --- /dev/null +++ b/.idea/libraries/annotations.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 51d3a7e..aaf4c19 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,9 @@ relproxy - Simple Java and Groovy hot class reloader,and Java based shell and scripting used by Dollar project, original project is https://github.com/jmarranz/relproxy + Simple Java and Groovy hot class reloader,and Java based shell and scripting used by Dollar project, + original project is https://github.com/jmarranz/relproxy + https://github.com/dollar-org/relproxy @@ -60,16 +62,31 @@ + 13.0 2.0.2 + 3.0.2 + 1.8 2.4 2.8 2.6 3.4 3.3.9 - 1.8 - 3.0.2 + + + org.jetbrains + annotations + ${annotations.version} + + + junit + junit + 4.12 + test + + + diff --git a/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleDocument.java b/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleDocument.java index f09bde7..f3d8267 100644 --- a/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleDocument.java +++ b/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleDocument.java @@ -8,6 +8,7 @@ import org.itsnat.comp.text.ItsNatHTMLInputText; import org.itsnat.core.ItsNatServletRequest; import org.itsnat.core.html.ItsNatHTMLDocument; +import org.jetbrains.annotations.NotNull; import org.w3c.dom.Element; import org.w3c.dom.events.Event; import org.w3c.dom.events.EventListener; @@ -32,7 +33,7 @@ public JProxyExampleDocument() // Requerido por el listener ejemplo anonymous in { } - public JProxyExampleDocument(ItsNatServletRequest request,ItsNatHTMLDocument itsNatDoc,FalseDB db) + public JProxyExampleDocument(ItsNatServletRequest request, @NotNull ItsNatHTMLDocument itsNatDoc, @NotNull FalseDB db) { class AuxMemberInMethod { @@ -59,7 +60,7 @@ public void log() } @Override - public void handleEvent(Event evt) + public void handleEvent(@NotNull Event evt) { String text = textInput.getText(); String comment = " YES I SAID THIS (" + evt.getType() + ")"; diff --git a/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleLoadListener.java b/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleLoadListener.java index 550320c..15314dc 100644 --- a/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleLoadListener.java +++ b/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleLoadListener.java @@ -8,10 +8,12 @@ import org.itsnat.core.ItsNatServletRequest; import org.itsnat.core.ItsNatServletResponse; import org.itsnat.core.html.ItsNatHTMLDocument; +import org.jetbrains.annotations.NotNull; public class JProxyExampleLoadListener implements ItsNatServletRequestListener { protected final FalseDB db; + @NotNull protected static Integer testStatic = 10; protected static final Integer testStaticFinal = 11; @@ -27,7 +29,7 @@ public JProxyExampleLoadListener(FalseDB db) @Override - public void processRequest(ItsNatServletRequest request, ItsNatServletResponse response) + public void processRequest(@NotNull ItsNatServletRequest request, ItsNatServletResponse response) { System.out.println("JProxyExampleLoadListener 1 " + this.getClass().getClassLoader().hashCode()); new example.javaex.JProxyExampleDocument(request,(ItsNatHTMLDocument)request.getItsNatDocument(),db); diff --git a/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxy.java b/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxy.java index 6fb5120..5ee51b4 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxy.java +++ b/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxy.java @@ -3,6 +3,8 @@ import com.sillelien.dollar.relproxy.impl.gproxy.GProxyConfigImpl; import com.sillelien.dollar.relproxy.impl.gproxy.GProxyDefaultImpl; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * Is the class to create Java proxy objects based on Groovy objects and keep track of Groovy source code changes reloading Groovy classes when detected. @@ -42,7 +44,8 @@ public static void init(GProxyConfig config) * @param clasz the class of the interface implemented by the original object and proxy object returned. * @return the java.lang.reflect.Proxy object associated or the original object when GProxy is disabled. */ - public static T create(T obj,Class clasz) + @Nullable + public static T create(T obj, Class clasz) { return GProxyDefaultImpl.createStatic(obj, clasz); } @@ -61,7 +64,8 @@ public static T create(T obj,Class clasz) * @param classes the classes of the interfaces implemented by the original object and proxy object returned. * @return the java.lang.reflect.Proxy object associated or the original object when GProxy is disabled. */ - public static Object create(Object obj,Class[] classes) + @Nullable + public static Object create(Object obj, @NotNull Class[] classes) { return GProxyDefaultImpl.createStatic(obj, classes); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyConfig.java b/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyConfig.java index ea57bcd..fd614e2 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyConfig.java +++ b/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyConfig.java @@ -2,6 +2,7 @@ package com.sillelien.dollar.relproxy.gproxy; import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; +import org.jetbrains.annotations.NotNull; /** * Interface implemented by the configuration object needed to initialize GProxy. @@ -21,6 +22,7 @@ public interface GProxyConfig * @param enabled whether automatic source code change detection and reload is enabled. By default is true. * @return this object for flow API use. */ + @NotNull public GProxyConfig setEnabled(boolean enabled); /** @@ -29,6 +31,7 @@ public interface GProxyConfig * @param relListener the class reload listener. By default is null. * @return this object for flow API use. */ + @NotNull public GProxyConfig setRelProxyOnReloadListener(RelProxyOnReloadListener relListener); /** @@ -39,5 +42,6 @@ public interface GProxyConfig * @param engine the GroovyScriptEngine wrapper. * @return this object for flow API use. */ + @NotNull public GProxyConfig setGProxyGroovyScriptEngine(GProxyGroovyScriptEngine engine); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyGroovyScriptEngine.java b/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyGroovyScriptEngine.java index 53957a5..714feeb 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyGroovyScriptEngine.java +++ b/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyGroovyScriptEngine.java @@ -1,5 +1,7 @@ package com.sillelien.dollar.relproxy.gproxy; +import org.jetbrains.annotations.NotNull; + /** * Interface to implement the object implementing the GroovyScriptEngine wrapper used to reload Groovy classes. * @@ -27,5 +29,6 @@ public interface GProxyGroovyScriptEngine * @param scriptName the name of the Groovy script/class. * @return the class associated to the specified Groovy script. */ + @NotNull public Class loadScriptByName(String scriptName); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/FileExt.java b/src/main/java/com/sillelien/dollar/relproxy/impl/FileExt.java index e3ab333..33c8866 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/FileExt.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/FileExt.java @@ -1,6 +1,8 @@ package com.sillelien.dollar.relproxy.impl; import com.sillelien.dollar.relproxy.RelProxyException; +import org.jetbrains.annotations.NotNull; + import java.io.File; import java.io.IOException; @@ -10,21 +12,25 @@ */ public class FileExt { + @NotNull protected final File file; + @NotNull protected final String cannonicalPath; // El obtener el cannonicalPath exige acceder al sistema de archivos, por eso nos inventamos esta clase, para evitar sucesivas llamadas a File.getCanonicalPath() - public FileExt(File file) + public FileExt(@NotNull File file) { this.file = file; try { this.cannonicalPath = file.getCanonicalPath(); } catch (IOException ex) { throw new RelProxyException(ex); } } + @NotNull public File getFile() { return file; } + @NotNull public String getCanonicalPath() { return cannonicalPath; diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyImpl.java index 53a8b3c..fa9a470 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyImpl.java @@ -2,6 +2,9 @@ import com.sillelien.dollar.relproxy.RelProxyException; import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; @@ -17,19 +20,19 @@ public GenericProxyImpl() { } - public static void checkSingletonNull(GenericProxyImpl singleton) + public static void checkSingletonNull(@Nullable GenericProxyImpl singleton) { if (singleton != null) throw new RelProxyException("Already initialized"); } - protected static void checkSingletonExists(GenericProxyImpl singleton) + protected static void checkSingletonExists(@Nullable GenericProxyImpl singleton) { if (singleton == null) throw new RelProxyException("Execute first the init method"); } - protected void init(GenericProxyConfigBaseImpl config) + protected void init(@NotNull GenericProxyConfigBaseImpl config) { this.reloadListener = config.getRelProxyOnReloadListener(); } @@ -39,14 +42,16 @@ public RelProxyOnReloadListener getRelProxyOnReloadListener() return reloadListener; } - public T create(T obj,Class clasz) + @Nullable + public T create(@Nullable T obj, Class clasz) { if (obj == null) return null; return (T)create(obj,new Class[] { clasz }); } - public Object create(Object obj,Class[] classes) + @Nullable + public Object create(@Nullable Object obj, @NotNull Class[] classes) { if (obj == null) return null; @@ -57,5 +62,6 @@ public Object create(Object obj,Class[] classes) } - public abstract GenericProxyInvocationHandler createGenericProxyInvocationHandler(Object obj); + @NotNull + public abstract GenericProxyInvocationHandler createGenericProxyInvocationHandler(Object obj); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyInvocationHandler.java b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyInvocationHandler.java index 76bf545..1c47def 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyInvocationHandler.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyInvocationHandler.java @@ -1,6 +1,9 @@ package com.sillelien.dollar.relproxy.impl; import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; @@ -30,7 +33,7 @@ private Object getNewVersion() throws Throwable } @Override - public synchronized Object invoke(Object proxy, Method method, Object[] args) throws Throwable + public synchronized Object invoke(Object proxy, @NotNull Method method, @Nullable Object[] args) throws Throwable { Object oldObj = getCurrent(); Object obj = getNewVersion(); diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyVersionedObject.java b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyVersionedObject.java index b941169..60a479c 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyVersionedObject.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyVersionedObject.java @@ -1,6 +1,9 @@ package com.sillelien.dollar.relproxy.impl; import com.sillelien.dollar.relproxy.RelProxyException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; @@ -22,7 +25,7 @@ public GenericProxyVersionedObject(Object obj,GenericProxyInvocationHandler pare this.parent = parent; } - protected static void getTreeFields(Class clasz,Object obj,ArrayList fieldList,ArrayList valueList) throws IllegalAccessException + protected static void getTreeFields(@NotNull Class clasz, Object obj, @NotNull ArrayList fieldList, ArrayList valueList) throws IllegalAccessException { getFields(clasz,obj,fieldList,valueList); Class superClass = clasz.getSuperclass(); @@ -30,7 +33,7 @@ protected static void getTreeFields(Class clasz,Object obj,ArrayList fiel getTreeFields(superClass,obj,fieldList,valueList); } - protected static void getFields(Class clasz,Object obj,ArrayList fieldList,ArrayList valueList) throws IllegalAccessException + protected static void getFields(@NotNull Class clasz, Object obj, @NotNull ArrayList fieldList, @Nullable ArrayList valueList) throws IllegalAccessException { Field[] fieldListClass = clasz.getDeclaredFields(); for(int i = 0; i < fieldListClass.length; i++) @@ -66,7 +69,7 @@ public Object getNewVersion() throws Throwable return obj; } - private Object copy(Class oldClass,Object oldObj,Class newClass) throws IllegalAccessException, InstantiationException, IllegalArgumentException, InvocationTargetException + private Object copy(@NotNull Class oldClass, Object oldObj, @NotNull Class newClass) throws IllegalAccessException, InstantiationException, IllegalArgumentException, InvocationTargetException { Object newObj; @@ -160,6 +163,7 @@ private Object copy(Class oldClass,Object oldObj,Class newClass) throws IllegalA return newObj; } - protected abstract Class reloadClass(); + @Nullable + protected abstract Class reloadClass(); protected abstract boolean ignoreField(Field field); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyConfigImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyConfigImpl.java index d549078..826cace 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyConfigImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyConfigImpl.java @@ -4,6 +4,7 @@ import com.sillelien.dollar.relproxy.gproxy.GProxyConfig; import com.sillelien.dollar.relproxy.gproxy.GProxyGroovyScriptEngine; import com.sillelien.dollar.relproxy.impl.GenericProxyConfigBaseImpl; +import org.jetbrains.annotations.NotNull; /** * @@ -13,18 +14,21 @@ public class GProxyConfigImpl extends GenericProxyConfigBaseImpl implements GPro { protected GProxyGroovyScriptEngine engine; + @NotNull public GProxyConfig setEnabled(boolean enabled) { this.enabled = enabled; return this; } + @NotNull public GProxyConfig setRelProxyOnReloadListener(RelProxyOnReloadListener relListener) { this.relListener = relListener; return this; } + @NotNull public GProxyConfig setGProxyGroovyScriptEngine(GProxyGroovyScriptEngine engine) { this.engine = engine; diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyDefaultImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyDefaultImpl.java index 03735ef..8f466a9 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyDefaultImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyDefaultImpl.java @@ -2,6 +2,8 @@ import com.sillelien.dollar.relproxy.gproxy.GProxyConfig; import com.sillelien.dollar.relproxy.impl.gproxy.core.GProxyImpl; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * @@ -14,7 +16,7 @@ public static GProxyConfig createGProxyConfig() return new GProxyConfigImpl(); } - public static void initStatic(GProxyConfigImpl config) + public static void initStatic(@NotNull GProxyConfigImpl config) { if (!config.isEnabled()) return; @@ -23,7 +25,8 @@ public static void initStatic(GProxyConfigImpl config) SINGLETON.init(config); } - public static T createStatic(T obj,Class clasz) + @Nullable + public static T createStatic(T obj, Class clasz) { if (SINGLETON == null) return obj; // No se ha llamado al init o enabled = false @@ -31,7 +34,8 @@ public static T createStatic(T obj,Class clasz) return SINGLETON.create(obj, clasz); } - public static Object createStatic(Object obj,Class[] classes) + @Nullable + public static Object createStatic(Object obj, @NotNull Class[] classes) { if (SINGLETON == null) return obj; // No se ha llamado al init o enabled = false diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyImpl.java index 40ab707..33de8ec 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyImpl.java @@ -4,6 +4,7 @@ import com.sillelien.dollar.relproxy.gproxy.GProxyGroovyScriptEngine; import com.sillelien.dollar.relproxy.impl.GenericProxyImpl; import com.sillelien.dollar.relproxy.impl.GenericProxyInvocationHandler; +import org.jetbrains.annotations.NotNull; /** @@ -15,7 +16,7 @@ public abstract class GProxyImpl extends GenericProxyImpl public static GProxyImpl SINGLETON; protected GProxyGroovyScriptEngine engine; - public void init(GProxyConfigImpl config) + public void init(@NotNull GProxyConfigImpl config) { super.init(config); this.engine = config.getGProxyGroovyScriptEngine(); @@ -26,8 +27,9 @@ public GProxyGroovyScriptEngine getGProxyGroovyScriptEngine() return engine; } + @NotNull @Override - public GenericProxyInvocationHandler createGenericProxyInvocationHandler(Object obj) + public GenericProxyInvocationHandler createGenericProxyInvocationHandler(@NotNull Object obj) { return new GProxyInvocationHandler(obj,this); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyInvocationHandler.java b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyInvocationHandler.java index 0bff93a..a1c54d3 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyInvocationHandler.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyInvocationHandler.java @@ -1,6 +1,7 @@ package com.sillelien.dollar.relproxy.impl.gproxy.core; import com.sillelien.dollar.relproxy.impl.GenericProxyInvocationHandler; +import org.jetbrains.annotations.NotNull; /** * @@ -8,12 +9,13 @@ */ public class GProxyInvocationHandler extends GenericProxyInvocationHandler { - public GProxyInvocationHandler(Object obj,GProxyImpl root) + public GProxyInvocationHandler(@NotNull Object obj, GProxyImpl root) { super(root); this.verObj = new GProxyVersionedObject(obj,this); } + @NotNull public GProxyImpl getGProxyImpl() { return (GProxyImpl)root; diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyVersionedObject.java b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyVersionedObject.java index c4edf28..f8cbc2a 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyVersionedObject.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyVersionedObject.java @@ -2,6 +2,9 @@ import com.sillelien.dollar.relproxy.gproxy.GProxyGroovyScriptEngine; import com.sillelien.dollar.relproxy.impl.GenericProxyVersionedObject; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.lang.reflect.Field; /** @@ -12,19 +15,21 @@ public class GProxyVersionedObject extends GenericProxyVersionedObject { protected String path; - public GProxyVersionedObject(Object obj,GProxyInvocationHandler parent) + public GProxyVersionedObject(@NotNull Object obj, GProxyInvocationHandler parent) { super(obj,parent); this.path = obj.getClass().getName().replace('.','/'); } + @NotNull public GProxyInvocationHandler getGProxyInvocationHandler() { return (GProxyInvocationHandler)parent; } - @Override + @Nullable + @Override protected Class reloadClass() { GProxyGroovyScriptEngine engine = getGProxyInvocationHandler().getGProxyImpl().getGProxyGroovyScriptEngine(); @@ -41,7 +46,7 @@ protected Class reloadClass() } @Override - protected boolean ignoreField(Field field) + protected boolean ignoreField(@NotNull Field field) { return field.getName().startsWith("__timeStamp__"); // Este atributo cambia de nombre en cada reload, no lo consideramos } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyConfigImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyConfigImpl.java index bd1fe4c..eb5c831 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyConfigImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyConfigImpl.java @@ -8,6 +8,9 @@ import com.sillelien.dollar.relproxy.jproxy.JProxyConfig; import com.sillelien.dollar.relproxy.jproxy.JProxyDiagnosticsListener; import com.sillelien.dollar.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.io.File; /** @@ -27,6 +30,7 @@ public class JProxyConfigImpl extends GenericProxyConfigBaseImpl implements JPro protected JProxyDiagnosticsListener diagnosticsListener; protected boolean test = false; + @NotNull @Override public JProxyConfig setEnabled(boolean enabled) { @@ -34,6 +38,7 @@ public JProxyConfig setEnabled(boolean enabled) return this; } + @NotNull @Override public JProxyConfig setRelProxyOnReloadListener(RelProxyOnReloadListener relListener) { @@ -41,13 +46,15 @@ public JProxyConfig setRelProxyOnReloadListener(RelProxyOnReloadListener relList return this; } + @NotNull @Override - public JProxyConfig setInputPath(String inputPath) + public JProxyConfig setInputPath(@Nullable String inputPath) { setInputPaths(inputPath != null ? new String[]{inputPath} : null); // inputPath es null en el caso de shell interactive return this; } + @NotNull @Override public JProxyConfig setInputPaths(String[] inputPaths) { @@ -55,27 +62,31 @@ public JProxyConfig setInputPaths(String[] inputPaths) return this; } - @Override + @NotNull + @Override public JProxyConfig setRequiredExtraJarPaths(String[] inputJarPaths) { this.requiredExtraJarPaths = new FolderSourceList(inputJarPaths,false); // inputPaths es null en el caso de shell interactive return this; } - @Override + @NotNull + @Override public JProxyConfig setJProxyInputSourceFileExcludedListener(JProxyInputSourceFileExcludedListener excludedListener) { this.excludedListener = excludedListener; return this; } - @Override + @NotNull + @Override public JProxyConfig setJProxyCompilerListener(JProxyCompilerListener compilerListener) { this.compilerListener = compilerListener; return this; } + @NotNull @Override public JProxyConfig setClassFolder(String classFolder) { @@ -83,6 +94,7 @@ public JProxyConfig setClassFolder(String classFolder) return this; } + @NotNull @Override public JProxyConfig setScanPeriod(long scanPeriod) { @@ -91,6 +103,7 @@ public JProxyConfig setScanPeriod(long scanPeriod) return this; } + @NotNull @Override public JProxyConfig setCompilationOptions(Iterable compilationOptions) { @@ -98,6 +111,7 @@ public JProxyConfig setCompilationOptions(Iterable compilationOptions) return this; } + @NotNull @Override public JProxyConfig setJProxyDiagnosticsListener(JProxyDiagnosticsListener diagnosticsListener) { diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyDefaultImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyDefaultImpl.java index a4ed4f5..83251da 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyDefaultImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyDefaultImpl.java @@ -2,6 +2,8 @@ import com.sillelien.dollar.relproxy.impl.jproxy.core.JProxyImpl; import com.sillelien.dollar.relproxy.jproxy.JProxyConfig; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * @@ -13,7 +15,8 @@ public JProxyDefaultImpl() { } - @Override + @Nullable + @Override public Class getMainParamClass() { return null; @@ -24,7 +27,7 @@ public static JProxyConfig createJProxyConfig() return new JProxyConfigImpl(); } - public static void initStatic(JProxyConfigImpl config) + public static void initStatic(@NotNull JProxyConfigImpl config) { if (!config.isEnabled()) return; @@ -34,7 +37,8 @@ public static void initStatic(JProxyConfigImpl config) } - public static T createStatic(T obj,Class clasz) + @Nullable + public static T createStatic(T obj, Class clasz) { if (SINGLETON == null) return obj; // No se ha llamado al init o enabled = false @@ -42,7 +46,8 @@ public static T createStatic(T obj,Class clasz) return SINGLETON.create(obj, clasz); } - public static Object createStatic(Object obj,Class[] classes) + @Nullable + public static Object createStatic(Object obj, @NotNull Class[] classes) { if (SINGLETON == null) return obj; // No se ha llamado al init o enabled = false diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyUtil.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyUtil.java index 86b3716..dcfa297 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyUtil.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyUtil.java @@ -1,6 +1,8 @@ package com.sillelien.dollar.relproxy.impl.jproxy; import com.sillelien.dollar.relproxy.RelProxyException; +import org.jetbrains.annotations.NotNull; + import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.File; @@ -20,7 +22,7 @@ */ public class JProxyUtil { - public static String getCanonicalPath(File file) + public static String getCanonicalPath(@NotNull File file) { try { @@ -32,7 +34,7 @@ public static String getCanonicalPath(File file) } } - public static String getFileExtension(File file) + public static String getFileExtension(@NotNull File file) { String path = file.getAbsolutePath(); int pos = path.lastIndexOf('.'); @@ -41,12 +43,12 @@ public static String getFileExtension(File file) return ""; } - public static File getParentDir(File file) + public static File getParentDir(@NotNull File file) { return file.getParentFile(); } - public static byte[] readURL(URL url) + public static byte[] readURL(@NotNull URL url) { URLConnection urlCon; try @@ -57,7 +59,7 @@ public static byte[] readURL(URL url) catch (IOException ex) { throw new RelProxyException(ex); } } - public static byte[] readFile(File file) + public static byte[] readFile(@NotNull File file) { FileInputStream fis = null; try @@ -72,12 +74,12 @@ public static byte[] readFile(File file) return readInputStream(fis); } - public static byte[] readInputStream(InputStream is) + public static byte[] readInputStream(@NotNull InputStream is) { return readInputStream(is,50); // 50Kb => unas 100 lecturas 5 Mb } - public static byte[] readInputStream(InputStream is,int bufferSizeKb) + public static byte[] readInputStream(@NotNull InputStream is, int bufferSizeKb) { ByteArrayOutputStream out = new ByteArrayOutputStream(); try @@ -102,7 +104,7 @@ public static byte[] readInputStream(InputStream is,int bufferSizeKb) return out.toByteArray(); } - public static void saveFile(File file,byte[] content) + public static void saveFile(@NotNull File file, @NotNull byte[] content) { File parent = getParentDir(file); if (parent != null) parent.mkdirs(); @@ -122,7 +124,7 @@ public static void saveFile(File file,byte[] content) } } - public static String readTextFile(File file,String encoding) + public static String readTextFile(@NotNull File file, @NotNull String encoding) { Reader reader = null; try @@ -134,7 +136,7 @@ public static String readTextFile(File file,String encoding) return readTextFile(reader); } - public static String readTextFile(Reader reader) + public static String readTextFile(@NotNull Reader reader) { BufferedReader br = null; try diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyImpl.java index 93c9fb9..8c9883c 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyImpl.java @@ -10,6 +10,8 @@ import com.sillelien.dollar.relproxy.jproxy.JProxyCompilerListener; import com.sillelien.dollar.relproxy.jproxy.JProxyDiagnosticsListener; import com.sillelien.dollar.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * @@ -30,12 +32,14 @@ public static ClassLoader getDefaultClassLoader() return Thread.currentThread().getContextClassLoader(); } - public ClassDescriptorSourceScript init(JProxyConfigImpl config) + @Nullable + public ClassDescriptorSourceScript init(@NotNull JProxyConfigImpl config) { return init(config,null,null); } - public ClassDescriptorSourceScript init(JProxyConfigImpl config,SourceScriptRoot scriptFile,ClassLoader classLoader) + @Nullable + public ClassDescriptorSourceScript init(@NotNull JProxyConfigImpl config, SourceScriptRoot scriptFile, ClassLoader classLoader) { super.init(config); @@ -80,11 +84,13 @@ public boolean start() return engine.start(); } + @NotNull @Override - public GenericProxyInvocationHandler createGenericProxyInvocationHandler(Object obj) + public GenericProxyInvocationHandler createGenericProxyInvocationHandler(@NotNull Object obj) { return new JProxyInvocationHandler(obj,this); } + @Nullable public abstract Class getMainParamClass(); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyInvocationHandler.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyInvocationHandler.java index 2cb390e..d4223e5 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyInvocationHandler.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyInvocationHandler.java @@ -2,6 +2,7 @@ package com.sillelien.dollar.relproxy.impl.jproxy.core; import com.sillelien.dollar.relproxy.impl.GenericProxyInvocationHandler; +import org.jetbrains.annotations.NotNull; /** * @@ -9,12 +10,13 @@ */ public class JProxyInvocationHandler extends GenericProxyInvocationHandler { - public JProxyInvocationHandler(Object obj,JProxyImpl root) + public JProxyInvocationHandler(@NotNull Object obj, JProxyImpl root) { super(root); this.verObj = new JProxyVersionedObject(obj,this); } + @NotNull public JProxyImpl getJProxyImpl() { return (JProxyImpl)root; diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyVersionedObject.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyVersionedObject.java index d3b07ca..2951dd4 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyVersionedObject.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyVersionedObject.java @@ -2,6 +2,9 @@ import com.sillelien.dollar.relproxy.impl.GenericProxyVersionedObject; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.lang.reflect.Field; /** @@ -12,17 +15,19 @@ public class JProxyVersionedObject extends GenericProxyVersionedObject { protected String className; - public JProxyVersionedObject(Object obj,JProxyInvocationHandler parent) + public JProxyVersionedObject(@NotNull Object obj, JProxyInvocationHandler parent) { super(obj,parent); this.className = obj.getClass().getName(); } + @NotNull public JProxyInvocationHandler getJProxyInvocationHandler() { return (JProxyInvocationHandler)parent; } + @Nullable @Override protected Class reloadClass() { diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java index d9b48e7..9e54d35 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java @@ -2,6 +2,9 @@ import com.sillelien.dollar.relproxy.RelProxyException; import com.sillelien.dollar.relproxy.impl.FileExt; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.io.File; /** @@ -12,7 +15,7 @@ public class FolderSourceList { protected FileExt[] sourceList; - public FolderSourceList(String[] sourcePathList,boolean expectedDirectory) + public FolderSourceList(@Nullable String[] sourcePathList, boolean expectedDirectory) { if (sourcePathList != null) // En el caso de shell interactivo es null { @@ -44,7 +47,8 @@ public FileExt[] getArray() return sourceList; } - public String buildClassNameFromFile(FileExt sourceFile) + @Nullable + public String buildClassNameFromFile(@NotNull FileExt sourceFile) { for(FileExt rootFolderOfSources : sourceList) { @@ -55,7 +59,7 @@ public String buildClassNameFromFile(FileExt sourceFile) throw new RelProxyException("File not found in source folders: " + sourceFile.getFile().getAbsolutePath()); } - public static String buildClassNameFromFile(FileExt sourceFile,FileExt rootFolderOfSources) + public static String buildClassNameFromFile(@NotNull FileExt sourceFile, @NotNull FileExt rootFolderOfSources) { String path = sourceFile.getCanonicalPath(); diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java index 328b1b9..8552bbc 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java @@ -3,6 +3,9 @@ import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.net.URL; /** @@ -11,16 +14,17 @@ */ public class JProxyClassLoader extends ClassLoader { + @NotNull protected final JProxyEngine engine; - public JProxyClassLoader(JProxyEngine engine) + public JProxyClassLoader(@NotNull JProxyEngine engine) { super(engine.getRootClassLoader()); this.engine = engine; } - public Class defineClass(ClassDescriptor classDesc) + public Class defineClass(@NotNull ClassDescriptor classDesc) { Object monitor = engine.getMonitor(); synchronized(monitor) @@ -34,7 +38,7 @@ public Class defineClass(ClassDescriptor classDesc) } @Override - protected Class findClass(String name) throws ClassNotFoundException + protected Class findClass(@NotNull String name) throws ClassNotFoundException { Object monitor = engine.getMonitor(); synchronized(monitor) @@ -54,7 +58,7 @@ protected Class findClass(String name) throws ClassNotFoundException } } - public Class loadClass(ClassDescriptor classDesc,boolean resolve) + public Class loadClass(@NotNull ClassDescriptor classDesc, boolean resolve) { Object monitor = engine.getMonitor(); synchronized(monitor) @@ -69,7 +73,8 @@ public Class loadClass(ClassDescriptor classDesc,boolean resolve) } } - public Class loadInnerClass(ClassDescriptorSourceUnit parentDesc,String innerClassName) + @Nullable + public Class loadInnerClass(@NotNull ClassDescriptorSourceUnit parentDesc, @NotNull String innerClassName) { Object monitor = engine.getMonitor(); synchronized(monitor) @@ -88,7 +93,7 @@ public Class loadInnerClass(ClassDescriptorSourceUnit parentDesc,String innerCla } @Override - protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException + protected Class loadClass(@NotNull String name, boolean resolve) throws ClassNotFoundException { // Inspiraciones en URLClassLoader.findClass y en el propio análisis de ClassLoader.loadClass // Lo redefinimos por si acaso porque el objetivo es recargar todas las clases hot-reloaded en este ClassLoader y no delegar en el parent @@ -140,7 +145,7 @@ protected Class loadClass(String name, boolean resolve) throws ClassNotFoundE } } - private byte[] getClassBytesFromResource(String className) + private byte[] getClassBytesFromResource(@NotNull String className) { String relClassPath = ClassDescriptor.getRelativeClassFilePathFromClassName(className); URL urlClass = getResource(relClassPath); diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java index 8fc57ad..efdfdd7 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java @@ -10,6 +10,9 @@ import com.sillelien.dollar.relproxy.jproxy.JProxyCompilerListener; import com.sillelien.dollar.relproxy.jproxy.JProxyDiagnosticsListener; import com.sillelien.dollar.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.util.LinkedList; import java.util.Timer; import java.util.TimerTask; @@ -22,12 +25,15 @@ public class JProxyEngine { protected final Object monitor = new Object(); // Podríamos usar este objeto JProxyEngine directamente pero el monitor es mejor para análisis de dependencias protected final JProxyImpl parent; + @NotNull protected final JProxyEngineChangeDetectorAndCompiler delegateChangeDetector; protected final ClassLoader rootClassLoader; + @Nullable protected JProxyClassLoader customClassLoader; protected final long scanPeriod; protected final String sourceEncoding = "UTF-8"; // Por ahora, provisional public volatile boolean stop = false; + @Nullable protected TimerTask task; protected boolean pendingReload = false; protected final boolean enabled; @@ -44,6 +50,7 @@ public JProxyEngine(JProxyImpl parent,boolean enabled,SourceScriptRoot scriptFil this.customClassLoader = null; //new JProxyClassLoader(this); } + @NotNull public Object getMonitor() { return monitor; @@ -59,6 +66,7 @@ public boolean isEnabled() return enabled; } + @Nullable public ClassDescriptorSourceScript init() { synchronized(getMonitor()) @@ -80,6 +88,7 @@ public JProxyClassLoader getJProxyClassLoader() } */ + @Nullable public ClassLoader getCurrentClassLoader() { if (customClassLoader != null) @@ -133,6 +142,7 @@ public ClassLoader getRootClassLoader() return rootClassLoader; } + @NotNull public String getSourceEncoding() { return sourceEncoding; @@ -179,7 +189,8 @@ public boolean start() - public ClassDescriptor getClassDescriptor(String className) + @Nullable + public ClassDescriptor getClassDescriptor(@NotNull String className) { synchronized(getMonitor()) { @@ -187,7 +198,8 @@ public ClassDescriptor getClassDescriptor(String className) } } - public Class findClass(String className) + @Nullable + public Class findClass(@NotNull String className) { // Si ya está cargada la devuelve, y si no se cargó por ningún JProxyClassLoader se intenta cargar por el parent ClassLoader, por lo que siempre devolverá distinto de null si la clase está en el classpath, que debería ser lo normal synchronized(getMonitor()) @@ -220,14 +232,14 @@ private void addNewClassLoader() - private Class reloadSource(ClassDescriptorSourceUnit sourceFile) + private Class reloadSource(@NotNull ClassDescriptorSourceUnit sourceFile) { Class clasz = customClassLoader.loadClass(sourceFile,true); reloadInnerClassesOnly(sourceFile,clasz); return clasz; } - private void reloadInnerClassesOnly(ClassDescriptorSourceUnit sourceFile,Class classParent) + private void reloadInnerClassesOnly(@NotNull ClassDescriptorSourceUnit sourceFile, @NotNull Class classParent) { LinkedList innerClassDescList = sourceFile.getInnerClassDescriptors(); @@ -262,11 +274,13 @@ private void reloadInnerClassesOnly(ClassDescriptorSourceUnit sourceFile,Class c } } + @Nullable public ClassDescriptorSourceScript detectChangesInSources() { return delegateChangeDetector.detectChangesInSources(); } + @Nullable public ClassDescriptorSourceScript detectChangesInSourcesAndReload() { ClassDescriptorSourceScript res = detectChangesInSources(); diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java index 4460e33..4e6f179 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java @@ -16,6 +16,9 @@ import com.sillelien.dollar.relproxy.jproxy.JProxyCompilerListener; import com.sillelien.dollar.relproxy.jproxy.JProxyDiagnosticsListener; import com.sillelien.dollar.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.io.File; import java.util.ArrayList; import java.util.LinkedList; @@ -27,12 +30,14 @@ public class JProxyEngineChangeDetectorAndCompiler { protected final JProxyEngine engine; - protected final JProxyCompilerInMemory compiler; + @NotNull + protected final JProxyCompilerInMemory compiler; protected final FolderSourceList folderSourceList; protected final FolderSourceList requiredExtraJarPaths; protected final SourceScriptRoot scriptFile; // Puede ser nulo protected final String folderClasses; // Puede ser nulo (es decir NO salvar como .class los cambios) protected final JProxyInputSourceFileExcludedListener excludedListener; + @NotNull protected final JavaSourcesSearch sourcesSearch; protected final JProxyCompilerListener compilerListener; protected volatile ClassDescriptorSourceFileRegistry sourceRegistry; @@ -77,7 +82,8 @@ public ClassDescriptorSourceFileRegistry getClassDescriptorSourceFileRegistry() return sourceRegistry; } - public ClassDescriptor getClassDescriptor(String className) + @Nullable + public ClassDescriptor getClassDescriptor(@NotNull String className) { return sourceRegistry.getClassDescriptor(className); } @@ -92,7 +98,7 @@ private JProxyCompilerListener getJProxyCompilerListener() return compilerListener; } - private void cleanBeforeCompile(ClassDescriptorSourceUnit sourceFile) + private void cleanBeforeCompile(@NotNull ClassDescriptorSourceUnit sourceFile) { if (isSaveClassesMode()) deleteClasses(sourceFile); // Antes de que nos las carguemos en memoria la clase principal y las inner tras recompilar @@ -100,7 +106,7 @@ private void cleanBeforeCompile(ClassDescriptorSourceUnit sourceFile) sourceFile.cleanOnSourceCodeChanged(); // El código fuente nuevo puede haber cambiado totalmente las innerclasses antiguas (añadido, eliminado) y por supuesto el bytecode necesita olvidarse } - private void compile(ClassDescriptorSourceUnit sourceFile,JProxyCompilerContext context) + private void compile(@NotNull ClassDescriptorSourceUnit sourceFile, @NotNull JProxyCompilerContext context) { if (sourceFile.getClassBytes() != null) return; // Ya ha sido compilado seguramente por dependencia de un archivo compilado inmediatamente antes, recuerda que el atributo classBytes se pone a null antes de compilar los archivos cambiados/nuevos @@ -108,6 +114,7 @@ private void compile(ClassDescriptorSourceUnit sourceFile,JProxyCompilerContext compiler.compileSourceFile(sourceFile,context,engine.getCurrentClassLoader(),sourceRegistry); } + @Nullable public ClassDescriptorSourceScript detectChangesInSources() { Object monitor = getJProxyEngine().getMonitor(); @@ -251,7 +258,7 @@ else if (srcUnit instanceof SourceScriptRootInMemory) // Caso de shell interacti return scriptFileDesc; } - private void saveClasses(ClassDescriptorSourceUnit sourceFile) + private void saveClasses(@NotNull ClassDescriptorSourceUnit sourceFile) { // Salvamos la clase principal { @@ -271,7 +278,7 @@ private void saveClasses(ClassDescriptorSourceUnit sourceFile) } } - private void deleteClasses(ClassDescriptorSourceUnit sourceFile) + private void deleteClasses(@NotNull ClassDescriptorSourceUnit sourceFile) { // Puede ocurrir que esta clase nunca se haya cargado y se ha modificado el código fuente y queramos limpiar los .class correspondientes pues se van a recrear // como no conocemos qué inner clases están asociadas para saber que .class hay que eliminar, pues lo que hacemos es directamente obtener los .class que hay diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java index 536113b..459278f 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java @@ -13,75 +13,79 @@ import com.sillelien.dollar.relproxy.impl.FileExt; import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; import com.sillelien.dollar.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.io.File; import java.net.URL; import java.util.LinkedList; /** + * Additions hello@neilellis.me * * @author jmarranz */ -public class JavaSourcesSearch -{ +public class JavaSourcesSearch { + @NotNull protected final JProxyEngineChangeDetectorAndCompiler parent; - - public JavaSourcesSearch(JProxyEngineChangeDetectorAndCompiler parent) - { + + public JavaSourcesSearch(@NotNull JProxyEngineChangeDetectorAndCompiler parent) { + if (parent == null) { + throw new IllegalArgumentException("JProxyEngineChangeDetectorAndCompiler parent was null"); + } this.parent = parent; } - public JProxyEngineChangeDetectorAndCompiler getJProxyEngineChangeDetectorAndCompiler() - { + @NotNull + public JProxyEngineChangeDetectorAndCompiler getJProxyEngineChangeDetectorAndCompiler() { return parent; } - - public ClassDescriptorSourceScript sourceFileSearch(boolean firstTime,SourceScriptRoot scriptFile,ClassDescriptorSourceFileRegistry sourceRegistry,LinkedList updatedSourceFiles,LinkedList newSourceFiles) - { - ClassDescriptorSourceScript scriptFileDesc = (scriptFile == null) ? null : processSourceFileScript(firstTime,scriptFile,sourceRegistry,updatedSourceFiles,newSourceFiles); - FileExt[] folderSourceList = parent.getFolderSourceList().getArray(); - if (folderSourceList == null) // Es el caso de shell interactivo o code snippet + + @Nullable + public ClassDescriptorSourceScript sourceFileSearch(boolean firstTime, @Nullable SourceScriptRoot scriptFile, @NotNull ClassDescriptorSourceFileRegistry sourceRegistry, @NotNull LinkedList updatedSourceFiles, @NotNull LinkedList newSourceFiles) { + ClassDescriptorSourceScript scriptFileDesc = (scriptFile == null) ? null : processSourceFileScript(firstTime, scriptFile, sourceRegistry, updatedSourceFiles, newSourceFiles); + @NotNull FolderSourceList folderSourceList = parent.getFolderSourceList(); + FileExt[] folderSourceArray = folderSourceList.getArray(); + // Es el caso de shell interactivo o code snippet + if (folderSourceArray == null) { return scriptFileDesc; - + } + boolean allEmpty = true; - String scriptFileJavaCannonPath = (scriptFile != null && (scriptFile instanceof SourceScriptRootFileJavaExt)) ? ((SourceScriptRootFileJavaExt)scriptFile).getFileExt().getCanonicalPath() : null; + String scriptFileJavaCannonPath = (scriptFile != null && (scriptFile instanceof SourceScriptRootFileJavaExt)) ? ((SourceScriptRootFileJavaExt) scriptFile).getFileExt().getCanonicalPath() : null; - for(int i = 0; i < folderSourceList.length; i++) - { - FileExt rootFolderOfSources = folderSourceList[i]; - String[] children = rootFolderOfSources.getFile().list(); - if (children == null) continue; // El que ha configurado los rootFolders es tonto y ha puesto alguno nulo o no es válido el path + for (int i = 0; i < folderSourceArray.length; i++) { + FileExt rootFolderOfSources = folderSourceArray[i]; + String[] children = rootFolderOfSources.getFile().list(); + if (children == null) + continue; // El que ha configurado los rootFolders es tonto y ha puesto alguno nulo o no es válido el path if (children.length == 0) continue; // Empty if (allEmpty) allEmpty = false; - recursiveSourceFileJavaSearch(firstTime,scriptFileJavaCannonPath, i ,rootFolderOfSources,children,sourceRegistry,updatedSourceFiles,newSourceFiles); - } - + recursiveSourceFileJavaSearch(firstTime, scriptFileJavaCannonPath, i, rootFolderOfSources, children, sourceRegistry, updatedSourceFiles, newSourceFiles); + } + if (allEmpty) throw new RelProxyException("All specified input source folders are empty"); return scriptFileDesc; } - - private void recursiveSourceFileJavaSearch(boolean firstTime,String scriptFileJavaCannonPath,int rootFolderOfSourcesIndex,FileExt parentPath,String[] relPathList,ClassDescriptorSourceFileRegistry sourceRegistry,LinkedList updatedSourceFiles,LinkedList newSourceFiles) - { - FileExt rootFolderOfSources = parent.getFolderSourceList().getArray()[rootFolderOfSourcesIndex]; - JProxyInputSourceFileExcludedListener listener = parent.getJProxyInputSourceFileExcludedListener(); - - for(String relPath : relPathList) - { + + private void recursiveSourceFileJavaSearch(boolean firstTime, @Nullable String scriptFileJavaCannonPath, int rootFolderOfSourcesIndex, @NotNull FileExt parentPath, @NotNull String[] relPathList, @NotNull ClassDescriptorSourceFileRegistry sourceRegistry, @NotNull LinkedList updatedSourceFiles, @NotNull LinkedList newSourceFiles) { + FileExt rootFolderOfSources = parent.getFolderSourceList().getArray()[rootFolderOfSourcesIndex]; + JProxyInputSourceFileExcludedListener listener = parent.getJProxyInputSourceFileExcludedListener(); + + for (String relPath : relPathList) { File file = new File(parentPath.getCanonicalPath() + "/" + relPath); - FileExt fileExt = new FileExt(file); - if (file.isDirectory()) - { - if (listener != null && listener.isExcluded(file,rootFolderOfSources.getFile())) - continue; - + FileExt fileExt = new FileExt(file); + if (file.isDirectory()) { + if (listener != null && listener.isExcluded(file, rootFolderOfSources.getFile())) + continue; + String[] children = file.list(); // Si está vacío el array está vacío pero existe - recursiveSourceFileJavaSearch(firstTime,scriptFileJavaCannonPath,rootFolderOfSourcesIndex,fileExt,children,sourceRegistry,updatedSourceFiles,newSourceFiles); - } - else - { + recursiveSourceFileJavaSearch(firstTime, scriptFileJavaCannonPath, rootFolderOfSourcesIndex, fileExt, children, sourceRegistry, updatedSourceFiles, newSourceFiles); + } else { String ext = JProxyUtil.getFileExtension(file); // Si no tiene extensión devuelve "" if (!"java".equals(ext)) continue; //if (!"jsh".equals(ext)) continue; @@ -89,105 +93,93 @@ private void recursiveSourceFileJavaSearch(boolean firstTime,String scriptFileJa String cannonPath = JProxyUtil.getCanonicalPath(file); if (scriptFileJavaCannonPath != null && scriptFileJavaCannonPath.equals(cannonPath)) continue; // Es el propio archivo script inicial que es .java, así evitamos considerarlo dos veces - - if (listener != null && listener.isExcluded(file,rootFolderOfSources.getFile())) + + if (listener != null && listener.isExcluded(file, rootFolderOfSources.getFile())) continue; - - SourceFileJavaNormal sourceFile = new SourceFileJavaNormal(fileExt,rootFolderOfSources); - processSourceFileJava(firstTime,sourceFile,sourceRegistry,updatedSourceFiles,newSourceFiles); + + SourceFileJavaNormal sourceFile = new SourceFileJavaNormal(fileExt, rootFolderOfSources); + processSourceFileJava(firstTime, sourceFile, sourceRegistry, updatedSourceFiles, newSourceFiles); } } - } - - private ClassDescriptorSourceScript processSourceFileScript(boolean firstTime,SourceScriptRoot file,ClassDescriptorSourceFileRegistry sourceRegistry,LinkedList updatedSourceFiles,LinkedList newSourceFiles) - { - return (ClassDescriptorSourceScript)processSourceFile(firstTime,file,true,sourceRegistry,updatedSourceFiles,newSourceFiles); - } - - private ClassDescriptorSourceFileJava processSourceFileJava(boolean firstTime,SourceFileJavaNormal file,ClassDescriptorSourceFileRegistry sourceRegistry,LinkedList updatedSourceFiles,LinkedList newSourceFiles) - { - return (ClassDescriptorSourceFileJava)processSourceFile(firstTime,file,false,sourceRegistry,updatedSourceFiles,newSourceFiles); } - - private ClassDescriptorSourceUnit processSourceFile(boolean firstTime,SourceUnit file,boolean script,ClassDescriptorSourceFileRegistry sourceRegistry,LinkedList updatedSourceFiles,LinkedList newSourceFiles) - { + + @NotNull + private ClassDescriptorSourceScript processSourceFileScript(boolean firstTime, @NotNull SourceScriptRoot file, @NotNull ClassDescriptorSourceFileRegistry sourceRegistry, @NotNull LinkedList updatedSourceFiles, @NotNull LinkedList newSourceFiles) { + return (ClassDescriptorSourceScript) processSourceFile(firstTime, file, true, sourceRegistry, updatedSourceFiles, newSourceFiles); + } + + @NotNull + private ClassDescriptorSourceFileJava processSourceFileJava(boolean firstTime, @NotNull SourceFileJavaNormal file, @NotNull ClassDescriptorSourceFileRegistry sourceRegistry, @NotNull LinkedList updatedSourceFiles, @NotNull LinkedList newSourceFiles) { + return (ClassDescriptorSourceFileJava) processSourceFile(firstTime, file, false, sourceRegistry, updatedSourceFiles, newSourceFiles); + } + + @Nullable + private ClassDescriptorSourceUnit processSourceFile(boolean firstTime, @NotNull SourceUnit file, boolean script, @NotNull ClassDescriptorSourceFileRegistry sourceRegistry, @NotNull LinkedList updatedSourceFiles, @NotNull LinkedList newSourceFiles) { JProxyEngine engine = parent.getJProxyEngine(); - String className = file.getClassName(); - + String className = file.getClassName(); + long timestampSourceFile = file.lastModified(); ClassDescriptorSourceUnit sourceFile; - if (!firstTime) - { + if (!firstTime) { Object monitor = engine.getMonitor(); - synchronized(monitor) - { + synchronized (monitor) { sourceFile = sourceRegistry.getClassDescriptorSourceUnit(className); } - + if (sourceFile != null) // Cambiado { long oldTimestamp = sourceFile.getTimestamp(); - - if (timestampSourceFile > oldTimestamp) - { - synchronized(monitor) - { + + if (timestampSourceFile > oldTimestamp) { + synchronized (monitor) { sourceFile.updateTimestamp(timestampSourceFile); } updatedSourceFiles.add(sourceFile); } - sourceFile.setPendingToRemove( false ); // Encontrado, no se elimina porque sigue existiendo - } - else // Clase nueva + sourceFile.setPendingToRemove(false); // Encontrado, no se elimina porque sigue existiendo + } else // Clase nueva { - sourceFile = ClassDescriptorSourceUnit.create(script,engine,className,file,timestampSourceFile); - sourceFile.setPendingToRemove( false ); // Está ya por defecto pero para que quede claro + sourceFile = ClassDescriptorSourceUnit.create(script, engine, className, file, timestampSourceFile); + sourceFile.setPendingToRemove(false); // Está ya por defecto pero para que quede claro newSourceFiles.add(sourceFile); } - } - else // Primera vez, vemos si el código fuente se ha cambiado respecto a los .class en el sistema de archivos + } else // Primera vez, vemos si el código fuente se ha cambiado respecto a los .class en el sistema de archivos { String relClassPath = ClassDescriptor.getRelativeClassFilePathFromClassName(className); ClassLoader parentClassLoader = engine.getRootClassLoader(); URL urlClass = parentClassLoader.getResource(relClassPath); - if (urlClass != null) - { + if (urlClass != null) { String urlClassExt = urlClass.toExternalForm(); // Si el .class está en un JAR podríamos obtener el timestamp del archivo dentro del jar pero que haya un .java "fuera" reloadable indica que queremos "reemplazar" el del jar por lo que siempre se considerará que el archivo fuente ha sido modificado más reciente long timestampCompiledClass = urlClassExt.startsWith("file:") ? new File(urlClass.getPath()).lastModified() : 0; // 0 cuando está en un JAR - if (timestampSourceFile > timestampCompiledClass) - { - sourceFile = ClassDescriptorSourceUnit.create(script,engine,className,file,timestampSourceFile); + if (timestampSourceFile > timestampCompiledClass) { + sourceFile = ClassDescriptorSourceUnit.create(script, engine, className, file, timestampSourceFile); updatedSourceFiles.add(sourceFile); // Hay que recompilar //System.out.println("UPDATED: " + className + " " + urlClass.toExternalForm() + " " + (timestampSourceFile - timestampCompiledClass)); - } - else - { + } else { // Esto es lo normal en carga si no hemos tocado el código tras el deploy, que el .class sea más reciente que el .java - sourceFile = ClassDescriptorSourceUnit.create(script,engine,className,file,timestampCompiledClass); + sourceFile = ClassDescriptorSourceUnit.create(script, engine, className, file, timestampCompiledClass); byte[] classBytes = JProxyUtil.readURL(urlClass); - sourceFile.setClassBytes(classBytes); + sourceFile.setClassBytes(classBytes); // Falta cargar las posibles inner classes, hay que tener en cuenta que este archivo NO se va a compilar porque no ha cambiado respecto a .class conocido //System.out.println("NOT UPDATED: " + className + " " + urlClass.toExternalForm() + " " + (timestampSourceFile - timestampCompiledClass)); } - } - else // No hay .class, es un archivo fuente nuevo creado antes de cargar la app web, hay que compilar si o si + } else // No hay .class, es un archivo fuente nuevo creado antes de cargar la app web, hay que compilar si o si { - sourceFile = ClassDescriptorSourceUnit.create(script,engine,className,file,timestampSourceFile); + sourceFile = ClassDescriptorSourceUnit.create(script, engine, className, file, timestampSourceFile); newSourceFiles.add(sourceFile); } - + Object monitor = engine.getMonitor(); - synchronized(monitor) - { + synchronized (monitor) { sourceRegistry.addClassDescriptorSourceUnit(sourceFile); // El registro de archivos se hace por primera vez por lo que hay que añadirlos todos inicialmente, updatedSourceFiles y newSourceFiles indicarán en este caso los que hay que recompilar además } } return sourceFile; - } + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java index 99bc7ac..3633838 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java @@ -1,5 +1,7 @@ package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc; +import org.jetbrains.annotations.NotNull; + import java.io.File; /** @@ -8,13 +10,16 @@ */ public abstract class ClassDescriptor { + @NotNull protected final String className; // El nombre basado en puntos pero usando $ en el caso de innerclasses + @NotNull protected final String simpleClassName; // className sin el package + @NotNull protected final String packageName; // El package pero acabado en un "." o bien "" si no hay package, el motivo de acabar en un punto es simplemente para poder concatenar ciegamente el package y el simpleClassName protected byte[] classBytes; protected Class clasz; - public ClassDescriptor(String className) + public ClassDescriptor(@NotNull String className) { this.className = className; int pos = className.lastIndexOf('.'); @@ -24,16 +29,19 @@ public ClassDescriptor(String className) public abstract boolean isInnerClass(); - public String getClassName() + @NotNull + public String getClassName() { return className; } + @NotNull public String getSimpleClassName() { return simpleClassName; } + @NotNull public String getPackageName() { return packageName; @@ -71,7 +79,7 @@ public String getClassFileNameFromClassName() } */ - public static String getClassFileNameFromClassName(String className) + public static String getClassFileNameFromClassName(@NotNull String className) { // Es válido también para las innerclasses (ej Nombre$Otro => Nombre$Otro.class, Nombre$1 => Nombre$1.class, Nombre$1Nombre => Nombre$1Nombre.class int pos = className.lastIndexOf("."); @@ -79,12 +87,13 @@ public static String getClassFileNameFromClassName(String className) return className + ".class"; } - public static String getRelativeClassFilePathFromClassName(String className) + public static String getRelativeClassFilePathFromClassName(@NotNull String className) { return className.replace('.','/') + ".class"; // alternativa: className.replaceAll("\\.", "/") + ".class" } - public static String getRelativePackagePathFromClassName(String className) + @NotNull + public static String getRelativePackagePathFromClassName(@NotNull String className) { String packageName = className.replace('.','/'); int pos = packageName.lastIndexOf('/'); @@ -92,7 +101,7 @@ public static String getRelativePackagePathFromClassName(String className) return packageName.substring(0,pos); } - public static File getAbsoluteClassFilePathFromClassNameAndClassPath(String className,String classPath) + public static File getAbsoluteClassFilePathFromClassNameAndClassPath(@NotNull String className, String classPath) { String relativePath = getRelativeClassFilePathFromClassName(className); classPath = classPath.trim(); @@ -100,7 +109,7 @@ public static File getAbsoluteClassFilePathFromClassNameAndClassPath(String clas return new File(classPath + relativePath); } - public static String getClassNameFromRelativeClassFilePath(String path) + public static String getClassNameFromRelativeClassFilePath(@NotNull String path) { // Ej. org/w3c/dom/Element.class => org.w3c.dom.Element String binaryName = path.replaceAll("/", "."); diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java index 7190866..118e81b 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java @@ -1,5 +1,7 @@ package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc; +import org.jetbrains.annotations.NotNull; + /** * * @author jmarranz @@ -8,7 +10,7 @@ public class ClassDescriptorInner extends ClassDescriptor { protected final ClassDescriptorSourceUnit parent; - public ClassDescriptorInner(String className,ClassDescriptorSourceUnit parent) + public ClassDescriptorInner(@NotNull String className, ClassDescriptorSourceUnit parent) { super(className); this.parent = parent; diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java index 1300fea..351d73b 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java @@ -3,6 +3,7 @@ import com.sillelien.dollar.relproxy.impl.FileExt; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; +import org.jetbrains.annotations.NotNull; /** * @@ -10,11 +11,12 @@ */ public class ClassDescriptorSourceFileJava extends ClassDescriptorSourceUnit { - public ClassDescriptorSourceFileJava(JProxyEngine engine,String className, SourceFileJavaNormal sourceFile, long timestamp) + public ClassDescriptorSourceFileJava(JProxyEngine engine, @NotNull String className, SourceFileJavaNormal sourceFile, long timestamp) { super(engine,className, sourceFile, timestamp); } + @NotNull public SourceFileJavaNormal getSourceFileJavaNormal() { return (SourceFileJavaNormal)sourceUnit; diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java index bf0b64b..a532809 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java @@ -1,5 +1,8 @@ package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.util.Collection; import java.util.HashMap; import java.util.LinkedList; @@ -11,6 +14,7 @@ */ public class ClassDescriptorSourceFileRegistry { + @NotNull protected final Map sourceUnitMapByClassName; public ClassDescriptorSourceFileRegistry() @@ -18,7 +22,7 @@ public ClassDescriptorSourceFileRegistry() this.sourceUnitMapByClassName = new HashMap(); } - public ClassDescriptorSourceFileRegistry(ClassDescriptorSourceFileRegistry origin) + public ClassDescriptorSourceFileRegistry(@NotNull ClassDescriptorSourceFileRegistry origin) { this.sourceUnitMapByClassName = new HashMap( origin.sourceUnitMapByClassName ); } @@ -28,6 +32,7 @@ public boolean isEmpty() return sourceUnitMapByClassName.isEmpty(); } + @NotNull public Collection getClassDescriptorSourceFileColl() { return sourceUnitMapByClassName.values(); @@ -43,7 +48,7 @@ public ClassDescriptorSourceUnit removeClassDescriptorSourceUnit(String classNam return sourceUnitMapByClassName.remove(className); } - public void addClassDescriptorSourceUnit(ClassDescriptorSourceUnit sourceFile) + public void addClassDescriptorSourceUnit(@NotNull ClassDescriptorSourceUnit sourceFile) { sourceUnitMapByClassName.put(sourceFile.getClassName(), sourceFile); } @@ -54,7 +59,8 @@ public void setAllClassDescriptorSourceFilesPendingToRemove(boolean pending) entries.getValue().setPendingToRemove(pending); } - public LinkedList getAllClassDescriptorSourceFilesPendingToRemove(LinkedList deletedSourceFiles) + @NotNull + public LinkedList getAllClassDescriptorSourceFilesPendingToRemove(@NotNull LinkedList deletedSourceFiles) { for(Map.Entry entries : sourceUnitMapByClassName.entrySet()) { @@ -66,7 +72,8 @@ public LinkedList getAllClassDescriptorSourceFilesPen return deletedSourceFiles; } - public ClassDescriptor getClassDescriptor(String className) + @Nullable + public ClassDescriptor getClassDescriptor(@NotNull String className) { // Puede ser el de una innerclass // Las innerclasses no están como tales en sourceFileMap pues sólo está la clase contenedora pero también la consideramos hotloadable diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java index 0dda05d..8b76640 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java @@ -4,6 +4,8 @@ import com.sillelien.dollar.relproxy.impl.jproxy.core.JProxyImpl; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import org.jetbrains.annotations.NotNull; + import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.LinkedList; @@ -18,7 +20,7 @@ public class ClassDescriptorSourceScript extends ClassDescriptorSourceUnit { protected String source; - public ClassDescriptorSourceScript(JProxyEngine engine,String className,SourceScriptRoot sourceFile,long timestamp) + public ClassDescriptorSourceScript(JProxyEngine engine, @NotNull String className, SourceScriptRoot sourceFile, long timestamp) { super(engine,className, sourceFile, timestamp); @@ -26,6 +28,7 @@ public ClassDescriptorSourceScript(JProxyEngine engine,String className,SourceSc } + @NotNull public SourceScriptRoot getSourceScript() { return (SourceScriptRoot)sourceUnit; @@ -73,7 +76,7 @@ else if (mainParamClass.equals(ScriptContext.class)) this.source = finalCode.toString(); } - private boolean isCompleteClass(String code) + private boolean isCompleteClass(@NotNull String code) { // Buscamos si hay un " class ..." o un "import..." al comienzo para soportar la definición de una clase completa como script int pos = code.indexOf("class"); @@ -96,7 +99,7 @@ private boolean isCompleteClass(String code) return ("private".equals(visibility) || "public".equals(visibility) || "protected".equals(visibility)); } - private int getFirstPosIgnoringCommentsAndSeparators(String code) + private int getFirstPosIgnoringCommentsAndSeparators(@NotNull String code) { int i = -1; for(i = 0; i < code.length(); i++) @@ -122,12 +125,12 @@ else if (c2 == '*') return i; } - private int getFirstPosIgnoringOneLineComment(String code,int start) + private int getFirstPosIgnoringOneLineComment(@NotNull String code, int start) { return code.indexOf('\n',start); } - private int getFirstPosIgnoringMultiLineComment(String code,int start) + private int getFirstPosIgnoringMultiLineComment(@NotNull String code, int start) { return code.indexOf("*/", start); } @@ -146,7 +149,7 @@ public String getSourceCode() return source; } - public void callMainMethod(LinkedList argsToScript) throws Throwable + public void callMainMethod(@NotNull LinkedList argsToScript) throws Throwable { try { @@ -168,7 +171,7 @@ public Object callMainMethod(ScriptEngine engine,ScriptContext context) throws T return callMainMethod(scriptClass,engine,context); } - public static Object callMainMethod(Class scriptClass,ScriptEngine engine,ScriptContext context) throws Throwable + public static Object callMainMethod(@NotNull Class scriptClass, ScriptEngine engine, ScriptContext context) throws Throwable { try { diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java index 4896ee1..fa8287e 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java @@ -4,6 +4,9 @@ import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceUnit; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.util.LinkedList; /** @@ -18,7 +21,7 @@ public abstract class ClassDescriptorSourceUnit extends ClassDescriptor protected LinkedList innerClasses; protected boolean pendingToRemove = false; // Se usa como monohilo, no hay problemas de sincronización - public ClassDescriptorSourceUnit(JProxyEngine engine,String className,SourceUnit sourceFile, long timestamp) + public ClassDescriptorSourceUnit(JProxyEngine engine, @NotNull String className, SourceUnit sourceFile, long timestamp) { super(className); this.engine = engine; @@ -26,7 +29,8 @@ public ClassDescriptorSourceUnit(JProxyEngine engine,String className,SourceUnit this.timestamp = timestamp; } - public static ClassDescriptorSourceUnit create(boolean script,JProxyEngine engine,String className,SourceUnit sourceFile, long timestamp) + @Nullable + public static ClassDescriptorSourceUnit create(boolean script, JProxyEngine engine, @NotNull String className, SourceUnit sourceFile, long timestamp) { if (sourceFile instanceof SourceScriptRoot) return new ClassDescriptorSourceScript(engine,className,(SourceScriptRoot)sourceFile,timestamp); @@ -41,6 +45,7 @@ public SourceUnit getSourceUnit() return sourceUnit; } + @NotNull public String getEncoding() { return engine.getSourceEncoding(); @@ -81,7 +86,7 @@ public void cleanOnSourceCodeChanged() clearInnerClassDescriptors(); // El código fuente nuevo puede haber cambiado totalmente las innerclasses antiguas (añadido, eliminado) } - public boolean isInnerClass(String className) + public boolean isInnerClass(@NotNull String className) { int pos = className.lastIndexOf('$'); if (pos == -1) @@ -101,7 +106,8 @@ public void clearInnerClassDescriptors() innerClasses.clear(); } - public ClassDescriptorInner getInnerClassDescriptor(String className,boolean addWhenMissing) + @Nullable + public ClassDescriptorInner getInnerClassDescriptor(@NotNull String className, boolean addWhenMissing) { if (innerClasses != null) { @@ -117,7 +123,8 @@ public ClassDescriptorInner getInnerClassDescriptor(String className,boolean add return addInnerClassDescriptor(className); } - public ClassDescriptorInner addInnerClassDescriptor(String className) + @Nullable + public ClassDescriptorInner addInnerClassDescriptor(@NotNull String className) { if (!isInnerClass(className)) return null; diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java index c8b20c8..8900a12 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java @@ -12,6 +12,8 @@ import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.JProxyEngineChangeDetectorAndCompiler; import com.sillelien.dollar.relproxy.jproxy.JProxyDiagnosticsListener; +import org.jetbrains.annotations.NotNull; + import java.io.File; import java.util.ArrayList; import java.util.LinkedList; @@ -42,14 +44,15 @@ public JProxyCompilerInMemory(JProxyEngineChangeDetectorAndCompiler engine,Itera this.compiler = ToolProvider.getSystemJavaCompiler(); } - public JProxyCompilerContext createJProxyCompilerContext() + @NotNull + public JProxyCompilerContext createJProxyCompilerContext() { DiagnosticCollector diagnostics = new DiagnosticCollector(); StandardJavaFileManager standardFileManager = compiler.getStandardFileManager(diagnostics, null, null); return new JProxyCompilerContext(standardFileManager,diagnostics,diagnosticsListener); } - public void compileSourceFile(ClassDescriptorSourceUnit sourceFileDesc,JProxyCompilerContext context,ClassLoader currentClassLoader,ClassDescriptorSourceFileRegistry sourceRegistry) + public void compileSourceFile(@NotNull ClassDescriptorSourceUnit sourceFileDesc, @NotNull JProxyCompilerContext context, ClassLoader currentClassLoader, @NotNull ClassDescriptorSourceFileRegistry sourceRegistry) { //File sourceFile = sourceFileDesc.getSourceFile(); LinkedList outClassList = compile(sourceFileDesc,context,currentClassLoader,sourceRegistry); @@ -104,7 +107,7 @@ public void compileSourceFile(ClassDescriptorSourceUnit sourceFileDesc,JProxyCom } } - private LinkedList compile(ClassDescriptorSourceUnit sourceFileDesc,JProxyCompilerContext context,ClassLoader currentClassLoader,ClassDescriptorSourceFileRegistry sourceRegistry) + private LinkedList compile(ClassDescriptorSourceUnit sourceFileDesc, @NotNull JProxyCompilerContext context, ClassLoader currentClassLoader, ClassDescriptorSourceFileRegistry sourceRegistry) { // http://stackoverflow.com/questions/12173294/compiling-fully-in-memory-with-javax-tools-javacompiler // http://www.accordess.com/wpblog/an-overview-of-java-compilation-api-jsr-199/ @@ -151,7 +154,7 @@ else if (sourceFileDesc instanceof ClassDescriptorSourceScript) return classObj; } - private boolean compile(Iterable compilationUnits,JavaFileManager fileManager,JProxyCompilerContext context) + private boolean compile(Iterable compilationUnits, JavaFileManager fileManager, @NotNull JProxyCompilerContext context) { /* String systemClassPath = System.getProperty("java.class.path"); diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java index 7de7a8e..0385854 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java @@ -7,6 +7,8 @@ import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import org.jetbrains.annotations.NotNull; + import java.io.IOException; import java.util.Collection; import java.util.Collections; @@ -33,23 +35,26 @@ public class JavaFileManagerInMemory extends ForwardingJavaFileManager { private final LinkedList outputClassList = new LinkedList(); - private final JavaFileObjectInputClassFinderByClassLoader classFinder; + @NotNull + private final JavaFileObjectInputClassFinderByClassLoader classFinder; private final ClassDescriptorSourceFileRegistry sourceRegistry; - public JavaFileManagerInMemory(StandardJavaFileManager standardFileManager,ClassLoader classLoader,ClassDescriptorSourceFileRegistry sourceRegistry,FolderSourceList requiredExtraJarPaths) + public JavaFileManagerInMemory(@NotNull StandardJavaFileManager standardFileManager, ClassLoader classLoader, ClassDescriptorSourceFileRegistry sourceRegistry, FolderSourceList requiredExtraJarPaths) { super(standardFileManager); this.sourceRegistry = sourceRegistry; this.classFinder = new JavaFileObjectInputClassFinderByClassLoader(classLoader,requiredExtraJarPaths); } + @NotNull public LinkedList getJavaFileObjectOutputClassList() { return outputClassList; } + @NotNull @Override - public JavaFileObject getJavaFileForOutput(Location location,String className, Kind kind, FileObject sibling) throws IOException + public JavaFileObject getJavaFileForOutput(Location location, @NotNull String className, @NotNull Kind kind, FileObject sibling) throws IOException { // Normalmente sólo habrá un resultado pero se da el caso de compilar una clase con una o varias inner classes, el compilador las compila de una vez JavaFileObjectOutputClass outClass = new JavaFileObjectOutputClass(className, kind); @@ -58,7 +63,7 @@ public JavaFileObject getJavaFileForOutput(Location location,String className, K } @Override - public Iterable list(Location location, String packageName, Set kinds, boolean recurse) throws IOException + public Iterable list(Location location, @NotNull String packageName, @NotNull Set kinds, boolean recurse) throws IOException { if (location == StandardLocation.PLATFORM_CLASS_PATH) // let standard manager hanfle return super.list(location, packageName, kinds, recurse); // En este caso nunca (con PLATFORM_CLASS_PATH) va a encontrar nuestros sources ni .class diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java index 62f950f..da16537 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java @@ -7,6 +7,8 @@ import com.sillelien.dollar.relproxy.impl.FileExt; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import org.jetbrains.annotations.NotNull; + import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; @@ -41,7 +43,8 @@ public JavaFileObjectInputClassFinderByClassLoader(ClassLoader classLoader,Folde this.requiredExtraJarPaths = requiredExtraJarPaths; } - public List find(String packageName) throws IOException + @NotNull + public List find(@NotNull String packageName) throws IOException { // http://www.dzone.com/snippets/get-all-classes-within-package // http://sourceforge.net/p/scannotation/code/HEAD/tree/scannotation/src/main/java/org/scannotation/ClasspathUrlFinder.java#l124 @@ -87,7 +90,7 @@ public List find(String packageName) throw } - private void listUnder(String packageName, URL packageFolderURL,Collection result) + private void listUnder(String packageName, @NotNull URL packageFolderURL, @NotNull Collection result) { String pkgPath = packageFolderURL.toExternalForm(); //packageFolderURL.getFile(); El problema de getFile es que también está URL-encoded (un espacio es %20) lo cual no es compatible con File @@ -101,7 +104,7 @@ private void listUnder(String packageName, URL packageFolderURL,Collection result) + private void listUnderDir(String packageName, String pkgPath, @NotNull Collection result) { pkgPath = pkgPath.substring("file:".length()); @@ -129,7 +132,7 @@ private void listUnderDir(String packageName,String pkgPath,Collection result) + private void listUnderJar(@NotNull URL packageFolderURL, @NotNull Collection result) { try { @@ -160,7 +163,7 @@ private void listUnderJar(URL packageFolderURL,Collection result) + private void listUnderJarCustom(@NotNull String packagePath, @NotNull FileExt jarFile, @NotNull Collection result) { String normalizedPath = jarFile.getCanonicalPath(); if (normalizedPath.contains("\\")) // Windows diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java index eeb1b23..3152dac 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java @@ -1,5 +1,7 @@ package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo; +import org.jetbrains.annotations.NotNull; + import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; @@ -15,12 +17,13 @@ public class JavaFileObjectInputClassInFile extends JavaFileObjectInputClassInFi { protected File file; - public JavaFileObjectInputClassInFile(File file,String binaryName, URI uri) + public JavaFileObjectInputClassInFile(File file, String binaryName, @NotNull URI uri) { super(binaryName,uri,uri.getPath()); this.file = file; } + @NotNull @Override public InputStream openInputStream() throws IOException { @@ -34,6 +37,7 @@ public long getLastModified() return file.lastModified(); } + @NotNull @Override public String toString() { return "JavaFileObjectInputClassInFile{uri=" + uri + '}'; diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java index 62bf61e..afbf586 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java @@ -1,5 +1,7 @@ package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo; +import org.jetbrains.annotations.NotNull; + import java.io.IOException; import java.io.OutputStream; import java.io.Reader; @@ -41,21 +43,25 @@ public String getBinaryName() { return binaryName; } + @NotNull @Override public OutputStream openOutputStream() throws IOException { throw new UnsupportedOperationException(); } + @NotNull @Override public Reader openReader(boolean ignoreEncodingErrors) throws IOException { throw new UnsupportedOperationException(); } + @NotNull @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { throw new UnsupportedOperationException(); } + @NotNull @Override public Writer openWriter() throws IOException { throw new UnsupportedOperationException(); @@ -66,24 +72,27 @@ public boolean delete() { throw new UnsupportedOperationException(); } + @NotNull @Override public Kind getKind() { return Kind.CLASS; } @Override // copied from SimpleJavaFileManager - public boolean isNameCompatible(String simpleName, Kind kind) { + public boolean isNameCompatible(String simpleName, @NotNull Kind kind) { String baseName = simpleName + kind.extension; return kind.equals(getKind()) && (baseName.equals(getName()) || getName().endsWith("/" + baseName)); } + @NotNull @Override public NestingKind getNestingKind() { throw new UnsupportedOperationException(); } + @NotNull @Override public Modifier getAccessLevel() { throw new UnsupportedOperationException(); diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java index 4dee882..dfe3757 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java @@ -1,5 +1,7 @@ package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo; +import org.jetbrains.annotations.NotNull; + import java.io.IOException; import java.io.InputStream; import java.net.URI; @@ -12,7 +14,7 @@ public class JavaFileObjectInputClassInJar extends JavaFileObjectInputClassInFil { protected long timestamp; - public JavaFileObjectInputClassInJar(String binaryName, URI uri,long timestamp) + public JavaFileObjectInputClassInJar(String binaryName, @NotNull URI uri, long timestamp) { super(binaryName,uri,uri.getSchemeSpecificPart()); this.timestamp = timestamp; @@ -30,6 +32,7 @@ public long getLastModified() return timestamp; } + @NotNull @Override public String toString() { diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java index d4d764c..c632d7a 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java @@ -1,5 +1,7 @@ package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo; +import org.jetbrains.annotations.NotNull; + import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; @@ -18,7 +20,7 @@ public class JavaFileObjectInputClassInMemory extends SimpleJavaFileObject imple protected byte[] byteCode; protected long timestamp; - public JavaFileObjectInputClassInMemory(String name,byte[] byteCode,long timestamp) + public JavaFileObjectInputClassInMemory(@NotNull String name, byte[] byteCode, long timestamp) { super(URI.create("string:///" + name.replace('.', '/') + Kind.CLASS.extension), Kind.CLASS); @@ -38,12 +40,14 @@ public long getLastModified() return timestamp; } + @NotNull @Override public InputStream openInputStream() throws IOException { return new ByteArrayInputStream(getBytes()); } + @NotNull @Override public OutputStream openOutputStream() throws IOException { diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java index cf40ca1..8e2c67a 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java @@ -1,6 +1,8 @@ package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo; import com.sillelien.dollar.relproxy.RelProxyException; +import org.jetbrains.annotations.NotNull; + import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; @@ -19,7 +21,7 @@ public abstract class JavaFileObjectInputSourceBase extends SimpleJavaFileObject protected String binaryName; protected String encoding; - public JavaFileObjectInputSourceBase(String name,String encoding) + public JavaFileObjectInputSourceBase(@NotNull String name, String encoding) { super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE); // La extensión .java es necesaria aunque sea falsa sino da error @@ -36,7 +38,8 @@ public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOExcept return getSource(); } - public byte[] getBytes() + @NotNull + public byte[] getBytes() { try { @@ -45,12 +48,14 @@ public byte[] getBytes() catch (UnsupportedEncodingException ex) { throw new RelProxyException(ex); } } + @NotNull @Override public InputStream openInputStream() throws IOException { return new ByteArrayInputStream(getBytes()); } + @NotNull @Override public OutputStream openOutputStream() throws IOException { diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java index 8683f69..801d10a 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java @@ -1,6 +1,8 @@ package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo; import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; +import org.jetbrains.annotations.NotNull; + import java.io.File; /** @@ -13,7 +15,7 @@ public class JavaFileObjectInputSourceInFile extends JavaFileObjectInputSourceBa protected File file; protected String source; - public JavaFileObjectInputSourceInFile(String name,File file,String encoding) + public JavaFileObjectInputSourceInFile(@NotNull String name, File file, String encoding) { super(name,encoding); this.file = file; diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java index dca46cd..b613805 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java @@ -1,5 +1,7 @@ package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo; +import org.jetbrains.annotations.NotNull; + /** * http://www.javablogging.com/dynamic-in-memory-compilation/ * @@ -10,7 +12,7 @@ public class JavaFileObjectInputSourceInMemory extends JavaFileObjectInputSource protected String source; protected long timestamp; - public JavaFileObjectInputSourceInMemory(String name,String source,String encoding,long timestamp) + public JavaFileObjectInputSourceInMemory(@NotNull String name, String source, String encoding, long timestamp) { super(name,encoding); this.source = source; diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java index 6fa68d0..62a90aa 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java @@ -1,6 +1,8 @@ package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo; import com.sillelien.dollar.relproxy.RelProxyException; +import org.jetbrains.annotations.NotNull; + import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; @@ -32,7 +34,7 @@ public class JavaFileObjectOutputClass extends SimpleJavaFileObject { * @param kind * Kind of the data. It will be CLASS in our case */ - public JavaFileObjectOutputClass(String name, Kind kind) + public JavaFileObjectOutputClass(@NotNull String name, @NotNull Kind kind) { super(URI.create("string:///" + name.replace('.', '/') + kind.extension), kind); @@ -50,6 +52,7 @@ public byte[] getBytes() return bos.toByteArray(); } + @NotNull @Override public OutputStream openOutputStream() throws IOException { diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java index b4432cf..836c2b0 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java @@ -1,6 +1,7 @@ package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit; import com.sillelien.dollar.relproxy.impl.FileExt; +import org.jetbrains.annotations.NotNull; /** * @@ -8,9 +9,10 @@ */ public class SourceFileJavaNormal extends SourceUnit { + @NotNull protected final FileExt sourceFile; - public SourceFileJavaNormal(FileExt sourceFile,FileExt rootFolderOfSources) + public SourceFileJavaNormal(@NotNull FileExt sourceFile, @NotNull FileExt rootFolderOfSources) { super(buildClassNameFromFile(sourceFile,rootFolderOfSources)); this.sourceFile = sourceFile; @@ -22,6 +24,7 @@ public long lastModified() return sourceFile.getFile().lastModified(); } + @NotNull public FileExt getFileExt() { return sourceFile; diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java index 60b46bb..5456fa3 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java @@ -3,6 +3,7 @@ import com.sillelien.dollar.relproxy.impl.FileExt; import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import org.jetbrains.annotations.NotNull; /** * @@ -12,13 +13,13 @@ public abstract class SourceScriptRootFile extends SourceScriptRoot { protected FileExt sourceFile; - public SourceScriptRootFile(FileExt sourceFile,FolderSourceList folderSourceList) + public SourceScriptRootFile(@NotNull FileExt sourceFile, @NotNull FolderSourceList folderSourceList) { super(buildClassNameFromFile(sourceFile,folderSourceList)); this.sourceFile = sourceFile; } - public static SourceScriptRootFile createSourceScriptRootFile(FileExt sourceFile,FolderSourceList folderSourceList) + public static SourceScriptRootFile createSourceScriptRootFile(@NotNull FileExt sourceFile, @NotNull FolderSourceList folderSourceList) { String ext = JProxyUtil.getFileExtension(sourceFile.getFile()); // Si no tiene extensión devuelve "" if ("java".equals(ext)) diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java index 4aeb091..5e22815 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java @@ -3,6 +3,7 @@ import com.sillelien.dollar.relproxy.impl.FileExt; import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import org.jetbrains.annotations.NotNull; /** * @@ -10,13 +11,14 @@ */ public class SourceScriptRootFileJavaExt extends SourceScriptRootFile { - public SourceScriptRootFileJavaExt(FileExt sourceFile,FolderSourceList folderSourceList) + public SourceScriptRootFileJavaExt(@NotNull FileExt sourceFile, @NotNull FolderSourceList folderSourceList) { super(sourceFile,folderSourceList); } + @NotNull @Override - public String getScriptCode(String encoding,boolean[] hasHashBang) + public String getScriptCode(@NotNull String encoding, boolean[] hasHashBang) { hasHashBang[0] = false; return JProxyUtil.readTextFile(sourceFile.getFile(),encoding); diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java index 154b757..84530c3 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java @@ -3,6 +3,7 @@ import com.sillelien.dollar.relproxy.impl.FileExt; import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import org.jetbrains.annotations.NotNull; /** * @@ -10,13 +11,14 @@ */ public class SourceScriptRootFileOtherExt extends SourceScriptRootFile { - public SourceScriptRootFileOtherExt(FileExt sourceFile,FolderSourceList folderSourceList) + public SourceScriptRootFileOtherExt(@NotNull FileExt sourceFile, @NotNull FolderSourceList folderSourceList) { super(sourceFile,folderSourceList); } + @NotNull @Override - public String getScriptCode(String encoding,boolean[] hasHashBang) + public String getScriptCode(@NotNull String encoding, boolean[] hasHashBang) { String codeBody = JProxyUtil.readTextFile(sourceFile.getFile(),encoding); // Eliminamos la primera línea #! (debe estar en la primera línea y sin espacios antes) diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java index f0b55e2..fd33113 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java @@ -2,6 +2,8 @@ import com.sillelien.dollar.relproxy.impl.FileExt; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * @@ -18,12 +20,14 @@ public SourceUnit(String className) public abstract long lastModified(); - protected static String buildClassNameFromFile(FileExt sourceFile,FolderSourceList sourceList) + @Nullable + protected static String buildClassNameFromFile(@NotNull FileExt sourceFile, @NotNull FolderSourceList sourceList) { return sourceList.buildClassNameFromFile(sourceFile); } - protected static String buildClassNameFromFile(FileExt sourceFile,FileExt rootFolderOfSources) + @Nullable + protected static String buildClassNameFromFile(@NotNull FileExt sourceFile, @NotNull FileExt rootFolderOfSources) { return FolderSourceList.buildClassNameFromFile(sourceFile,rootFolderOfSources); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java index 461c2d5..e658569 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java @@ -9,6 +9,9 @@ import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootInMemory; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.JProxyCompilationException; import com.sillelien.dollar.relproxy.impl.jproxy.shell.JProxyShellClassLoader; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.io.File; import javax.script.ScriptContext; import javax.script.ScriptException; @@ -20,6 +23,7 @@ public class JProxyScriptEngineDelegateImpl extends JProxyImpl { protected JProxyScriptEngineImpl parent; + @Nullable protected ClassDescriptorSourceScript classDescSourceScript; protected long codeBufferModTimestamp = 0; protected long lastCodeCompiledTimestamp = 0; @@ -29,8 +33,9 @@ public JProxyScriptEngineDelegateImpl(JProxyScriptEngineImpl parent) this.parent = parent; } - @Override - public ClassDescriptorSourceScript init(JProxyConfigImpl config) + @Nullable + @Override + public ClassDescriptorSourceScript init(@NotNull JProxyConfigImpl config) { SourceScriptRoot sourceFileScript = SourceScriptRootInMemory.createSourceScriptInMemory(""); @@ -43,12 +48,14 @@ public ClassDescriptorSourceScript init(JProxyConfigImpl config) return classDescSourceScript; } + @NotNull @Override public Class getMainParamClass() { return ScriptContext.class; } + @NotNull private SourceScriptRootInMemory getSourceScriptInMemory() { return (SourceScriptRootInMemory)classDescSourceScript.getSourceScript(); diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java index aab0f23..4c657b3 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java @@ -2,6 +2,8 @@ import com.sillelien.dollar.relproxy.RelProxy; import com.sillelien.dollar.relproxy.jproxy.JProxyScriptEngineFactory; +import org.jetbrains.annotations.NotNull; + import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -17,8 +19,11 @@ public class JProxyScriptEngineFactoryImpl extends JProxyScriptEngineFactory protected static final String SHORT_NAME = "java"; protected static final String LANGUAGE_NAME = "Java"; - protected static final List names; + @NotNull + protected static final List names; + @NotNull protected static final List extensions; + @NotNull protected static final List mimeTypes; static @@ -49,36 +54,42 @@ public static JProxyScriptEngineFactory create() return new JProxyScriptEngineFactoryImpl(); } + @NotNull @Override public String getEngineName() { return "RelProxy Java Script Engine"; } + @NotNull @Override public String getEngineVersion() { return RelProxy.getVersion(); } + @NotNull @Override public List getExtensions() { return extensions; } + @NotNull @Override public List getMimeTypes() { return mimeTypes; } + @NotNull @Override public List getNames() { return names; } + @NotNull @Override public String getLanguageName() { @@ -111,8 +122,9 @@ public Object getParameter(String key) } } + @NotNull @Override - public String getMethodCallSyntax(String obj, String method, String... args) + public String getMethodCallSyntax(String obj, String method, @NotNull String... args) { StringBuilder ret = new StringBuilder(); ret.append(obj + "." + method + "("); @@ -133,8 +145,9 @@ public String getMethodCallSyntax(String obj, String method, String... args) return ret.toString(); } + @NotNull @Override - public String getOutputStatement(String toDisplay) + public String getOutputStatement(@NotNull String toDisplay) { StringBuilder buf = new StringBuilder(); buf.append("System.out.println(\""); @@ -158,8 +171,9 @@ public String getOutputStatement(String toDisplay) return buf.toString(); } + @NotNull @Override - public String getProgram(String... statements) + public String getProgram(@NotNull String... statements) { StringBuilder ret = new StringBuilder(); int len = statements.length; @@ -171,6 +185,7 @@ public String getProgram(String... statements) return ret.toString(); } + @NotNull @Override public ScriptEngine getScriptEngine() { diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java index eab9862..8781e61 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java @@ -6,6 +6,9 @@ import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; import com.sillelien.dollar.relproxy.jproxy.JProxyConfig; import com.sillelien.dollar.relproxy.jproxy.JProxyScriptEngine; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.io.Reader; import javax.script.AbstractScriptEngine; import javax.script.Bindings; @@ -50,12 +53,13 @@ public Object eval(String script, ScriptContext context) throws ScriptException } @Override - public Object eval(Reader reader, ScriptContext context) throws ScriptException + public Object eval(@NotNull Reader reader, ScriptContext context) throws ScriptException { String script = JProxyUtil.readTextFile(reader); return eval(script,context); } + @NotNull @Override public Bindings createBindings() { @@ -68,6 +72,7 @@ public ScriptEngineFactory getFactory() return factory; } + @Nullable @Override public T create(T obj,Class clasz) { @@ -76,8 +81,9 @@ public T create(T obj,Class clasz) return jproxy.create(obj, clasz); } + @Nullable @Override - public Object create(Object obj,Class[] classes) + public Object create(Object obj, @NotNull Class[] classes) { if (jproxy == null) return obj; // No se ha llamado al init o enabled = false diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java index 1941300..6cd7faf 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java @@ -2,6 +2,8 @@ import com.sillelien.dollar.relproxy.RelProxyException; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; +import org.jetbrains.annotations.NotNull; + import java.io.File; import java.net.MalformedURLException; import java.net.URL; @@ -13,12 +15,12 @@ */ public class JProxyShellClassLoader extends URLClassLoader { - public JProxyShellClassLoader(ClassLoader parent,File classFolder) + public JProxyShellClassLoader(ClassLoader parent, @NotNull File classFolder) { super(toURLArray(classFolder),parent); } - private static URL[] toURLArray(File file) + private static URL[] toURLArray(@NotNull File file) { try { return new URL[]{file.toURI().toURL()}; } catch (MalformedURLException ex) { throw new RelProxyException(ex); } @@ -36,7 +38,7 @@ protected synchronized Class loadClass(String name, boolean resolve) throws C return super.loadClass(name, resolve); } - public synchronized Class defineClass(ClassDescriptor classDesc) + public synchronized Class defineClass(@NotNull ClassDescriptor classDesc) { String className = classDesc.getClassName(); byte[] classBytes = classDesc.getClassBytes(); diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java index 220909a..df4510a 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java @@ -6,6 +6,9 @@ import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootInMemory; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.util.LinkedList; /** @@ -14,13 +17,13 @@ */ public class JProxyShellCodeSnippetImpl extends JProxyShellImpl { - public void init(String[] args) + public void init(@NotNull String[] args) { super.init(args, null); } @Override - protected void executeFirstTime(ClassDescriptorSourceScript scriptFileDesc,LinkedList argsToScript,JProxyShellClassLoader classLoader) + protected void executeFirstTime(@NotNull ClassDescriptorSourceScript scriptFileDesc, @NotNull LinkedList argsToScript, JProxyShellClassLoader classLoader) { try { @@ -33,7 +36,7 @@ protected void executeFirstTime(ClassDescriptorSourceScript scriptFileDesc,Linke } @Override - protected void processConfigParams(String[] args,LinkedList argsToScript,JProxyConfigImpl config) + protected void processConfigParams(@NotNull String[] args, @NotNull LinkedList argsToScript, @NotNull JProxyConfigImpl config) { super.processConfigParams(args, argsToScript, config); @@ -41,8 +44,9 @@ protected void processConfigParams(String[] args,LinkedList argsToScript if (classFolder != null && !classFolder.trim().isEmpty()) throw new RelProxyException("cacheClassFolder is useless to execute a code snippet"); } - @Override - protected SourceScriptRoot createSourceScriptRoot(String[] args,LinkedList argsToScript,FolderSourceList folderSourceList) + @NotNull + @Override + protected SourceScriptRoot createSourceScriptRoot(String[] args, @NotNull LinkedList argsToScript, FolderSourceList folderSourceList) { // En argsToScript no está el args[0] ni falta que hace porque es el flag "-c" StringBuilder code = new StringBuilder(); @@ -51,7 +55,8 @@ protected SourceScriptRoot createSourceScriptRoot(String[] args,LinkedList no hay necesidad de nuevo ClassLoader diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellImpl.java index adba4a7..e88a295 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellImpl.java @@ -7,6 +7,9 @@ import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.lang.reflect.Method; import java.util.LinkedList; @@ -18,7 +21,7 @@ public abstract class JProxyShellImpl extends JProxyImpl { - public static void main(String[] args) + public static void main(@NotNull String[] args) { if (args[0].isEmpty()) { @@ -43,7 +46,8 @@ public static void main(String[] args) } } - protected ClassDescriptorSourceScript init(String[] args,String inputPath) + @Nullable + protected ClassDescriptorSourceScript init(@NotNull String[] args, String inputPath) { // Esto quizás necesite una opción en plan "verbose" o "log" para mostrar por pantalla o nada RelProxyOnReloadListener proxyListener = new RelProxyOnReloadListener() { @@ -75,6 +79,7 @@ public void onReload(Object objOld, Object objNew, Object proxy, Method method, return scriptFileDesc; } + @NotNull @Override public Class getMainParamClass() { @@ -82,11 +87,14 @@ public Class getMainParamClass() } - protected abstract SourceScriptRoot createSourceScriptRoot(String[] args,LinkedList argsToScript,FolderSourceList folderSourceList); - protected abstract JProxyShellClassLoader getJProxyShellClassLoader(JProxyConfigImpl config); + @NotNull + protected abstract SourceScriptRoot createSourceScriptRoot(String[] args, LinkedList argsToScript, FolderSourceList folderSourceList); + @Nullable + protected abstract JProxyShellClassLoader getJProxyShellClassLoader(JProxyConfigImpl config); protected abstract void executeFirstTime(ClassDescriptorSourceScript scriptFileDesc,LinkedList argsToScript,JProxyShellClassLoader classLoader); - private static Iterable parseCompilationOptions(String value) + @NotNull + private static Iterable parseCompilationOptions(@NotNull String value) { // Ej -source 1.6 -target 1.6 se convertiría en Arrays.asList(new String[]{"-source","1.6","-target","1.6"}); String[] options = value.split(" "); @@ -101,7 +109,7 @@ private static Iterable parseCompilationOptions(String value) } - protected void processConfigParams(String[] args,LinkedList argsToScript,JProxyConfigImpl config) + protected void processConfigParams(@NotNull String[] args, @NotNull LinkedList argsToScript, @NotNull JProxyConfigImpl config) { String classFolder = null; long scanPeriod = -1; diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java index 1a72f62..7ab2f67 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java @@ -7,6 +7,9 @@ import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootInMemory; import com.sillelien.dollar.relproxy.impl.jproxy.shell.inter.JProxyShellProcessor; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.util.LinkedList; /** @@ -17,10 +20,12 @@ public class JProxyShellInteractiveImpl extends JProxyShellImpl { protected boolean test = false; + @NotNull protected JProxyShellProcessor processor = new JProxyShellProcessor(this); + @Nullable protected ClassDescriptorSourceScript classDescSourceScript; - public void init(String[] args) + public void init(@NotNull String[] args) { this.classDescSourceScript = super.init(args, null); @@ -33,18 +38,21 @@ public void init(String[] args) processor.loop(); } + @Nullable public ClassDescriptorSourceScript getClassDescriptorSourceScript() { return classDescSourceScript; } + @NotNull public SourceScriptRootInMemory getSourceScriptInMemory() { return (SourceScriptRootInMemory)classDescSourceScript.getSourceScript(); } + @Nullable @Override - public ClassDescriptorSourceScript init(JProxyConfigImpl config,SourceScriptRoot scriptFile,ClassLoader classLoader) + public ClassDescriptorSourceScript init(@NotNull JProxyConfigImpl config, SourceScriptRoot scriptFile, ClassLoader classLoader) { ClassDescriptorSourceScript script = super.init(config,scriptFile, classLoader); @@ -60,7 +68,7 @@ protected void executeFirstTime(ClassDescriptorSourceScript scriptFileDesc,Linke } @Override - protected void processConfigParams(String[] args,LinkedList argsToScript,JProxyConfigImpl config) + protected void processConfigParams(@NotNull String[] args, @NotNull LinkedList argsToScript, @NotNull JProxyConfigImpl config) { super.processConfigParams(args, argsToScript, config); @@ -68,13 +76,15 @@ protected void processConfigParams(String[] args,LinkedList argsToScript if (classFolder != null && !classFolder.trim().isEmpty()) throw new RelProxyException("cacheClassFolder is useless to execute in interactive mode"); } - @Override + @NotNull + @Override protected SourceScriptRoot createSourceScriptRoot(String[] args,LinkedList argsToScript,FolderSourceList folderSourceList) { return SourceScriptRootInMemory.createSourceScriptInMemory(""); // La primera vez no hace nada, sirve para "calentar" la app } - @Override + @Nullable + @Override protected JProxyShellClassLoader getJProxyShellClassLoader(JProxyConfigImpl config) { // No hay classFolder => no hay necesidad de nuevo ClassLoader diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java index b19d3bb..821fde7 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java @@ -8,6 +8,9 @@ import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.io.File; import java.util.LinkedList; @@ -19,7 +22,7 @@ public class JProxyShellScriptFileImpl extends JProxyShellImpl { protected FileExt scriptFile; - public void init(String[] args) + public void init(@NotNull String[] args) { File scriptFile = new File(args[0]); if (!scriptFile.exists()) @@ -33,7 +36,7 @@ public void init(String[] args) } @Override - protected void executeFirstTime(ClassDescriptorSourceScript scriptFileDesc,LinkedList argsToScript,JProxyShellClassLoader classLoader) + protected void executeFirstTime(@NotNull ClassDescriptorSourceScript scriptFileDesc, @NotNull LinkedList argsToScript, JProxyShellClassLoader classLoader) { fixLastLoadedClass(scriptFileDesc,classLoader); @@ -47,14 +50,16 @@ protected void executeFirstTime(ClassDescriptorSourceScript scriptFileDesc,Linke } } - @Override - protected SourceScriptRoot createSourceScriptRoot(String[] args,LinkedList argsToScript,FolderSourceList folderSourceList) + @NotNull + @Override + protected SourceScriptRoot createSourceScriptRoot(String[] args, LinkedList argsToScript, @NotNull FolderSourceList folderSourceList) { return SourceScriptRootFile.createSourceScriptRootFile(scriptFile,folderSourceList); } - @Override - protected JProxyShellClassLoader getJProxyShellClassLoader(JProxyConfigImpl config) + @Nullable + @Override + protected JProxyShellClassLoader getJProxyShellClassLoader(@NotNull JProxyConfigImpl config) { String classFolder = config.getClassFolder(); if (classFolder != null) @@ -63,7 +68,7 @@ protected JProxyShellClassLoader getJProxyShellClassLoader(JProxyConfigImpl conf return null; } - protected void fixLastLoadedClass(ClassDescriptorSourceScript scriptFileDesc,JProxyShellClassLoader classLoader) + protected void fixLastLoadedClass(@NotNull ClassDescriptorSourceScript scriptFileDesc, @Nullable JProxyShellClassLoader classLoader) { Class scriptClass = scriptFileDesc.getLastLoadedClass(); if (scriptClass != null) return; diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/Command.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/Command.java index b41f3bb..06b0ebc 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/Command.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/Command.java @@ -1,5 +1,7 @@ package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; +import org.jetbrains.annotations.NotNull; + /** * * @author jmarranz @@ -15,7 +17,7 @@ public Command(JProxyShellProcessor parent,String name) this.name = name; } - public static Command createCommand(JProxyShellProcessor parent,String cmd) + public static Command createCommand(@NotNull JProxyShellProcessor parent, String cmd) { cmd = cmd.trim(); if (cmd.equals("clear")) @@ -86,7 +88,7 @@ else if (cmd.startsWith("save")) return null; // No es un comando } - protected static String getParameter(String cmdName,String cmd) + protected static String getParameter(String cmdName, @NotNull String cmd) { int pos = cmd.indexOf(cmdName + " "); if (pos != 0) diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java index 5884b0c..3ecd2e3 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java @@ -1,6 +1,8 @@ package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; +import org.jetbrains.annotations.NotNull; + /** * * @author jmarranz @@ -23,7 +25,7 @@ public CommandCodeChangerBase(JProxyShellProcessor parent,String name,int line) this.line = line; } - public static int getLineFromParam(JProxyShellProcessor parent,String name,String cmd) + public static int getLineFromParam(@NotNull JProxyShellProcessor parent, String name, @NotNull String cmd) { String param = getParameter(name,cmd); if (param == null) diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandDelete.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandDelete.java index f4d6b29..956501f 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandDelete.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandDelete.java @@ -1,6 +1,8 @@ package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; +import org.jetbrains.annotations.NotNull; + /** * * @author jmarranz @@ -14,7 +16,7 @@ public CommandDelete(JProxyShellProcessor parent,int line) super(parent,NAME,line); } - public static CommandDelete createCommandDelete(JProxyShellProcessor parent,String cmd) + public static CommandDelete createCommandDelete(@NotNull JProxyShellProcessor parent, @NotNull String cmd) { int line = getLineFromParam(parent,NAME,cmd); if (line < 0) diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandEdit.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandEdit.java index d86f854..6ddb775 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandEdit.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandEdit.java @@ -1,6 +1,8 @@ package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; +import org.jetbrains.annotations.NotNull; + /** * * @author jmarranz @@ -16,7 +18,7 @@ public CommandEdit(JProxyShellProcessor parent,int line,String codeLine) this.codeLine = codeLine; } - public static CommandEdit createCommandEdit(JProxyShellProcessor parent,String cmd) + public static CommandEdit createCommandEdit(@NotNull JProxyShellProcessor parent, @NotNull String cmd) { int line = getLineFromParam(parent,NAME,cmd); if (line < 0) diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandInsert.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandInsert.java index cf36e4f..5fe5983 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandInsert.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandInsert.java @@ -1,6 +1,8 @@ package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; +import org.jetbrains.annotations.NotNull; + /** * * @author jmarranz @@ -14,7 +16,7 @@ public CommandInsert(JProxyShellProcessor parent,int line) super(parent,NAME,line); } - public static CommandInsert createCommandInsert(JProxyShellProcessor parent,String cmd) + public static CommandInsert createCommandInsert(@NotNull JProxyShellProcessor parent, @NotNull String cmd) { int line = getLineFromParam(parent,NAME,cmd); if (line < 0) diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandLoad.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandLoad.java index cf4e7b8..7afdaf0 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandLoad.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandLoad.java @@ -1,6 +1,8 @@ package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; +import org.jetbrains.annotations.NotNull; + import java.io.File; import java.net.URI; import java.net.URL; @@ -22,7 +24,7 @@ public CommandLoad(JProxyShellProcessor parent,String url) this.url = url; } - public static CommandLoad createCommandLoad(JProxyShellProcessor parent,String cmd) + public static CommandLoad createCommandLoad(JProxyShellProcessor parent, @NotNull String cmd) { String url = getParameter(NAME,cmd); if (url == null) diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandSave.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandSave.java index b19f83c..5797667 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandSave.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandSave.java @@ -1,6 +1,8 @@ package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; +import org.jetbrains.annotations.NotNull; + import java.io.File; import java.util.List; @@ -19,7 +21,7 @@ public CommandSave(JProxyShellProcessor parent,String url) this.path = url; } - public static CommandSave createCommandSave(JProxyShellProcessor parent,String cmd) + public static CommandSave createCommandSave(JProxyShellProcessor parent, @NotNull String cmd) { String url = getParameter(NAME,cmd); if (url == null) diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java index 4f14985..488b0d4 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java @@ -6,6 +6,8 @@ import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.JProxyCompilationException; import com.sillelien.dollar.relproxy.impl.jproxy.shell.JProxyShellInteractiveImpl; +import org.jetbrains.annotations.NotNull; + import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collections; @@ -22,8 +24,11 @@ public class JProxyShellProcessor public static final int LINE_OFFSET = 2; // El índice en codeBuffer + este valor = al valor de la línea que se muestra al usuario, hay que tener en cuenta que contamos desde uno y la primera línea es siempre vacía protected JProxyShellInteractiveImpl parent; + @NotNull protected Charset encoding = Charset.defaultCharset(); - protected ArrayList codeBuffer = new ArrayList(20); + @NotNull + protected ArrayList codeBuffer = new ArrayList(20); + @NotNull protected Keyboard keyboard = KeyboardNotUsingClipboard.create(encoding); protected int lastLine = -1; // Indice respecto a codeBuffer protected int lineEditing = -1; // Indice respecto a codeBuffer @@ -35,11 +40,13 @@ public JProxyShellProcessor(JProxyShellInteractiveImpl parent) this.parent = parent; } + @NotNull public Keyboard getKeyboard() { return keyboard; } + @NotNull public Charset getEncoding() { return encoding; @@ -108,6 +115,7 @@ public void loop() } } + @NotNull public List getCodeBuffer() { return Collections.unmodifiableList(codeBuffer); @@ -120,7 +128,7 @@ public void setCodeBuffer(int index,String line) this.lastLine = index; } - public void setCodeBuffer(LinkedList codeBuffer) + public void setCodeBuffer(@NotNull LinkedList codeBuffer) { codeBuffer.clear(); this.codeBuffer.addAll(codeBuffer); diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java index bef7800..1214e86 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java @@ -2,6 +2,8 @@ import com.sillelien.dollar.relproxy.RelProxyException; +import org.jetbrains.annotations.NotNull; + import java.awt.AWTException; import java.awt.Robot; import static java.awt.event.KeyEvent.VK_0; @@ -64,6 +66,7 @@ */ public abstract class KeyboardNotUsingClipboard extends Keyboard { + @NotNull protected final Robot robot; protected Charset cs; @@ -90,6 +93,7 @@ public static KeyboardNotUsingClipboard create(Charset cs) else return new LinuxUnicodeKeyboard(cs); } + @NotNull private int[] getUnicodeInt(char character) { if (isUseCodePoint()) @@ -116,7 +120,8 @@ private int[] getUnicodeInt(char character) } } - protected String getUnicodeDigits(char character,int radix) + @NotNull + protected String getUnicodeDigits(char character, int radix) { int[] uds = getUnicodeInt(character); StringBuilder res = new StringBuilder(); @@ -150,7 +155,7 @@ protected void typeNumPad(int digit) { } - public void type(CharSequence characters) { + public void type(@NotNull CharSequence characters) { int length = characters.length(); for (int i = 0; i < length; i++) { char character = characters.charAt(i); @@ -271,11 +276,11 @@ public boolean type(char character) { return true; } - protected void doType(int... keyCodes) { + protected void doType(@NotNull int... keyCodes) { doTypeArr(keyCodes); } - private void doTypeArr(int[] keyCodes) { + private void doTypeArr(@NotNull int[] keyCodes) { int length = keyCodes.length; if (length == 1) { diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java index 0f42d3b..3999e14 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java @@ -2,6 +2,8 @@ import com.sillelien.dollar.relproxy.RelProxyException; +import org.jetbrains.annotations.NotNull; + import java.awt.AWTException; import java.awt.Robot; import java.awt.Toolkit; @@ -21,6 +23,7 @@ */ public class KeyboardUsingClipboard extends Keyboard implements ClipboardOwner { + @NotNull protected final Robot robot; protected Charset cs; @@ -45,7 +48,7 @@ public static KeyboardUsingClipboard create(Charset cs) @Override - public void type(CharSequence characters) + public void type(@NotNull CharSequence characters) { Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); StringSelection stringSelection = new StringSelection( characters.toString() ); diff --git a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxy.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxy.java index a101b83..47c9838 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxy.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxy.java @@ -3,6 +3,8 @@ import com.sillelien.dollar.relproxy.impl.jproxy.JProxyConfigImpl; import com.sillelien.dollar.relproxy.impl.jproxy.JProxyDefaultImpl; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * Is the class to create Java proxy objects based on Java objects and keep track of source code changes reloading classes when detected. @@ -44,7 +46,8 @@ public static void init(JProxyConfig config) * @param clasz the class of the interface implemented by the original object and proxy object returned. * @return the java.lang.reflect.Proxy object associated or the original object when GProxy is disabled. */ - public static T create(T obj,Class clasz) + @Nullable + public static T create(T obj, Class clasz) { return JProxyDefaultImpl.createStatic(obj, clasz); } @@ -63,7 +66,8 @@ public static T create(T obj,Class clasz) * @param classes the classes of the interfaces implemented by the original object and proxy object returned. * @return the java.lang.reflect.Proxy object associated or the original object when JProxy is disabled. */ - public static Object create(Object obj,Class[] classes) + @Nullable + public static Object create(Object obj, @NotNull Class[] classes) { return JProxyDefaultImpl.createStatic(obj, classes); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyConfig.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyConfig.java index 1c8a235..81e53ea 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyConfig.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyConfig.java @@ -2,6 +2,7 @@ package com.sillelien.dollar.relproxy.jproxy; import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; +import org.jetbrains.annotations.NotNull; /** * Interface implemented by the configuration object needed to initialize JProxy and {@link JProxyScriptEngineFactory}. @@ -21,6 +22,7 @@ public interface JProxyConfig * @param enabled whether automatic source code change detection and reload is enabled. By default is true. * @return this object for flow API use. */ + @NotNull public JProxyConfig setEnabled(boolean enabled); /** @@ -29,6 +31,7 @@ public interface JProxyConfig * @param relListener the class reload listener. By default is null. * @return this object for flow API use. */ + @NotNull public JProxyConfig setRelProxyOnReloadListener(RelProxyOnReloadListener relListener); /** @@ -43,6 +46,7 @@ public interface JProxyConfig * @return this object for flow API use. * @see #setInputPaths(java.lang.String[]) */ + @NotNull public JProxyConfig setInputPath(String inputPath); /** @@ -58,7 +62,8 @@ public interface JProxyConfig * @see #setJProxyInputSourceFileExcludedListener(JProxyInputSourceFileExcludedListener) * @see #setRequiredExtraJarPaths(String[]) */ - public JProxyConfig setInputPaths(String[] inputPaths); + @NotNull + public JProxyConfig setInputPaths(String[] inputPaths); /** * Defines the extra required jars providing the absolute paths to them. @@ -73,7 +78,8 @@ public interface JProxyConfig * @return this object for flow API use. * @see #setInputPaths(String[]) */ - public JProxyConfig setRequiredExtraJarPaths(String[] inputJarPaths); + @NotNull + public JProxyConfig setRequiredExtraJarPaths(String[] inputJarPaths); /** * Registers the listener implementing excluding rules to filter source files not to be part of the hot reloading system in spite of included in input paths. @@ -81,7 +87,8 @@ public interface JProxyConfig * @param listener the listener. By default is null. * @return this object for flow API use. */ - public JProxyConfig setJProxyInputSourceFileExcludedListener(JProxyInputSourceFileExcludedListener listener); + @NotNull + public JProxyConfig setJProxyInputSourceFileExcludedListener(JProxyInputSourceFileExcludedListener listener); /** * Registers the listener for monitoring files being compiled. @@ -89,7 +96,8 @@ public interface JProxyConfig * @param listener the listener. By default is null. * @return this object for flow API use. */ - public JProxyConfig setJProxyCompilerListener(JProxyCompilerListener listener); + @NotNull + public JProxyConfig setJProxyCompilerListener(JProxyCompilerListener listener); /** @@ -102,6 +110,7 @@ public interface JProxyConfig * @param classFolder the folder where to save .class files. By default is null (not defined, .class files are not saved). * @return this object for flow API use. */ + @NotNull public JProxyConfig setClassFolder(String classFolder); /** @@ -113,6 +122,7 @@ public interface JProxyConfig * @param scanPeriod the delay between source code change checking. * @return this object for flow API use. */ + @NotNull public JProxyConfig setScanPeriod(long scanPeriod); /** @@ -124,6 +134,7 @@ public interface JProxyConfig * @param compilationOptions compilation options passed to the internal compiler. By default is null (default compiler settings). * @return this object for flow API use. */ + @NotNull public JProxyConfig setCompilationOptions(Iterable compilationOptions); /** @@ -160,5 +171,6 @@ public interface JProxyConfig * @param diagnosticsListener the diagnostic listener to capture compilation errors and warnings. By default is null, an internal listener is used logging to System.err. * @return this object for flow API use. */ + @NotNull public JProxyConfig setJProxyDiagnosticsListener(JProxyDiagnosticsListener diagnosticsListener); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyScriptEngine.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyScriptEngine.java index ea1ae96..ddc12c1 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyScriptEngine.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyScriptEngine.java @@ -1,5 +1,7 @@ package com.sillelien.dollar.relproxy.jproxy; +import org.jetbrains.annotations.Nullable; + import javax.script.ScriptEngine; /** @@ -26,7 +28,8 @@ public interface JProxyScriptEngine extends ScriptEngine * @param clasz the class of the interface implemented by the original object and proxy object returned. * @return the java.lang.reflect.Proxy object associated or the original object when is disabled. */ - public T create(T obj,Class clasz); + @Nullable + public T create(T obj, Class clasz); /** * This method is the same as {@link JProxy#create(java.lang.Object, java.lang.Class[])} but applied to this JProxyScriptEngine @@ -35,7 +38,8 @@ public interface JProxyScriptEngine extends ScriptEngine * @param classes the classes of the interfaces implemented by the original object and proxy object returned. * @return the java.lang.reflect.Proxy object associated or the original object when is disabled. */ - public Object create(Object obj,Class[] classes); + @Nullable + public Object create(Object obj, Class[] classes); /** * This method is the same as {@link JProxy#isEnabled()} but applied to this JProxyScriptEngine diff --git a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyShell.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyShell.java index 0afa40a..3ea27a2 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyShell.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyShell.java @@ -1,6 +1,7 @@ package com.sillelien.dollar.relproxy.jproxy; import com.sillelien.dollar.relproxy.impl.jproxy.shell.JProxyShellImpl; +import org.jetbrains.annotations.NotNull; /** * Is the main class to execute shell scripting based on Java. @@ -16,7 +17,7 @@ public class JProxyShell * * @param args arguments with the necessary data to initialize and executing the provided script. */ - public static void main(String[] args) + public static void main(@NotNull String[] args) { JProxyShellImpl.main(args); } diff --git a/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyCodeSnippetCompleteClassTest.java b/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyCodeSnippetCompleteClassTest.java new file mode 100644 index 0000000..1d859cf --- /dev/null +++ b/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyCodeSnippetCompleteClassTest.java @@ -0,0 +1,74 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package com.sillelien.dollar.relproxy.jproxy; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +/** + * + * @author jmarranz + */ +public class JProxyCodeSnippetCompleteClassTest +{ + public static boolean RESULT; + + public JProxyCodeSnippetCompleteClassTest() + { + } + + @BeforeClass + public static void setUpClass() + { + } + + @AfterClass + public static void tearDownClass() + { + } + + @Before + public void setUp() + { + RESULT = false; + } + + @After + public void tearDown() + { + RESULT = false; + } + + @Test + public void test_code_snippet_complete_class() + { + String compilationOptions = "-source 1.6 -target 1.6"; + + String[] args = new String[] + { + "-c", + "public class _jproxyMainClass_ { ", + " public static void main(String[] args) { ", + " System.out.print(\"This code snippet says: \");", + " System.out.println(\"Hello World!!\");", + JProxyCodeSnippetCompleteClassTest.class.getName() + ".RESULT = true;", + " }", + "}", + "-DcompilationOptions=" + compilationOptions + }; + + JProxyShell.main(args); + + assertTrue(RESULT); + + } +} diff --git a/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyCodeSnippetTest.java b/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyCodeSnippetTest.java new file mode 100644 index 0000000..e9902eb --- /dev/null +++ b/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyCodeSnippetTest.java @@ -0,0 +1,68 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package com.sillelien.dollar.relproxy.jproxy; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * + * @author jmarranz + */ +public class JProxyCodeSnippetTest +{ + public static boolean RESULT; + + public JProxyCodeSnippetTest() + { + } + + @BeforeClass + public static void setUpClass() + { + } + + @AfterClass + public static void tearDownClass() + { + } + + @Before + public void setUp() + { + RESULT = false; + } + + @After + public void tearDown() + { + RESULT = false; + } + + @Test + public void test_code_snippet() + { + String compilationOptions = "-source 1.6 -target 1.6"; + + String[] args = new String[] + { + "-c", + "System.out.print(\"This code snippet says: \");", + "System.out.println(\"Hello World!!\");", + JProxyCodeSnippetTest.class.getName() + ".RESULT = true;", + "-DcompilationOptions=" + compilationOptions + }; + + JProxyShell.main(args); + + assertTrue(RESULT); + } +} diff --git a/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaScriptEngineNoManagerTest.java b/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaScriptEngineNoManagerTest.java new file mode 100644 index 0000000..a4b6f1c --- /dev/null +++ b/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaScriptEngineNoManagerTest.java @@ -0,0 +1,183 @@ +package com.sillelien.dollar.relproxy.jproxy; + +import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import javax.script.Bindings; +import javax.script.ScriptEngine; +import javax.script.ScriptException; +import javax.tools.Diagnostic; +import javax.tools.DiagnosticCollector; +import javax.tools.JavaFileObject; +import java.io.File; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.List; + +import static com.sillelien.dollar.relproxy.jproxy.util.JProxyTestUtil.RESOURCES_FOLDER; +import static com.sillelien.dollar.relproxy.jproxy.util.JProxyTestUtil.getProjectFolder; +import static org.junit.Assert.*; + +/** + * + * @author jmarranz + */ +public class JProxyJavaScriptEngineNoManagerTest +{ + + public JProxyJavaScriptEngineNoManagerTest() + { + } + + @BeforeClass + public static void setUpClass() + { + } + + @AfterClass + public static void tearDownClass() + { + } + + @Before + public void setUp() + { + + } + + @After + public void tearDown() + { + + } + + + @Test + public void test_java_script_engine() + { + File projectFolder = getProjectFolder(); + + File inputFolderFile = new File(projectFolder,RESOURCES_FOLDER); + // File classFolderFile = new File(projectFolder,"tmp/java_shell_test_classes"); + String inputPath = inputFolderFile.getAbsolutePath(); + String classFolder = null; // Optional + Iterable compilationOptions = Arrays.asList(new String[]{"-source","1.6","-target","1.6"}); + long scanPeriod = 300; + + RelProxyOnReloadListener proxyListener = new RelProxyOnReloadListener() { + @Override + public void onReload(Object objOld, Object objNew, Object proxy, Method method, Object[] args) { + System.out.println("Reloaded " + objNew + " Calling method: " + method); + } + }; + + JProxyCompilerListener compilerListener = new JProxyCompilerListener(){ + @Override + public void beforeCompile(File file) + { + System.out.println("Before compile: " + file); + } + + @Override + public void afterCompile(File file) + { + System.out.println("After compile: " + file); + } + }; + + JProxyDiagnosticsListener diagnosticsListener = new JProxyDiagnosticsListener() + { + @Override + public void onDiagnostics(DiagnosticCollector diagnostics) + { + List> diagList = diagnostics.getDiagnostics(); + int i = 1; + for (Diagnostic diagnostic : diagList) + { + System.err.println("Diagnostic " + i); + System.err.println(" code: " + diagnostic.getCode()); + System.err.println(" kind: " + diagnostic.getKind()); + System.err.println(" line number: " + diagnostic.getLineNumber()); + System.err.println(" column number: " + diagnostic.getColumnNumber()); + System.err.println(" start position: " + diagnostic.getStartPosition()); + System.err.println(" position: " + diagnostic.getPosition()); + System.err.println(" end position: " + diagnostic.getEndPosition()); + System.err.println(" source: " + diagnostic.getSource()); + System.err.println(" message: " + diagnostic.getMessage(null)); + i++; + } + } + }; + + JProxyConfig jpConfig = JProxy.createJProxyConfig(); + jpConfig.setEnabled(true) + .setRelProxyOnReloadListener(proxyListener) + .setInputPath(inputPath) + .setJProxyInputSourceFileExcludedListener(null) + .setJProxyCompilerListener(compilerListener) + .setScanPeriod(scanPeriod) + .setClassFolder(classFolder) + .setCompilationOptions(compilationOptions) + .setJProxyDiagnosticsListener(diagnosticsListener); + + JProxyScriptEngineFactory factory = JProxyScriptEngineFactory.create(); + + ScriptEngine engine = factory.getScriptEngine(); + + ((JProxyScriptEngine)engine).init(jpConfig); + + assertNotNull(engine); + + try + { + + // El javax.script.ScriptContext.GLOBAL_SCOPE no está disponible porque no hemos usado el ScriptEngineManager para obtener el JProxyScriptEngine + // pero si podemos crear un javax.script.ScriptContext.ENGINE_SCOPE: + + Bindings bindings = engine.createBindings(); + bindings.put("msg","HELLO ENGINE SCOPE WORLD!"); + + + StringBuilder code = new StringBuilder(); + code.append( " javax.script.Bindings bindings = context.getBindings(javax.script.ScriptContext.ENGINE_SCOPE); \n"); + code.append( " String msg = (String)bindings.get(\"msg\"); \n"); + code.append( " System.out.println(msg); \n"); + code.append( " example.javashellex.JProxyShellExample.exec(engine); \n"); + code.append( " return \"SUCCESS\";"); + + String result = (String)engine.eval( code.toString() , bindings); + assertEquals("SUCCESS",result); + + bindings = engine.createBindings(); + bindings.put("msg","HELLO ENGINE SCOPE WORLD 2!"); + + code = new StringBuilder(); + code.append( "public class _jproxyMainClass_ { \n"); + code.append( " public static Object main(javax.script.ScriptEngine engine,javax.script.ScriptContext context) { \n"); + code.append( " javax.script.Bindings bindings = context.getBindings(javax.script.ScriptContext.ENGINE_SCOPE); \n"); + code.append( " String msg = (String)bindings.get(\"msg\"); \n"); + code.append( " System.out.println(msg); \n"); + code.append( " example.javashellex.JProxyShellExample.exec(engine); \n"); + code.append( " return \"SUCCESS 2\";"); + code.append( " }"); + code.append( "}"); + + result = (String)engine.eval( code.toString() , bindings); + assertEquals("SUCCESS 2",result); + } + catch(ScriptException ex) + { + ex.printStackTrace(); + assertTrue(false); + } + finally + { + boolean res = ((JProxyScriptEngine)engine).stop(); // Necessary if scanPeriod > 0 was defined + assertTrue(res); + } + } +} diff --git a/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaScriptEngineTest.java b/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaScriptEngineTest.java new file mode 100644 index 0000000..2249dab --- /dev/null +++ b/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaScriptEngineTest.java @@ -0,0 +1,201 @@ +package com.sillelien.dollar.relproxy.jproxy; + +import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; +import static com.sillelien.dollar.relproxy.jproxy.util.JProxyTestUtil.RESOURCES_FOLDER; +import static com.sillelien.dollar.relproxy.jproxy.util.JProxyTestUtil.getProjectFolder; + + +import java.io.File; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.List; +import javax.script.Bindings; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +import javax.script.ScriptException; +import javax.tools.Diagnostic; +import javax.tools.DiagnosticCollector; +import javax.tools.JavaFileObject; + +import com.sillelien.dollar.relproxy.jproxy.JProxy; +import com.sillelien.dollar.relproxy.jproxy.JProxyCompilerListener; +import com.sillelien.dollar.relproxy.jproxy.JProxyConfig; +import com.sillelien.dollar.relproxy.jproxy.JProxyDiagnosticsListener; +import com.sillelien.dollar.relproxy.jproxy.JProxyScriptEngine; +import com.sillelien.dollar.relproxy.jproxy.JProxyScriptEngineFactory; +import org.junit.After; +import org.junit.AfterClass; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +/** + * + * @author jmarranz + */ +public class JProxyJavaScriptEngineTest +{ + + public JProxyJavaScriptEngineTest() + { + } + + @BeforeClass + public static void setUpClass() + { + } + + @AfterClass + public static void tearDownClass() + { + } + + @Before + public void setUp() + { + + } + + @After + public void tearDown() + { + + } + + + @Test + public void test_java_script_engine() + { + File projectFolder = getProjectFolder(); + + File inputFolderFile = new File(projectFolder,RESOURCES_FOLDER); + // File classFolderFile = new File(projectFolder,"tmp/java_shell_test_classes"); + String inputPath = inputFolderFile.getAbsolutePath(); + String classFolder = null; // Optional + Iterable compilationOptions = Arrays.asList(new String[]{"-source","1.6","-target","1.6"}); + long scanPeriod = 300; + + RelProxyOnReloadListener proxyListener = new RelProxyOnReloadListener() { + @Override + public void onReload(Object objOld, Object objNew, Object proxy, Method method, Object[] args) { + System.out.println("Reloaded " + objNew + " Calling method: " + method); + } + }; + + JProxyCompilerListener compilerListener = new JProxyCompilerListener(){ + @Override + public void beforeCompile(File file) + { + System.out.println("Before compile: " + file); + } + + @Override + public void afterCompile(File file) + { + System.out.println("After compile: " + file); + } + }; + + JProxyDiagnosticsListener diagnosticsListener = new JProxyDiagnosticsListener() + { + @Override + public void onDiagnostics(DiagnosticCollector diagnostics) + { + List> diagList = diagnostics.getDiagnostics(); + int i = 1; + for (Diagnostic diagnostic : diagList) + { + System.err.println("Diagnostic " + i); + System.err.println(" code: " + diagnostic.getCode()); + System.err.println(" kind: " + diagnostic.getKind()); + System.err.println(" line number: " + diagnostic.getLineNumber()); + System.err.println(" column number: " + diagnostic.getColumnNumber()); + System.err.println(" start position: " + diagnostic.getStartPosition()); + System.err.println(" position: " + diagnostic.getPosition()); + System.err.println(" end position: " + diagnostic.getEndPosition()); + System.err.println(" source: " + diagnostic.getSource()); + System.err.println(" message: " + diagnostic.getMessage(null)); + i++; + } + } + }; + + JProxyConfig jpConfig = JProxy.createJProxyConfig(); + jpConfig.setEnabled(true) + .setRelProxyOnReloadListener(proxyListener) + .setInputPath(inputPath) + .setJProxyInputSourceFileExcludedListener(null) + .setJProxyCompilerListener(compilerListener) + .setScanPeriod(scanPeriod) + .setClassFolder(classFolder) + .setCompilationOptions(compilationOptions) + .setJProxyDiagnosticsListener(diagnosticsListener); + + JProxyScriptEngineFactory factory = JProxyScriptEngineFactory.create(); + + ScriptEngineManager manager = new ScriptEngineManager(); + manager.registerEngineName("Java", factory); + + manager.getBindings().put("msg","HELLO GLOBAL WORLD!"); + + ScriptEngine engine = manager.getEngineByName("Java"); + + ((JProxyScriptEngine)engine).init(jpConfig); + + assertNotNull(engine); + + try + { + + Bindings bindings = engine.createBindings(); + bindings.put("msg","HELLO ENGINE SCOPE WORLD!"); + + + StringBuilder code = new StringBuilder(); + code.append( " javax.script.Bindings bindings = context.getBindings(javax.script.ScriptContext.ENGINE_SCOPE); \n"); + code.append( " String msg = (String)bindings.get(\"msg\"); \n"); + code.append( " System.out.println(msg); \n"); + code.append( " bindings = context.getBindings(javax.script.ScriptContext.GLOBAL_SCOPE); \n"); + code.append( " msg = (String)bindings.get(\"msg\"); \n"); + code.append( " System.out.println(msg); \n"); + code.append( " example.javashellex.JProxyShellExample.exec(engine); \n"); + code.append( " return \"SUCCESS\";"); + + String result = (String)engine.eval( code.toString() , bindings); + assertEquals("SUCCESS",result); + + bindings = engine.createBindings(); + bindings.put("msg","HELLO ENGINE SCOPE WORLD 2!"); + + code = new StringBuilder(); + code.append( "public class _jproxyMainClass_ { \n"); + code.append( " public static Object main(javax.script.ScriptEngine engine,javax.script.ScriptContext context) { \n"); + code.append( " javax.script.Bindings bindings = context.getBindings(javax.script.ScriptContext.ENGINE_SCOPE); \n"); + code.append( " String msg = (String)bindings.get(\"msg\"); \n"); + code.append( " System.out.println(msg); \n"); + code.append( " bindings = context.getBindings(javax.script.ScriptContext.GLOBAL_SCOPE); \n"); + code.append( " msg = (String)bindings.get(\"msg\"); \n"); + code.append( " System.out.println(msg); \n"); + code.append( " example.javashellex.JProxyShellExample.exec(engine); \n"); + code.append( " return \"SUCCESS 2\";"); + code.append( " }"); + code.append( "}"); + + result = (String)engine.eval( code.toString() , bindings); + assertEquals("SUCCESS 2",result); + } + catch(ScriptException ex) + { + ex.printStackTrace(); + assertTrue(false); + } + finally + { + boolean res = ((JProxyScriptEngine)engine).stop(); // Necessary if scanPeriod > 0 was defined + assertTrue(res); + } + } +} diff --git a/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaShellCompleteClassTest.java b/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaShellCompleteClassTest.java new file mode 100644 index 0000000..b9c8110 --- /dev/null +++ b/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaShellCompleteClassTest.java @@ -0,0 +1,72 @@ +package com.sillelien.dollar.relproxy.jproxy; + +import com.sillelien.dollar.relproxy.jproxy.JProxyShell; +import com.sillelien.dollar.relproxy.jproxy.util.JProxyTestUtil; +import java.io.File; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +/** + * + * @author jmarranz + */ +public class JProxyJavaShellCompleteClassTest +{ + + + + public JProxyJavaShellCompleteClassTest() + { + } + + @BeforeClass + public static void setUpClass() + { + } + + @AfterClass + public static void tearDownClass() + { + } + + @Before + public void setUp() + { + + } + + @After + public void tearDown() + { + + } + + + @Test + public void test_java_shell() + { + File projectFolder = JProxyTestUtil.getProjectFolder(); + File inputFolderFile = new File(projectFolder,JProxyTestUtil.RESOURCES_FOLDER); + File cacheClassFolderFile = new File(projectFolder,JProxyTestUtil.CACHE_CLASS_FOLDER); + + String inputPath = inputFolderFile.getAbsolutePath(); + String cacheClassFolder = cacheClassFolderFile.getAbsolutePath(); + String compilationOptions = "-source 1.6 -target 1.6"; + + String[] args = new String[] + { + inputPath + "/example_java_shell_complete_class", + "HELLO ", + "WORLD!", + "-DcacheClassFolder=" + cacheClassFolder, + "-DcompilationOptions=" + compilationOptions, + }; + + JProxyShell.main(args); + } + + +} diff --git a/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaShellInteractiveTest.java b/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaShellInteractiveTest.java new file mode 100644 index 0000000..08b7772 --- /dev/null +++ b/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaShellInteractiveTest.java @@ -0,0 +1,63 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package com.sillelien.dollar.relproxy.jproxy; + +import com.sillelien.dollar.relproxy.jproxy.JProxyShell; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * + * @author jmarranz + */ +public class JProxyJavaShellInteractiveTest +{ + public JProxyJavaShellInteractiveTest() + { + } + + @BeforeClass + public static void setUpClass() + { + } + + @AfterClass + public static void tearDownClass() + { + } + + @Before + public void setUp() + { + + } + + @After + public void tearDown() + { + + } + + @Test + public void test_java_shell_interactive() + { + String compilationOptions = "-source 1.6 -target 1.6"; + + String[] args = new String[] + { + "", // El args[0] esperado + "-DcompilationOptions=" + compilationOptions, + "-Dtest=true" + }; + + JProxyShell.main(args); + } +} diff --git a/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaShellNormalClassTest.java b/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaShellNormalClassTest.java new file mode 100644 index 0000000..2c3df46 --- /dev/null +++ b/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaShellNormalClassTest.java @@ -0,0 +1,69 @@ +package com.sillelien.dollar.relproxy.jproxy; + +import com.sillelien.dollar.relproxy.jproxy.JProxyShell; +import com.sillelien.dollar.relproxy.jproxy.util.JProxyTestUtil; +import java.io.File; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +/** + * + * @author jmarranz + */ +public class JProxyJavaShellNormalClassTest +{ + public JProxyJavaShellNormalClassTest() + { + } + + @BeforeClass + public static void setUpClass() + { + } + + @AfterClass + public static void tearDownClass() + { + } + + @Before + public void setUp() + { + + } + + @After + public void tearDown() + { + + } + + + @Test + public void test_java_shell() + { + File projectFolder = JProxyTestUtil.getProjectFolder(); + File inputFolderFile = new File(projectFolder,JProxyTestUtil.RESOURCES_FOLDER); + File cacheClassFolderFile = new File(projectFolder,JProxyTestUtil.CACHE_CLASS_FOLDER); + + String inputPath = inputFolderFile.getAbsolutePath(); + String cacheClassFolder = cacheClassFolderFile.getAbsolutePath(); + String compilationOptions = "-source 1.6 -target 1.6"; + + String[] args = new String[] + { + inputPath + "/example_normal_class.java", + "HELLO ", + "WORLD!", + "-DcacheClassFolder=" + cacheClassFolder, + "-DcompilationOptions=" + compilationOptions + }; + + JProxyShell.main(args); + } + + +} diff --git a/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaShellTest.java b/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaShellTest.java new file mode 100644 index 0000000..94abc8f --- /dev/null +++ b/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaShellTest.java @@ -0,0 +1,74 @@ +package com.sillelien.dollar.relproxy.jproxy; + +import com.sillelien.dollar.relproxy.jproxy.JProxyShell; +import com.sillelien.dollar.relproxy.jproxy.util.JProxyTestUtil; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.File; + +/** + * + * @author jmarranz + */ +public class JProxyJavaShellTest +{ + + + + public JProxyJavaShellTest() + { + } + + @BeforeClass + public static void setUpClass() + { + } + + @AfterClass + public static void tearDownClass() + { + } + + @Before + public void setUp() + { + + } + + @After + public void tearDown() + { + + } + + + @Test + public void test_java_shell() + { + File projectFolder = JProxyTestUtil.getProjectFolder(); + File inputFolderFile = new File(projectFolder,JProxyTestUtil.RESOURCES_FOLDER); + File cacheClassFolderFile = new File(projectFolder,JProxyTestUtil.CACHE_CLASS_FOLDER); + + String inputPath = inputFolderFile.getAbsolutePath(); + String cacheClassFolder = cacheClassFolderFile.getAbsolutePath(); + String compilationOptions = "-source 1.6 -target 1.6"; + + + String[] args = new String[] + { + inputPath + "/example_java_shell", + "HELLO ", + "WORLD!", + "-DcacheClassFolder=" + cacheClassFolder, + "-DcompilationOptions=" + compilationOptions + }; + + JProxyShell.main(args); + } + + +} diff --git a/src/test/java/com/sillelien/dollar/relproxy/jproxy/util/JProxyTestUtil.java b/src/test/java/com/sillelien/dollar/relproxy/jproxy/util/JProxyTestUtil.java new file mode 100644 index 0000000..d4d51df --- /dev/null +++ b/src/test/java/com/sillelien/dollar/relproxy/jproxy/util/JProxyTestUtil.java @@ -0,0 +1,16 @@ +package com.sillelien.dollar.relproxy.jproxy.util; + +import java.io.File; + +/** + * @author jmarranz + */ +public class JProxyTestUtil { + public static final String RESOURCES_FOLDER = "src/test/resources"; + public static final String CACHE_CLASS_FOLDER = "tmp/java_shell_test_classes"; + + public static File getProjectFolder() { + + return new File(".").getAbsoluteFile(); + } +} diff --git a/relproxy/src/test/resources/example/javashellex/JProxyShellExample.java b/src/test/resources/example/javashellex/JProxyShellExample.java similarity index 96% rename from relproxy/src/test/resources/example/javashellex/JProxyShellExample.java rename to src/test/resources/example/javashellex/JProxyShellExample.java index b0b5dcf..0da7133 100644 --- a/relproxy/src/test/resources/example/javashellex/JProxyShellExample.java +++ b/src/test/resources/example/javashellex/JProxyShellExample.java @@ -1,22 +1,22 @@ -package example.javashellex; - -import javax.script.ScriptEngine; -import com.sillelien.dollar.relproxy.jproxy.JProxyScriptEngine; - -/** - * - * @author jmarranz - */ -public class JProxyShellExample -{ - public static void exec() - { - System.out.println("JProxyShellExample exec() 1 "); - } - - public static void exec(ScriptEngine engine) - { - JProxyScriptEngine jengine = ((JProxyScriptEngine)engine); // Just to show that ScriptEngine is a JProxyScriptEngine object - System.out.println("JProxyShellExample exec(ScriptEngine) 1 "); - } -} +package example.javashellex; + +import javax.script.ScriptEngine; +import com.sillelien.dollar.relproxy.jproxy.JProxyScriptEngine; + +/** + * + * @author jmarranz + */ +public class JProxyShellExample +{ + public static void exec() + { + System.out.println("JProxyShellExample exec() 1 "); + } + + public static void exec(ScriptEngine engine) + { + JProxyScriptEngine jengine = ((JProxyScriptEngine)engine); // Just to show that ScriptEngine is a JProxyScriptEngine object + System.out.println("JProxyShellExample exec(ScriptEngine) 1 "); + } +} diff --git a/relproxy/src/test/resources/example_java_shell b/src/test/resources/example_java_shell similarity index 100% rename from relproxy/src/test/resources/example_java_shell rename to src/test/resources/example_java_shell diff --git a/relproxy/src/test/resources/example_java_shell_complete_class b/src/test/resources/example_java_shell_complete_class similarity index 100% rename from relproxy/src/test/resources/example_java_shell_complete_class rename to src/test/resources/example_java_shell_complete_class diff --git a/relproxy/src/test/resources/example_normal_class.java b/src/test/resources/example_normal_class.java similarity index 100% rename from relproxy/src/test/resources/example_normal_class.java rename to src/test/resources/example_normal_class.java From f99170b177cfcf037a9abefae2d73b588d7f865b Mon Sep 17 00:00:00 2001 From: neilellis Date: Fri, 7 Jul 2017 22:15:49 +0100 Subject: [PATCH 028/135] Reformatting only --- .../sillelien/dollar/relproxy/RelProxy.java | 10 +- .../dollar/relproxy/RelProxyException.java | 36 +- .../relproxy/RelProxyOnReloadListener.java | 18 +- .../dollar/relproxy/gproxy/GProxy.java | 57 ++- .../dollar/relproxy/gproxy/GProxyConfig.java | 18 +- .../gproxy/GProxyGroovyScriptEngine.java | 24 +- .../dollar/relproxy/gproxy/package.html | 6 +- .../dollar/relproxy/impl/FileExt.java | 26 +- .../impl/GenericProxyConfigBaseImpl.java | 10 +- .../relproxy/impl/GenericProxyImpl.java | 67 ++- .../impl/GenericProxyInvocationHandler.java | 48 +- .../impl/GenericProxyVersionedObject.java | 150 +++---- .../impl/gproxy/GProxyConfigImpl.java | 28 +- .../impl/gproxy/GProxyDefaultImpl.java | 44 +- .../relproxy/impl/gproxy/core/GProxyImpl.java | 25 +- .../gproxy/core/GProxyInvocationHandler.java | 14 +- .../gproxy/core/GProxyVersionedObject.java | 41 +- .../impl/jproxy/JProxyConfigImpl.java | 129 +++--- .../impl/jproxy/JProxyDefaultImpl.java | 98 ++-- .../relproxy/impl/jproxy/JProxyUtil.java | 177 ++++---- .../relproxy/impl/jproxy/core/JProxyImpl.java | 82 ++-- .../jproxy/core/JProxyInvocationHandler.java | 18 +- .../jproxy/core/JProxyVersionedObject.java | 36 +- .../jproxy/core/clsmgr/FolderSourceList.java | 68 ++- .../jproxy/core/clsmgr/JProxyClassLoader.java | 111 ++--- .../impl/jproxy/core/clsmgr/JProxyEngine.java | 281 +++++------- ...JProxyEngineChangeDetectorAndCompiler.java | 249 +++++------ .../core/clsmgr/cldesc/ClassDescriptor.java | 103 ++--- .../clsmgr/cldesc/ClassDescriptorInner.java | 23 +- .../cldesc/ClassDescriptorSourceFileJava.java | 25 +- .../ClassDescriptorSourceFileRegistry.java | 94 ++-- .../cldesc/ClassDescriptorSourceScript.java | 217 +++++---- .../cldesc/ClassDescriptorSourceUnit.java | 117 ++--- .../comp/JProxyCompilationException.java | 16 +- .../clsmgr/comp/JProxyCompilerContext.java | 71 ++- .../clsmgr/comp/JProxyCompilerInMemory.java | 130 +++--- .../clsmgr/comp/JavaFileManagerInMemory.java | 73 ++- ...leObjectInputClassFinderByClassLoader.java | 198 ++++----- .../comp/jfo/JProxyJavaFileObjectInput.java | 4 +- .../jfo/JavaFileObjectInputClassInFile.java | 21 +- .../JavaFileObjectInputClassInFileSystem.java | 29 +- .../jfo/JavaFileObjectInputClassInJar.java | 20 +- .../jfo/JavaFileObjectInputClassInMemory.java | 43 +- .../jfo/JavaFileObjectInputSourceBase.java | 53 +-- .../jfo/JavaFileObjectInputSourceInFile.java | 24 +- .../JavaFileObjectInputSourceInMemory.java | 26 +- .../comp/jfo/JavaFileObjectOutputClass.java | 44 +- .../clsmgr/srcunit/SourceFileJavaNormal.java | 21 +- .../core/clsmgr/srcunit/SourceScriptRoot.java | 11 +- .../clsmgr/srcunit/SourceScriptRootFile.java | 32 +- .../srcunit/SourceScriptRootFileJavaExt.java | 22 +- .../srcunit/SourceScriptRootFileOtherExt.java | 30 +- .../srcunit/SourceScriptRootInMemory.java | 47 +- .../core/clsmgr/srcunit/SourceUnit.java | 36 +- .../impl/jproxy/screngine/BindingsImpl.java | 4 +- .../JProxyScriptEngineDelegateImpl.java | 83 ++-- .../JProxyScriptEngineFactoryImpl.java | 124 +++--- .../screngine/JProxyScriptEngineImpl.java | 95 ++-- .../jproxy/shell/JProxyShellClassLoader.java | 36 +- .../shell/JProxyShellCodeSnippetImpl.java | 57 +-- .../impl/jproxy/shell/JProxyShellImpl.java | 113 ++--- .../shell/JProxyShellInteractiveImpl.java | 73 ++- .../shell/JProxyShellScriptFileImpl.java | 64 ++- .../impl/jproxy/shell/inter/Command.java | 114 ++--- .../shell/inter/CommandCodeChangerBase.java | 85 ++-- .../jproxy/shell/inter/CommandDelete.java | 55 +-- .../impl/jproxy/shell/inter/CommandEdit.java | 63 ++- .../impl/jproxy/shell/inter/CommandError.java | 15 +- .../jproxy/shell/inter/CommandInsert.java | 61 ++- .../impl/jproxy/shell/inter/CommandLoad.java | 60 +-- .../impl/jproxy/shell/inter/CommandOther.java | 139 +++--- .../impl/jproxy/shell/inter/CommandSave.java | 55 +-- .../shell/inter/JProxyShellProcessor.java | 214 ++++----- .../impl/jproxy/shell/inter/Keyboard.java | 24 +- .../inter/KeyboardNotUsingClipboard.java | 420 ++++++++++++------ .../shell/inter/KeyboardUsingClipboard.java | 34 +- .../shell/inter/LinuxUnicodeKeyboard.java | 46 +- .../shell/inter/MacOSXUnicodeKeyboard.java | 39 +- .../shell/inter/WindowUnicodeKeyboard.java | 40 +- .../dollar/relproxy/jproxy/JProxy.java | 112 +++-- .../jproxy/JProxyCompilerListener.java | 10 +- .../dollar/relproxy/jproxy/JProxyConfig.java | 139 +++--- .../jproxy/JProxyDiagnosticsListener.java | 9 +- ...JProxyInputSourceFileExcludedListener.java | 13 +- .../relproxy/jproxy/JProxyScriptEngine.java | 53 ++- .../jproxy/JProxyScriptEngineFactory.java | 11 +- .../dollar/relproxy/jproxy/JProxyShell.java | 14 +- .../dollar/relproxy/jproxy/package.html | 6 +- .../sillelien/dollar/relproxy/package.html | 6 +- 89 files changed, 2603 insertions(+), 3284 deletions(-) diff --git a/src/main/java/com/sillelien/dollar/relproxy/RelProxy.java b/src/main/java/com/sillelien/dollar/relproxy/RelProxy.java index 8b2ee78..ec16e4b 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/RelProxy.java +++ b/src/main/java/com/sillelien/dollar/relproxy/RelProxy.java @@ -2,18 +2,16 @@ /** * Is the root of RelProxy - * + * * @author Jose Maria Arranz Santamaria */ -public class RelProxy -{ +public class RelProxy { /** * Returns the version of this RelProxy library. - * + * * @return the version of the library. */ - public static String getVersion() - { + public static String getVersion() { return "0.8.8"; } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/RelProxyException.java b/src/main/java/com/sillelien/dollar/relproxy/RelProxyException.java index 1d0e5d4..d4bbf09 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/RelProxyException.java +++ b/src/main/java/com/sillelien/dollar/relproxy/RelProxyException.java @@ -2,45 +2,41 @@ /** * Internal checked exceptions thrown by RelProxy and library specific errors are wrapped into this exception class. - * + * * @author Jose Maria Arranz Santamaria */ -public class RelProxyException extends RuntimeException -{ +public class RelProxyException extends RuntimeException { /** * Constructs a new exception with the specified message and cause. - * + *

*

Parameters are passed to the super constructor.

- * + * * @param message the detail message - * @param cause the cause + * @param cause the cause */ - public RelProxyException(String message, Throwable cause) - { + public RelProxyException(String message, Throwable cause) { super(message, cause); } - + /** * Constructs a new exception with the specified message. - * + *

*

Parameter is passed to the super constructor.

- * + * * @param message the detail message */ - public RelProxyException(String message) - { + public RelProxyException(String message) { super(message); - } - + } + /** * Constructs a new exception with the specified cause. - * + *

*

Parameter is passed to the super constructor.

- * + * * @param cause the cause */ - public RelProxyException(Throwable cause) - { + public RelProxyException(Throwable cause) { super(cause); - } + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/RelProxyOnReloadListener.java b/src/main/java/com/sillelien/dollar/relproxy/RelProxyOnReloadListener.java index 1750bf3..d84ad4b 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/RelProxyOnReloadListener.java +++ b/src/main/java/com/sillelien/dollar/relproxy/RelProxyOnReloadListener.java @@ -4,26 +4,24 @@ /** * Is the interface needed to register a class reload listener. - * + *

*

An object implementing this interface can optionally be registered on RelProxy to listen when the method of a proxy object has been called * and the class of the original object associated has been reloaded (and a new "original" object based on the new class was created to replace it). *

- * - * + * + * @author Jose Maria Arranz Santamaria * @see com.sillelien.dollar.relproxy.jproxy.JProxyConfig#setRelProxyOnReloadListener(com.sillelien.dollar.relproxy.RelProxyOnReloadListener) * @see com.sillelien.dollar.relproxy.gproxy.GProxyConfig#setRelProxyOnReloadListener(com.sillelien.dollar.relproxy.RelProxyOnReloadListener) - * @author Jose Maria Arranz Santamaria */ -public interface RelProxyOnReloadListener -{ +public interface RelProxyOnReloadListener { /** * Called when some source code change has happened and a new class has been compiled and reloaded. - * + * * @param objOld the old object before class reload. * @param objNew the new object based on the new class loaded by the new class loader. - * @param proxy the proxy object created by {@link java.lang.reflect.Proxy} being used. + * @param proxy the proxy object created by {@link java.lang.reflect.Proxy} being used. * @param method the method being called through the proxy object. - * @param args the parameters being used in the method call. + * @param args the parameters being used in the method call. */ - public void onReload(Object objOld,Object objNew,Object proxy, Method method, Object[] args); + public void onReload(Object objOld, Object objNew, Object proxy, Method method, Object[] args); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxy.java b/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxy.java index 5ee51b4..1f084ed 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxy.java +++ b/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxy.java @@ -8,65 +8,60 @@ /** * Is the class to create Java proxy objects based on Groovy objects and keep track of Groovy source code changes reloading Groovy classes when detected. - * + * * @author Jose Maria Arranz Santamaria */ -public class GProxy -{ +public class GProxy { /** * Creates a {@link GProxyConfig} object to be used to configure GProxy. - * + * * @return a new configuration object. * @see #init(GProxyConfig) */ - public static GProxyConfig createGProxyConfig() - { + public static GProxyConfig createGProxyConfig() { return GProxyDefaultImpl.createGProxyConfig(); - } - + } + /** * Initializes GProxy with the provided configuration object. - * + * * @param config config */ - public static void init(GProxyConfig config) - { - GProxyDefaultImpl.initStatic((GProxyConfigImpl)config); - } - + public static void init(GProxyConfig config) { + GProxyDefaultImpl.initStatic((GProxyConfigImpl) config); + } + /** * Creates a proxy object using java.lang.reflect.Proxy based on the provided Groovy object and the class of the implemented Java interface. - * - *

This method is a simplification for a single interface (the most common case) of {@link #create(Object,Class[])} .

- * - * @param the interface implemented by the original object and proxy object returned. - * @param obj the original object to proxy. + *

+ *

This method is a simplification for a single interface (the most common case) of {@link #create(Object, Class[])} .

+ * + * @param the interface implemented by the original object and proxy object returned. + * @param obj the original object to proxy. * @param clasz the class of the interface implemented by the original object and proxy object returned. * @return the java.lang.reflect.Proxy object associated or the original object when GProxy is disabled. */ @Nullable - public static T create(T obj, Class clasz) - { + public static T create(T obj, Class clasz) { return GProxyDefaultImpl.createStatic(obj, clasz); - } - + } + /** * Creates a proxy object using java.lang.reflect.Proxy based on the provided Groovy object and the classes of the implemented Java interfaces. - * - *

If GProxy has been configured and is enabled this method returns a java.lang.reflect.Proxy object implementing instead of + *

+ *

If GProxy has been configured and is enabled this method returns a java.lang.reflect.Proxy object implementing instead of * the original object provided. Methods called in proxy object are received by GProxy and forwarded to the original object, if source code * managed by GProxy has been changed, the class of the original object is reloaded based on the new source and the original object * is recreated with the new class and fields are re-set in the new object, then the method is called on the new original object.

- * + *

*

If GProxy is disabled returns the original object provided with no performance penalty.

- * - * @param obj the original object to proxy. + * + * @param obj the original object to proxy. * @param classes the classes of the interfaces implemented by the original object and proxy object returned. * @return the java.lang.reflect.Proxy object associated or the original object when GProxy is disabled. */ @Nullable - public static Object create(Object obj, @NotNull Class[] classes) - { + public static Object create(Object obj, @NotNull Class[] classes) { return GProxyDefaultImpl.createStatic(obj, classes); - } + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyConfig.java b/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyConfig.java index fd614e2..511ab75 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyConfig.java +++ b/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyConfig.java @@ -6,19 +6,17 @@ /** * Interface implemented by the configuration object needed to initialize GProxy. - * - * - * @see GProxy#init(GProxyConfig) + * * @author Jose Maria Arranz Santamaria + * @see GProxy#init(GProxyConfig) */ -public interface GProxyConfig -{ +public interface GProxyConfig { /** * Sets whether automatic detection of source code changes is enabled. - * + *

*

If set to false other configuration parameters are ignored, there is no automatic source code change detection/reload and original objects are returned * instead of proxies, performance penalty is zero. Setting to false is recommended in production whether source code change detection/reload is not required.

- * + * * @param enabled whether automatic source code change detection and reload is enabled. By default is true. * @return this object for flow API use. */ @@ -27,7 +25,7 @@ public interface GProxyConfig /** * Sets the class reload listener. - * + * * @param relListener the class reload listener. By default is null. * @return this object for flow API use. */ @@ -36,9 +34,9 @@ public interface GProxyConfig /** * Sets the object implementing the GroovyScriptEngine wrapper used to reload Groovy classes. - * + *

*

This parameter is required otherwise there is no bridge between RelProxy and Groovy because there is no explicit Groovy dependency in RelProxy. - * + * * @param engine the GroovyScriptEngine wrapper. * @return this object for flow API use. */ diff --git a/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyGroovyScriptEngine.java b/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyGroovyScriptEngine.java index 714feeb..02e4aa7 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyGroovyScriptEngine.java +++ b/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyGroovyScriptEngine.java @@ -4,28 +4,26 @@ /** * Interface to implement the object implementing the GroovyScriptEngine wrapper used to reload Groovy classes. - * + *

*

The following is a very simple example of the required implementation, groovyEngine is the groovy.util.GroovyScriptEngine * object:

- - def gproxyGroovyEngine = { - String scriptName -> return (java.lang.Class)groovyEngine.loadScriptByName(scriptName) - } as GProxyGroovyScriptEngine; - - * - * - * @see GProxyConfig#setGProxyGroovyScriptEngine(GProxyGroovyScriptEngine) + * + * def gproxyGroovyEngine = { + * String scriptName -> return (java.lang.Class)groovyEngine.loadScriptByName(scriptName) + * } as GProxyGroovyScriptEngine; + * + * * @author Jose Maria Arranz Santamaria + * @see GProxyConfig#setGProxyGroovyScriptEngine(GProxyGroovyScriptEngine) */ -public interface GProxyGroovyScriptEngine -{ +public interface GProxyGroovyScriptEngine { /** * The class implementing this method must call the method groovy.util.GroovyScriptEngine.loadScriptByName(String scriptName) passing * the scriptName. - * + *

*

This method is called by GProxy when it needs to get the Class associated to the specified Groovy script/class to check if this class * has changed because Groovy has reloaded the class when a source code has been detected. - * + * * @param scriptName the name of the Groovy script/class. * @return the class associated to the specified Groovy script. */ diff --git a/src/main/java/com/sillelien/dollar/relproxy/gproxy/package.html b/src/main/java/com/sillelien/dollar/relproxy/gproxy/package.html index 3edbfbf..c6bd773 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/gproxy/package.html +++ b/src/main/java/com/sillelien/dollar/relproxy/gproxy/package.html @@ -1,9 +1,9 @@ - + diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/FileExt.java b/src/main/java/com/sillelien/dollar/relproxy/impl/FileExt.java index 33c8866..d5912f6 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/FileExt.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/FileExt.java @@ -7,32 +7,30 @@ import java.io.IOException; /** - * * @author jmarranz */ -public class FileExt -{ +public class FileExt { @NotNull protected final File file; @NotNull protected final String cannonicalPath; // El obtener el cannonicalPath exige acceder al sistema de archivos, por eso nos inventamos esta clase, para evitar sucesivas llamadas a File.getCanonicalPath() - - public FileExt(@NotNull File file) - { + + public FileExt(@NotNull File file) { this.file = file; - try { this.cannonicalPath = file.getCanonicalPath(); } - catch (IOException ex) { throw new RelProxyException(ex); } + try { + this.cannonicalPath = file.getCanonicalPath(); + } catch (IOException ex) { + throw new RelProxyException(ex); + } } - + @NotNull - public File getFile() - { + public File getFile() { return file; } - + @NotNull - public String getCanonicalPath() - { + public String getCanonicalPath() { return cannonicalPath; } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyConfigBaseImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyConfigBaseImpl.java index 2dd406d..483c142 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyConfigBaseImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyConfigBaseImpl.java @@ -3,21 +3,17 @@ import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; /** - * * @author jmarranz */ -public class GenericProxyConfigBaseImpl -{ +public class GenericProxyConfigBaseImpl { protected boolean enabled = true; protected RelProxyOnReloadListener relListener; - public boolean isEnabled() - { + public boolean isEnabled() { return enabled; } - public RelProxyOnReloadListener getRelProxyOnReloadListener() - { + public RelProxyOnReloadListener getRelProxyOnReloadListener() { return relListener; } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyImpl.java index fa9a470..47f1b12 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyImpl.java @@ -9,59 +9,50 @@ import java.lang.reflect.Proxy; /** - * * @author jmarranz */ -public abstract class GenericProxyImpl -{ +public abstract class GenericProxyImpl { protected RelProxyOnReloadListener reloadListener; - - public GenericProxyImpl() - { + + public GenericProxyImpl() { } - public static void checkSingletonNull(@Nullable GenericProxyImpl singleton) - { - if (singleton != null) + public static void checkSingletonNull(@Nullable GenericProxyImpl singleton) { + if (singleton != null) throw new RelProxyException("Already initialized"); } - - protected static void checkSingletonExists(@Nullable GenericProxyImpl singleton) - { - if (singleton == null) + + protected static void checkSingletonExists(@Nullable GenericProxyImpl singleton) { + if (singleton == null) throw new RelProxyException("Execute first the init method"); - } - - protected void init(@NotNull GenericProxyConfigBaseImpl config) - { - this.reloadListener = config.getRelProxyOnReloadListener(); - } - - public RelProxyOnReloadListener getRelProxyOnReloadListener() - { + } + + protected void init(@NotNull GenericProxyConfigBaseImpl config) { + this.reloadListener = config.getRelProxyOnReloadListener(); + } + + public RelProxyOnReloadListener getRelProxyOnReloadListener() { return reloadListener; } - + @Nullable - public T create(@Nullable T obj, Class clasz) - { - if (obj == null) return null; - - return (T)create(obj,new Class[] { clasz }); + public T create(@Nullable T obj, Class clasz) { + if (obj == null) return null; + + return (T) create(obj, new Class[]{clasz}); } - + @Nullable - public Object create(@Nullable Object obj, @NotNull Class[] classes) - { - if (obj == null) return null; - + public Object create(@Nullable Object obj, @NotNull Class[] classes) { + if (obj == null) return null; + InvocationHandler handler = createGenericProxyInvocationHandler(obj); - - Object proxy = Proxy.newProxyInstance(obj.getClass().getClassLoader(),classes, handler); + + Object proxy = Proxy.newProxyInstance(obj.getClass().getClassLoader(), classes, handler); return proxy; - } - - + } + + @NotNull public abstract GenericProxyInvocationHandler createGenericProxyInvocationHandler(Object obj); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyInvocationHandler.java b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyInvocationHandler.java index 1c47def..9761664 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyInvocationHandler.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyInvocationHandler.java @@ -9,61 +9,51 @@ import java.lang.reflect.Proxy; /** - * * @author jmarranz */ -public abstract class GenericProxyInvocationHandler implements InvocationHandler -{ +public abstract class GenericProxyInvocationHandler implements InvocationHandler { protected GenericProxyImpl root; protected GenericProxyVersionedObject verObj; - - public GenericProxyInvocationHandler(GenericProxyImpl root) - { + + public GenericProxyInvocationHandler(GenericProxyImpl root) { this.root = root; - } - - private Object getCurrent() - { + } + + private Object getCurrent() { return verObj.getCurrent(); } - - private Object getNewVersion() throws Throwable - { + + private Object getNewVersion() throws Throwable { return verObj.getNewVersion(); - } - + } + @Override - public synchronized Object invoke(Object proxy, @NotNull Method method, @Nullable Object[] args) throws Throwable - { + public synchronized Object invoke(Object proxy, @NotNull Method method, @Nullable Object[] args) throws Throwable { Object oldObj = getCurrent(); Object obj = getNewVersion(); RelProxyOnReloadListener reloadListener = root.getRelProxyOnReloadListener(); if (oldObj != obj && reloadListener != null) - reloadListener.onReload(oldObj,obj,proxy,method,args); + reloadListener.onReload(oldObj, obj, proxy, method, args); - if (args != null && args.length == 1) - { + if (args != null && args.length == 1) { // Conseguimos que en proxy1.equals(proxy2) se usen los objetos asociados no los propios proxies, para ello obtenemos el objeto asociado al parámetro // No hace falta que equals forme parte de la interface, pero está ahí implícitamente // hashCode() como no tiene params es llamado sin problema de conversiones Object param = args[0]; if (param instanceof Proxy && // Si es una clase generada com.sun.proxy.$ProxyN (N=1,2...) es también derivada de Proxy - method.getName().equals("equals") && - method.getReturnType().equals(boolean.class)) - { + method.getName().equals("equals") && + method.getReturnType().equals(boolean.class)) { Class[] paramTypes = method.getParameterTypes(); - if (paramTypes.length == 1 && paramTypes[0].equals(Object.class)) - { + if (paramTypes.length == 1 && paramTypes[0].equals(Object.class)) { InvocationHandler paramInvHandler = Proxy.getInvocationHandler(param); - if (paramInvHandler instanceof GenericProxyInvocationHandler) - { - args[0] = ((GenericProxyInvocationHandler)paramInvHandler).getCurrent(); // reemplazamos el Proxy por el objeto asociado + if (paramInvHandler instanceof GenericProxyInvocationHandler) { + args[0] = ((GenericProxyInvocationHandler) paramInvHandler).getCurrent(); // reemplazamos el Proxy por el objeto asociado } } } } return method.invoke(obj, args); - } + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyVersionedObject.java b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyVersionedObject.java index 60a479c..8fe21d1 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyVersionedObject.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyVersionedObject.java @@ -11,98 +11,79 @@ import java.util.ArrayList; /** - * * @author jmarranz */ -public abstract class GenericProxyVersionedObject -{ - protected Object obj; +public abstract class GenericProxyVersionedObject { + protected Object obj; protected GenericProxyInvocationHandler parent; - - public GenericProxyVersionedObject(Object obj,GenericProxyInvocationHandler parent) - { - this.obj = obj; + + public GenericProxyVersionedObject(Object obj, GenericProxyInvocationHandler parent) { + this.obj = obj; this.parent = parent; } - - protected static void getTreeFields(@NotNull Class clasz, Object obj, @NotNull ArrayList fieldList, ArrayList valueList) throws IllegalAccessException - { - getFields(clasz,obj,fieldList,valueList); + + protected static void getTreeFields(@NotNull Class clasz, Object obj, @NotNull ArrayList fieldList, ArrayList valueList) throws IllegalAccessException { + getFields(clasz, obj, fieldList, valueList); Class superClass = clasz.getSuperclass(); if (superClass != null) - getTreeFields(superClass,obj,fieldList,valueList); + getTreeFields(superClass, obj, fieldList, valueList); } - protected static void getFields(@NotNull Class clasz, Object obj, @NotNull ArrayList fieldList, @Nullable ArrayList valueList) throws IllegalAccessException - { - Field[] fieldListClass = clasz.getDeclaredFields(); - for(int i = 0; i < fieldListClass.length; i++) - { - Field field = fieldListClass[i]; + protected static void getFields(@NotNull Class clasz, Object obj, @NotNull ArrayList fieldList, @Nullable ArrayList valueList) throws IllegalAccessException { + Field[] fieldListClass = clasz.getDeclaredFields(); + for (int i = 0; i < fieldListClass.length; i++) { + Field field = fieldListClass[i]; fieldList.add(field); - if (valueList != null) - { - field.setAccessible(true); - Object value = field.get(obj); + if (valueList != null) { + field.setAccessible(true); + Object value = field.get(obj); valueList.add(value); } - } - } - - public Object getCurrent() - { + } + } + + public Object getCurrent() { return obj; - } - - public Object getNewVersion() throws Throwable - { + } + + public Object getNewVersion() throws Throwable { Class newClass = reloadClass(); if (newClass == null) return obj; - Class oldClass = obj.getClass(); - if (newClass != oldClass) - { - this.obj = copy(oldClass,obj,newClass); + Class oldClass = obj.getClass(); + if (newClass != oldClass) { + this.obj = copy(oldClass, obj, newClass); } - + return obj; - } - - private Object copy(@NotNull Class oldClass, Object oldObj, @NotNull Class newClass) throws IllegalAccessException, InstantiationException, IllegalArgumentException, InvocationTargetException - { + } + + private Object copy(@NotNull Class oldClass, Object oldObj, @NotNull Class newClass) throws IllegalAccessException, InstantiationException, IllegalArgumentException, InvocationTargetException { Object newObj; ArrayList fieldListOld = new ArrayList(); - ArrayList valueListOld = new ArrayList(); + ArrayList valueListOld = new ArrayList(); - getTreeFields(oldClass,oldObj,fieldListOld,valueListOld); + getTreeFields(oldClass, oldObj, fieldListOld, valueListOld); Class enclosingClassNew = newClass.getEnclosingClass(); - if (enclosingClassNew == null) - { + if (enclosingClassNew == null) { Constructor construc; - try - { + try { construc = newClass.getConstructor(new Class[0]); + } catch (NoSuchMethodException ex) { + throw new RelProxyException("Cannot reload " + newClass.getName() + " a default empty of params constructor is required", ex); } - catch(NoSuchMethodException ex) - { - throw new RelProxyException("Cannot reload " + newClass.getName() + " a default empty of params constructor is required",ex); - } - newObj = construc.newInstance(); - } - else - { + newObj = construc.newInstance(); + } else { // En el caso de inner class o anonymous inner class el constructor por defecto se obtiene de forma diferente, útil para los EventListener de ItsNat Constructor construc; - try + try { + construc = newClass.getDeclaredConstructor(new Class[]{enclosingClassNew}); + } catch (NoSuchMethodException ex) // Yo creo que nunca ocurre al menos no en anonymous inner classes pero por si acaso { - construc = newClass.getDeclaredConstructor(new Class[]{enclosingClassNew}); - } - catch(NoSuchMethodException ex) // Yo creo que nunca ocurre al menos no en anonymous inner classes pero por si acaso - { - throw new RelProxyException("Cannot reload " + newClass.getName() + " a default empty of params constructor is required",ex); + throw new RelProxyException("Cannot reload " + newClass.getName() + " a default empty of params constructor is required", ex); } construc.setAccessible(true); // Necesario @@ -110,60 +91,63 @@ private Object copy(@NotNull Class oldClass, Object oldObj, @NotNull Class newCl Field enclosingFieldOld; - try { enclosingFieldOld = oldClass.getDeclaredField("this$0"); } - catch (NoSuchFieldException ex) { throw new RelProxyException(ex); } + try { + enclosingFieldOld = oldClass.getDeclaredField("this$0"); + } catch (NoSuchFieldException ex) { + throw new RelProxyException(ex); + } enclosingFieldOld.setAccessible(true); - Object enclosingObjectOld = enclosingFieldOld.get(oldObj); - Object enclosingObjectNew = copy(enclosingObjectOld.getClass(),enclosingObjectOld,enclosingClassNew); + Object enclosingObjectOld = enclosingFieldOld.get(oldObj); + Object enclosingObjectNew = copy(enclosingObjectOld.getClass(), enclosingObjectOld, enclosingClassNew); - newObj = construc.newInstance(enclosingObjectNew); + newObj = construc.newInstance(enclosingObjectNew); } ArrayList fieldListNew = new ArrayList(); - getTreeFields(newClass,newObj,fieldListNew,null); + getTreeFields(newClass, newObj, fieldListNew, null); - if (fieldListOld.size() != fieldListNew.size()) throw new RelProxyException("Cannot reload " + newClass.getName() + " number of fields have changed, redeploy"); + if (fieldListOld.size() != fieldListNew.size()) + throw new RelProxyException("Cannot reload " + newClass.getName() + " number of fields have changed, redeploy"); - for(int i = 0; i < fieldListOld.size(); i++) - { + for (int i = 0; i < fieldListOld.size(); i++) { Field fieldOld = fieldListOld.get(i); Field fieldNew = fieldListNew.get(i); - if (enclosingClassNew != null && fieldOld.getName().equals("this$0") && fieldNew.getName().equals("this$0")) + if (enclosingClassNew != null && fieldOld.getName().equals("this$0") && fieldNew.getName().equals("this$0")) continue; // Ya están correctamente definidos - if ( (!ignoreField(fieldOld) && !fieldOld.getName().equals(fieldNew.getName())) || - !fieldOld.getType().equals(fieldNew.getType())) + if ((!ignoreField(fieldOld) && !fieldOld.getName().equals(fieldNew.getName())) || + !fieldOld.getType().equals(fieldNew.getType())) throw new RelProxyException("Cannot reload " + newClass.getName() + " fields have changed, redeploy"); Object fieldObj = valueListOld.get(i); fieldNew.setAccessible(true); - int modifiersNew = fieldNew.getModifiers(); + int modifiersNew = fieldNew.getModifiers(); boolean isStaticFinal = Modifier.isStatic(modifiersNew) && Modifier.isFinal(modifiersNew); Field modifiersField = null; - if (isStaticFinal) - { + if (isStaticFinal) { // http://stackoverflow.com/questions/3301635/change-private-static-final-field-using-java-reflection try { modifiersField = Field.class.getDeclaredField("modifiers"); + } catch (NoSuchFieldException ex) { + throw new RelProxyException(ex); } - catch (NoSuchFieldException ex) { throw new RelProxyException(ex); } modifiersField.setAccessible(true); modifiersField.setInt(fieldNew, fieldNew.getModifiers() & ~Modifier.FINAL); // Quitamos el modifier final - } + } fieldNew.set(newObj, fieldObj); - if (modifiersField != null) - { + if (modifiersField != null) { modifiersField.setInt(fieldNew, fieldNew.getModifiers() & ~Modifier.FINAL); // Restauramos el modifier final } - } + } return newObj; } - + @Nullable protected abstract Class reloadClass(); - protected abstract boolean ignoreField(Field field); + + protected abstract boolean ignoreField(Field field); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyConfigImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyConfigImpl.java index 826cace..0497adb 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyConfigImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyConfigImpl.java @@ -7,36 +7,30 @@ import org.jetbrains.annotations.NotNull; /** - * * @author jmarranz */ -public class GProxyConfigImpl extends GenericProxyConfigBaseImpl implements GProxyConfig -{ +public class GProxyConfigImpl extends GenericProxyConfigBaseImpl implements GProxyConfig { protected GProxyGroovyScriptEngine engine; @NotNull - public GProxyConfig setEnabled(boolean enabled) - { + public GProxyConfig setEnabled(boolean enabled) { this.enabled = enabled; return this; } @NotNull - public GProxyConfig setRelProxyOnReloadListener(RelProxyOnReloadListener relListener) - { - this.relListener = relListener; - return this; + public GProxyConfig setRelProxyOnReloadListener(RelProxyOnReloadListener relListener) { + this.relListener = relListener; + return this; } - + @NotNull - public GProxyConfig setGProxyGroovyScriptEngine(GProxyGroovyScriptEngine engine) - { - this.engine = engine; - return this; + public GProxyConfig setGProxyGroovyScriptEngine(GProxyGroovyScriptEngine engine) { + this.engine = engine; + return this; } - - public GProxyGroovyScriptEngine getGProxyGroovyScriptEngine() - { + + public GProxyGroovyScriptEngine getGProxyGroovyScriptEngine() { return engine; } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyDefaultImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyDefaultImpl.java index 8f466a9..25d0796 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyDefaultImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyDefaultImpl.java @@ -6,40 +6,34 @@ import org.jetbrains.annotations.Nullable; /** - * * @author jmarranz */ -public class GProxyDefaultImpl extends GProxyImpl -{ - public static GProxyConfig createGProxyConfig() - { +public class GProxyDefaultImpl extends GProxyImpl { + public static GProxyConfig createGProxyConfig() { return new GProxyConfigImpl(); - } - - public static void initStatic(@NotNull GProxyConfigImpl config) - { + } + + public static void initStatic(@NotNull GProxyConfigImpl config) { if (!config.isEnabled()) return; - - checkSingletonNull(SINGLETON); + + checkSingletonNull(SINGLETON); SINGLETON = new GProxyDefaultImpl(); SINGLETON.init(config); - } - + } + @Nullable - public static T createStatic(T obj, Class clasz) - { - if (SINGLETON == null) + public static T createStatic(T obj, Class clasz) { + if (SINGLETON == null) return obj; // No se ha llamado al init o enabled = false - + return SINGLETON.create(obj, clasz); - } - + } + @Nullable - public static Object createStatic(Object obj, @NotNull Class[] classes) - { - if (SINGLETON == null) + public static Object createStatic(Object obj, @NotNull Class[] classes) { + if (SINGLETON == null) return obj; // No se ha llamado al init o enabled = false - - return SINGLETON.create(obj, classes); - } + + return SINGLETON.create(obj, classes); + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyImpl.java index 33de8ec..0b07d79 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyImpl.java @@ -8,29 +8,24 @@ /** - * * @author jmarranz */ -public abstract class GProxyImpl extends GenericProxyImpl -{ - public static GProxyImpl SINGLETON; +public abstract class GProxyImpl extends GenericProxyImpl { + public static GProxyImpl SINGLETON; protected GProxyGroovyScriptEngine engine; - - public void init(@NotNull GProxyConfigImpl config) - { + + public void init(@NotNull GProxyConfigImpl config) { super.init(config); this.engine = config.getGProxyGroovyScriptEngine(); } - - public GProxyGroovyScriptEngine getGProxyGroovyScriptEngine() - { + + public GProxyGroovyScriptEngine getGProxyGroovyScriptEngine() { return engine; - } - + } + @NotNull @Override - public GenericProxyInvocationHandler createGenericProxyInvocationHandler(@NotNull Object obj) - { - return new GProxyInvocationHandler(obj,this); + public GenericProxyInvocationHandler createGenericProxyInvocationHandler(@NotNull Object obj) { + return new GProxyInvocationHandler(obj, this); } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyInvocationHandler.java b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyInvocationHandler.java index a1c54d3..9859dce 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyInvocationHandler.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyInvocationHandler.java @@ -4,21 +4,17 @@ import org.jetbrains.annotations.NotNull; /** - * * @author jmarranz */ -public class GProxyInvocationHandler extends GenericProxyInvocationHandler -{ - public GProxyInvocationHandler(@NotNull Object obj, GProxyImpl root) - { +public class GProxyInvocationHandler extends GenericProxyInvocationHandler { + public GProxyInvocationHandler(@NotNull Object obj, GProxyImpl root) { super(root); - this.verObj = new GProxyVersionedObject(obj,this); + this.verObj = new GProxyVersionedObject(obj, this); } @NotNull - public GProxyImpl getGProxyImpl() - { - return (GProxyImpl)root; + public GProxyImpl getGProxyImpl() { + return (GProxyImpl) root; } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyVersionedObject.java b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyVersionedObject.java index f8cbc2a..8f20b99 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyVersionedObject.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyVersionedObject.java @@ -8,46 +8,37 @@ import java.lang.reflect.Field; /** - * * @author jmarranz */ -public class GProxyVersionedObject extends GenericProxyVersionedObject -{ - protected String path; - - public GProxyVersionedObject(@NotNull Object obj, GProxyInvocationHandler parent) - { - super(obj,parent); - this.path = obj.getClass().getName().replace('.','/'); - } +public class GProxyVersionedObject extends GenericProxyVersionedObject { + protected String path; + + public GProxyVersionedObject(@NotNull Object obj, GProxyInvocationHandler parent) { + super(obj, parent); + this.path = obj.getClass().getName().replace('.', '/'); + } @NotNull - public GProxyInvocationHandler getGProxyInvocationHandler() - { - return (GProxyInvocationHandler)parent; + public GProxyInvocationHandler getGProxyInvocationHandler() { + return (GProxyInvocationHandler) parent; } @Nullable @Override - protected Class reloadClass() - { + protected Class reloadClass() { GProxyGroovyScriptEngine engine = getGProxyInvocationHandler().getGProxyImpl().getGProxyGroovyScriptEngine(); - - try - { + + try { return engine.loadScriptByName(path + ".groovy"); //Ej: example/groovyex/GroovyExampleLoadListener.groovy - } - catch(Exception ex) - { + } catch (Exception ex) { ex.printStackTrace(System.err); return null; - } + } } - + @Override - protected boolean ignoreField(@NotNull Field field) - { + protected boolean ignoreField(@NotNull Field field) { return field.getName().startsWith("__timeStamp__"); // Este atributo cambia de nombre en cada reload, no lo consideramos } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyConfigImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyConfigImpl.java index eb5c831..7b62e6f 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyConfigImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyConfigImpl.java @@ -14,12 +14,10 @@ import java.io.File; /** - * * @author jmarranz */ -public class JProxyConfigImpl extends GenericProxyConfigBaseImpl implements JProxyConfig -{ - protected File folderSources; +public class JProxyConfigImpl extends GenericProxyConfigBaseImpl implements JProxyConfig { + protected File folderSources; protected FolderSourceList folderSourceList; protected FolderSourceList requiredExtraJarPaths; protected JProxyInputSourceFileExcludedListener excludedListener; @@ -29,144 +27,123 @@ public class JProxyConfigImpl extends GenericProxyConfigBaseImpl implements JPro protected Iterable compilationOptions; protected JProxyDiagnosticsListener diagnosticsListener; protected boolean test = false; - + @NotNull @Override - public JProxyConfig setEnabled(boolean enabled) - { + public JProxyConfig setEnabled(boolean enabled) { this.enabled = enabled; return this; } @NotNull @Override - public JProxyConfig setRelProxyOnReloadListener(RelProxyOnReloadListener relListener) - { - this.relListener = relListener; - return this; - } - + public JProxyConfig setRelProxyOnReloadListener(RelProxyOnReloadListener relListener) { + this.relListener = relListener; + return this; + } + @NotNull @Override - public JProxyConfig setInputPath(@Nullable String inputPath) - { + public JProxyConfig setInputPath(@Nullable String inputPath) { setInputPaths(inputPath != null ? new String[]{inputPath} : null); // inputPath es null en el caso de shell interactive return this; } @NotNull @Override - public JProxyConfig setInputPaths(String[] inputPaths) - { - this.folderSourceList = new FolderSourceList(inputPaths,true); // inputPaths es null en el caso de shell interactive + public JProxyConfig setInputPaths(String[] inputPaths) { + this.folderSourceList = new FolderSourceList(inputPaths, true); // inputPaths es null en el caso de shell interactive return this; - } + } @NotNull @Override - public JProxyConfig setRequiredExtraJarPaths(String[] inputJarPaths) - { - this.requiredExtraJarPaths = new FolderSourceList(inputJarPaths,false); // inputPaths es null en el caso de shell interactive + public JProxyConfig setRequiredExtraJarPaths(String[] inputJarPaths) { + this.requiredExtraJarPaths = new FolderSourceList(inputJarPaths, false); // inputPaths es null en el caso de shell interactive return this; - } - + } + @NotNull @Override - public JProxyConfig setJProxyInputSourceFileExcludedListener(JProxyInputSourceFileExcludedListener excludedListener) - { + public JProxyConfig setJProxyInputSourceFileExcludedListener(JProxyInputSourceFileExcludedListener excludedListener) { this.excludedListener = excludedListener; return this; } - + @NotNull @Override - public JProxyConfig setJProxyCompilerListener(JProxyCompilerListener compilerListener) - { + public JProxyConfig setJProxyCompilerListener(JProxyCompilerListener compilerListener) { this.compilerListener = compilerListener; return this; - } - + } + @NotNull @Override - public JProxyConfig setClassFolder(String classFolder) - { - this.classFolder = classFolder; - return this; + public JProxyConfig setClassFolder(String classFolder) { + this.classFolder = classFolder; + return this; } @NotNull @Override - public JProxyConfig setScanPeriod(long scanPeriod) - { + public JProxyConfig setScanPeriod(long scanPeriod) { if (scanPeriod == 0) throw new RelProxyException("scanPeriod cannot be zero"); - this.scanPeriod = scanPeriod; - return this; + this.scanPeriod = scanPeriod; + return this; } @NotNull @Override - public JProxyConfig setCompilationOptions(Iterable compilationOptions) - { - this.compilationOptions = compilationOptions; - return this; + public JProxyConfig setCompilationOptions(Iterable compilationOptions) { + this.compilationOptions = compilationOptions; + return this; } @NotNull @Override - public JProxyConfig setJProxyDiagnosticsListener(JProxyDiagnosticsListener diagnosticsListener) - { + public JProxyConfig setJProxyDiagnosticsListener(JProxyDiagnosticsListener diagnosticsListener) { this.diagnosticsListener = diagnosticsListener; - return this; - } - - public FolderSourceList getFolderSourceList() - { + return this; + } + + public FolderSourceList getFolderSourceList() { return folderSourceList; } - - public FolderSourceList getRequiredExtraJarPaths() - { + + public FolderSourceList getRequiredExtraJarPaths() { return requiredExtraJarPaths; - } - - public JProxyInputSourceFileExcludedListener getJProxyInputSourceFileExcludedListener() - { + } + + public JProxyInputSourceFileExcludedListener getJProxyInputSourceFileExcludedListener() { return excludedListener; - } - - public JProxyCompilerListener getJProxyCompilerListener() - { + } + + public JProxyCompilerListener getJProxyCompilerListener() { return compilerListener; } - - public String getClassFolder() - { + + public String getClassFolder() { return classFolder; } - public long getScanPeriod() - { + public long getScanPeriod() { return scanPeriod; } - public Iterable getCompilationOptions() - { + public Iterable getCompilationOptions() { return compilationOptions; } - public JProxyDiagnosticsListener getJProxyDiagnosticsListener() - { + public JProxyDiagnosticsListener getJProxyDiagnosticsListener() { return diagnosticsListener; } - - public boolean isTest() - { + + public boolean isTest() { return test; } - public void setTest(boolean test) - { + public void setTest(boolean test) { this.test = test; } - + } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyDefaultImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyDefaultImpl.java index 83251da..d674f35 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyDefaultImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyDefaultImpl.java @@ -6,86 +6,74 @@ import org.jetbrains.annotations.Nullable; /** - * * @author jmarranz */ -public class JProxyDefaultImpl extends JProxyImpl -{ - public JProxyDefaultImpl() - { +public class JProxyDefaultImpl extends JProxyImpl { + public JProxyDefaultImpl() { } - + @Nullable @Override - public Class getMainParamClass() - { + public Class getMainParamClass() { return null; } - public static JProxyConfig createJProxyConfig() - { + public static JProxyConfig createJProxyConfig() { return new JProxyConfigImpl(); - } - - public static void initStatic(@NotNull JProxyConfigImpl config) - { + } + + public static void initStatic(@NotNull JProxyConfigImpl config) { if (!config.isEnabled()) return; - + checkSingletonNull(SINGLETON); SINGLETON = new JProxyDefaultImpl(); SINGLETON.init(config); - } - - + } + + @Nullable - public static T createStatic(T obj, Class clasz) - { - if (SINGLETON == null) + public static T createStatic(T obj, Class clasz) { + if (SINGLETON == null) return obj; // No se ha llamado al init o enabled = false - + return SINGLETON.create(obj, clasz); - } + } @Nullable - public static Object createStatic(Object obj, @NotNull Class[] classes) - { - if (SINGLETON == null) + public static Object createStatic(Object obj, @NotNull Class[] classes) { + if (SINGLETON == null) return obj; // No se ha llamado al init o enabled = false - - return SINGLETON.create(obj, classes); - } - - - public static boolean isEnabledStatic() - { - if (SINGLETON == null) + + return SINGLETON.create(obj, classes); + } + + + public static boolean isEnabledStatic() { + if (SINGLETON == null) return false; - + return SINGLETON.isEnabled(); - } - - - public static boolean isRunningStatic() - { - if (SINGLETON == null) + } + + + public static boolean isRunningStatic() { + if (SINGLETON == null) return false; - + return SINGLETON.isRunning(); - } - - public static boolean stopStatic() - { - if (SINGLETON == null) + } + + public static boolean stopStatic() { + if (SINGLETON == null) return false; - + return SINGLETON.stop(); - } - - public static boolean startStatic() - { - if (SINGLETON == null) + } + + public static boolean startStatic() { + if (SINGLETON == null) return false; - + return SINGLETON.start(); - } + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyUtil.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyUtil.java index dcfa297..ba850d0 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyUtil.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyUtil.java @@ -17,149 +17,126 @@ import java.net.URLConnection; /** - * * @author jmarranz */ -public class JProxyUtil -{ - public static String getCanonicalPath(@NotNull File file) - { - try - { +public class JProxyUtil { + public static String getCanonicalPath(@NotNull File file) { + try { return file.getCanonicalPath(); - } - catch (IOException ex) - { + } catch (IOException ex) { throw new RelProxyException(ex); } } - - public static String getFileExtension(@NotNull File file) - { + + public static String getFileExtension(@NotNull File file) { String path = file.getAbsolutePath(); - int pos = path.lastIndexOf('.'); - if (pos != -1) - return path.substring(pos + 1); + int pos = path.lastIndexOf('.'); + if (pos != -1) + return path.substring(pos + 1); return ""; - } - - public static File getParentDir(@NotNull File file) - { + } + + public static File getParentDir(@NotNull File file) { return file.getParentFile(); } - - public static byte[] readURL(@NotNull URL url) - { + + public static byte[] readURL(@NotNull URL url) { URLConnection urlCon; - try - { - urlCon = url.openConnection(); - return readInputStream(urlCon.getInputStream()); - } - catch (IOException ex) { throw new RelProxyException(ex); } + try { + urlCon = url.openConnection(); + return readInputStream(urlCon.getInputStream()); + } catch (IOException ex) { + throw new RelProxyException(ex); + } } - - public static byte[] readFile(@NotNull File file) - { + + public static byte[] readFile(@NotNull File file) { FileInputStream fis = null; - try - { - fis = new FileInputStream(file); - } - catch (FileNotFoundException ex) - { + try { + fis = new FileInputStream(file); + } catch (FileNotFoundException ex) { throw new RelProxyException(ex); - } + } return readInputStream(fis); - } + } - public static byte[] readInputStream(@NotNull InputStream is) - { - return readInputStream(is,50); // 50Kb => unas 100 lecturas 5 Mb + public static byte[] readInputStream(@NotNull InputStream is) { + return readInputStream(is, 50); // 50Kb => unas 100 lecturas 5 Mb } - public static byte[] readInputStream(@NotNull InputStream is, int bufferSizeKb) - { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - try - { - byte[] buffer = new byte[bufferSizeKb*1024]; + public static byte[] readInputStream(@NotNull InputStream is, int bufferSizeKb) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + try { + byte[] buffer = new byte[bufferSizeKb * 1024]; int size; - while( (size = is.read(buffer)) != -1 ) - { - out.write(buffer, 0, size); - } - } - catch (IOException ex) - { + while ((size = is.read(buffer)) != -1) { + out.write(buffer, 0, size); + } + } catch (IOException ex) { throw new RelProxyException(ex); - } - finally - { - try { is.close(); } catch (IOException ex2) { throw new RelProxyException(ex2); } + } finally { + try { + is.close(); + } catch (IOException ex2) { + throw new RelProxyException(ex2); + } } return out.toByteArray(); - } - - public static void saveFile(@NotNull File file, @NotNull byte[] content) - { + } + + public static void saveFile(@NotNull File file, @NotNull byte[] content) { File parent = getParentDir(file); if (parent != null) parent.mkdirs(); - FileOutputStream out = null; - try - { - out = new FileOutputStream(file); - out.write(content, 0, content.length); - } - catch (IOException ex) - { + FileOutputStream out = null; + try { + out = new FileOutputStream(file); + out.write(content, 0, content.length); + } catch (IOException ex) { throw new RelProxyException(ex); - } - finally - { - if (out != null) try { out.close(); } catch (IOException ex2) { throw new RelProxyException(ex2); } + } finally { + if (out != null) try { + out.close(); + } catch (IOException ex2) { + throw new RelProxyException(ex2); + } } - } + } - public static String readTextFile(@NotNull File file, @NotNull String encoding) - { + public static String readTextFile(@NotNull File file, @NotNull String encoding) { Reader reader = null; - try - { - reader = new InputStreamReader(new FileInputStream(file),encoding); // FileReader no permite especificar el encoding y total no hace nada que no haga InputStreamReader + try { + reader = new InputStreamReader(new FileInputStream(file), encoding); // FileReader no permite especificar el encoding y total no hace nada que no haga InputStreamReader + } catch (IOException ex) { + throw new RelProxyException(ex); } - catch(IOException ex) { throw new RelProxyException(ex); } - + return readTextFile(reader); - } - - public static String readTextFile(@NotNull Reader reader) - { + } + + public static String readTextFile(@NotNull Reader reader) { BufferedReader br = null; - try - { + try { br = new BufferedReader(reader); // FileReader no permite especificar el encoding y total no hace nada que no haga InputStreamReader StringBuilder sb = new StringBuilder(); String line = br.readLine(); - while (line != null) - { + while (line != null) { sb.append(line); sb.append('\n'); line = br.readLine(); } return sb.toString(); - } - catch(IOException ex) - { + } catch (IOException ex) { throw new RelProxyException(ex); + } finally { + if (br != null) try { + br.close(); + } catch (IOException ex) { + throw new RelProxyException(ex); + } } - finally - { - if (br != null) try { br.close(); } catch (IOException ex) { throw new RelProxyException(ex); } - } - } + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyImpl.java index 8c9883c..df213eb 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyImpl.java @@ -14,35 +14,29 @@ import org.jetbrains.annotations.Nullable; /** - * * @author jmarranz */ -public abstract class JProxyImpl extends GenericProxyImpl -{ - public static JProxyImpl SINGLETON; +public abstract class JProxyImpl extends GenericProxyImpl { + public static JProxyImpl SINGLETON; protected JProxyEngine engine; - - protected JProxyImpl() - { + + protected JProxyImpl() { } - - public static ClassLoader getDefaultClassLoader() - { + + public static ClassLoader getDefaultClassLoader() { return Thread.currentThread().getContextClassLoader(); } - + @Nullable - public ClassDescriptorSourceScript init(@NotNull JProxyConfigImpl config) - { - return init(config,null,null); - } - + public ClassDescriptorSourceScript init(@NotNull JProxyConfigImpl config) { + return init(config, null, null); + } + @Nullable - public ClassDescriptorSourceScript init(@NotNull JProxyConfigImpl config, SourceScriptRoot scriptFile, ClassLoader classLoader) - { + public ClassDescriptorSourceScript init(@NotNull JProxyConfigImpl config, SourceScriptRoot scriptFile, ClassLoader classLoader) { super.init(config); - + FolderSourceList folderSourceList = config.getFolderSourceList(); FolderSourceList requiredExtraJarPaths = config.getRequiredExtraJarPaths(); JProxyInputSourceFileExcludedListener excludedListener = config.getJProxyInputSourceFileExcludedListener(); @@ -52,45 +46,39 @@ public ClassDescriptorSourceScript init(@NotNull JProxyConfigImpl config, Source Iterable compilationOptions = config.getCompilationOptions(); JProxyDiagnosticsListener diagnosticsListener = config.getJProxyDiagnosticsListener(); boolean enabled = config.isEnabled(); - - classLoader = classLoader != null ? classLoader : getDefaultClassLoader(); - this.engine = new JProxyEngine(this,enabled,scriptFile,classLoader,folderSourceList,requiredExtraJarPaths,classFolder,scanPeriod,excludedListener,compilerListener,compilationOptions,diagnosticsListener); - + + classLoader = classLoader != null ? classLoader : getDefaultClassLoader(); + this.engine = new JProxyEngine(this, enabled, scriptFile, classLoader, folderSourceList, requiredExtraJarPaths, classFolder, scanPeriod, excludedListener, compilerListener, compilationOptions, diagnosticsListener); + return engine.init(); - } - - public JProxyEngine getJProxyEngine() - { + } + + public JProxyEngine getJProxyEngine() { return engine; } - - public boolean isEnabled() - { + + public boolean isEnabled() { return engine.isEnabled(); } - - public boolean isRunning() - { + + public boolean isRunning() { return engine.isRunning(); - } - - public boolean stop() - { + } + + public boolean stop() { return engine.stop(); - } - - public boolean start() - { + } + + public boolean start() { return engine.start(); - } - + } + @NotNull @Override - public GenericProxyInvocationHandler createGenericProxyInvocationHandler(@NotNull Object obj) - { - return new JProxyInvocationHandler(obj,this); + public GenericProxyInvocationHandler createGenericProxyInvocationHandler(@NotNull Object obj) { + return new JProxyInvocationHandler(obj, this); } - + @Nullable public abstract Class getMainParamClass(); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyInvocationHandler.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyInvocationHandler.java index d4223e5..4820f08 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyInvocationHandler.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyInvocationHandler.java @@ -5,21 +5,17 @@ import org.jetbrains.annotations.NotNull; /** - * * @author jmarranz */ -public class JProxyInvocationHandler extends GenericProxyInvocationHandler -{ - public JProxyInvocationHandler(@NotNull Object obj, JProxyImpl root) - { +public class JProxyInvocationHandler extends GenericProxyInvocationHandler { + public JProxyInvocationHandler(@NotNull Object obj, JProxyImpl root) { super(root); - this.verObj = new JProxyVersionedObject(obj,this); + this.verObj = new JProxyVersionedObject(obj, this); } @NotNull - public JProxyImpl getJProxyImpl() - { - return (JProxyImpl)root; - } - + public JProxyImpl getJProxyImpl() { + return (JProxyImpl) root; + } + } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyVersionedObject.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyVersionedObject.java index 2951dd4..55e2931 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyVersionedObject.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyVersionedObject.java @@ -8,37 +8,31 @@ import java.lang.reflect.Field; /** - * * @author jmarranz */ -public class JProxyVersionedObject extends GenericProxyVersionedObject -{ - protected String className; +public class JProxyVersionedObject extends GenericProxyVersionedObject { + protected String className; - public JProxyVersionedObject(@NotNull Object obj, JProxyInvocationHandler parent) - { - super(obj,parent); + public JProxyVersionedObject(@NotNull Object obj, JProxyInvocationHandler parent) { + super(obj, parent); this.className = obj.getClass().getName(); - } + } @NotNull - public JProxyInvocationHandler getJProxyInvocationHandler() - { - return (JProxyInvocationHandler)parent; - } - + public JProxyInvocationHandler getJProxyInvocationHandler() { + return (JProxyInvocationHandler) parent; + } + @Nullable @Override - protected Class reloadClass() - { - JProxyEngine engine = getJProxyInvocationHandler().getJProxyImpl().getJProxyEngine(); + protected Class reloadClass() { + JProxyEngine engine = getJProxyInvocationHandler().getJProxyImpl().getJProxyEngine(); engine.reloadWhenChanged(); - return (Class)engine.findClass(className); + return (Class) engine.findClass(className); } - + @Override - protected boolean ignoreField(Field field) - { + protected boolean ignoreField(Field field) { return false; // Todos cuentan (útil en Groovy no en Java) - } + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java index 9e54d35..925da6d 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java @@ -8,76 +8,64 @@ import java.io.File; /** - * * @author jmarranz */ -public class FolderSourceList -{ +public class FolderSourceList { protected FileExt[] sourceList; - - public FolderSourceList(@Nullable String[] sourcePathList, boolean expectedDirectory) - { + + public FolderSourceList(@Nullable String[] sourcePathList, boolean expectedDirectory) { if (sourcePathList != null) // En el caso de shell interactivo es null { // El convertir siempre a File los paths es para normalizar paths this.sourceList = new FileExt[sourcePathList.length]; - for(int i = 0; i < sourcePathList.length; i++) - { + for (int i = 0; i < sourcePathList.length; i++) { File folder = new File(sourcePathList[i]); if (!folder.exists()) throw new RelProxyException("Source folder does not exist: " + folder.getAbsolutePath()); boolean isDirectory = folder.isDirectory(); - if (expectedDirectory) - { + if (expectedDirectory) { if (!isDirectory) - throw new RelProxyException("Source folder is not a directory: " + folder.getAbsolutePath()); - } - else - { + throw new RelProxyException("Source folder is not a directory: " + folder.getAbsolutePath()); + } else { if (isDirectory) - throw new RelProxyException("Expected a file not a directory: " + folder.getAbsolutePath()); + throw new RelProxyException("Expected a file not a directory: " + folder.getAbsolutePath()); } - sourceList[i] = new FileExt(folder); + sourceList[i] = new FileExt(folder); } } - } - - public FileExt[] getArray() - { - return sourceList; } - + + public FileExt[] getArray() { + return sourceList; + } + @Nullable - public String buildClassNameFromFile(@NotNull FileExt sourceFile) - { - for(FileExt rootFolderOfSources : sourceList) - { - String className = buildClassNameFromFile(sourceFile,rootFolderOfSources); + public String buildClassNameFromFile(@NotNull FileExt sourceFile) { + for (FileExt rootFolderOfSources : sourceList) { + String className = buildClassNameFromFile(sourceFile, rootFolderOfSources); if (className != null) - return className; + return className; } throw new RelProxyException("File not found in source folders: " + sourceFile.getFile().getAbsolutePath()); - } - - public static String buildClassNameFromFile(@NotNull FileExt sourceFile, @NotNull FileExt rootFolderOfSources) - { + } + + public static String buildClassNameFromFile(@NotNull FileExt sourceFile, @NotNull FileExt rootFolderOfSources) { String path = sourceFile.getCanonicalPath(); String rootFolderOfSourcesAbsPath = rootFolderOfSources.getCanonicalPath(); - int pos = path.indexOf(rootFolderOfSourcesAbsPath); + int pos = path.indexOf(rootFolderOfSourcesAbsPath); if (pos == 0) // Está en este source folder { path = path.substring(rootFolderOfSourcesAbsPath.length() + 1); // Sumamos +1 para quitar también el / separador del pathInput y el path relativo de la clase // Puede no tener extensión (script) o bien ser .java o bien ser una inventada (ej .jsh), la quitamos si existe - pos = path.lastIndexOf('.'); - if (pos != -1) - path = path.substring(0, pos); + pos = path.lastIndexOf('.'); + if (pos != -1) + path = path.substring(0, pos); path = path.replace(File.separatorChar, '.'); // getAbsolutePath() normaliza con el caracter de la plataforma return path; } return null; - } - - - + } + + } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java index 8552bbc..4a14c6b 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java @@ -9,42 +9,35 @@ import java.net.URL; /** - * * @author jmarranz */ -public class JProxyClassLoader extends ClassLoader -{ +public class JProxyClassLoader extends ClassLoader { @NotNull protected final JProxyEngine engine; - - public JProxyClassLoader(@NotNull JProxyEngine engine) - { + + public JProxyClassLoader(@NotNull JProxyEngine engine) { super(engine.getRootClassLoader()); - + this.engine = engine; } - - public Class defineClass(@NotNull ClassDescriptor classDesc) - { + + public Class defineClass(@NotNull ClassDescriptor classDesc) { Object monitor = engine.getMonitor(); - synchronized(monitor) - { + synchronized (monitor) { String className = classDesc.getClassName(); byte[] classBytes = classDesc.getClassBytes(); - Class clasz = defineClass(className,classBytes, 0, classBytes.length); + Class clasz = defineClass(className, classBytes, 0, classBytes.length); classDesc.setLastLoadedClass(clasz); - return clasz; + return clasz; } } - + @Override - protected Class findClass(@NotNull String name) throws ClassNotFoundException - { + protected Class findClass(@NotNull String name) throws ClassNotFoundException { Object monitor = engine.getMonitor(); - synchronized(monitor) - { - return loadClass(name,true); - + synchronized (monitor) { + return loadClass(name, true); + /* Class cls = findLoadedClass(name); if (cls == null) @@ -56,49 +49,43 @@ protected Class findClass(@NotNull String name) throws ClassNotFoundException return cls; */ } - } + } - public Class loadClass(@NotNull ClassDescriptor classDesc, boolean resolve) - { + public Class loadClass(@NotNull ClassDescriptor classDesc, boolean resolve) { Object monitor = engine.getMonitor(); - synchronized(monitor) - { + synchronized (monitor) { Class clasz = classDesc.getLastLoadedClass(); if (clasz != null && clasz.getClassLoader() == this) return clasz; // Glup, ya fue cargada - clasz = defineClass(classDesc); + clasz = defineClass(classDesc); if (resolve) { resolveClass(clasz); - } + } return clasz; } - } - + } + @Nullable - public Class loadInnerClass(@NotNull ClassDescriptorSourceUnit parentDesc, @NotNull String innerClassName) - { + public Class loadInnerClass(@NotNull ClassDescriptorSourceUnit parentDesc, @NotNull String innerClassName) { Object monitor = engine.getMonitor(); - synchronized(monitor) - { - ClassDescriptor classDesc = parentDesc.getInnerClassDescriptor(innerClassName,false); - if (classDesc == null || classDesc.getClassBytes() == null) - { - byte[] classBytes = getClassBytesFromResource(innerClassName); - if (classBytes == null) return null; + synchronized (monitor) { + ClassDescriptor classDesc = parentDesc.getInnerClassDescriptor(innerClassName, false); + if (classDesc == null || classDesc.getClassBytes() == null) { + byte[] classBytes = getClassBytesFromResource(innerClassName); + if (classBytes == null) return null; if (classDesc == null) classDesc = parentDesc.addInnerClassDescriptor(innerClassName); classDesc.setClassBytes(classBytes); - } + } - return defineClass(classDesc); + return defineClass(classDesc); } } - + @Override - protected Class loadClass(@NotNull String name, boolean resolve) throws ClassNotFoundException - { + protected Class loadClass(@NotNull String name, boolean resolve) throws ClassNotFoundException { // Inspiraciones en URLClassLoader.findClass y en el propio análisis de ClassLoader.loadClass // Lo redefinimos por si acaso porque el objetivo es recargar todas las clases hot-reloaded en este ClassLoader y no delegar en el parent // (el comportamiento por defecto de loadClass) pues las clases cargadas con el parent tenderán a cargar las clases vinculadas con dicho ClassLoader - + // En teoría este método redefinido no es necesario porque manualmente detectamos los cambios de código fuente, recompilamos y recargamos explícitamente // con defineClass el cual no carga también las innerclasses vinculadas, // pero si el código fuente tiene innerclasses y no ha sido cambiado nunca, las innerclasses pueden no ser conocidas como ClassDescriptor, @@ -110,32 +97,27 @@ protected Class loadClass(@NotNull String name, boolean resolve) throws Class // por lo que pasaremos por aquí y debemos cargarla aquí, luego no hay problema de recarga explícita porque sabemos que ha sido ya cargada // y tampoco hay problema de auto-salvado del .class o eliminación del mismo puesto que al ser un archivo fuente normal se tratará por si mismo // aunque la carga en el class loader se haya hecho a través de una clase derivada quizás antes - + Object monitor = engine.getMonitor(); - synchronized(monitor) - { + synchronized (monitor) { Class cls = findLoadedClass(name); - if (cls == null) - { + if (cls == null) { ClassDescriptor classDesc = engine.getClassDescriptor(name); // Si es una inner class se crea el descriptor y se añade al source file asociado automáticamente - if (classDesc != null) - { + if (classDesc != null) { byte[] classBytes = classDesc.getClassBytes(); - if (classBytes == null) - { + if (classBytes == null) { classBytes = getClassBytesFromResource(name); // No puede ser nulo classDesc.setClassBytes(classBytes); } - cls = defineClass(classDesc); + cls = defineClass(classDesc); } - - if (cls == null) - { + + if (cls == null) { cls = getParent().loadClass(name); // Dará un ClassNotFoundException si no puede cargarla } - } - + } + if (cls == null) throw new ClassNotFoundException(name); if (resolve) { @@ -144,12 +126,11 @@ protected Class loadClass(@NotNull String name, boolean resolve) throws Class return cls; } } - - private byte[] getClassBytesFromResource(@NotNull String className) - { - String relClassPath = ClassDescriptor.getRelativeClassFilePathFromClassName(className); + + private byte[] getClassBytesFromResource(@NotNull String className) { + String relClassPath = ClassDescriptor.getRelativeClassFilePathFromClassName(className); URL urlClass = getResource(relClassPath); if (urlClass == null) return null; - return JProxyUtil.readURL(urlClass); + return JProxyUtil.readURL(urlClass); } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java index efdfdd7..303706c 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java @@ -18,11 +18,9 @@ import java.util.TimerTask; /** - * * @author jmarranz */ -public class JProxyEngine -{ +public class JProxyEngine { protected final Object monitor = new Object(); // Podríamos usar este objeto JProxyEngine directamente pero el monitor es mejor para análisis de dependencias protected final JProxyImpl parent; @NotNull @@ -30,47 +28,41 @@ public class JProxyEngine protected final ClassLoader rootClassLoader; @Nullable protected JProxyClassLoader customClassLoader; - protected final long scanPeriod; + protected final long scanPeriod; protected final String sourceEncoding = "UTF-8"; // Por ahora, provisional public volatile boolean stop = false; @Nullable protected TimerTask task; - protected boolean pendingReload = false; - protected final boolean enabled; - - public JProxyEngine(JProxyImpl parent,boolean enabled,SourceScriptRoot scriptFile,ClassLoader rootClassLoader,FolderSourceList folderSourceList,FolderSourceList requiredExtraJarPaths, - String folderClasses,long scanPeriod,JProxyInputSourceFileExcludedListener excludedListener, - JProxyCompilerListener compilerListener,Iterable compilationOptions,JProxyDiagnosticsListener diagnosticsListener) - { + protected boolean pendingReload = false; + protected final boolean enabled; + + public JProxyEngine(JProxyImpl parent, boolean enabled, SourceScriptRoot scriptFile, ClassLoader rootClassLoader, FolderSourceList folderSourceList, FolderSourceList requiredExtraJarPaths, + String folderClasses, long scanPeriod, JProxyInputSourceFileExcludedListener excludedListener, + JProxyCompilerListener compilerListener, Iterable compilationOptions, JProxyDiagnosticsListener diagnosticsListener) { this.parent = parent; - this.enabled = enabled; + this.enabled = enabled; this.rootClassLoader = rootClassLoader; this.scanPeriod = scanPeriod; - this.delegateChangeDetector = new JProxyEngineChangeDetectorAndCompiler(this,scriptFile,folderSourceList,requiredExtraJarPaths,folderClasses,excludedListener,compilationOptions,diagnosticsListener,compilerListener); + this.delegateChangeDetector = new JProxyEngineChangeDetectorAndCompiler(this, scriptFile, folderSourceList, requiredExtraJarPaths, folderClasses, excludedListener, compilationOptions, diagnosticsListener, compilerListener); this.customClassLoader = null; //new JProxyClassLoader(this); } - + @NotNull - public Object getMonitor() - { + public Object getMonitor() { return monitor; } - - public JProxyImpl getJProxy() - { + + public JProxyImpl getJProxy() { return parent; } - - public boolean isEnabled() - { + + public boolean isEnabled() { return enabled; - } - + } + @Nullable - public ClassDescriptorSourceScript init() - { - synchronized(getMonitor()) - { + public ClassDescriptorSourceScript init() { + synchronized (getMonitor()) { ClassDescriptorSourceScript scriptFileDesc = detectChangesInSources(); // Primera vez para detectar cambios en los .java respecto a los .class mientras el servidor estaba parado reloadWhenChanged(); // La primera vez cargamos pues el código fuente manda sobre los .class @@ -87,230 +79,185 @@ public JProxyClassLoader getJProxyClassLoader() return customClassLoader; } */ - + @Nullable - public ClassLoader getCurrentClassLoader() - { + public ClassLoader getCurrentClassLoader() { if (customClassLoader != null) return customClassLoader; return rootClassLoader; - } - - private boolean startScanner() - { + } + + private boolean startScanner() { if (scanPeriod > 0) // Si es 0 o negativo sólo se recargan una vez (la inicial ya ejecutada) - { - this.task = new TimerTask() - { + { + this.task = new TimerTask() { @Override - public void run() - { - if (stop) - { + public void run() { + if (stop) { cancel(); return; } - - try - { + + try { detectChangesInSources(); // Está sincronizado las partes que lo necesitan - } - catch(Exception ex) - { + } catch (Exception ex) { ex.printStackTrace(System.err); // Si dejamos subir la excepción se acabó el timer } } - }; - + }; + new Timer().schedule(task, scanPeriod, scanPeriod); // Ojo, después de la primera llamada a detectChangesInSources() return true; - } - else - { + } else { return false; } } - - public void setPendingReload() - { + + public void setPendingReload() { this.pendingReload = true; - } - - - public ClassLoader getRootClassLoader() - { + } + + + public ClassLoader getRootClassLoader() { return rootClassLoader; } - + @NotNull - public String getSourceEncoding() - { + public String getSourceEncoding() { return sourceEncoding; } - - public boolean isRunning() - { - synchronized(getMonitor()) - { + + public boolean isRunning() { + synchronized (getMonitor()) { return task != null && scanPeriod > 0; } } - - public boolean stop() - { - synchronized(getMonitor()) - { - if (task != null) - { + + public boolean stop() { + synchronized (getMonitor()) { + if (task != null) { this.stop = true; task.cancel(); this.task = null; return true; - } - else - { + } else { return false; } } - } - - public boolean start() - { - synchronized(getMonitor()) - { - if (task == null) - { + } + + public boolean start() { + synchronized (getMonitor()) { + if (task == null) { this.stop = false; return startScanner(); - } - else return false; + } else return false; } - } - + } + - @Nullable - public ClassDescriptor getClassDescriptor(@NotNull String className) - { - synchronized(getMonitor()) - { + public ClassDescriptor getClassDescriptor(@NotNull String className) { + synchronized (getMonitor()) { return delegateChangeDetector.getClassDescriptor(className); } } - + @Nullable - public Class findClass(@NotNull String className) - { + public Class findClass(@NotNull String className) { // Si ya está cargada la devuelve, y si no se cargó por ningún JProxyClassLoader se intenta cargar por el parent ClassLoader, por lo que siempre devolverá distinto de null si la clase está en el classpath, que debería ser lo normal - synchronized(getMonitor()) - { - try - { + synchronized (getMonitor()) { + try { if (customClassLoader != null) - return customClassLoader.findClass(className); + return customClassLoader.findClass(className); else return rootClassLoader.loadClass(className); - } - catch (ClassNotFoundException ex) - { + } catch (ClassNotFoundException ex) { return null; } } } - - private void addNewClassLoader() - { + + private void addNewClassLoader() { ClassDescriptorSourceFileRegistry sourceRegistry = delegateChangeDetector.getClassDescriptorSourceFileRegistry(); - - for(ClassDescriptorSourceUnit sourceFile : sourceRegistry.getClassDescriptorSourceFileColl()) - { + + for (ClassDescriptorSourceUnit sourceFile : sourceRegistry.getClassDescriptorSourceFileColl()) { sourceFile.resetLastLoadedClass(); // resetea también las innerclasses } - - this.customClassLoader = new JProxyClassLoader(this); + + this.customClassLoader = new JProxyClassLoader(this); } - - - private Class reloadSource(@NotNull ClassDescriptorSourceUnit sourceFile) - { - Class clasz = customClassLoader.loadClass(sourceFile,true); - reloadInnerClassesOnly(sourceFile,clasz); + + private Class reloadSource(@NotNull ClassDescriptorSourceUnit sourceFile) { + Class clasz = customClassLoader.loadClass(sourceFile, true); + reloadInnerClassesOnly(sourceFile, clasz); return clasz; } - - private void reloadInnerClassesOnly(@NotNull ClassDescriptorSourceUnit sourceFile, @NotNull Class classParent) - { - - LinkedList innerClassDescList = sourceFile.getInnerClassDescriptors(); - if (innerClassDescList != null && !innerClassDescList.isEmpty()) - { + + private void reloadInnerClassesOnly(@NotNull ClassDescriptorSourceUnit sourceFile, @NotNull Class classParent) { + + LinkedList innerClassDescList = sourceFile.getInnerClassDescriptors(); + if (innerClassDescList != null && !innerClassDescList.isEmpty()) { // En el caso de una clase que ha sido compilada, las inner classes se descubren todas - for(ClassDescriptorInner innerClassDesc : innerClassDescList) - { - customClassLoader.loadClass(innerClassDesc,true); + for (ClassDescriptorInner innerClassDesc : innerClassDescList) { + customClassLoader.loadClass(innerClassDesc, true); } - } - else // Auto-Detección de innerclasses: puede ser un archivo fuente que posiblemente nunca se hayan tocado desde la carga inicial y por tanto quizás se desconocen las innerclasses + } else // Auto-Detección de innerclasses: puede ser un archivo fuente que posiblemente nunca se hayan tocado desde la carga inicial y por tanto quizás se desconocen las innerclasses { // Aprovechando la carga de la clase, hacemos el esfuerzo de cargar todas las clases dependientes lo más posible classParent.getDeclaredClasses(); // Provoca que las inner clases miembro indirectamente se procesen y carguen a través del JProxyClassLoader de la clase padre clasz - + // Ahora bien, lo anterior NO sirve para las anonymous inner classes, afortunadamente en ese caso podemos conocer y cargar por fuerza bruta // http://stackoverflow.com/questions/1654889/java-reflection-how-can-i-retrieve-anonymous-inner-classes?rq=1 - - for(int i = 1; i < Integer.MAX_VALUE; i++) // No te asustes por el MAX_VALUE, se parará tras unos poquitos ciclos + + for (int i = 1; i < Integer.MAX_VALUE; i++) // No te asustes por el MAX_VALUE, se parará tras unos poquitos ciclos { - String anonClassName = sourceFile.getClassName() + "$" + i; - Class innerClasz = customClassLoader.loadInnerClass(sourceFile,anonClassName); + String anonClassName = sourceFile.getClassName() + "$" + i; + Class innerClasz = customClassLoader.loadInnerClass(sourceFile, anonClassName); if (innerClasz == null) break; // No hay más o no hay ninguna (si i es 1) - } - + } + // ¿Qué es lo que queda por cargar pero que no podemos hacer explícitamente? // 1) Las clases privadas autónomas que fueron definidas en el mismo archivo que la clase principal: no las soportamos pues no podemos identificar en el ClassLoader que es una clase "hot reloadable", no son inner classes en el sentido estricto // 2) Las clases privadas "inner" locales, es decir no anónimas declaradas dentro de un método, se cargarán la primera vez que se usen, no podemos conocerlas a priori // porque siguen la notación className$NclassName ej. JReloadExampleDocument$1AuxMemberInMethod. No hay problema con que se carguen con un class loader antiguo pues // el ClassLoader de la clase padre contenedora será el encargado de cargarla en cuanto se pase por el método que la declara. - } - } - + } + } + @Nullable - public ClassDescriptorSourceScript detectChangesInSources() - { - return delegateChangeDetector.detectChangesInSources(); - } - + public ClassDescriptorSourceScript detectChangesInSources() { + return delegateChangeDetector.detectChangesInSources(); + } + @Nullable - public ClassDescriptorSourceScript detectChangesInSourcesAndReload() - { - ClassDescriptorSourceScript res = detectChangesInSources(); + public ClassDescriptorSourceScript detectChangesInSourcesAndReload() { + ClassDescriptorSourceScript res = detectChangesInSources(); reloadWhenChanged(); - return res; - } - - public boolean reloadWhenChanged() - { - synchronized(getMonitor()) - { - if (pendingReload) - { + return res; + } + + public boolean reloadWhenChanged() { + synchronized (getMonitor()) { + if (pendingReload) { addNewClassLoader(); - ClassDescriptorSourceFileRegistry sourceRegistry = delegateChangeDetector.getClassDescriptorSourceFileRegistry(); + ClassDescriptorSourceFileRegistry sourceRegistry = delegateChangeDetector.getClassDescriptorSourceFileRegistry(); - for(ClassDescriptorSourceUnit sourceFile : sourceRegistry.getClassDescriptorSourceFileColl()) // sourceRegistry NUNCA es nulo pues se ejecuta una primera vez en tiempo de inicialización + for (ClassDescriptorSourceUnit sourceFile : sourceRegistry.getClassDescriptorSourceFileColl()) // sourceRegistry NUNCA es nulo pues se ejecuta una primera vez en tiempo de inicialización { - // if (sourceFilesCompiled.contains(sourceFile)) - // continue; + // if (sourceFilesCompiled.contains(sourceFile)) + // continue; // las clases deleted no están en sourceFileMap por lo que no hay que filtrarlas reloadSource(sourceFile); // Ponemos detectInnerClasses a true porque son archivos fuente que posiblemente nunca se hayan tocado desde la carga inicial y por tanto quizás se desconocen las innerclasses - } + } this.pendingReload = false; return true; } - return false; + return false; } } - + } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java index 4e6f179..90df143 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java @@ -24,225 +24,194 @@ import java.util.LinkedList; /** - * * @author jmarranz */ -public class JProxyEngineChangeDetectorAndCompiler -{ +public class JProxyEngineChangeDetectorAndCompiler { protected final JProxyEngine engine; @NotNull protected final JProxyCompilerInMemory compiler; - protected final FolderSourceList folderSourceList; + protected final FolderSourceList folderSourceList; protected final FolderSourceList requiredExtraJarPaths; protected final SourceScriptRoot scriptFile; // Puede ser nulo protected final String folderClasses; // Puede ser nulo (es decir NO salvar como .class los cambios) - protected final JProxyInputSourceFileExcludedListener excludedListener; + protected final JProxyInputSourceFileExcludedListener excludedListener; @NotNull protected final JavaSourcesSearch sourcesSearch; - protected final JProxyCompilerListener compilerListener; + protected final JProxyCompilerListener compilerListener; protected volatile ClassDescriptorSourceFileRegistry sourceRegistry; - - public JProxyEngineChangeDetectorAndCompiler(JProxyEngine engine,SourceScriptRoot scriptFile,FolderSourceList folderSourceList,FolderSourceList requiredExtraJarPaths, - String folderClasses, JProxyInputSourceFileExcludedListener excludedListener,Iterable compilationOptions,JProxyDiagnosticsListener diagnosticsListener, - JProxyCompilerListener compilerListener) - { + + public JProxyEngineChangeDetectorAndCompiler(JProxyEngine engine, SourceScriptRoot scriptFile, FolderSourceList folderSourceList, FolderSourceList requiredExtraJarPaths, + String folderClasses, JProxyInputSourceFileExcludedListener excludedListener, Iterable compilationOptions, JProxyDiagnosticsListener diagnosticsListener, + JProxyCompilerListener compilerListener) { this.engine = engine; this.scriptFile = scriptFile; - this.folderSourceList = folderSourceList; + this.folderSourceList = folderSourceList; this.requiredExtraJarPaths = requiredExtraJarPaths; this.folderClasses = folderClasses; this.excludedListener = excludedListener; - this.compiler = new JProxyCompilerInMemory(this,compilationOptions,diagnosticsListener); - this.sourcesSearch = new JavaSourcesSearch(this); + this.compiler = new JProxyCompilerInMemory(this, compilationOptions, diagnosticsListener); + this.sourcesSearch = new JavaSourcesSearch(this); this.compilerListener = compilerListener; } - - public JProxyEngine getJProxyEngine() - { + + public JProxyEngine getJProxyEngine() { return engine; } - - public FolderSourceList getFolderSourceList() - { + + public FolderSourceList getFolderSourceList() { return folderSourceList; - } - - public FolderSourceList getRequiredExtraJarPaths() - { + } + + public FolderSourceList getRequiredExtraJarPaths() { return requiredExtraJarPaths; - } - - public JProxyInputSourceFileExcludedListener getJProxyInputSourceFileExcludedListener() - { + } + + public JProxyInputSourceFileExcludedListener getJProxyInputSourceFileExcludedListener() { return excludedListener; - } - - public ClassDescriptorSourceFileRegistry getClassDescriptorSourceFileRegistry() - { + } + + public ClassDescriptorSourceFileRegistry getClassDescriptorSourceFileRegistry() { return sourceRegistry; - } - + } + @Nullable - public ClassDescriptor getClassDescriptor(@NotNull String className) - { + public ClassDescriptor getClassDescriptor(@NotNull String className) { return sourceRegistry.getClassDescriptor(className); - } - - private boolean isSaveClassesMode() - { + } + + private boolean isSaveClassesMode() { return (folderClasses != null); - } - - private JProxyCompilerListener getJProxyCompilerListener() - { + } + + private JProxyCompilerListener getJProxyCompilerListener() { return compilerListener; } - - private void cleanBeforeCompile(@NotNull ClassDescriptorSourceUnit sourceFile) - { - if (isSaveClassesMode()) + + private void cleanBeforeCompile(@NotNull ClassDescriptorSourceUnit sourceFile) { + if (isSaveClassesMode()) deleteClasses(sourceFile); // Antes de que nos las carguemos en memoria la clase principal y las inner tras recompilar - + sourceFile.cleanOnSourceCodeChanged(); // El código fuente nuevo puede haber cambiado totalmente las innerclasses antiguas (añadido, eliminado) y por supuesto el bytecode necesita olvidarse } - - private void compile(@NotNull ClassDescriptorSourceUnit sourceFile, @NotNull JProxyCompilerContext context) - { + + private void compile(@NotNull ClassDescriptorSourceUnit sourceFile, @NotNull JProxyCompilerContext context) { if (sourceFile.getClassBytes() != null) return; // Ya ha sido compilado seguramente por dependencia de un archivo compilado inmediatamente antes, recuerda que el atributo classBytes se pone a null antes de compilar los archivos cambiados/nuevos - - compiler.compileSourceFile(sourceFile,context,engine.getCurrentClassLoader(),sourceRegistry); - } - + + compiler.compileSourceFile(sourceFile, context, engine.getCurrentClassLoader(), sourceRegistry); + } + @Nullable - public ClassDescriptorSourceScript detectChangesInSources() - { + public ClassDescriptorSourceScript detectChangesInSources() { Object monitor = getJProxyEngine().getMonitor(); - + boolean firstTime; - - synchronized(monitor) - { + + synchronized (monitor) { if (this.sourceRegistry == null) // Es null la primera vez { firstTime = true; this.sourceRegistry = new ClassDescriptorSourceFileRegistry(); - } - else - { + } else { firstTime = false; - sourceRegistry.setAllClassDescriptorSourceFilesPendingToRemove( true ); // A medida que los vamos encontrando ponemos a false, es mucho más rápido que recrear el registro si no ha cambiado nada (lo normal) + sourceRegistry.setAllClassDescriptorSourceFilesPendingToRemove(true); // A medida que los vamos encontrando ponemos a false, es mucho más rápido que recrear el registro si no ha cambiado nada (lo normal) } - } + } LinkedList updatedSourceFiles = new LinkedList(); - LinkedList newSourceFiles = new LinkedList(); - - ClassDescriptorSourceScript scriptFileDesc = sourcesSearch.sourceFileSearch(firstTime,scriptFile,sourceRegistry,updatedSourceFiles,newSourceFiles); + LinkedList newSourceFiles = new LinkedList(); + + ClassDescriptorSourceScript scriptFileDesc = sourcesSearch.sourceFileSearch(firstTime, scriptFile, sourceRegistry, updatedSourceFiles, newSourceFiles); LinkedList deletedSourceFiles = new LinkedList(); - - if (!firstTime) - { - synchronized(monitor) - { + + if (!firstTime) { + synchronized (monitor) { // Obtenemos los deletedSourceFiles detectados (si es firstTime no tiene sentido hacer esto no haría nada pero nos ahorramos synchronized y llamada) sourceRegistry.getAllClassDescriptorSourceFilesPendingToRemove(deletedSourceFiles); } } - + if (updatedSourceFiles.isEmpty() && newSourceFiles.isEmpty() && deletedSourceFiles.isEmpty()) return scriptFileDesc; // También el hecho de eliminar una clase debe implicar crear un ClassLoader nuevo para que dicha clase desaparezca de las clases cargadas aunque será muy raro que sólo eliminemos un .java y no añadamos/cambiemos otros, otro motico es porque si tenemos configurado el autosalvado de .class tenemos que eliminar en ese caso - synchronized(monitor) - { - if (!firstTime) - { + synchronized (monitor) { + if (!firstTime) { if (!deletedSourceFiles.isEmpty()) // En firstTime no tiene sentido que haya eliminados { - for(ClassDescriptorSourceUnit classDesc : deletedSourceFiles) + for (ClassDescriptorSourceUnit classDesc : deletedSourceFiles) sourceRegistry.removeClassDescriptorSourceUnit(classDesc.getClassName()); } if (!newSourceFiles.isEmpty()) // En firstTime ya están añadidos en sourceRegistry explícitamente al recorrer los sources { - for(ClassDescriptorSourceUnit classDesc : newSourceFiles) + for (ClassDescriptorSourceUnit classDesc : newSourceFiles) sourceRegistry.addClassDescriptorSourceUnit(classDesc); - } + } } - + ArrayList sourceFilesToCompile = new ArrayList(updatedSourceFiles.size() + newSourceFiles.size()); sourceFilesToCompile.addAll(updatedSourceFiles); - sourceFilesToCompile.addAll(newSourceFiles); + sourceFilesToCompile.addAll(newSourceFiles); updatedSourceFiles = null; // Ya no se necesita newSourceFiles = null; // Ya no se necesita - if (!sourceFilesToCompile.isEmpty()) - { + if (!sourceFilesToCompile.isEmpty()) { // Eliminamos el estado de la anterior compilación de todas las clases que van a recompilarse antes de compilarlas porque al compilar una clase es posible que // se necesite recompilar al mismo tiempo una dependiente de otra (ej clase base) y luego se intente compilar la dependiente y sería un problema que limpiáramos antes de compilar cada archivo - for(ClassDescriptorSourceUnit sourceFile : sourceFilesToCompile) - cleanBeforeCompile(sourceFile); + for (ClassDescriptorSourceUnit sourceFile : sourceFilesToCompile) + cleanBeforeCompile(sourceFile); JProxyCompilerContext context = compiler.createJProxyCompilerContext(); JProxyCompilerListener compilerListener = getJProxyCompilerListener(); - try - { + try { - for(ClassDescriptorSourceUnit sourceFile : sourceFilesToCompile) - { + for (ClassDescriptorSourceUnit sourceFile : sourceFilesToCompile) { File file = null; - if (compilerListener != null) - { + if (compilerListener != null) { SourceUnit srcUnit = sourceFile.getSourceUnit(); if (srcUnit instanceof SourceFileJavaNormal) - file = ((SourceFileJavaNormal)srcUnit).getFileExt().getFile(); + file = ((SourceFileJavaNormal) srcUnit).getFileExt().getFile(); else if (srcUnit instanceof SourceScriptRootFile) - file = ((SourceScriptRootFile)srcUnit).getFileExt().getFile(); + file = ((SourceScriptRootFile) srcUnit).getFileExt().getFile(); else if (srcUnit instanceof SourceScriptRootInMemory) // Caso de shell interactive y code snippet, en ese caso NO hay listener porque no hay forma de definirlo file = null; } if (compilerListener != null && file != null) - compilerListener.beforeCompile(file); + compilerListener.beforeCompile(file); - compile(sourceFile,context); + compile(sourceFile, context); if (compilerListener != null && file != null) - compilerListener.afterCompile(file); + compilerListener.afterCompile(file); } - } - finally - { + } finally { context.close(); } - if (isSaveClassesMode()) - { - for(ClassDescriptorSourceUnit sourceFile : sourceFilesToCompile) - { - saveClasses(sourceFile); - } + if (isSaveClassesMode()) { + for (ClassDescriptorSourceUnit sourceFile : sourceFilesToCompile) { + saveClasses(sourceFile); + } } } if (isSaveClassesMode() && !deletedSourceFiles.isEmpty()) - for(ClassDescriptorSourceUnit sourceFile : deletedSourceFiles) - deleteClasses(sourceFile); + for (ClassDescriptorSourceUnit sourceFile : deletedSourceFiles) + deleteClasses(sourceFile); deletedSourceFiles = null; // Ya no se necesita boolean setPendingReload = true; - if (sourceFilesToCompile.size() == 1) - { + if (sourceFilesToCompile.size() == 1) { ClassDescriptorSourceUnit sourceFile = sourceFilesToCompile.get(0); SourceUnit sourceUnit = sourceFile.getSourceUnit(); - if ((sourceUnit instanceof SourceScriptRootInMemory) && ((SourceScriptRootInMemory)sourceUnit).isEmptyCode()) - { + if ((sourceUnit instanceof SourceScriptRootInMemory) && ((SourceScriptRootInMemory) sourceUnit).isEmptyCode()) { // Leer notas en SourceScriptRootInMemory.isEmptyCode() de esta manera evitamos crear un ClassLoader nuevo inútilmente por culpa de una clase // root que no sirve para nada, ello impide que el registro/desregistro en colecciones funcione bien pues la instancia // en el proxy que añade se ha recreado y es diferente por tanto a la instancia del proxy que elimina pues hace lo mismo por su parte @@ -250,63 +219,57 @@ else if (srcUnit instanceof SourceScriptRootInMemory) // Caso de shell interacti setPendingReload = false; } } - + if (setPendingReload) engine.setPendingReload(); } return scriptFileDesc; - } - - private void saveClasses(@NotNull ClassDescriptorSourceUnit sourceFile) - { + } + + private void saveClasses(@NotNull ClassDescriptorSourceUnit sourceFile) { // Salvamos la clase principal { - File classFilePath = ClassDescriptor.getAbsoluteClassFilePathFromClassNameAndClassPath(sourceFile.getClassName(),folderClasses); - JProxyUtil.saveFile(classFilePath,sourceFile.getClassBytes()); + File classFilePath = ClassDescriptor.getAbsoluteClassFilePathFromClassNameAndClassPath(sourceFile.getClassName(), folderClasses); + JProxyUtil.saveFile(classFilePath, sourceFile.getClassBytes()); } // Salvamos las innerclasses si hay, no hay problema de clases inner no detectadas pues lo están todas pues sólo se salva tras una compilación - LinkedList innerClassDescList = sourceFile.getInnerClassDescriptors(); - if (innerClassDescList != null && !innerClassDescList.isEmpty()) - { - for(ClassDescriptorInner innerClassDesc : innerClassDescList) - { - File classFilePath = ClassDescriptor.getAbsoluteClassFilePathFromClassNameAndClassPath(innerClassDesc.getClassName(),folderClasses); - JProxyUtil.saveFile(classFilePath,innerClassDesc.getClassBytes()); + LinkedList innerClassDescList = sourceFile.getInnerClassDescriptors(); + if (innerClassDescList != null && !innerClassDescList.isEmpty()) { + for (ClassDescriptorInner innerClassDesc : innerClassDescList) { + File classFilePath = ClassDescriptor.getAbsoluteClassFilePathFromClassNameAndClassPath(innerClassDesc.getClassName(), folderClasses); + JProxyUtil.saveFile(classFilePath, innerClassDesc.getClassBytes()); } - } - } - - private void deleteClasses(@NotNull ClassDescriptorSourceUnit sourceFile) - { + } + } + + private void deleteClasses(@NotNull ClassDescriptorSourceUnit sourceFile) { // Puede ocurrir que esta clase nunca se haya cargado y se ha modificado el código fuente y queramos limpiar los .class correspondientes pues se van a recrear // como no conocemos qué inner clases están asociadas para saber que .class hay que eliminar, pues lo que hacemos es directamente obtener los .class que hay // en el directorio con el fin de eliminar todos .class que tengan el patrón de ser inner classes del source file de acuerdo a su nombre // así conseguimos por ejemplo también eliminar las local classes (inner clases con nombre declaradas dentro de un método) que no hay manera de conocer // a través de la carga de la clase - + // Hay un caso en el que puede haber .class que ya no están en el código fuente y es cuando tocamos el código fuente ANTES de cargar y eliminamos algún .java, // al cargar como no existe el archivo no lo relacionamos con los .class // La solución sería en tiempo de carga forzar una carga de todas las clases y de ahí deducir todos los .class que deben existir (excepto las clases locales // que no podríamos detectarlas), pero el que haya .class sobrantes antiguos no es gran problema. - - File classFilePath = ClassDescriptor.getAbsoluteClassFilePathFromClassNameAndClassPath(sourceFile.getClassName(),folderClasses); + + File classFilePath = ClassDescriptor.getAbsoluteClassFilePathFromClassNameAndClassPath(sourceFile.getClassName(), folderClasses); File parentDir = JProxyUtil.getParentDir(classFilePath); String[] fileNameList = parentDir.list(); // Es más ligero que listFiles() que crea File por cada resultado if (fileNameList != null) // Si es null es que el directorio no está creado { - for (String fileName : fileNameList) - { + for (String fileName : fileNameList) { int pos = fileName.lastIndexOf(".class"); if (pos == -1) continue; String simpleClassName = fileName.substring(0, pos); if (sourceFile.getSimpleClassName().equals(simpleClassName) || - sourceFile.isInnerClass(sourceFile.getPackageName() + simpleClassName)) - { - new File(parentDir,fileName).delete(); + sourceFile.isInnerClass(sourceFile.getPackageName() + simpleClassName)) { + new File(parentDir, fileName).delete(); } } } - } + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java index 3633838..15bdf65 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java @@ -5,11 +5,9 @@ import java.io.File; /** - * * @author jmarranz */ -public abstract class ClassDescriptor -{ +public abstract class ClassDescriptor { @NotNull protected final String className; // El nombre basado en puntos pero usando $ en el caso de innerclasses @NotNull @@ -17,59 +15,50 @@ public abstract class ClassDescriptor @NotNull protected final String packageName; // El package pero acabado en un "." o bien "" si no hay package, el motivo de acabar en un punto es simplemente para poder concatenar ciegamente el package y el simpleClassName protected byte[] classBytes; - protected Class clasz; - - public ClassDescriptor(@NotNull String className) - { + protected Class clasz; + + public ClassDescriptor(@NotNull String className) { this.className = className; int pos = className.lastIndexOf('.'); this.simpleClassName = (pos != -1) ? className.substring(pos + 1) : className; - this.packageName = (pos != -1) ? className.substring(0,pos + 1) : ""; // SE INCLUYE EL . en el caso de existir package + this.packageName = (pos != -1) ? className.substring(0, pos + 1) : ""; // SE INCLUYE EL . en el caso de existir package } - + public abstract boolean isInnerClass(); - + @NotNull - public String getClassName() - { + public String getClassName() { return className; } - + @NotNull - public String getSimpleClassName() - { + public String getSimpleClassName() { return simpleClassName; } - + @NotNull - public String getPackageName() - { + public String getPackageName() { return packageName; - } - - public byte[] getClassBytes() - { + } + + public byte[] getClassBytes() { return classBytes; } - - public void setClassBytes(byte[] classBytes) - { + + public void setClassBytes(byte[] classBytes) { this.classBytes = classBytes; } - public Class getLastLoadedClass() - { + public Class getLastLoadedClass() { return clasz; } - public void setLastLoadedClass(Class clasz) - { + public void setLastLoadedClass(Class clasz) { this.clasz = clasz; - } + } - public void resetLastLoadedClass() - { - setLastLoadedClass(null); + public void resetLastLoadedClass() { + setLastLoadedClass(null); } /* @@ -78,46 +67,40 @@ public String getClassFileNameFromClassName() return getClassFileNameFromClassName(className); } */ - - public static String getClassFileNameFromClassName(@NotNull String className) - { + + public static String getClassFileNameFromClassName(@NotNull String className) { // Es válido también para las innerclasses (ej Nombre$Otro => Nombre$Otro.class, Nombre$1 => Nombre$1.class, Nombre$1Nombre => Nombre$1Nombre.class int pos = className.lastIndexOf("."); - if(pos != -1) className = className.substring(pos + 1); - return className + ".class"; + if (pos != -1) className = className.substring(pos + 1); + return className + ".class"; } - - public static String getRelativeClassFilePathFromClassName(@NotNull String className) - { - return className.replace('.','/') + ".class"; // alternativa: className.replaceAll("\\.", "/") + ".class" + + public static String getRelativeClassFilePathFromClassName(@NotNull String className) { + return className.replace('.', '/') + ".class"; // alternativa: className.replaceAll("\\.", "/") + ".class" } - + @NotNull - public static String getRelativePackagePathFromClassName(@NotNull String className) - { - String packageName = className.replace('.','/'); + public static String getRelativePackagePathFromClassName(@NotNull String className) { + String packageName = className.replace('.', '/'); int pos = packageName.lastIndexOf('/'); if (pos == -1) return packageName; - return packageName.substring(0,pos); - } - - public static File getAbsoluteClassFilePathFromClassNameAndClassPath(@NotNull String className, String classPath) - { + return packageName.substring(0, pos); + } + + public static File getAbsoluteClassFilePathFromClassNameAndClassPath(@NotNull String className, String classPath) { String relativePath = getRelativeClassFilePathFromClassName(className); classPath = classPath.trim(); - if (!classPath.endsWith("/") && !classPath.endsWith("\\")) classPath += File.separatorChar; - return new File(classPath + relativePath); - } - - public static String getClassNameFromRelativeClassFilePath(@NotNull String path) - { + if (!classPath.endsWith("/") && !classPath.endsWith("\\")) classPath += File.separatorChar; + return new File(classPath + relativePath); + } + + public static String getClassNameFromRelativeClassFilePath(@NotNull String path) { // Ej. org/w3c/dom/Element.class => org.w3c.dom.Element String binaryName = path.replaceAll("/", "."); return binaryName.replaceAll(".class$", ""); // El $ indica "el .class del final" } - - public static String getClassNameFromPackageAndClassFileName(String packageName,String fileName) - { + + public static String getClassNameFromPackageAndClassFileName(String packageName, String fileName) { String className = packageName + "." + fileName; return className.replaceAll(".class$", ""); // El $ indica "el .class del final" } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java index 118e81b..190c067 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java @@ -3,27 +3,22 @@ import org.jetbrains.annotations.NotNull; /** - * * @author jmarranz */ -public class ClassDescriptorInner extends ClassDescriptor -{ +public class ClassDescriptorInner extends ClassDescriptor { protected final ClassDescriptorSourceUnit parent; - - public ClassDescriptorInner(@NotNull String className, ClassDescriptorSourceUnit parent) - { + + public ClassDescriptorInner(@NotNull String className, ClassDescriptorSourceUnit parent) { super(className); this.parent = parent; - } - + } + @Override - public boolean isInnerClass() - { + public boolean isInnerClass() { return true; - } - - public ClassDescriptorSourceUnit getClassDescriptorSourceUnit() - { + } + + public ClassDescriptorSourceUnit getClassDescriptorSourceUnit() { return parent; } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java index 351d73b..4e87460 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java @@ -6,25 +6,20 @@ import org.jetbrains.annotations.NotNull; /** - * * @author jmarranz */ -public class ClassDescriptorSourceFileJava extends ClassDescriptorSourceUnit -{ - public ClassDescriptorSourceFileJava(JProxyEngine engine, @NotNull String className, SourceFileJavaNormal sourceFile, long timestamp) - { - super(engine,className, sourceFile, timestamp); +public class ClassDescriptorSourceFileJava extends ClassDescriptorSourceUnit { + public ClassDescriptorSourceFileJava(JProxyEngine engine, @NotNull String className, SourceFileJavaNormal sourceFile, long timestamp) { + super(engine, className, sourceFile, timestamp); } - + @NotNull - public SourceFileJavaNormal getSourceFileJavaNormal() - { - return (SourceFileJavaNormal)sourceUnit; + public SourceFileJavaNormal getSourceFileJavaNormal() { + return (SourceFileJavaNormal) sourceUnit; } - - public FileExt getSourceFile() - { + + public FileExt getSourceFile() { return getSourceFileJavaNormal().getFileExt(); - } - + } + } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java index a532809..53fb273 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java @@ -9,91 +9,75 @@ import java.util.Map; /** - * * @author jmarranz */ -public class ClassDescriptorSourceFileRegistry -{ +public class ClassDescriptorSourceFileRegistry { @NotNull - protected final Map sourceUnitMapByClassName; - - public ClassDescriptorSourceFileRegistry() - { - this.sourceUnitMapByClassName = new HashMap(); + protected final Map sourceUnitMapByClassName; + + public ClassDescriptorSourceFileRegistry() { + this.sourceUnitMapByClassName = new HashMap(); + } + + public ClassDescriptorSourceFileRegistry(@NotNull ClassDescriptorSourceFileRegistry origin) { + this.sourceUnitMapByClassName = new HashMap(origin.sourceUnitMapByClassName); } - public ClassDescriptorSourceFileRegistry(@NotNull ClassDescriptorSourceFileRegistry origin) - { - this.sourceUnitMapByClassName = new HashMap( origin.sourceUnitMapByClassName ); - } - - public boolean isEmpty() - { + public boolean isEmpty() { return sourceUnitMapByClassName.isEmpty(); } - + @NotNull - public Collection getClassDescriptorSourceFileColl() - { + public Collection getClassDescriptorSourceFileColl() { return sourceUnitMapByClassName.values(); } - - public ClassDescriptorSourceUnit getClassDescriptorSourceUnit(String className) - { + + public ClassDescriptorSourceUnit getClassDescriptorSourceUnit(String className) { return sourceUnitMapByClassName.get(className); - } - - public ClassDescriptorSourceUnit removeClassDescriptorSourceUnit(String className) - { + } + + public ClassDescriptorSourceUnit removeClassDescriptorSourceUnit(String className) { return sourceUnitMapByClassName.remove(className); - } - - public void addClassDescriptorSourceUnit(@NotNull ClassDescriptorSourceUnit sourceFile) - { + } + + public void addClassDescriptorSourceUnit(@NotNull ClassDescriptorSourceUnit sourceFile) { sourceUnitMapByClassName.put(sourceFile.getClassName(), sourceFile); } - - public void setAllClassDescriptorSourceFilesPendingToRemove(boolean pending) - { - for(Map.Entry entries : sourceUnitMapByClassName.entrySet()) - entries.getValue().setPendingToRemove(pending); + + public void setAllClassDescriptorSourceFilesPendingToRemove(boolean pending) { + for (Map.Entry entries : sourceUnitMapByClassName.entrySet()) + entries.getValue().setPendingToRemove(pending); } - + @NotNull - public LinkedList getAllClassDescriptorSourceFilesPendingToRemove(@NotNull LinkedList deletedSourceFiles) - { - for(Map.Entry entries : sourceUnitMapByClassName.entrySet()) - { + public LinkedList getAllClassDescriptorSourceFilesPendingToRemove(@NotNull LinkedList deletedSourceFiles) { + for (Map.Entry entries : sourceUnitMapByClassName.entrySet()) { ClassDescriptorSourceUnit classDesc = entries.getValue(); - boolean pending = classDesc.isPendingToRemove(); + boolean pending = classDesc.isPendingToRemove(); if (pending) - deletedSourceFiles.add(classDesc); + deletedSourceFiles.add(classDesc); } return deletedSourceFiles; - } - + } + @Nullable - public ClassDescriptor getClassDescriptor(@NotNull String className) - { + public ClassDescriptor getClassDescriptor(@NotNull String className) { // Puede ser el de una innerclass // Las innerclasses no están como tales en sourceFileMap pues sólo está la clase contenedora pero también la consideramos hotloadable String parentClassName; - int pos = className.lastIndexOf('$'); - boolean inner; - if (pos != -1) - { + int pos = className.lastIndexOf('$'); + boolean inner; + if (pos != -1) { parentClassName = className.substring(0, pos); inner = true; - } - else - { + } else { parentClassName = className; inner = false; } - ClassDescriptorSourceUnit sourceDesc = sourceUnitMapByClassName.get(parentClassName); + ClassDescriptorSourceUnit sourceDesc = sourceUnitMapByClassName.get(parentClassName); if (sourceDesc == null) return null; if (!inner) return sourceDesc; - return sourceDesc.getInnerClassDescriptor(className,true); - } + return sourceDesc.getInnerClassDescriptor(className, true); + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java index 8b76640..2dea6f9 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java @@ -13,81 +13,70 @@ import javax.script.ScriptEngine; /** - * * @author jmarranz */ -public class ClassDescriptorSourceScript extends ClassDescriptorSourceUnit -{ - protected String source; - - public ClassDescriptorSourceScript(JProxyEngine engine, @NotNull String className, SourceScriptRoot sourceFile, long timestamp) - { - super(engine,className, sourceFile, timestamp); +public class ClassDescriptorSourceScript extends ClassDescriptorSourceUnit { + protected String source; + + public ClassDescriptorSourceScript(JProxyEngine engine, @NotNull String className, SourceScriptRoot sourceFile, long timestamp) { + super(engine, className, sourceFile, timestamp); generateSourceCode(); } - + @NotNull - public SourceScriptRoot getSourceScript() - { - return (SourceScriptRoot)sourceUnit; + public SourceScriptRoot getSourceScript() { + return (SourceScriptRoot) sourceUnit; } - - private void generateSourceCode() - { + + private void generateSourceCode() { boolean[] hasHashBang = new boolean[1]; - - String scriptCode = getSourceScript().getScriptCode(getEncoding(),hasHashBang); - + + String scriptCode = getSourceScript().getScriptCode(getEncoding(), hasHashBang); + boolean completeClass = isCompleteClass(scriptCode); - - StringBuilder finalCode = new StringBuilder(); - if (completeClass) - { - if (hasHashBang[0]) finalCode.append("\n"); // Como hemos quitado la línea #! añadimos una nueva para que los números de línea en caso de error coincidan con el original - finalCode.append(scriptCode); - } - else - { - JProxyImpl jproxy = engine.getJProxy(); - String mainParamsDec = null; - String mainReturnType = null; - + + StringBuilder finalCode = new StringBuilder(); + if (completeClass) { + if (hasHashBang[0]) + finalCode.append("\n"); // Como hemos quitado la línea #! añadimos una nueva para que los números de línea en caso de error coincidan con el original + finalCode.append(scriptCode); + } else { + JProxyImpl jproxy = engine.getJProxy(); + String mainParamsDec = null; + String mainReturnType = null; + Class mainParamClass = jproxy.getMainParamClass(); - if (mainParamClass.equals(String[].class)) - { + if (mainParamClass.equals(String[].class)) { mainParamsDec = "String[] args"; mainReturnType = "void"; - } - else if (mainParamClass.equals(ScriptContext.class)) - { + } else if (mainParamClass.equals(ScriptContext.class)) { mainParamsDec = ScriptEngine.class.getName() + " engine," + ScriptContext.class.getName() + " context"; mainReturnType = "Object"; - + if (scriptCode.equals("")) scriptCode = "return null;"; } - + finalCode.append("public class " + className + " { public static " + mainReturnType + " main(" + mainParamsDec + ") {\n"); // Lo ponemos todo en una línea para que en caso de error la línea de error coincida con el script original pues hemos quitado la primera línea #! - finalCode.append(scriptCode); - finalCode.append(" }\n"); - finalCode.append("}\n"); + finalCode.append(scriptCode); + finalCode.append(" }\n"); + finalCode.append("}\n"); } - this.source = finalCode.toString(); + this.source = finalCode.toString(); } - - private boolean isCompleteClass(@NotNull String code) - { + + private boolean isCompleteClass(@NotNull String code) { // Buscamos si hay un " class ..." o un "import..." al comienzo para soportar la definición de una clase completa como script - int pos = code.indexOf("class"); - if (pos == -1) return false; + int pos = code.indexOf("class"); + if (pos == -1) return false; // Hay al menos un "class", ojo que puede ser parte de una variable o dentro de un comentario, pero si no existiera desde luego que no es clase completa - + pos = getFirstPosIgnoringCommentsAndSeparators(code); if (pos == -1) return false; - + // Lo primero que nos tenemos encontrar es un import o una declaración de class - int pos2 = code.indexOf("import",pos); + int pos2 = code.indexOf("import", pos); if (pos2 == pos) return true; // Si hay un import hay declaración de clase @@ -96,92 +85,86 @@ private boolean isCompleteClass(@NotNull String code) String visibility = code.substring(pos, posClass); visibility = visibility.trim(); // No consideramos \n hay que ser retorcido poner un \n entre el public y el class por ejemplo if (visibility.isEmpty()) return true; // No hay visibilidad, que no compile no es cosa nuestra - return ("private".equals(visibility) || "public".equals(visibility) || "protected".equals(visibility)); + return ("private".equals(visibility) || "public".equals(visibility) || "protected".equals(visibility)); } - - private int getFirstPosIgnoringCommentsAndSeparators(@NotNull String code) - { + + private int getFirstPosIgnoringCommentsAndSeparators(@NotNull String code) { int i = -1; - for(i = 0; i < code.length(); i++) - { + for (i = 0; i < code.length(); i++) { char c = code.charAt(i); if (c == ' ' || c == '\n' || c == '\t') continue; - else if (c == '/' && i + 1 < code.length()) - { + else if (c == '/' && i + 1 < code.length()) { char c2 = code.charAt(i + 1); - if (c2 == '/') - { - i = getFirstPosIgnoringOneLineComment(code,i); + if (c2 == '/') { + i = getFirstPosIgnoringOneLineComment(code, i); if (i == -1) return -1; // Comentario mal formado - } - else if (c2 == '*') - { - i = getFirstPosIgnoringMultiLineComment(code,i); + } else if (c2 == '*') { + i = getFirstPosIgnoringMultiLineComment(code, i); if (i == -1) return -1; // Comentario mal formado } - } - else break; + } else break; } return i; } - - private int getFirstPosIgnoringOneLineComment(@NotNull String code, int start) - { - return code.indexOf('\n',start); - } - - private int getFirstPosIgnoringMultiLineComment(@NotNull String code, int start) - { + + private int getFirstPosIgnoringOneLineComment(@NotNull String code, int start) { + return code.indexOf('\n', start); + } + + private int getFirstPosIgnoringMultiLineComment(@NotNull String code, int start) { return code.indexOf("*/", start); - } - + } + @Override - public void updateTimestamp(long timestamp) - { + public void updateTimestamp(long timestamp) { long oldTimestamp = this.timestamp; if (oldTimestamp != timestamp) - generateSourceCode(); + generateSourceCode(); super.updateTimestamp(timestamp); } - - public String getSourceCode() - { + + public String getSourceCode() { return source; } - - public void callMainMethod(@NotNull LinkedList argsToScript) throws Throwable - { - try - { - Class scriptClass = getLastLoadedClass(); - Method method = scriptClass.getDeclaredMethod("main",new Class[]{ String[].class }); + + public void callMainMethod(@NotNull LinkedList argsToScript) throws Throwable { + try { + Class scriptClass = getLastLoadedClass(); + Method method = scriptClass.getDeclaredMethod("main", new Class[]{String[].class}); String[] argsToScriptArr = argsToScript.size() > 0 ? argsToScript.toArray(new String[argsToScript.size()]) : new String[0]; - method.invoke(null, new Object[]{ argsToScriptArr }); - } - catch (IllegalAccessException ex) { throw new RelProxyException(ex); } - catch (NoSuchMethodException ex) { throw new RelProxyException(ex); } - catch (SecurityException ex) { throw new RelProxyException(ex); } - catch (IllegalArgumentException ex) { throw new RelProxyException(ex); } - catch (InvocationTargetException ex) { throw ex.getCause(); } // Los errores de ejecución se envuelven en un InvocationTargetException - } - - public Object callMainMethod(ScriptEngine engine,ScriptContext context) throws Throwable - { - Class scriptClass = getLastLoadedClass(); - return callMainMethod(scriptClass,engine,context); + method.invoke(null, new Object[]{argsToScriptArr}); + } catch (IllegalAccessException ex) { + throw new RelProxyException(ex); + } catch (NoSuchMethodException ex) { + throw new RelProxyException(ex); + } catch (SecurityException ex) { + throw new RelProxyException(ex); + } catch (IllegalArgumentException ex) { + throw new RelProxyException(ex); + } catch (InvocationTargetException ex) { + throw ex.getCause(); + } // Los errores de ejecución se envuelven en un InvocationTargetException + } + + public Object callMainMethod(ScriptEngine engine, ScriptContext context) throws Throwable { + Class scriptClass = getLastLoadedClass(); + return callMainMethod(scriptClass, engine, context); + } + + public static Object callMainMethod(@NotNull Class scriptClass, ScriptEngine engine, ScriptContext context) throws Throwable { + try { + Method method = scriptClass.getDeclaredMethod("main", new Class[]{ScriptEngine.class, ScriptContext.class}); + return method.invoke(null, new Object[]{engine, context}); + } catch (IllegalAccessException ex) { + throw new RelProxyException(ex); + } catch (NoSuchMethodException ex) { + throw new RelProxyException(ex); + } catch (SecurityException ex) { + throw new RelProxyException(ex); + } catch (IllegalArgumentException ex) { + throw new RelProxyException(ex); + } catch (InvocationTargetException ex) { + throw ex.getCause(); + } // Los errores de ejecución se envuelven en un InvocationTargetException } - - public static Object callMainMethod(@NotNull Class scriptClass, ScriptEngine engine, ScriptContext context) throws Throwable - { - try - { - Method method = scriptClass.getDeclaredMethod("main",new Class[]{ ScriptEngine.class,ScriptContext.class }); - return method.invoke(null, new Object[]{ engine, context }); - } - catch (IllegalAccessException ex) { throw new RelProxyException(ex); } - catch (NoSuchMethodException ex) { throw new RelProxyException(ex); } - catch (SecurityException ex) { throw new RelProxyException(ex); } - catch (IllegalArgumentException ex) { throw new RelProxyException(ex); } - catch (InvocationTargetException ex) { throw ex.getCause(); } // Los errores de ejecución se envuelven en un InvocationTargetException - } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java index fa8287e..3e112d9 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java @@ -10,19 +10,16 @@ import java.util.LinkedList; /** - * * @author jmarranz */ -public abstract class ClassDescriptorSourceUnit extends ClassDescriptor -{ +public abstract class ClassDescriptorSourceUnit extends ClassDescriptor { protected final JProxyEngine engine; protected volatile long timestamp; - protected final SourceUnit sourceUnit; + protected final SourceUnit sourceUnit; protected LinkedList innerClasses; protected boolean pendingToRemove = false; // Se usa como monohilo, no hay problemas de sincronización - - public ClassDescriptorSourceUnit(JProxyEngine engine, @NotNull String className, SourceUnit sourceFile, long timestamp) - { + + public ClassDescriptorSourceUnit(JProxyEngine engine, @NotNull String className, SourceUnit sourceFile, long timestamp) { super(className); this.engine = engine; this.sourceUnit = sourceFile; @@ -30,124 +27,106 @@ public ClassDescriptorSourceUnit(JProxyEngine engine, @NotNull String className, } @Nullable - public static ClassDescriptorSourceUnit create(boolean script, JProxyEngine engine, @NotNull String className, SourceUnit sourceFile, long timestamp) - { + public static ClassDescriptorSourceUnit create(boolean script, JProxyEngine engine, @NotNull String className, SourceUnit sourceFile, long timestamp) { if (sourceFile instanceof SourceScriptRoot) - return new ClassDescriptorSourceScript(engine,className,(SourceScriptRoot)sourceFile,timestamp); + return new ClassDescriptorSourceScript(engine, className, (SourceScriptRoot) sourceFile, timestamp); else if (sourceFile instanceof SourceFileJavaNormal) - return new ClassDescriptorSourceFileJava(engine,className,(SourceFileJavaNormal)sourceFile,timestamp); + return new ClassDescriptorSourceFileJava(engine, className, (SourceFileJavaNormal) sourceFile, timestamp); else return null; // WTF!! } - - public SourceUnit getSourceUnit() - { + + public SourceUnit getSourceUnit() { return sourceUnit; } - + @NotNull - public String getEncoding() - { + public String getEncoding() { return engine.getSourceEncoding(); } - + @Override - public boolean isInnerClass() - { + public boolean isInnerClass() { return false; - } - - public long getTimestamp() - { + } + + public long getTimestamp() { return timestamp; } - public void updateTimestamp(long timestamp) - { + public void updateTimestamp(long timestamp) { this.timestamp = timestamp; } - public boolean isPendingToRemove() - { + public boolean isPendingToRemove() { return pendingToRemove; } - public void setPendingToRemove(boolean pendingToRemove) - { + public void setPendingToRemove(boolean pendingToRemove) { this.pendingToRemove = pendingToRemove; } - - - public void cleanOnSourceCodeChanged() - { + + + public void cleanOnSourceCodeChanged() { // Como ha cambiado la clase, reseteamos las dependencias setClassBytes(null); setLastLoadedClass(null); clearInnerClassDescriptors(); // El código fuente nuevo puede haber cambiado totalmente las innerclasses antiguas (añadido, eliminado) } - - public boolean isInnerClass(@NotNull String className) - { + + public boolean isInnerClass(@NotNull String className) { int pos = className.lastIndexOf('$'); if (pos == -1) return false; // No es innerclass String baseClassName = className.substring(0, pos); return this.className.equals(baseClassName); // Si es false es que es una innerclass pero de otra clase } - - public LinkedList getInnerClassDescriptors() - { + + public LinkedList getInnerClassDescriptors() { return innerClasses; } - - public void clearInnerClassDescriptors() - { + + public void clearInnerClassDescriptors() { if (innerClasses != null) - innerClasses.clear(); + innerClasses.clear(); } - + @Nullable - public ClassDescriptorInner getInnerClassDescriptor(@NotNull String className, boolean addWhenMissing) - { - if (innerClasses != null) - { - for(ClassDescriptorInner classDesc : innerClasses) - { + public ClassDescriptorInner getInnerClassDescriptor(@NotNull String className, boolean addWhenMissing) { + if (innerClasses != null) { + for (ClassDescriptorInner classDesc : innerClasses) { if (classDesc.getClassName().equals(className)) return classDesc; } } - + if (!addWhenMissing) return null; - + return addInnerClassDescriptor(className); } - + @Nullable - public ClassDescriptorInner addInnerClassDescriptor(@NotNull String className) - { + public ClassDescriptorInner addInnerClassDescriptor(@NotNull String className) { if (!isInnerClass(className)) return null; - + if (innerClasses == null) innerClasses = new LinkedList(); - - ClassDescriptorInner classDesc = new ClassDescriptorInner(className,this); + + ClassDescriptorInner classDesc = new ClassDescriptorInner(className, this); innerClasses.add(classDesc); return classDesc; - } - + } + @Override - public void resetLastLoadedClass() - { + public void resetLastLoadedClass() { super.resetLastLoadedClass(); LinkedList innerClassDescList = getInnerClassDescriptors(); - if (innerClassDescList != null) - { - for(ClassDescriptorInner innerClassDesc : innerClassDescList) - innerClassDesc.resetLastLoadedClass(); - } + if (innerClassDescList != null) { + for (ClassDescriptorInner innerClassDesc : innerClassDescList) + innerClassDesc.resetLastLoadedClass(); + } } - + } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java index dd43381..cf0c86e 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java @@ -5,21 +5,17 @@ import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; /** - * * @author jmarranz */ -public class JProxyCompilationException extends RelProxyException -{ +public class JProxyCompilationException extends RelProxyException { protected ClassDescriptorSourceUnit sourceUnit; - - public JProxyCompilationException(ClassDescriptorSourceUnit sourceUnit) - { + + public JProxyCompilationException(ClassDescriptorSourceUnit sourceUnit) { super("Compilation error"); this.sourceUnit = sourceUnit; - } - - public ClassDescriptorSourceUnit getClassDescriptorSourceUnit() - { + } + + public ClassDescriptorSourceUnit getClassDescriptorSourceUnit() { return sourceUnit; } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java index 2ad1bd7..c5d4f0e 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java @@ -2,6 +2,7 @@ import com.sillelien.dollar.relproxy.RelProxyException; import com.sillelien.dollar.relproxy.jproxy.JProxyDiagnosticsListener; + import java.io.IOException; import java.util.List; import javax.tools.Diagnostic; @@ -10,62 +11,54 @@ import javax.tools.StandardJavaFileManager; /** - * * @author jmarranz */ -public class JProxyCompilerContext -{ - protected StandardJavaFileManager standardFileManager; +public class JProxyCompilerContext { + protected StandardJavaFileManager standardFileManager; protected DiagnosticCollector diagnostics; protected JProxyDiagnosticsListener diagnosticsListener; - - public JProxyCompilerContext(StandardJavaFileManager standardFileManager,DiagnosticCollector diagnostics,JProxyDiagnosticsListener diagnosticsListener) - { + + public JProxyCompilerContext(StandardJavaFileManager standardFileManager, DiagnosticCollector diagnostics, JProxyDiagnosticsListener diagnosticsListener) { this.standardFileManager = standardFileManager; this.diagnostics = diagnostics; this.diagnosticsListener = diagnosticsListener; } - public StandardJavaFileManager getStandardFileManager() - { + public StandardJavaFileManager getStandardFileManager() { return standardFileManager; - } + } - public DiagnosticCollector getDiagnosticCollector() - { + public DiagnosticCollector getDiagnosticCollector() { return diagnostics; } - - public void close() - { - try { this.standardFileManager.close(); } - catch (IOException ex) { throw new RelProxyException(ex); } - + + public void close() { + try { + this.standardFileManager.close(); + } catch (IOException ex) { + throw new RelProxyException(ex); + } + List> diagList = diagnostics.getDiagnostics(); - if (!diagList.isEmpty()) - { - if (diagnosticsListener != null) - { + if (!diagList.isEmpty()) { + if (diagnosticsListener != null) { diagnosticsListener.onDiagnostics(diagnostics); - } - else - { + } else { int i = 1; - for (Diagnostic diagnostic : diagList) - { - System.err.println("Diagnostic " + i); - System.err.println(" code: " + diagnostic.getCode()); - System.err.println(" kind: " + diagnostic.getKind()); - System.err.println(" line number: " + diagnostic.getLineNumber()); - System.err.println(" column number: " + diagnostic.getColumnNumber()); - System.err.println(" start position: " + diagnostic.getStartPosition()); - System.err.println(" position: " + diagnostic.getPosition()); - System.err.println(" end position: " + diagnostic.getEndPosition()); - System.err.println(" source: " + diagnostic.getSource()); - System.err.println(" message: " + diagnostic.getMessage(null)); - i++; + for (Diagnostic diagnostic : diagList) { + System.err.println("Diagnostic " + i); + System.err.println(" code: " + diagnostic.getCode()); + System.err.println(" kind: " + diagnostic.getKind()); + System.err.println(" line number: " + diagnostic.getLineNumber()); + System.err.println(" column number: " + diagnostic.getColumnNumber()); + System.err.println(" start position: " + diagnostic.getStartPosition()); + System.err.println(" position: " + diagnostic.getPosition()); + System.err.println(" end position: " + diagnostic.getEndPosition()); + System.err.println(" source: " + diagnostic.getSource()); + System.err.println(" message: " + diagnostic.getMessage(null)); + i++; } } - } + } } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java index 8900a12..f1757bc 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java @@ -26,74 +26,59 @@ import javax.tools.ToolProvider; /** - * * @author jmarranz */ -public class JProxyCompilerInMemory -{ +public class JProxyCompilerInMemory { protected JProxyEngineChangeDetectorAndCompiler parent; protected JavaCompiler compiler; protected Iterable compilationOptions; // puede ser null protected JProxyDiagnosticsListener diagnosticsListener; // puede ser null - public JProxyCompilerInMemory(JProxyEngineChangeDetectorAndCompiler engine,Iterable compilationOptions,JProxyDiagnosticsListener diagnosticsListener) - { + public JProxyCompilerInMemory(JProxyEngineChangeDetectorAndCompiler engine, Iterable compilationOptions, JProxyDiagnosticsListener diagnosticsListener) { this.parent = engine; this.compilationOptions = compilationOptions; this.diagnosticsListener = diagnosticsListener; - this.compiler = ToolProvider.getSystemJavaCompiler(); + this.compiler = ToolProvider.getSystemJavaCompiler(); } - + @NotNull - public JProxyCompilerContext createJProxyCompilerContext() - { + public JProxyCompilerContext createJProxyCompilerContext() { DiagnosticCollector diagnostics = new DiagnosticCollector(); - StandardJavaFileManager standardFileManager = compiler.getStandardFileManager(diagnostics, null, null); - return new JProxyCompilerContext(standardFileManager,diagnostics,diagnosticsListener); + StandardJavaFileManager standardFileManager = compiler.getStandardFileManager(diagnostics, null, null); + return new JProxyCompilerContext(standardFileManager, diagnostics, diagnosticsListener); } - - public void compileSourceFile(@NotNull ClassDescriptorSourceUnit sourceFileDesc, @NotNull JProxyCompilerContext context, ClassLoader currentClassLoader, @NotNull ClassDescriptorSourceFileRegistry sourceRegistry) - { + + public void compileSourceFile(@NotNull ClassDescriptorSourceUnit sourceFileDesc, @NotNull JProxyCompilerContext context, ClassLoader currentClassLoader, @NotNull ClassDescriptorSourceFileRegistry sourceRegistry) { //File sourceFile = sourceFileDesc.getSourceFile(); - LinkedList outClassList = compile(sourceFileDesc,context,currentClassLoader,sourceRegistry); - - if (outClassList == null) + LinkedList outClassList = compile(sourceFileDesc, context, currentClassLoader, sourceRegistry); + + if (outClassList == null) throw new JProxyCompilationException(sourceFileDesc); - - String className = sourceFileDesc.getClassName(); - + + String className = sourceFileDesc.getClassName(); + // Puede haber más de un resultado cuando hay inner classes y/o clase privada en el mismo archivo o bien simplemente clases dependientes - for(JavaFileObjectOutputClass outClass : outClassList) - { + for (JavaFileObjectOutputClass outClass : outClassList) { String currClassName = outClass.binaryName(); - byte[] classBytes = outClass.getBytes(); - if (className.equals(currClassName)) - { - sourceFileDesc.setClassBytes(classBytes); - } - else - { - ClassDescriptorInner innerClass = sourceFileDesc.getInnerClassDescriptor(currClassName,true); - if (innerClass != null) - { - innerClass.setClassBytes(classBytes); - } - else - { + byte[] classBytes = outClass.getBytes(); + if (className.equals(currClassName)) { + sourceFileDesc.setClassBytes(classBytes); + } else { + ClassDescriptorInner innerClass = sourceFileDesc.getInnerClassDescriptor(currClassName, true); + if (innerClass != null) { + innerClass.setClassBytes(classBytes); + } else { // Lo mismo es un archivo dependiente e incluso una inner class pero de otra clase que está siendo usada en el archivo compilado ClassDescriptor dependentClass = sourceRegistry.getClassDescriptor(currClassName); - if (dependentClass != null) - { - dependentClass.setClassBytes(classBytes); - } - else - { + if (dependentClass != null) { + dependentClass.setClassBytes(classBytes); + } else { // Seguramente es debido a que el archivo java tiene una clase privada autónoma declarada en el mismo archivo .java (las que se ponen después de la clase principal pública normal), no permitimos estas clases porque sólo podemos // detectarlas cuando cambiamos el código fuente, pero no si el código fuente no se ha tocado, por ejemplo no tenemos // forma de conseguir que se recarguen de forma determinista y si posteriormente se cargara via ClassLoader al usarse no podemos reconocer que es una clase // "hot reloadable" (quizás a través del package respecto a las demás clases hot pero no es muy determinista pues nada impide la mezcla de hot y no hot en el mismo package) // Es una limitación mínima. - + // También puede ser un caso de clase excluida por el listener de exclusión, no debería ocurrir, tengo un caso de test en donde ocurre a posta // (caso de JProxyExampleAuxIgnored cuando se cambia la JProxyExampleDocument que la usa) pero en programación normal no. @@ -105,10 +90,9 @@ public void compileSourceFile(@NotNull ClassDescriptorSourceUnit sourceFileDesc, } } } - } - - private LinkedList compile(ClassDescriptorSourceUnit sourceFileDesc, @NotNull JProxyCompilerContext context, ClassLoader currentClassLoader, ClassDescriptorSourceFileRegistry sourceRegistry) - { + } + + private LinkedList compile(ClassDescriptorSourceUnit sourceFileDesc, @NotNull JProxyCompilerContext context, ClassLoader currentClassLoader, ClassDescriptorSourceFileRegistry sourceRegistry) { // http://stackoverflow.com/questions/12173294/compiling-fully-in-memory-with-javax-tools-javacompiler // http://www.accordess.com/wpblog/an-overview-of-java-compilation-api-jsr-199/ // http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/com/sun/tools/javac/util/JavacFileManager.java?av=h#JavacFileManager @@ -123,66 +107,58 @@ private LinkedList compile(ClassDescriptorSourceUnit StandardJavaFileManager standardFileManager = context.getStandardFileManager(); // recuerda que el StandardJavaFileManager puede reutilizarse entre varias compilaciones consecutivas mientras se cierre al final - + Iterable compilationUnits; - if (sourceFileDesc instanceof ClassDescriptorSourceFileJava) - { + if (sourceFileDesc instanceof ClassDescriptorSourceFileJava) { List sourceFileList = new ArrayList(); - sourceFileList.add(((ClassDescriptorSourceFileJava)sourceFileDesc).getSourceFile().getFile()); + sourceFileList.add(((ClassDescriptorSourceFileJava) sourceFileDesc).getSourceFile().getFile()); compilationUnits = standardFileManager.getJavaFileObjectsFromFiles(sourceFileList); - } - else if (sourceFileDesc instanceof ClassDescriptorSourceScript) - { - ClassDescriptorSourceScript sourceFileDescScript = (ClassDescriptorSourceScript)sourceFileDesc; - LinkedList compilationUnitsList = new LinkedList(); + } else if (sourceFileDesc instanceof ClassDescriptorSourceScript) { + ClassDescriptorSourceScript sourceFileDescScript = (ClassDescriptorSourceScript) sourceFileDesc; + LinkedList compilationUnitsList = new LinkedList(); String code = sourceFileDescScript.getSourceCode(); - compilationUnitsList.add(new JavaFileObjectInputSourceInMemory(sourceFileDescScript.getClassName(),code,sourceFileDescScript.getEncoding(),sourceFileDescScript.getTimestamp())); - compilationUnits = compilationUnitsList; - } - else - { + compilationUnitsList.add(new JavaFileObjectInputSourceInMemory(sourceFileDescScript.getClassName(), code, sourceFileDescScript.getEncoding(), sourceFileDescScript.getTimestamp())); + compilationUnits = compilationUnitsList; + } else { throw new RelProxyException("Internal error"); } - JavaFileManagerInMemory fileManagerInMemory = new JavaFileManagerInMemory(standardFileManager,currentClassLoader,sourceRegistry,parent.getRequiredExtraJarPaths()); + JavaFileManagerInMemory fileManagerInMemory = new JavaFileManagerInMemory(standardFileManager, currentClassLoader, sourceRegistry, parent.getRequiredExtraJarPaths()); - boolean success = compile(compilationUnits,fileManagerInMemory,context); + boolean success = compile(compilationUnits, fileManagerInMemory, context); if (!success) return null; LinkedList classObj = fileManagerInMemory.getJavaFileObjectOutputClassList(); return classObj; } - private boolean compile(Iterable compilationUnits, JavaFileManager fileManager, @NotNull JProxyCompilerContext context) - { + private boolean compile(Iterable compilationUnits, JavaFileManager fileManager, @NotNull JProxyCompilerContext context) { /* String systemClassPath = System.getProperty("java.class.path"); */ LinkedList finalCompilationOptions = new LinkedList(); - if (compilationOptions != null) - for(String option : compilationOptions) finalCompilationOptions.add(option); - + if (compilationOptions != null) + for (String option : compilationOptions) finalCompilationOptions.add(option); + FileExt[] folderSourceList = parent.getFolderSourceList().getArray(); - if (folderSourceList != null) - { + if (folderSourceList != null) { finalCompilationOptions.add("-classpath"); StringBuilder classPath = new StringBuilder(); - for(int i = 0; i < folderSourceList.length; i++) - { + for (int i = 0; i < folderSourceList.length; i++) { FileExt folderSources = folderSourceList[i]; classPath.append(folderSources.getCanonicalPath()); if (i < folderSourceList.length - 1) - classPath.append(File.pathSeparatorChar); + classPath.append(File.pathSeparatorChar); } - finalCompilationOptions.add(classPath.toString()); + finalCompilationOptions.add(classPath.toString()); } - + DiagnosticCollector diagnostics = context.getDiagnosticCollector(); - JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnostics, finalCompilationOptions,null, compilationUnits); + JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnostics, finalCompilationOptions, null, compilationUnits); boolean success = task.call(); - + return success; } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java index 0385854..d9d68f9 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java @@ -25,37 +25,32 @@ /** - * * http://www.javablogging.com/dynamic-in-memory-compilation/ * http://atamur.blogspot.com.es/2009/10/using-built-in-javacompiler-with-custom.html * http://grepcode.com/file/repo1.maven.org/maven2/org.st-js/generator/3.0.3/org/stjs/generator/javac/CustomClassloaderJavaFileManager.java - * + * * @author jmarranz */ -public class JavaFileManagerInMemory extends ForwardingJavaFileManager -{ +public class JavaFileManagerInMemory extends ForwardingJavaFileManager { private final LinkedList outputClassList = new LinkedList(); @NotNull private final JavaFileObjectInputClassFinderByClassLoader classFinder; private final ClassDescriptorSourceFileRegistry sourceRegistry; - - public JavaFileManagerInMemory(@NotNull StandardJavaFileManager standardFileManager, ClassLoader classLoader, ClassDescriptorSourceFileRegistry sourceRegistry, FolderSourceList requiredExtraJarPaths) - { + + public JavaFileManagerInMemory(@NotNull StandardJavaFileManager standardFileManager, ClassLoader classLoader, ClassDescriptorSourceFileRegistry sourceRegistry, FolderSourceList requiredExtraJarPaths) { super(standardFileManager); this.sourceRegistry = sourceRegistry; - this.classFinder = new JavaFileObjectInputClassFinderByClassLoader(classLoader,requiredExtraJarPaths); + this.classFinder = new JavaFileObjectInputClassFinderByClassLoader(classLoader, requiredExtraJarPaths); } @NotNull - public LinkedList getJavaFileObjectOutputClassList() - { + public LinkedList getJavaFileObjectOutputClassList() { return outputClassList; } - + @NotNull @Override - public JavaFileObject getJavaFileForOutput(Location location, @NotNull String className, @NotNull Kind kind, FileObject sibling) throws IOException - { + public JavaFileObject getJavaFileForOutput(Location location, @NotNull String className, @NotNull Kind kind, FileObject sibling) throws IOException { // Normalmente sólo habrá un resultado pero se da el caso de compilar una clase con una o varias inner classes, el compilador las compila de una vez JavaFileObjectOutputClass outClass = new JavaFileObjectOutputClass(className, kind); outputClassList.add(outClass); @@ -63,57 +58,46 @@ public JavaFileObject getJavaFileForOutput(Location location, @NotNull String cl } @Override - public Iterable list(Location location, @NotNull String packageName, @NotNull Set kinds, boolean recurse) throws IOException - { + public Iterable list(Location location, @NotNull String packageName, @NotNull Set kinds, boolean recurse) throws IOException { if (location == StandardLocation.PLATFORM_CLASS_PATH) // let standard manager hanfle return super.list(location, packageName, kinds, recurse); // En este caso nunca (con PLATFORM_CLASS_PATH) va a encontrar nuestros sources ni .class - else if (location == StandardLocation.CLASS_PATH && kinds.contains(JavaFileObject.Kind.CLASS)) - { + else if (location == StandardLocation.CLASS_PATH && kinds.contains(JavaFileObject.Kind.CLASS)) { if (packageName.equals("java") || packageName.startsWith("java.")) // a hack to let standard manager handle locations like "java.lang" or "java.util", clases sólo cargables por el system class loader. Estrictamente no es necesario pero derivamos la inmensa mayoría de las clases estándar al método por defecto, NO añadimos "javax." pues hay extensiones tal y como el estándar servlet que no forma parte del Java core return super.list(location, packageName, kinds, recurse); - else - { + else { // El StandardJavaFileManager al que hacemos forward es "configurado" por el compilador al que está asociado cuando hay una tarea de compilación // dicha configuración es por ejemplo el classpath tanto para encontrar .class como .java // En nuestro caso no disponemos del classpath de los .class, disponemos del ClassLoader a través del cual podemos obtener "a mano" via resources los // JavaFileObject de los .class que necesitamos. // Ahora bien, no es el caso de los archivos fuente en donde sí tenemos un path claro el cual pasamos como classpath al compilador y por tanto un super.list(location, packageName, kinds, recurse) // nos devolverá los .java (como JavaFileObject claro) si encuentra archivos correspondientes al package buscado. - - LinkedList result = new LinkedList(); - + + LinkedList result = new LinkedList(); + Iterable inFileMgr = super.list(location, packageName, kinds, recurse); // Esperamos o archivos fuente o .class de clases no recargables - if (inFileMgr instanceof Collection) - { - result.addAll((Collection)inFileMgr); - } - else - { - for(Iterator it = inFileMgr.iterator(); it.hasNext(); ) - { - JavaFileObject file = (JavaFileObject)it.next(); + if (inFileMgr instanceof Collection) { + result.addAll((Collection) inFileMgr); + } else { + for (Iterator it = inFileMgr.iterator(); it.hasNext(); ) { + JavaFileObject file = (JavaFileObject) it.next(); result.add(file); } } - + List classList = classFinder.find(packageName); - + // Reemplazamos los .class de classList que son los que están en archivo "deployados" que pueden ser más antiguos que los que están en memoria - for(JavaFileObjectInputClassInFileSystem fileObj : classList) - { + for (JavaFileObjectInputClassInFileSystem fileObj : classList) { String className = fileObj.getBinaryName(); ClassDescriptorSourceUnit sourceFileDesc = sourceRegistry.getClassDescriptorSourceUnit(className); - if (sourceFileDesc != null && sourceFileDesc.getClassBytes() != null) - { - JavaFileObjectInputClassInMemory fileInput = new JavaFileObjectInputClassInMemory(className,sourceFileDesc.getClassBytes(),sourceFileDesc.getTimestamp()); + if (sourceFileDesc != null && sourceFileDesc.getClassBytes() != null) { + JavaFileObjectInputClassInMemory fileInput = new JavaFileObjectInputClassInMemory(className, sourceFileDesc.getClassBytes(), sourceFileDesc.getTimestamp()); result.add(fileInput); - } - else - { + } else { result.add(fileObj); } } - + // Los JavaFileObject de archivos fuente pueden ser los mimas clases que los de .class, el compilador se encargará de comparar los timestamp y elegir el .class o el source return result; @@ -123,10 +107,9 @@ else if (location == StandardLocation.CLASS_PATH && kinds.contains(JavaFileObjec } @Override - public String inferBinaryName(Location location, JavaFileObject file) - { + public String inferBinaryName(Location location, JavaFileObject file) { if (file instanceof JProxyJavaFileObjectInput) - return ((JProxyJavaFileObjectInput)file).getBinaryName(); + return ((JProxyJavaFileObjectInput) file).getBinaryName(); return super.inferBinaryName(location, file); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java index da16537..cadabc2 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java @@ -30,40 +30,33 @@ * * @author jmarranz */ -public class JavaFileObjectInputClassFinderByClassLoader -{ +public class JavaFileObjectInputClassFinderByClassLoader { private static final String CLASS_FILE_EXTENSION = ".class"; - private final ClassLoader classLoader; + private final ClassLoader classLoader; private final FolderSourceList requiredExtraJarPaths; - - public JavaFileObjectInputClassFinderByClassLoader(ClassLoader classLoader,FolderSourceList requiredExtraJarPaths) - { + + public JavaFileObjectInputClassFinderByClassLoader(ClassLoader classLoader, FolderSourceList requiredExtraJarPaths) { this.classLoader = classLoader; this.requiredExtraJarPaths = requiredExtraJarPaths; } @NotNull - public List find(@NotNull String packageName) throws IOException - { - // http://www.dzone.com/snippets/get-all-classes-within-package - // http://sourceforge.net/p/scannotation/code/HEAD/tree/scannotation/src/main/java/org/scannotation/ClasspathUrlFinder.java#l124 + public List find(@NotNull String packageName) throws IOException { + // http://www.dzone.com/snippets/get-all-classes-within-package + // http://sourceforge.net/p/scannotation/code/HEAD/tree/scannotation/src/main/java/org/scannotation/ClasspathUrlFinder.java#l124 String packagePath = packageName.replaceAll("\\.", "/"); List result = new ArrayList(); Enumeration urlEnumeration = classLoader.getResources(packagePath); - if (urlEnumeration.hasMoreElements()) - { - while (urlEnumeration.hasMoreElements()) - { // one URL for each jar on the classpath that has the given package + if (urlEnumeration.hasMoreElements()) { + while (urlEnumeration.hasMoreElements()) { // one URL for each jar on the classpath that has the given package URL packageFolderURL = urlEnumeration.nextElement(); - listUnder(packageName,packageFolderURL,result); + listUnder(packageName, packageFolderURL, result); } - } - else - { + } else { // Enumeration vacía, chungo, esto nos ha ocurrido con el jar lib/ext/portlet.jar del Tomcat 6.2 del bundle liferay-portal-6.2-ce-ga3 // daba un error de de javax.portlet.PortletRquest not found. // En teoría debería responder a la búsqueda classLoader.getResources("javax/portlet") devolviendo el jar, pero devuelve un Enumeration vacío @@ -73,145 +66,132 @@ public List find(@NotNull String packageNa // requerido en el parámetro de este método find() y le evitamos modificar un jar de infraestructura que queda muy feo e inmantenible respecto a una solución // basada en configuración del usuario. - if (requiredExtraJarPaths != null) - { + if (requiredExtraJarPaths != null) { FileExt[] jarFileList = requiredExtraJarPaths.getArray(); - if (jarFileList != null) - { - for (FileExt jarFile : jarFileList) - { - listUnderJarCustom(packagePath,jarFile,result); + if (jarFileList != null) { + for (FileExt jarFile : jarFileList) { + listUnderJarCustom(packagePath, jarFile, result); } } } } - + return result; } - - private void listUnder(String packageName, @NotNull URL packageFolderURL, @NotNull Collection result) - { - String pkgPath = packageFolderURL.toExternalForm(); //packageFolderURL.getFile(); El problema de getFile es que también está URL-encoded (un espacio es %20) lo cual no es compatible con File - if (pkgPath.startsWith("file:")) - { - listUnderDir(packageName,pkgPath,result); - } - else - { // browse a jar file - listUnderJar(packageFolderURL,result); + private void listUnder(String packageName, @NotNull URL packageFolderURL, @NotNull Collection result) { + String pkgPath = packageFolderURL.toExternalForm(); //packageFolderURL.getFile(); El problema de getFile es que también está URL-encoded (un espacio es %20) lo cual no es compatible con File + + if (pkgPath.startsWith("file:")) { + listUnderDir(packageName, pkgPath, result); + } else { // browse a jar file + listUnderJar(packageFolderURL, result); } // maybe there can be something else for more involved class loaders } - private void listUnderDir(String packageName, String pkgPath, @NotNull Collection result) - { + private void listUnderDir(String packageName, String pkgPath, @NotNull Collection result) { pkgPath = pkgPath.substring("file:".length()); - try { pkgPath = URLDecoder.decode(pkgPath, "UTF-8"); } // Detecté el problema con Vaadin en un path con "Documents%20and%20Settings" con %20 obviamente no es un path correcto, deben ser espacios - catch (UnsupportedEncodingException ex) { throw new RelProxyException(ex); } + try { + pkgPath = URLDecoder.decode(pkgPath, "UTF-8"); + } // Detecté el problema con Vaadin en un path con "Documents%20and%20Settings" con %20 obviamente no es un path correcto, deben ser espacios + catch (UnsupportedEncodingException ex) { + throw new RelProxyException(ex); + } - File directory = new File(pkgPath); - if (!directory.isDirectory()) + File directory = new File(pkgPath); + if (!directory.isDirectory()) throw new RelProxyException("Internal Error:" + pkgPath); - + // browse local .class files - useful for local execution - + File[] childFiles = directory.listFiles(); - for (File childFile : childFiles) - { + for (File childFile : childFiles) { if (!childFile.isFile()) continue; - + // We only want the .class files. String name = childFile.getName(); - if (name.endsWith(CLASS_FILE_EXTENSION)) - { - String binaryName = ClassDescriptor.getClassNameFromPackageAndClassFileName(packageName,name); - result.add(new JavaFileObjectInputClassInFile(childFile,binaryName, childFile.toURI())); - } - } - } - - private void listUnderJar(@NotNull URL packageFolderURL, @NotNull Collection result) - { - try - { + if (name.endsWith(CLASS_FILE_EXTENSION)) { + String binaryName = ClassDescriptor.getClassNameFromPackageAndClassFileName(packageName, name); + result.add(new JavaFileObjectInputClassInFile(childFile, binaryName, childFile.toURI())); + } + } + } + + private void listUnderJar(@NotNull URL packageFolderURL, @NotNull Collection result) { + try { String jarUri = packageFolderURL.toExternalForm().split("!")[0]; - + JarURLConnection jarConn = (JarURLConnection) packageFolderURL.openConnection(); String rootEntryName = jarConn.getEntryName(); int rootEnd = rootEntryName.length() + 1; Enumeration entryEnum = jarConn.getJarFile().entries(); - while (entryEnum.hasMoreElements()) - { + while (entryEnum.hasMoreElements()) { JarEntry jarEntry = entryEnum.nextElement(); String name = jarEntry.getName(); // Empieza por packagePath y no hay más folders siguientes, terminando en un .class (una clase concreta) - if (name.startsWith(rootEntryName) && name.indexOf('/', rootEnd) == -1 && name.endsWith(CLASS_FILE_EXTENSION)) - { + if (name.startsWith(rootEntryName) && name.indexOf('/', rootEnd) == -1 && name.endsWith(CLASS_FILE_EXTENSION)) { URI uri = URI.create(jarUri + "!/" + name); String binaryName = ClassDescriptor.getClassNameFromRelativeClassFilePath(name); - result.add(new JavaFileObjectInputClassInJar(binaryName, uri,jarEntry.getTime())); + result.add(new JavaFileObjectInputClassInJar(binaryName, uri, jarEntry.getTime())); } } - } - catch (Exception e) - { + } catch (Exception e) { throw new RelProxyException("Wasn't able to open " + packageFolderURL + " as a jar file", e); } } - - private void listUnderJarCustom(@NotNull String packagePath, @NotNull FileExt jarFile, @NotNull Collection result) - { - String normalizedPath = jarFile.getCanonicalPath(); - if (normalizedPath.contains("\\")) // Windows - { + + private void listUnderJarCustom(@NotNull String packagePath, @NotNull FileExt jarFile, @NotNull Collection result) { + String normalizedPath = jarFile.getCanonicalPath(); + if (normalizedPath.contains("\\")) // Windows + { // No estoy seguro de que sea necesario normalizar pero por si acaso - normalizedPath = normalizedPath.replace("\\","/"); // "C:/folder" + normalizedPath = normalizedPath.replace("\\", "/"); // "C:/folder" normalizedPath = "/" + normalizedPath; // "/C:/folder" - } - - String urlPath = "file:" + normalizedPath; - - URL packageFolderURL; - try { packageFolderURL = new URL(urlPath); } - catch (MalformedURLException ex) { throw new RelProxyException(ex); } - - String jarUri = "jar:" + packageFolderURL.toExternalForm(); - - int posEnd = packagePath.length() + 1; - + } + + String urlPath = "file:" + normalizedPath; + + URL packageFolderURL; + try { + packageFolderURL = new URL(urlPath); + } catch (MalformedURLException ex) { + throw new RelProxyException(ex); + } + + String jarUri = "jar:" + packageFolderURL.toExternalForm(); + + int posEnd = packagePath.length() + 1; + ZipInputStream zip = null; - - try - { + + try { zip = new ZipInputStream(packageFolderURL.openStream()); ZipEntry zipEntry = zip.getNextEntry(); - while(zipEntry != null) - { - String name = zipEntry.getName(); + while (zipEntry != null) { + String name = zipEntry.getName(); // Empieza por packagePath y no hay más folders siguientes, terminando en un .class (una clase concreta) - if (name.startsWith(packagePath) && name.indexOf('/', posEnd) == -1 && name.endsWith(CLASS_FILE_EXTENSION)) - { + if (name.startsWith(packagePath) && name.indexOf('/', posEnd) == -1 && name.endsWith(CLASS_FILE_EXTENSION)) { URI uri = URI.create(jarUri + "!/" + name); String binaryName = ClassDescriptor.getClassNameFromRelativeClassFilePath(name); - result.add(new JavaFileObjectInputClassInJar(binaryName, uri,zipEntry.getTime())); - } + result.add(new JavaFileObjectInputClassInJar(binaryName, uri, zipEntry.getTime())); + } zipEntry = zip.getNextEntry(); - } - } - catch(IOException ex) - { + } + } catch (IOException ex) { throw new RelProxyException(ex); + } finally { + if (zip != null) try { + zip.close(); + } catch (IOException ex) { + throw new RelProxyException(ex); + } } - finally - { - if (zip != null) try { zip.close(); } catch (IOException ex) { throw new RelProxyException(ex); } - } - } - - + } + + } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JProxyJavaFileObjectInput.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JProxyJavaFileObjectInput.java index 8faf5a6..af404f9 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JProxyJavaFileObjectInput.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JProxyJavaFileObjectInput.java @@ -1,10 +1,8 @@ package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo; /** - * * @author jmarranz */ -public interface JProxyJavaFileObjectInput -{ +public interface JProxyJavaFileObjectInput { public String getBinaryName(); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java index 3152dac..db32523 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java @@ -10,30 +10,25 @@ import java.net.URI; /** - * * @author jmarranz */ -public class JavaFileObjectInputClassInFile extends JavaFileObjectInputClassInFileSystem -{ +public class JavaFileObjectInputClassInFile extends JavaFileObjectInputClassInFileSystem { protected File file; - - public JavaFileObjectInputClassInFile(File file, String binaryName, @NotNull URI uri) - { - super(binaryName,uri,uri.getPath()); + + public JavaFileObjectInputClassInFile(File file, String binaryName, @NotNull URI uri) { + super(binaryName, uri, uri.getPath()); this.file = file; } @NotNull @Override - public InputStream openInputStream() throws IOException - { + public InputStream openInputStream() throws IOException { // Podríamos hacer uri.toURL().openStream() pero si tenemos el File es para algo - return new BufferedInputStream(new FileInputStream(file),10 * 1024); + return new BufferedInputStream(new FileInputStream(file), 10 * 1024); } - + @Override - public long getLastModified() - { + public long getLastModified() { return file.lastModified(); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java index afbf586..c59610c 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java @@ -12,37 +12,34 @@ import javax.tools.JavaFileObject; /** - * * @author jmarranz */ -public abstract class JavaFileObjectInputClassInFileSystem implements JavaFileObject,JProxyJavaFileObjectInput -{ +public abstract class JavaFileObjectInputClassInFileSystem implements JavaFileObject, JProxyJavaFileObjectInput { protected final String binaryName; protected final URI uri; protected final String name; - - public JavaFileObjectInputClassInFileSystem(String binaryName, URI uri,String name) - { + + public JavaFileObjectInputClassInFileSystem(String binaryName, URI uri, String name) { this.uri = uri; this.binaryName = binaryName; this.name = name; - } - + } + @Override public URI toUri() { return uri; } - + @Override public String getName() { return name; } - - @Override + + @Override public String getBinaryName() { return binaryName; - } - + } + @NotNull @Override public OutputStream openOutputStream() throws IOException { @@ -70,8 +67,8 @@ public Writer openWriter() throws IOException { @Override public boolean delete() { throw new UnsupportedOperationException(); - } - + } + @NotNull @Override public Kind getKind() { @@ -97,5 +94,5 @@ public NestingKind getNestingKind() { public Modifier getAccessLevel() { throw new UnsupportedOperationException(); } - + } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java index dfe3757..9f24cce 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java @@ -7,35 +7,29 @@ import java.net.URI; /** - * * @author jmarranz */ -public class JavaFileObjectInputClassInJar extends JavaFileObjectInputClassInFileSystem -{ +public class JavaFileObjectInputClassInJar extends JavaFileObjectInputClassInFileSystem { protected long timestamp; - - public JavaFileObjectInputClassInJar(String binaryName, @NotNull URI uri, long timestamp) - { - super(binaryName,uri,uri.getSchemeSpecificPart()); + + public JavaFileObjectInputClassInJar(String binaryName, @NotNull URI uri, long timestamp) { + super(binaryName, uri, uri.getSchemeSpecificPart()); this.timestamp = timestamp; } @Override - public InputStream openInputStream() throws IOException - { + public InputStream openInputStream() throws IOException { return uri.toURL().openStream(); // easy way to handle any URI! } @Override - public long getLastModified() - { + public long getLastModified() { return timestamp; } @NotNull @Override - public String toString() - { + public String toString() { return "JavaFileObjectInputClassInJar{uri=" + uri + '}'; } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java index c632d7a..480d393 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java @@ -11,52 +11,45 @@ /** * http://www.javablogging.com/dynamic-in-memory-compilation/ - * + * * @author jmarranz */ -public class JavaFileObjectInputClassInMemory extends SimpleJavaFileObject implements JProxyJavaFileObjectInput -{ +public class JavaFileObjectInputClassInMemory extends SimpleJavaFileObject implements JProxyJavaFileObjectInput { protected String binaryName; protected byte[] byteCode; protected long timestamp; - - public JavaFileObjectInputClassInMemory(@NotNull String name, byte[] byteCode, long timestamp) - { + + public JavaFileObjectInputClassInMemory(@NotNull String name, byte[] byteCode, long timestamp) { super(URI.create("string:///" + name.replace('.', '/') + Kind.CLASS.extension), Kind.CLASS); - + this.binaryName = name; this.byteCode = byteCode; this.timestamp = timestamp; } - public byte[] getBytes() - { + public byte[] getBytes() { return byteCode; } - - @Override - public long getLastModified() - { + + @Override + public long getLastModified() { return timestamp; - } - + } + @NotNull @Override - public InputStream openInputStream() throws IOException - { + public InputStream openInputStream() throws IOException { return new ByteArrayInputStream(getBytes()); - } - + } + @NotNull @Override - public OutputStream openOutputStream() throws IOException - { + public OutputStream openOutputStream() throws IOException { throw new UnsupportedOperationException(); } - - @Override - public String getBinaryName() - { + + @Override + public String getBinaryName() { return binaryName; } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java index 8e2c67a..5e9b250 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java @@ -13,57 +13,50 @@ /** * http://www.javablogging.com/dynamic-in-memory-compilation/ - * + * * @author jmarranz */ -public abstract class JavaFileObjectInputSourceBase extends SimpleJavaFileObject implements JProxyJavaFileObjectInput -{ +public abstract class JavaFileObjectInputSourceBase extends SimpleJavaFileObject implements JProxyJavaFileObjectInput { protected String binaryName; protected String encoding; - - public JavaFileObjectInputSourceBase(@NotNull String name, String encoding) - { + + public JavaFileObjectInputSourceBase(@NotNull String name, String encoding) { super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE); // La extensión .java es necesaria aunque sea falsa sino da error - + this.binaryName = name; this.encoding = encoding; } - + protected abstract String getSource(); - - + + @Override - public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException - { + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { return getSource(); - } - + } + @NotNull - public byte[] getBytes() - { - try - { + public byte[] getBytes() { + try { return getSource().getBytes(encoding); + } catch (UnsupportedEncodingException ex) { + throw new RelProxyException(ex); } - catch (UnsupportedEncodingException ex) { throw new RelProxyException(ex); } - } - + } + @NotNull @Override - public InputStream openInputStream() throws IOException - { + public InputStream openInputStream() throws IOException { return new ByteArrayInputStream(getBytes()); - } - + } + @NotNull @Override - public OutputStream openOutputStream() throws IOException - { + public OutputStream openOutputStream() throws IOException { throw new UnsupportedOperationException(); } - - public String getBinaryName() - { + + public String getBinaryName() { return binaryName; } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java index 801d10a..28505a1 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java @@ -7,32 +7,28 @@ /** * http://www.javablogging.com/dynamic-in-memory-compilation/ - * + * * @author jmarranz */ -public class JavaFileObjectInputSourceInFile extends JavaFileObjectInputSourceBase -{ +public class JavaFileObjectInputSourceInFile extends JavaFileObjectInputSourceBase { protected File file; protected String source; - - public JavaFileObjectInputSourceInFile(@NotNull String name, File file, String encoding) - { - super(name,encoding); + + public JavaFileObjectInputSourceInFile(@NotNull String name, File file, String encoding) { + super(name, encoding); this.file = file; } @Override - protected String getSource() - { + protected String getSource() { if (source != null) return source; this.source = JProxyUtil.readTextFile(file, encoding); return source; - } - + } + @Override - public long getLastModified() - { + public long getLastModified() { return file.lastModified(); - } + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java index b613805..6e6aacc 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java @@ -4,30 +4,26 @@ /** * http://www.javablogging.com/dynamic-in-memory-compilation/ - * + * * @author jmarranz */ -public class JavaFileObjectInputSourceInMemory extends JavaFileObjectInputSourceBase -{ +public class JavaFileObjectInputSourceInMemory extends JavaFileObjectInputSourceBase { protected String source; protected long timestamp; - - public JavaFileObjectInputSourceInMemory(@NotNull String name, String source, String encoding, long timestamp) - { - super(name,encoding); + + public JavaFileObjectInputSourceInMemory(@NotNull String name, String source, String encoding, long timestamp) { + super(name, encoding); this.source = source; this.timestamp = timestamp; } @Override - protected String getSource() - { + protected String getSource() { return source; - } - - @Override - public long getLastModified() - { + } + + @Override + public long getLastModified() { return timestamp; - } + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java index 62a90aa..a49056b 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java @@ -11,51 +11,45 @@ /** * http://www.javablogging.com/dynamic-in-memory-compilation/ - * + * * @author jmarranz */ public class JavaFileObjectOutputClass extends SimpleJavaFileObject { /** - * Byte code created by the compiler will be stored in this - * ByteArrayOutputStream so that we can later get the - * byte array out of it - * and put it in the memory as an instance of our class. - */ + * Byte code created by the compiler will be stored in this + * ByteArrayOutputStream so that we can later get the + * byte array out of it + * and put it in the memory as an instance of our class. + */ protected final ByteArrayOutputStream bos = new ByteArrayOutputStream(); protected String binaryName; - + /** - * Registers the compiled class object under URI - * containing the class full name - * - * @param name - * Full name of the compiled class - * @param kind - * Kind of the data. It will be CLASS in our case - */ - public JavaFileObjectOutputClass(@NotNull String name, @NotNull Kind kind) - { + * Registers the compiled class object under URI + * containing the class full name + * + * @param name Full name of the compiled class + * @param kind Kind of the data. It will be CLASS in our case + */ + public JavaFileObjectOutputClass(@NotNull String name, @NotNull Kind kind) { super(URI.create("string:///" + name.replace('.', '/') + kind.extension), kind); - + if (!Kind.CLASS.equals(kind)) throw new RelProxyException("Unexpected"); this.binaryName = name; } - public String binaryName() - { + public String binaryName() { return binaryName; } - - public byte[] getBytes() - { + + public byte[] getBytes() { return bos.toByteArray(); } @NotNull @Override - public OutputStream openOutputStream() throws IOException - { + public OutputStream openOutputStream() throws IOException { return bos; } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java index 836c2b0..3ae32ba 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java @@ -4,29 +4,24 @@ import org.jetbrains.annotations.NotNull; /** - * * @author jmarranz */ -public class SourceFileJavaNormal extends SourceUnit -{ +public class SourceFileJavaNormal extends SourceUnit { @NotNull protected final FileExt sourceFile; - - public SourceFileJavaNormal(@NotNull FileExt sourceFile, @NotNull FileExt rootFolderOfSources) - { - super(buildClassNameFromFile(sourceFile,rootFolderOfSources)); - this.sourceFile = sourceFile; + + public SourceFileJavaNormal(@NotNull FileExt sourceFile, @NotNull FileExt rootFolderOfSources) { + super(buildClassNameFromFile(sourceFile, rootFolderOfSources)); + this.sourceFile = sourceFile; } @Override - public long lastModified() - { + public long lastModified() { return sourceFile.getFile().lastModified(); } - + @NotNull - public FileExt getFileExt() - { + public FileExt getFileExt() { return sourceFile; } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRoot.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRoot.java index 5d81119..3907af1 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRoot.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRoot.java @@ -1,15 +1,12 @@ package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit; /** - * * @author jmarranz */ -public abstract class SourceScriptRoot extends SourceUnit -{ - public SourceScriptRoot(String className) - { +public abstract class SourceScriptRoot extends SourceUnit { + public SourceScriptRoot(String className) { super(className); } - - public abstract String getScriptCode(String encoding,boolean[] hasHashBang); + + public abstract String getScriptCode(String encoding, boolean[] hasHashBang); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java index 5456fa3..a8add45 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java @@ -6,36 +6,30 @@ import org.jetbrains.annotations.NotNull; /** - * * @author jmarranz */ -public abstract class SourceScriptRootFile extends SourceScriptRoot -{ +public abstract class SourceScriptRootFile extends SourceScriptRoot { protected FileExt sourceFile; - - public SourceScriptRootFile(@NotNull FileExt sourceFile, @NotNull FolderSourceList folderSourceList) - { - super(buildClassNameFromFile(sourceFile,folderSourceList)); - this.sourceFile = sourceFile; + + public SourceScriptRootFile(@NotNull FileExt sourceFile, @NotNull FolderSourceList folderSourceList) { + super(buildClassNameFromFile(sourceFile, folderSourceList)); + this.sourceFile = sourceFile; } - - public static SourceScriptRootFile createSourceScriptRootFile(@NotNull FileExt sourceFile, @NotNull FolderSourceList folderSourceList) - { + + public static SourceScriptRootFile createSourceScriptRootFile(@NotNull FileExt sourceFile, @NotNull FolderSourceList folderSourceList) { String ext = JProxyUtil.getFileExtension(sourceFile.getFile()); // Si no tiene extensión devuelve "" if ("java".equals(ext)) - return new SourceScriptRootFileJavaExt(sourceFile,folderSourceList); + return new SourceScriptRootFileJavaExt(sourceFile, folderSourceList); else - return new SourceScriptRootFileOtherExt(sourceFile,folderSourceList); // Caso de archivo script inicial sin extensión .java (puede ser sin extensión) + return new SourceScriptRootFileOtherExt(sourceFile, folderSourceList); // Caso de archivo script inicial sin extensión .java (puede ser sin extensión) } - + @Override - public long lastModified() - { + public long lastModified() { return sourceFile.getFile().lastModified(); - } + } - public FileExt getFileExt() - { + public FileExt getFileExt() { return sourceFile; } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java index 5e22815..3fc69a2 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java @@ -6,21 +6,17 @@ import org.jetbrains.annotations.NotNull; /** - * * @author jmarranz */ -public class SourceScriptRootFileJavaExt extends SourceScriptRootFile -{ - public SourceScriptRootFileJavaExt(@NotNull FileExt sourceFile, @NotNull FolderSourceList folderSourceList) - { - super(sourceFile,folderSourceList); - } - +public class SourceScriptRootFileJavaExt extends SourceScriptRootFile { + public SourceScriptRootFileJavaExt(@NotNull FileExt sourceFile, @NotNull FolderSourceList folderSourceList) { + super(sourceFile, folderSourceList); + } + @NotNull @Override - public String getScriptCode(@NotNull String encoding, boolean[] hasHashBang) - { - hasHashBang[0] = false; - return JProxyUtil.readTextFile(sourceFile.getFile(),encoding); - } + public String getScriptCode(@NotNull String encoding, boolean[] hasHashBang) { + hasHashBang[0] = false; + return JProxyUtil.readTextFile(sourceFile.getFile(), encoding); + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java index 84530c3..cbc97bf 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java @@ -6,32 +6,26 @@ import org.jetbrains.annotations.NotNull; /** - * * @author jmarranz */ -public class SourceScriptRootFileOtherExt extends SourceScriptRootFile -{ - public SourceScriptRootFileOtherExt(@NotNull FileExt sourceFile, @NotNull FolderSourceList folderSourceList) - { - super(sourceFile,folderSourceList); - } - +public class SourceScriptRootFileOtherExt extends SourceScriptRootFile { + public SourceScriptRootFileOtherExt(@NotNull FileExt sourceFile, @NotNull FolderSourceList folderSourceList) { + super(sourceFile, folderSourceList); + } + @NotNull @Override - public String getScriptCode(@NotNull String encoding, boolean[] hasHashBang) - { - String codeBody = JProxyUtil.readTextFile(sourceFile.getFile(),encoding); + public String getScriptCode(@NotNull String encoding, boolean[] hasHashBang) { + String codeBody = JProxyUtil.readTextFile(sourceFile.getFile(), encoding); // Eliminamos la primera línea #! (debe estar en la primera línea y sin espacios antes) - if (codeBody.startsWith("#!")) - { - hasHashBang[0] = true; + if (codeBody.startsWith("#!")) { + hasHashBang[0] = true; int pos = codeBody.indexOf('\n'); if (pos != -1) // Rarísimo que sólo esté el hash bang (script vacío) { codeBody = codeBody.substring(pos + 1); - } - } - else hasHashBang[0] = false; + } + } else hasHashBang[0] = false; return codeBody; - } + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootInMemory.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootInMemory.java index 9ad61e0..a258205 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootInMemory.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootInMemory.java @@ -1,56 +1,47 @@ package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit; /** - * * @author jmarranz */ -public class SourceScriptRootInMemory extends SourceScriptRoot -{ +public class SourceScriptRootInMemory extends SourceScriptRoot { public static final String DEFAULT_CLASS_NAME = "_jproxyMainClass_"; // OJO NO CAMBIAR, está ya documentada - + protected String code; protected long timestamp; - - private SourceScriptRootInMemory(String className,String code) - { + + private SourceScriptRootInMemory(String className, String code) { super(className); - setScriptCode(code,System.currentTimeMillis()); + setScriptCode(code, System.currentTimeMillis()); } - - public static SourceScriptRootInMemory createSourceScriptInMemory(String code) - { - return new SourceScriptRootInMemory(DEFAULT_CLASS_NAME,code); + + public static SourceScriptRootInMemory createSourceScriptInMemory(String code) { + return new SourceScriptRootInMemory(DEFAULT_CLASS_NAME, code); } - + @Override - public long lastModified() - { + public long lastModified() { return timestamp; // Siempre ha sido modificado - } + } @Override - public String getScriptCode(String encoding,boolean[] hasHashBang) - { + public String getScriptCode(String encoding, boolean[] hasHashBang) { hasHashBang[0] = false; return code; } - - public boolean isEmptyCode() - { + + public boolean isEmptyCode() { // Si code es "" la clase especial se genera pero no hace nada simplemente devuelve un null. // Este es el caso en el que utilizamos RelProxy embebido en un framework utilizando la API ScriptEngine pero únicamente porque se usa una API basada // en interfaces, pero tiene el inconveniente de generarse un SourceScriptRootInMemory inútil que no hace nada return code.isEmpty(); } - - public String getScriptCode() - { + + public String getScriptCode() { return code; } - - public final void setScriptCode(String code,long timestamp) - { + + public final void setScriptCode(String code, long timestamp) { this.code = code; this.timestamp = timestamp; - } + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java index fd33113..16818ea 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java @@ -6,35 +6,29 @@ import org.jetbrains.annotations.Nullable; /** - * * @author jmarranz */ -public abstract class SourceUnit -{ +public abstract class SourceUnit { protected final String className; - - public SourceUnit(String className) - { + + public SourceUnit(String className) { this.className = className; } - + public abstract long lastModified(); - + @Nullable - protected static String buildClassNameFromFile(@NotNull FileExt sourceFile, @NotNull FolderSourceList sourceList) - { + protected static String buildClassNameFromFile(@NotNull FileExt sourceFile, @NotNull FolderSourceList sourceList) { return sourceList.buildClassNameFromFile(sourceFile); - } - + } + @Nullable - protected static String buildClassNameFromFile(@NotNull FileExt sourceFile, @NotNull FileExt rootFolderOfSources) - { - return FolderSourceList.buildClassNameFromFile(sourceFile,rootFolderOfSources); - } - - public String getClassName() - { + protected static String buildClassNameFromFile(@NotNull FileExt sourceFile, @NotNull FileExt rootFolderOfSources) { + return FolderSourceList.buildClassNameFromFile(sourceFile, rootFolderOfSources); + } + + public String getClassName() { return className; - } - + } + } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/BindingsImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/BindingsImpl.java index e960b2a..536f81a 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/BindingsImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/BindingsImpl.java @@ -5,10 +5,8 @@ import javax.script.Bindings; /** - * * @author jmarranz */ -public class BindingsImpl extends HashMap implements Bindings -{ +public class BindingsImpl extends HashMap implements Bindings { } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java index e658569..2877591 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java @@ -17,96 +17,85 @@ import javax.script.ScriptException; /** - * * @author jmarranz */ -public class JProxyScriptEngineDelegateImpl extends JProxyImpl -{ +public class JProxyScriptEngineDelegateImpl extends JProxyImpl { protected JProxyScriptEngineImpl parent; @Nullable protected ClassDescriptorSourceScript classDescSourceScript; - protected long codeBufferModTimestamp = 0; + protected long codeBufferModTimestamp = 0; protected long lastCodeCompiledTimestamp = 0; - - public JProxyScriptEngineDelegateImpl(JProxyScriptEngineImpl parent) - { - this.parent = parent; - } - + + public JProxyScriptEngineDelegateImpl(JProxyScriptEngineImpl parent) { + this.parent = parent; + } + @Nullable @Override - public ClassDescriptorSourceScript init(@NotNull JProxyConfigImpl config) - { + public ClassDescriptorSourceScript init(@NotNull JProxyConfigImpl config) { SourceScriptRoot sourceFileScript = SourceScriptRootInMemory.createSourceScriptInMemory(""); JProxyShellClassLoader classLoader = null; String classFolder = config.getClassFolder(); if (classFolder != null) - classLoader = new JProxyShellClassLoader(getDefaultClassLoader(),new File(classFolder)); + classLoader = new JProxyShellClassLoader(getDefaultClassLoader(), new File(classFolder)); - this.classDescSourceScript = init(config,sourceFileScript,classLoader); + this.classDescSourceScript = init(config, sourceFileScript, classLoader); return classDescSourceScript; } - + @NotNull @Override - public Class getMainParamClass() - { + public Class getMainParamClass() { return ScriptContext.class; } - + @NotNull - private SourceScriptRootInMemory getSourceScriptInMemory() - { - return (SourceScriptRootInMemory)classDescSourceScript.getSourceScript(); - } - - public Object execute(String code,ScriptContext context) throws ScriptException - { + private SourceScriptRootInMemory getSourceScriptInMemory() { + return (SourceScriptRootInMemory) classDescSourceScript.getSourceScript(); + } + + public Object execute(String code, ScriptContext context) throws ScriptException { Class scriptClass; JProxyEngine jproxyEngine = getJProxyEngine(); Object monitor = jproxyEngine.getMonitor(); - synchronized(monitor) - { - if (!getSourceScriptInMemory().getScriptCode().equals(code)) - { + synchronized (monitor) { + if (!getSourceScriptInMemory().getScriptCode().equals(code)) { this.codeBufferModTimestamp = System.currentTimeMillis(); - getSourceScriptInMemory().setScriptCode(code,codeBufferModTimestamp); + getSourceScriptInMemory().setScriptCode(code, codeBufferModTimestamp); // Recuerda que cada vez que se obtiene el timestamp se llama a System.currentTimeMillis(), es imposible que el usuario haga algo en menos de 1ms ClassDescriptorSourceScript classDescSourceScript2 = null; - try - { + try { classDescSourceScript2 = jproxyEngine.detectChangesInSourcesAndReload(); - } - catch(JProxyCompilationException ex) - { + } catch (JProxyCompilationException ex) { throw new ScriptException(ex); } if (classDescSourceScript2 != classDescSourceScript) throw new RelProxyException("Internal Error"); - this.lastCodeCompiledTimestamp = System.currentTimeMillis(); + this.lastCodeCompiledTimestamp = System.currentTimeMillis(); if (lastCodeCompiledTimestamp == codeBufferModTimestamp) // Demasiado rápido compilando { // Aseguramos que el siguiente código se ejecuta si o si con un codeBufferModTimestamp mayor que el timestamp de la compilación - try { Thread.sleep(1); } catch (InterruptedException ex) { throw new RelProxyException(ex); } + try { + Thread.sleep(1); + } catch (InterruptedException ex) { + throw new RelProxyException(ex); + } } } scriptClass = classDescSourceScript.getLastLoadedClass(); } - - try - { - return ClassDescriptorSourceScript.callMainMethod(scriptClass,parent,context); - } - catch(Throwable ex) - { - Exception ex2 = (ex instanceof Exception) ? (Exception)ex : new RelProxyException(ex); + + try { + return ClassDescriptorSourceScript.callMainMethod(scriptClass, parent, context); + } catch (Throwable ex) { + Exception ex2 = (ex instanceof Exception) ? (Exception) ex : new RelProxyException(ex); throw new ScriptException(ex2); - } - } + } + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java index 4c657b3..1ff0969 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java @@ -11,108 +11,98 @@ /** * Ideas: http://grepcode.com/file/repo1.maven.org/maven2/org.codehaus.groovy/groovy/1.6.0/org/codehaus/groovy/jsr223/GroovyScriptEngineFactory.java - * + * * @author jmarranz */ -public class JProxyScriptEngineFactoryImpl extends JProxyScriptEngineFactory -{ - protected static final String SHORT_NAME = "java"; - protected static final String LANGUAGE_NAME = "Java"; - +public class JProxyScriptEngineFactoryImpl extends JProxyScriptEngineFactory { + protected static final String SHORT_NAME = "java"; + protected static final String LANGUAGE_NAME = "Java"; + @NotNull protected static final List names; @NotNull protected static final List extensions; @NotNull protected static final List mimeTypes; - - static - { + + static { ArrayList n; - + n = new ArrayList(2); n.add(SHORT_NAME); n.add(LANGUAGE_NAME); - names = Collections.unmodifiableList(n); + names = Collections.unmodifiableList(n); n = new ArrayList(1); n.add("java"); - extensions = Collections.unmodifiableList(n); - - n = new ArrayList(2); http://reference.sitepoint.com/html/mime-types-full + extensions = Collections.unmodifiableList(n); + + n = new ArrayList(2); + http: +//reference.sitepoint.com/html/mime-types-full n.add("text/x-java-source"); - n.add("text/plain"); - mimeTypes = Collections.unmodifiableList(n); + n.add("text/plain"); + mimeTypes = Collections.unmodifiableList(n); } - public JProxyScriptEngineFactoryImpl() - { + public JProxyScriptEngineFactoryImpl() { } - - public static JProxyScriptEngineFactory create() - { + + public static JProxyScriptEngineFactory create() { return new JProxyScriptEngineFactoryImpl(); - } - + } + @NotNull @Override - public String getEngineName() - { + public String getEngineName() { return "RelProxy Java Script Engine"; } @NotNull @Override - public String getEngineVersion() - { + public String getEngineVersion() { return RelProxy.getVersion(); } @NotNull @Override - public List getExtensions() - { + public List getExtensions() { return extensions; } @NotNull @Override - public List getMimeTypes() - { + public List getMimeTypes() { return mimeTypes; } @NotNull @Override - public List getNames() - { + public List getNames() { return names; } @NotNull @Override - public String getLanguageName() - { + public String getLanguageName() { return LANGUAGE_NAME; } @Override - public String getLanguageVersion() - { + public String getLanguageVersion() { return System.getProperty("java.version"); // Ej 1.6.0_18 } @Override - public Object getParameter(String key) - { - if (ScriptEngine.NAME.equals(key)) { - return SHORT_NAME; - } else if (ScriptEngine.ENGINE.equals(key)) { - return getEngineName(); - } else if (ScriptEngine.ENGINE_VERSION.equals(key)) { - return getEngineVersion(); - } else if (ScriptEngine.LANGUAGE.equals(key)) { - return getLanguageName(); + public Object getParameter(String key) { + if (ScriptEngine.NAME.equals(key)) { + return SHORT_NAME; + } else if (ScriptEngine.ENGINE.equals(key)) { + return getEngineName(); + } else if (ScriptEngine.ENGINE_VERSION.equals(key)) { + return getEngineVersion(); + } else if (ScriptEngine.LANGUAGE.equals(key)) { + return getLanguageName(); } else if (ScriptEngine.LANGUAGE_VERSION.equals(key)) { return getLanguageVersion(); } else if ("THREADING".equals(key)) { @@ -124,8 +114,7 @@ public Object getParameter(String key) @NotNull @Override - public String getMethodCallSyntax(String obj, String method, @NotNull String... args) - { + public String getMethodCallSyntax(String obj, String method, @NotNull String... args) { StringBuilder ret = new StringBuilder(); ret.append(obj + "." + method + "("); int len = args.length; @@ -133,7 +122,7 @@ public String getMethodCallSyntax(String obj, String method, @NotNull String... ret.append(")"); return ret.toString(); } - + for (int i = 0; i < len; i++) { ret.append(args[i]); if (i != len - 1) { @@ -147,24 +136,22 @@ public String getMethodCallSyntax(String obj, String method, @NotNull String... @NotNull @Override - public String getOutputStatement(@NotNull String toDisplay) - { + public String getOutputStatement(@NotNull String toDisplay) { StringBuilder buf = new StringBuilder(); buf.append("System.out.println(\""); int len = toDisplay.length(); - for (int i = 0; i < len; i++) - { + for (int i = 0; i < len; i++) { char ch = toDisplay.charAt(i); switch (ch) { - case '"': - buf.append("\\\""); - break; - case '\\': - buf.append("\\\\"); - break; - default: - buf.append(ch); - break; + case '"': + buf.append("\\\""); + break; + case '\\': + buf.append("\\\\"); + break; + default: + buf.append(ch); + break; } } buf.append("\")"); @@ -173,12 +160,10 @@ public String getOutputStatement(@NotNull String toDisplay) @NotNull @Override - public String getProgram(@NotNull String... statements) - { + public String getProgram(@NotNull String... statements) { StringBuilder ret = new StringBuilder(); int len = statements.length; - for (int i = 0; i < len; i++) - { + for (int i = 0; i < len; i++) { ret.append(statements[i]); ret.append('\n'); } @@ -187,8 +172,7 @@ public String getProgram(@NotNull String... statements) @NotNull @Override - public ScriptEngine getScriptEngine() - { + public ScriptEngine getScriptEngine() { return new JProxyScriptEngineImpl(this); - } + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java index 8781e61..aeda178 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java @@ -18,111 +18,98 @@ /** * Methods of this class are similar to JProxyDefaultImpl - * + * * @author jmarranz */ -public class JProxyScriptEngineImpl extends AbstractScriptEngine implements JProxyScriptEngine -{ +public class JProxyScriptEngineImpl extends AbstractScriptEngine implements JProxyScriptEngine { protected JProxyScriptEngineDelegateImpl jproxy; protected JProxyScriptEngineFactoryImpl factory; - public JProxyScriptEngineImpl(JProxyScriptEngineFactoryImpl factory) - { + public JProxyScriptEngineImpl(JProxyScriptEngineFactoryImpl factory) { this.factory = factory; } - @Override - public void init(JProxyConfig config) - { - JProxyConfigImpl configImpl = (JProxyConfigImpl)config; + @Override + public void init(JProxyConfig config) { + JProxyConfigImpl configImpl = (JProxyConfigImpl) config; if (!configImpl.isEnabled()) return; // jproxy quedará null - GenericProxyImpl.checkSingletonNull(jproxy); + GenericProxyImpl.checkSingletonNull(jproxy); this.jproxy = new JProxyScriptEngineDelegateImpl(this); - jproxy.init(configImpl); + jproxy.init(configImpl); } - + @Override - public Object eval(String script, ScriptContext context) throws ScriptException - { - if (jproxy == null) + public Object eval(String script, ScriptContext context) throws ScriptException { + if (jproxy == null) throw new RelProxyException("Engine is disabled"); - - return jproxy.execute(script,context); + + return jproxy.execute(script, context); } @Override - public Object eval(@NotNull Reader reader, ScriptContext context) throws ScriptException - { + public Object eval(@NotNull Reader reader, ScriptContext context) throws ScriptException { String script = JProxyUtil.readTextFile(reader); - return eval(script,context); + return eval(script, context); } @NotNull @Override - public Bindings createBindings() - { + public Bindings createBindings() { return new BindingsImpl(); } @Override - public ScriptEngineFactory getFactory() - { + public ScriptEngineFactory getFactory() { return factory; } @Nullable @Override - public T create(T obj,Class clasz) - { - if (jproxy == null) + public T create(T obj, Class clasz) { + if (jproxy == null) return obj; // No se ha llamado al init o enabled = false return jproxy.create(obj, clasz); } @Nullable @Override - public Object create(Object obj, @NotNull Class[] classes) - { - if (jproxy == null) + public Object create(Object obj, @NotNull Class[] classes) { + if (jproxy == null) return obj; // No se ha llamado al init o enabled = false return jproxy.create(obj, classes); - } - - @Override - public boolean isEnabled() - { - if (jproxy == null) + } + + @Override + public boolean isEnabled() { + if (jproxy == null) return false; - + return jproxy.isEnabled(); - } - - @Override - public boolean isRunning() - { - if (jproxy == null) + } + + @Override + public boolean isRunning() { + if (jproxy == null) return false; - + return jproxy.isRunning(); - } - + } + @Override - public boolean start() - { - if (jproxy == null) + public boolean start() { + if (jproxy == null) return false; - + return jproxy.start(); } @Override - public boolean stop() - { - if (jproxy == null) + public boolean stop() { + if (jproxy == null) return false; - + return jproxy.stop(); } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java index 6cd7faf..4055ffd 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java @@ -10,40 +10,36 @@ import java.net.URLClassLoader; /** - * * @author jmarranz */ -public class JProxyShellClassLoader extends URLClassLoader -{ - public JProxyShellClassLoader(ClassLoader parent, @NotNull File classFolder) - { - super(toURLArray(classFolder),parent); +public class JProxyShellClassLoader extends URLClassLoader { + public JProxyShellClassLoader(ClassLoader parent, @NotNull File classFolder) { + super(toURLArray(classFolder), parent); } - private static URL[] toURLArray(@NotNull File file) - { - try { return new URL[]{file.toURI().toURL()}; } - catch (MalformedURLException ex) { throw new RelProxyException(ex); } + private static URL[] toURLArray(@NotNull File file) { + try { + return new URL[]{file.toURI().toURL()}; + } catch (MalformedURLException ex) { + throw new RelProxyException(ex); + } } @Override - protected Class findClass(String name) throws ClassNotFoundException - { - return super.findClass(name); + protected Class findClass(String name) throws ClassNotFoundException { + return super.findClass(name); } @Override - protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException - { - return super.loadClass(name, resolve); + protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + return super.loadClass(name, resolve); } - public synchronized Class defineClass(@NotNull ClassDescriptor classDesc) - { + public synchronized Class defineClass(@NotNull ClassDescriptor classDesc) { String className = classDesc.getClassName(); byte[] classBytes = classDesc.getClassBytes(); - Class clasz = defineClass(className,classBytes, 0, classBytes.length); + Class clasz = defineClass(className, classBytes, 0, classBytes.length); classDesc.setLastLoadedClass(clasz); return clasz; - } + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java index df4510a..b362a4c 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java @@ -12,55 +12,46 @@ import java.util.LinkedList; /** - * * @author jmarranz */ -public class JProxyShellCodeSnippetImpl extends JProxyShellImpl -{ - public void init(@NotNull String[] args) - { +public class JProxyShellCodeSnippetImpl extends JProxyShellImpl { + public void init(@NotNull String[] args) { super.init(args, null); - } - - @Override - protected void executeFirstTime(@NotNull ClassDescriptorSourceScript scriptFileDesc, @NotNull LinkedList argsToScript, JProxyShellClassLoader classLoader) - { - try - { - scriptFileDesc.callMainMethod(argsToScript); - } - catch(Throwable ex) - { + } + + @Override + protected void executeFirstTime(@NotNull ClassDescriptorSourceScript scriptFileDesc, @NotNull LinkedList argsToScript, JProxyShellClassLoader classLoader) { + try { + scriptFileDesc.callMainMethod(argsToScript); + } catch (Throwable ex) { ex.printStackTrace(System.out); - } - } - + } + } + @Override - protected void processConfigParams(@NotNull String[] args, @NotNull LinkedList argsToScript, @NotNull JProxyConfigImpl config) - { + protected void processConfigParams(@NotNull String[] args, @NotNull LinkedList argsToScript, @NotNull JProxyConfigImpl config) { super.processConfigParams(args, argsToScript, config); - + String classFolder = config.getClassFolder(); - if (classFolder != null && !classFolder.trim().isEmpty()) throw new RelProxyException("cacheClassFolder is useless to execute a code snippet"); - } - + if (classFolder != null && !classFolder.trim().isEmpty()) + throw new RelProxyException("cacheClassFolder is useless to execute a code snippet"); + } + @NotNull @Override - protected SourceScriptRoot createSourceScriptRoot(String[] args, @NotNull LinkedList argsToScript, FolderSourceList folderSourceList) - { + protected SourceScriptRoot createSourceScriptRoot(String[] args, @NotNull LinkedList argsToScript, FolderSourceList folderSourceList) { // En argsToScript no está el args[0] ni falta que hace porque es el flag "-c" StringBuilder code = new StringBuilder(); - for(String chunk : argsToScript) + for (String chunk : argsToScript) code.append(chunk); return SourceScriptRootInMemory.createSourceScriptInMemory(code.toString()); - } - + } + @Nullable @Override - protected JProxyShellClassLoader getJProxyShellClassLoader(JProxyConfigImpl config) - { + protected JProxyShellClassLoader getJProxyShellClassLoader(JProxyConfigImpl config) { // No hay classFolder => no hay necesidad de nuevo ClassLoader - return null; + return null; } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellImpl.java index e88a295..bfaef31 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellImpl.java @@ -18,37 +18,28 @@ * * @author jmarranz */ -public abstract class JProxyShellImpl extends JProxyImpl -{ - - public static void main(@NotNull String[] args) - { - if (args[0].isEmpty()) - { +public abstract class JProxyShellImpl extends JProxyImpl { + + public static void main(@NotNull String[] args) { + if (args[0].isEmpty()) { // Esto tiene explicación: cuando invocamos jproxysh sin parámetros (o espacios da igual) invocamos dentro jproxysh con com.sillelien.dollar.relproxy.jproxy.JProxyShell "$@" // el parámetro "$@" se convierte en "" que es un parámetro de verdad que recibimos pero de cadena vacía, lo cual nos viene GENIAL para distinguir el caso shell interactive - SINGLETON = new JProxyShellInteractiveImpl(); - ((JProxyShellInteractiveImpl)SINGLETON).init(args); - } - else - { - if (args[0].equals("-c")) - { + SINGLETON = new JProxyShellInteractiveImpl(); + ((JProxyShellInteractiveImpl) SINGLETON).init(args); + } else { + if (args[0].equals("-c")) { SINGLETON = new JProxyShellCodeSnippetImpl(); - ((JProxyShellCodeSnippetImpl)SINGLETON).init(args); - } - else - { - SINGLETON = new JProxyShellScriptFileImpl(); - ((JProxyShellScriptFileImpl)SINGLETON).init(args); + ((JProxyShellCodeSnippetImpl) SINGLETON).init(args); + } else { + SINGLETON = new JProxyShellScriptFileImpl(); + ((JProxyShellScriptFileImpl) SINGLETON).init(args); } } } - + @Nullable - protected ClassDescriptorSourceScript init(@NotNull String[] args, String inputPath) - { + protected ClassDescriptorSourceScript init(@NotNull String[] args, String inputPath) { // Esto quizás necesite una opción en plan "verbose" o "log" para mostrar por pantalla o nada RelProxyOnReloadListener proxyListener = new RelProxyOnReloadListener() { @Override @@ -61,91 +52,79 @@ public void onReload(Object objOld, Object objNew, Object proxy, Method method, config.setEnabled(true); config.setRelProxyOnReloadListener(proxyListener); config.setInputPath(inputPath); - config.setJProxyInputSourceFileExcludedListener(null); + config.setJProxyInputSourceFileExcludedListener(null); config.setJProxyCompilerListener(null); config.setJProxyDiagnosticsListener(null); // Nos vale el log por defecto y no hay manera de espeficar otra cosa via comando - + LinkedList argsToScript = new LinkedList(); - processConfigParams(args,argsToScript,config); - - SourceScriptRoot sourceFileScript = createSourceScriptRoot(args,argsToScript,config.getFolderSourceList()); + processConfigParams(args, argsToScript, config); + + SourceScriptRoot sourceFileScript = createSourceScriptRoot(args, argsToScript, config.getFolderSourceList()); JProxyShellClassLoader classLoader = getJProxyShellClassLoader(config); - ClassDescriptorSourceScript scriptFileDesc = init(config,sourceFileScript,classLoader); + ClassDescriptorSourceScript scriptFileDesc = init(config, sourceFileScript, classLoader); + + executeFirstTime(scriptFileDesc, argsToScript, classLoader); - executeFirstTime(scriptFileDesc,argsToScript,classLoader); - return scriptFileDesc; - } + } @NotNull @Override - public Class getMainParamClass() - { + public Class getMainParamClass() { return String[].class; } - - + + @NotNull protected abstract SourceScriptRoot createSourceScriptRoot(String[] args, LinkedList argsToScript, FolderSourceList folderSourceList); + @Nullable protected abstract JProxyShellClassLoader getJProxyShellClassLoader(JProxyConfigImpl config); - protected abstract void executeFirstTime(ClassDescriptorSourceScript scriptFileDesc,LinkedList argsToScript,JProxyShellClassLoader classLoader); - + + protected abstract void executeFirstTime(ClassDescriptorSourceScript scriptFileDesc, LinkedList argsToScript, JProxyShellClassLoader classLoader); + @NotNull - private static Iterable parseCompilationOptions(@NotNull String value) - { + private static Iterable parseCompilationOptions(@NotNull String value) { // Ej -source 1.6 -target 1.6 se convertiría en Arrays.asList(new String[]{"-source","1.6","-target","1.6"}); String[] options = value.split(" "); LinkedList opCol = new LinkedList(); - for (String option : options) - { + for (String option : options) { String op = option.trim(); // Por si hubiera dos espacios if (op.isEmpty()) continue; opCol.add(op); } return opCol; } - - - protected void processConfigParams(@NotNull String[] args, @NotNull LinkedList argsToScript, @NotNull JProxyConfigImpl config) - { + + + protected void processConfigParams(@NotNull String[] args, @NotNull LinkedList argsToScript, @NotNull JProxyConfigImpl config) { String classFolder = null; long scanPeriod = -1; Iterable compilationOptions = null; boolean test = false; - - for(int i = 1; i < args.length; i++) - { + + for (int i = 1; i < args.length; i++) { String arg = args[i]; - if (arg.startsWith("-D")) - { + if (arg.startsWith("-D")) { String param = arg.substring(2); int pos = param.indexOf('='); if (pos == -1) throw new RelProxyException("Bad parameter format: " + arg); - String name = param.substring(0,pos); + String name = param.substring(0, pos); String value = param.substring(pos + 1); - if ("cacheClassFolder".equals(name)) - { + if ("cacheClassFolder".equals(name)) { classFolder = value; - } - else if ("compilationOptions".equals(name)) - { + } else if ("compilationOptions".equals(name)) { compilationOptions = parseCompilationOptions(value); - } - else if ("test".equals(name)) - { + } else if ("test".equals(name)) { test = Boolean.parseBoolean(value); - } - else throw new RelProxyException("Unknown parameter: " + arg); - } - else - { + } else throw new RelProxyException("Unknown parameter: " + arg); + } else { argsToScript.add(arg); } } @@ -153,8 +132,8 @@ else if ("test".equals(name)) config.setClassFolder(classFolder); config.setScanPeriod(scanPeriod); config.setCompilationOptions(compilationOptions); - config.setTest(test); + config.setTest(test); } - + } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java index 7ab2f67..f42955b 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java @@ -14,80 +14,71 @@ /** * Alguna inspiración: http://groovy.codehaus.org/Groovy+Shell - * + * * @author jmarranz */ -public class JProxyShellInteractiveImpl extends JProxyShellImpl -{ +public class JProxyShellInteractiveImpl extends JProxyShellImpl { protected boolean test = false; @NotNull protected JProxyShellProcessor processor = new JProxyShellProcessor(this); @Nullable protected ClassDescriptorSourceScript classDescSourceScript; - - public void init(@NotNull String[] args) - { + + public void init(@NotNull String[] args) { this.classDescSourceScript = super.init(args, null); - if (test) - { + if (test) { processor.test(); return; } - + processor.loop(); - } - + } + @Nullable - public ClassDescriptorSourceScript getClassDescriptorSourceScript() - { + public ClassDescriptorSourceScript getClassDescriptorSourceScript() { return classDescSourceScript; } - + @NotNull - public SourceScriptRootInMemory getSourceScriptInMemory() - { - return (SourceScriptRootInMemory)classDescSourceScript.getSourceScript(); + public SourceScriptRootInMemory getSourceScriptInMemory() { + return (SourceScriptRootInMemory) classDescSourceScript.getSourceScript(); } - + @Nullable @Override - public ClassDescriptorSourceScript init(@NotNull JProxyConfigImpl config, SourceScriptRoot scriptFile, ClassLoader classLoader) - { - ClassDescriptorSourceScript script = super.init(config,scriptFile, classLoader); - + public ClassDescriptorSourceScript init(@NotNull JProxyConfigImpl config, SourceScriptRoot scriptFile, ClassLoader classLoader) { + ClassDescriptorSourceScript script = super.init(config, scriptFile, classLoader); + this.test = config.isTest(); - + return script; } - + @Override - protected void executeFirstTime(ClassDescriptorSourceScript scriptFileDesc,LinkedList argsToScript,JProxyShellClassLoader classLoader) - { + protected void executeFirstTime(ClassDescriptorSourceScript scriptFileDesc, LinkedList argsToScript, JProxyShellClassLoader classLoader) { // La primera vez el script es vacío, no hay nada que ejecutar - } - + } + @Override - protected void processConfigParams(@NotNull String[] args, @NotNull LinkedList argsToScript, @NotNull JProxyConfigImpl config) - { + protected void processConfigParams(@NotNull String[] args, @NotNull LinkedList argsToScript, @NotNull JProxyConfigImpl config) { super.processConfigParams(args, argsToScript, config); - + String classFolder = config.getClassFolder(); - if (classFolder != null && !classFolder.trim().isEmpty()) throw new RelProxyException("cacheClassFolder is useless to execute in interactive mode"); - } + if (classFolder != null && !classFolder.trim().isEmpty()) + throw new RelProxyException("cacheClassFolder is useless to execute in interactive mode"); + } @NotNull @Override - protected SourceScriptRoot createSourceScriptRoot(String[] args,LinkedList argsToScript,FolderSourceList folderSourceList) - { + protected SourceScriptRoot createSourceScriptRoot(String[] args, LinkedList argsToScript, FolderSourceList folderSourceList) { return SourceScriptRootInMemory.createSourceScriptInMemory(""); // La primera vez no hace nada, sirve para "calentar" la app - } - + } + @Nullable @Override - protected JProxyShellClassLoader getJProxyShellClassLoader(JProxyConfigImpl config) - { + protected JProxyShellClassLoader getJProxyShellClassLoader(JProxyConfigImpl config) { // No hay classFolder => no hay necesidad de nuevo ClassLoader - return null; - } + return null; + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java index 821fde7..ffc45c6 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java @@ -15,69 +15,59 @@ import java.util.LinkedList; /** - * * @author jmarranz */ -public class JProxyShellScriptFileImpl extends JProxyShellImpl -{ +public class JProxyShellScriptFileImpl extends JProxyShellImpl { protected FileExt scriptFile; - - public void init(@NotNull String[] args) - { + + public void init(@NotNull String[] args) { File scriptFile = new File(args[0]); - if (!scriptFile.exists()) + if (!scriptFile.exists()) throw new RelProxyException("File " + args[0] + " does not exist"); - + this.scriptFile = new FileExt(scriptFile); - + File parentDir = JProxyUtil.getParentDir(scriptFile); - String inputPath = parentDir.getAbsolutePath(); + String inputPath = parentDir.getAbsolutePath(); super.init(args, inputPath); - } - + } + @Override - protected void executeFirstTime(@NotNull ClassDescriptorSourceScript scriptFileDesc, @NotNull LinkedList argsToScript, JProxyShellClassLoader classLoader) - { - fixLastLoadedClass(scriptFileDesc,classLoader); - - try - { - scriptFileDesc.callMainMethod(argsToScript); - } - catch(Throwable ex) - { + protected void executeFirstTime(@NotNull ClassDescriptorSourceScript scriptFileDesc, @NotNull LinkedList argsToScript, JProxyShellClassLoader classLoader) { + fixLastLoadedClass(scriptFileDesc, classLoader); + + try { + scriptFileDesc.callMainMethod(argsToScript); + } catch (Throwable ex) { ex.printStackTrace(System.out); - } + } } - + @NotNull @Override - protected SourceScriptRoot createSourceScriptRoot(String[] args, LinkedList argsToScript, @NotNull FolderSourceList folderSourceList) - { - return SourceScriptRootFile.createSourceScriptRootFile(scriptFile,folderSourceList); - } - + protected SourceScriptRoot createSourceScriptRoot(String[] args, LinkedList argsToScript, @NotNull FolderSourceList folderSourceList) { + return SourceScriptRootFile.createSourceScriptRootFile(scriptFile, folderSourceList); + } + @Nullable @Override - protected JProxyShellClassLoader getJProxyShellClassLoader(@NotNull JProxyConfigImpl config) - { + protected JProxyShellClassLoader getJProxyShellClassLoader(@NotNull JProxyConfigImpl config) { String classFolder = config.getClassFolder(); if (classFolder != null) - return new JProxyShellClassLoader(getDefaultClassLoader(),new File(classFolder)); + return new JProxyShellClassLoader(getDefaultClassLoader(), new File(classFolder)); else return null; } - - protected void fixLastLoadedClass(@NotNull ClassDescriptorSourceScript scriptFileDesc, @Nullable JProxyShellClassLoader classLoader) - { + + protected void fixLastLoadedClass(@NotNull ClassDescriptorSourceScript scriptFileDesc, @Nullable JProxyShellClassLoader classLoader) { Class scriptClass = scriptFileDesc.getLastLoadedClass(); if (scriptClass != null) return; - + // Esto es esperable cuando especificamos un classFolder en donde está ya compilado el script lanzador y es más actual que el fuente // no ha habido necesidad de crear un class loader "reloader" ni de recargar todos los archivos fuente con él if (classLoader == null) throw new RelProxyException("INTERNAL ERROR"); if (scriptFileDesc.getClassBytes() == null) throw new RelProxyException("INTERNAL ERROR"); scriptClass = classLoader.defineClass(scriptFileDesc); - scriptFileDesc.setLastLoadedClass(scriptClass); + scriptFileDesc.setLastLoadedClass(scriptClass); } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/Command.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/Command.java index 06b0ebc..f331c17 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/Command.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/Command.java @@ -3,103 +3,77 @@ import org.jetbrains.annotations.NotNull; /** - * * @author jmarranz */ -public abstract class Command -{ - protected JProxyShellProcessor parent; +public abstract class Command { + protected JProxyShellProcessor parent; protected String name; - - public Command(JProxyShellProcessor parent,String name) - { + + public Command(JProxyShellProcessor parent, String name) { this.parent = parent; this.name = name; } - - public static Command createCommand(@NotNull JProxyShellProcessor parent, String cmd) - { + + public static Command createCommand(@NotNull JProxyShellProcessor parent, String cmd) { cmd = cmd.trim(); - if (cmd.equals("clear")) - { - return new CommandOther(parent,cmd); - } - else if (cmd.startsWith("delete")) - { - CommandDelete command = CommandDelete.createCommandDelete(parent,cmd); + if (cmd.equals("clear")) { + return new CommandOther(parent, cmd); + } else if (cmd.startsWith("delete")) { + CommandDelete command = CommandDelete.createCommandDelete(parent, cmd); if (command != null) return command; else - return new CommandError(parent); - } - else if (cmd.equals("display")) - { - return new CommandOther(parent,cmd); - } - else if (cmd.startsWith("edit")) - { - CommandEdit command = CommandEdit.createCommandEdit(parent,cmd); + return new CommandError(parent); + } else if (cmd.equals("display")) { + return new CommandOther(parent, cmd); + } else if (cmd.startsWith("edit")) { + CommandEdit command = CommandEdit.createCommandEdit(parent, cmd); if (command != null) return command; else - return new CommandError(parent); - } - else if (cmd.equals("exec")) - { - return new CommandOther(parent,cmd); - } - else if (cmd.equals("exit")) - { - return new CommandOther(parent,cmd); - } - else if (cmd.equals("help")) - { - return new CommandOther(parent,cmd); - } - else if (cmd.startsWith("insert")) - { - CommandInsert command = CommandInsert.createCommandInsert(parent,cmd); + return new CommandError(parent); + } else if (cmd.equals("exec")) { + return new CommandOther(parent, cmd); + } else if (cmd.equals("exit")) { + return new CommandOther(parent, cmd); + } else if (cmd.equals("help")) { + return new CommandOther(parent, cmd); + } else if (cmd.startsWith("insert")) { + CommandInsert command = CommandInsert.createCommandInsert(parent, cmd); if (command != null) return command; else - return new CommandError(parent); - } - else if (cmd.startsWith("load")) - { - CommandLoad command = CommandLoad.createCommandLoad(parent,cmd); + return new CommandError(parent); + } else if (cmd.startsWith("load")) { + CommandLoad command = CommandLoad.createCommandLoad(parent, cmd); if (command != null) return command; else - return new CommandError(parent); - } - else if (cmd.equals("quit")) - { - return new CommandOther(parent,cmd); - } - else if (cmd.startsWith("save")) - { - CommandSave command = CommandSave.createCommandSave(parent,cmd); + return new CommandError(parent); + } else if (cmd.equals("quit")) { + return new CommandOther(parent, cmd); + } else if (cmd.startsWith("save")) { + CommandSave command = CommandSave.createCommandSave(parent, cmd); if (command != null) return command; else - return new CommandError(parent); - } - + return new CommandError(parent); + } + return null; // No es un comando - } - - protected static String getParameter(String cmdName, @NotNull String cmd) - { + } + + protected static String getParameter(String cmdName, @NotNull String cmd) { int pos = cmd.indexOf(cmdName + " "); if (pos != 0) return null; - pos = cmd.indexOf(' '); + pos = cmd.indexOf(' '); String param = cmd.substring(pos + 1); - param = param.trim(); + param = param.trim(); return param; } - - public abstract boolean run(); - - public abstract void runPostCommand(); + + public abstract boolean run(); + + public abstract void runPostCommand(); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java index 3ecd2e3..522d2a0 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java @@ -4,79 +4,62 @@ import org.jetbrains.annotations.NotNull; /** - * * @author jmarranz */ -public abstract class CommandCodeChangerBase extends Command -{ +public abstract class CommandCodeChangerBase extends Command { public static final int ERROR_LAST_REQUIRED = -1; - public static final int ERROR_NO_LAST_LINE = -2; - public static final int ERROR_NOT_A_NUMBER = -3; - public static final int ERROR_VALUE_NOT_0_OR_NEGATIVE = -4; - public static final int ERROR_LINE_1_NOT_VALID = -5; - public static final int ERROR_OUT_OF_RANGE = -6; - - - protected int line; - - public CommandCodeChangerBase(JProxyShellProcessor parent,String name,int line) - { - super(parent,name); - this.line = line; - } - - public static int getLineFromParam(@NotNull JProxyShellProcessor parent, String name, @NotNull String cmd) - { - String param = getParameter(name,cmd); - if (param == null) - { + public static final int ERROR_NO_LAST_LINE = -2; + public static final int ERROR_NOT_A_NUMBER = -3; + public static final int ERROR_VALUE_NOT_0_OR_NEGATIVE = -4; + public static final int ERROR_LINE_1_NOT_VALID = -5; + public static final int ERROR_OUT_OF_RANGE = -6; + + + protected int line; + + public CommandCodeChangerBase(JProxyShellProcessor parent, String name, int line) { + super(parent, name); + this.line = line; + } + + public static int getLineFromParam(@NotNull JProxyShellProcessor parent, String name, @NotNull String cmd) { + String param = getParameter(name, cmd); + if (param == null) { return ERROR_LAST_REQUIRED; - } + } int line; - if (param.equals("last")) - { + if (param.equals("last")) { int lastLine = parent.getLastLine(); - if (lastLine == -1) - { + if (lastLine == -1) { return ERROR_NO_LAST_LINE; } line = lastLine; - } - else - { - try - { - line = Integer.parseInt(param); - } - catch(NumberFormatException ex) - { + } else { + try { + line = Integer.parseInt(param); + } catch (NumberFormatException ex) { return ERROR_NOT_A_NUMBER; } // Ojo es el valor dado por el usuario (empezando en 1 y con línea vacía) - if (line <= 0) - { + if (line <= 0) { return ERROR_VALUE_NOT_0_OR_NEGATIVE; - } - else if (line == 1) - { + } else if (line == 1) { return ERROR_LINE_1_NOT_VALID; } - line -= JProxyShellProcessor.LINE_OFFSET; + line -= JProxyShellProcessor.LINE_OFFSET; - if (line >= parent.getCodeBuffer().size()) - { + if (line >= parent.getCodeBuffer().size()) { return ERROR_OUT_OF_RANGE; } - } + } return line; } - - + + @Override - public boolean run() - { + public boolean run() { return true; - } + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandDelete.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandDelete.java index 956501f..8b7331f 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandDelete.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandDelete.java @@ -4,55 +4,48 @@ import org.jetbrains.annotations.NotNull; /** - * * @author jmarranz */ -public class CommandDelete extends CommandCodeChangerBase -{ - public static final String NAME = "delete"; - - public CommandDelete(JProxyShellProcessor parent,int line) - { - super(parent,NAME,line); - } - - public static CommandDelete createCommandDelete(@NotNull JProxyShellProcessor parent, @NotNull String cmd) - { - int line = getLineFromParam(parent,NAME,cmd); - if (line < 0) - { - switch(line) - { - case ERROR_LAST_REQUIRED: +public class CommandDelete extends CommandCodeChangerBase { + public static final String NAME = "delete"; + + public CommandDelete(JProxyShellProcessor parent, int line) { + super(parent, NAME, line); + } + + public static CommandDelete createCommandDelete(@NotNull JProxyShellProcessor parent, @NotNull String cmd) { + int line = getLineFromParam(parent, NAME, cmd); + if (line < 0) { + switch (line) { + case ERROR_LAST_REQUIRED: System.out.println("Command error: parameter \"last\" or a line number is required"); break; case ERROR_NO_LAST_LINE: System.out.println("Command error: no new or edited line code has been introduced"); break; case ERROR_NOT_A_NUMBER: - System.out.println("Command error: line value is not a number"); - break; + System.out.println("Command error: line value is not a number"); + break; case ERROR_VALUE_NOT_0_OR_NEGATIVE: - System.out.println("Command error: line value cannot be 0 or negative"); - break; + System.out.println("Command error: line value cannot be 0 or negative"); + break; case ERROR_LINE_1_NOT_VALID: - System.out.println("Command error: line 1 is ever empty and cannot be deleted"); - break; + System.out.println("Command error: line 1 is ever empty and cannot be deleted"); + break; case ERROR_OUT_OF_RANGE: - System.out.println("Command error: line number out of range"); - break; + System.out.println("Command error: line number out of range"); + break; default: // Para que se calle el FindBugs } return null; } - - return new CommandDelete(parent,line); + + return new CommandDelete(parent, line); } - + @Override - public void runPostCommand() - { + public void runPostCommand() { parent.removeCodeBuffer(line); } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandEdit.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandEdit.java index 6ddb775..5aeb53b 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandEdit.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandEdit.java @@ -4,58 +4,51 @@ import org.jetbrains.annotations.NotNull; /** - * * @author jmarranz */ -public class CommandEdit extends CommandCodeChangerBase -{ +public class CommandEdit extends CommandCodeChangerBase { public static final String NAME = "edit"; - protected String codeLine; - - public CommandEdit(JProxyShellProcessor parent,int line,String codeLine) - { - super(parent,NAME,line); - this.codeLine = codeLine; - } - - public static CommandEdit createCommandEdit(@NotNull JProxyShellProcessor parent, @NotNull String cmd) - { - int line = getLineFromParam(parent,NAME,cmd); - if (line < 0) - { - switch(line) - { - case ERROR_LAST_REQUIRED: + protected String codeLine; + + public CommandEdit(JProxyShellProcessor parent, int line, String codeLine) { + super(parent, NAME, line); + this.codeLine = codeLine; + } + + public static CommandEdit createCommandEdit(@NotNull JProxyShellProcessor parent, @NotNull String cmd) { + int line = getLineFromParam(parent, NAME, cmd); + if (line < 0) { + switch (line) { + case ERROR_LAST_REQUIRED: System.out.println("Command error: parameter \"last\" or a line number is required"); break; case ERROR_NO_LAST_LINE: - System.out.println("Command error: no new or edited line code has been introduced"); + System.out.println("Command error: no new or edited line code has been introduced"); break; case ERROR_NOT_A_NUMBER: - System.out.println("Command error: line value is not a number"); - break; + System.out.println("Command error: line value is not a number"); + break; case ERROR_VALUE_NOT_0_OR_NEGATIVE: - System.out.println("Command error: line value cannot be 0 or negative"); - break; + System.out.println("Command error: line value cannot be 0 or negative"); + break; case ERROR_LINE_1_NOT_VALID: - System.out.println("Command error: line 1 is ever empty and cannot be edited"); - break; + System.out.println("Command error: line 1 is ever empty and cannot be edited"); + break; case ERROR_OUT_OF_RANGE: - System.out.println("Command error: line number out of range"); - break; + System.out.println("Command error: line number out of range"); + break; default: // Para que se calle el FindBugs } return null; - } - - String codeLine = parent.getCodeBuffer().get(line); - return new CommandEdit(parent,line,codeLine); + } + + String codeLine = parent.getCodeBuffer().get(line); + return new CommandEdit(parent, line, codeLine); } - + @Override - public void runPostCommand() - { + public void runPostCommand() { parent.getKeyboard().type(codeLine); parent.setLineEditing(line); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandError.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandError.java index 2c7480e..58a14c8 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandError.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandError.java @@ -1,25 +1,20 @@ package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; /** - * * @author jmarranz */ -public class CommandError extends Command -{ - public CommandError(JProxyShellProcessor parent) - { +public class CommandError extends Command { + public CommandError(JProxyShellProcessor parent) { super(parent, "ERROR"); } @Override - public boolean run() - { + public boolean run() { return false; } @Override - public void runPostCommand() - { + public void runPostCommand() { } - + } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandInsert.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandInsert.java index 5fe5983..79a7245 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandInsert.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandInsert.java @@ -4,56 +4,49 @@ import org.jetbrains.annotations.NotNull; /** - * * @author jmarranz */ -public class CommandInsert extends CommandCodeChangerBase -{ - public static final String NAME = "insert"; - - public CommandInsert(JProxyShellProcessor parent,int line) - { - super(parent,NAME,line); - } - - public static CommandInsert createCommandInsert(@NotNull JProxyShellProcessor parent, @NotNull String cmd) - { - int line = getLineFromParam(parent,NAME,cmd); - if (line < 0) - { - switch(line) - { - case ERROR_LAST_REQUIRED: +public class CommandInsert extends CommandCodeChangerBase { + public static final String NAME = "insert"; + + public CommandInsert(JProxyShellProcessor parent, int line) { + super(parent, NAME, line); + } + + public static CommandInsert createCommandInsert(@NotNull JProxyShellProcessor parent, @NotNull String cmd) { + int line = getLineFromParam(parent, NAME, cmd); + if (line < 0) { + switch (line) { + case ERROR_LAST_REQUIRED: System.out.println("Command error: parameter \"last\" or a line number is required"); break; case ERROR_NO_LAST_LINE: System.out.println("Command error: no new or edited line code has been introduced"); break; case ERROR_NOT_A_NUMBER: - System.out.println("Command error: line value is not a number"); - break; + System.out.println("Command error: line value is not a number"); + break; case ERROR_VALUE_NOT_0_OR_NEGATIVE: - System.out.println("Command error: line value cannot be 0 or negative"); - break; + System.out.println("Command error: line value cannot be 0 or negative"); + break; case ERROR_LINE_1_NOT_VALID: - System.out.println("Command error: line 1 is ever empty and no code can be inserted before"); - break; + System.out.println("Command error: line 1 is ever empty and no code can be inserted before"); + break; case ERROR_OUT_OF_RANGE: - System.out.println("Command error: line number out of range"); - break; + System.out.println("Command error: line number out of range"); + break; default: - // Para que se calle el FindBugs + // Para que se calle el FindBugs } return null; - } - - return new CommandInsert(parent,line); + } + + return new CommandInsert(parent, line); } - + @Override - public void runPostCommand() - { - parent.insertCodeBuffer(line,""); + public void runPostCommand() { + parent.insertCodeBuffer(line, ""); parent.setLineEditing(line); } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandLoad.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandLoad.java index 7afdaf0..e3c2227 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandLoad.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandLoad.java @@ -10,71 +10,59 @@ import java.util.Scanner; /** - * * @author jmarranz */ -public class CommandLoad extends Command -{ +public class CommandLoad extends Command { public static final String NAME = "load"; - protected String url; - - public CommandLoad(JProxyShellProcessor parent,String url) - { - super(parent,NAME); - this.url = url; - } - - public static CommandLoad createCommandLoad(JProxyShellProcessor parent, @NotNull String cmd) - { - String url = getParameter(NAME,cmd); - if (url == null) - { + protected String url; + + public CommandLoad(JProxyShellProcessor parent, String url) { + super(parent, NAME); + this.url = url; + } + + public static CommandLoad createCommandLoad(JProxyShellProcessor parent, @NotNull String cmd) { + String url = getParameter(NAME, cmd); + if (url == null) { System.out.println("Command error: parameter is required"); return null; } - return new CommandLoad(parent,url); + return new CommandLoad(parent, url); } - + @Override - public boolean run() - { - try - { + public boolean run() { + try { byte[] content; URI uri = new URI(url); if (uri.getScheme() == null) // Archivo { File file = new File(url); content = JProxyUtil.readFile(file); - } - else // URL (incluyendo file:///...) + } else // URL (incluyendo file:///...) { URL urlObj = new URL(url); content = JProxyUtil.readURL(urlObj); // Como no conocemos encoding... } - String code = new String(content,parent.getEncoding()); // Como no conocemos encoding... + String code = new String(content, parent.getEncoding()); // Como no conocemos encoding... LinkedList lines = new LinkedList(); Scanner scanner = new Scanner(code); - while (scanner.hasNextLine()) - { + while (scanner.hasNextLine()) { String line = scanner.nextLine(); lines.add(line); - } - + } + parent.setCodeBuffer(lines); return true; - } - catch (Exception ex) - { + } catch (Exception ex) { ex.printStackTrace(); return false; } - } - + } + @Override - public void runPostCommand() - { + public void runPostCommand() { } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandOther.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandOther.java index e93c5e4..cbca514 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandOther.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandOther.java @@ -4,107 +4,84 @@ import com.sillelien.dollar.relproxy.RelProxyException; /** - * * @author jmarranz */ -public class CommandOther extends Command -{ - public CommandOther(JProxyShellProcessor parent,String name) - { - super(parent,name); - } - +public class CommandOther extends Command { + public CommandOther(JProxyShellProcessor parent, String name) { + super(parent, name); + } + @Override - public boolean run() - { - if (name.equals("clear")) - { + public boolean run() { + if (name.equals("clear")) { commandClear(); - } - else if (name.equals("display")) - { + } else if (name.equals("display")) { commandDisplay(); - } - else if (name.equals("exec")) - { + } else if (name.equals("exec")) { commandExec(); - } - else if (name.equals("exit")) - { + } else if (name.equals("exit")) { commandExit(); - } - else if (name.equals("help")) - { + } else if (name.equals("help")) { commandHelp(); - } - else if (name.equals("quit")) - { + } else if (name.equals("quit")) { commandExit(); - } - else throw new RelProxyException("Internal Error"); - + } else throw new RelProxyException("Internal Error"); + return true; - } - + } + @Override - public void runPostCommand() - { + public void runPostCommand() { } - - private void commandClear() - { + + private void commandClear() { parent.clearCodeBuffer(); } - - private void commandExit() - { + + private void commandExit() { System.exit(0); - } - - private void commandDisplay() - { + } + + private void commandDisplay() { System.out.println("001>"); // La primera línea es siempre vacía porque en ella es donde ponemos el "public class /_jproxyShellInMemoryClass_ { " que el usuario ignora, así al dar error el número de línea será correcto respecto al "display" - + int i = 2; - for(String line : parent.getCodeBuffer()) - { - for(int j = 0; j < 3 - String.valueOf(i).length(); j++) System.out.print("0"); + for (String line : parent.getCodeBuffer()) { + for (int j = 0; j < 3 - String.valueOf(i).length(); j++) System.out.print("0"); System.out.print(i + ">"); - System.out.print(line); - System.out.println(); + System.out.print(line); + System.out.println(); i++; - } + } } - - private void commandExec() - { - parent.executeCodeBuffer(); - } - - private void commandHelp() - { + + private void commandExec() { + parent.executeCodeBuffer(); + } + + private void commandHelp() { System.out.println("Everything you write in the prompt is added to a code buffer, code buffer is compiled on the fly and executed by exec command, unless a command is detected"); - System.out.println(""); + System.out.println(""); System.out.println("Available commands:"); - System.out.println(" clear"); - System.out.println(" Clears the buffer"); - System.out.println(" display"); - System.out.println(" Shows the buffer content"); - System.out.println(" edit last | "); - System.out.println(" Edits the last introduced line code or the specified line number"); - System.out.println(" exec"); - System.out.println(" Compile and execute the buffer content"); - System.out.println(" exit"); - System.out.println(" Exits shell"); - System.out.println(" help"); - System.out.println(" This command"); - System.out.println(" insert last | "); - System.out.println(" Insert the next line of code before the last introduced line or the specified line number"); - System.out.println(" load | "); - System.out.println(" Load a file or URL into the buffer"); - System.out.println(" quit"); - System.out.println(" Same as exit"); - System.out.println(" save "); - System.out.println(" Save the current buffer to a file"); - } + System.out.println(" clear"); + System.out.println(" Clears the buffer"); + System.out.println(" display"); + System.out.println(" Shows the buffer content"); + System.out.println(" edit last | "); + System.out.println(" Edits the last introduced line code or the specified line number"); + System.out.println(" exec"); + System.out.println(" Compile and execute the buffer content"); + System.out.println(" exit"); + System.out.println(" Exits shell"); + System.out.println(" help"); + System.out.println(" This command"); + System.out.println(" insert last | "); + System.out.println(" Insert the next line of code before the last introduced line or the specified line number"); + System.out.println(" load | "); + System.out.println(" Load a file or URL into the buffer"); + System.out.println(" quit"); + System.out.println(" Same as exit"); + System.out.println(" save "); + System.out.println(" Save the current buffer to a file"); + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandSave.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandSave.java index 5797667..ff47a30 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandSave.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandSave.java @@ -7,57 +7,46 @@ import java.util.List; /** - * * @author jmarranz */ -public class CommandSave extends Command -{ +public class CommandSave extends Command { public static final String NAME = "save"; - protected String path; - - public CommandSave(JProxyShellProcessor parent,String url) - { - super(parent,NAME); - this.path = url; - } - - public static CommandSave createCommandSave(JProxyShellProcessor parent, @NotNull String cmd) - { - String url = getParameter(NAME,cmd); - if (url == null) - { + protected String path; + + public CommandSave(JProxyShellProcessor parent, String url) { + super(parent, NAME); + this.path = url; + } + + public static CommandSave createCommandSave(JProxyShellProcessor parent, @NotNull String cmd) { + String url = getParameter(NAME, cmd); + if (url == null) { System.out.println("Command error: parameter is required"); return null; } - return new CommandSave(parent,url); + return new CommandSave(parent, url); } - + @Override - public boolean run() - { - try - { + public boolean run() { + try { List codeBuffer = parent.getCodeBuffer(); StringBuilder code = new StringBuilder(); - for(String line : codeBuffer) - { + for (String line : codeBuffer) { code.append(line); - code.append("\n"); + code.append("\n"); } byte[] content = code.toString().getBytes(parent.getEncoding()); // Como no conocemos encoding... - JProxyUtil.saveFile(new File(path),content); + JProxyUtil.saveFile(new File(path), content); return true; - } - catch (Exception ex) - { + } catch (Exception ex) { ex.printStackTrace(); return false; } - } - + } + @Override - public void runPostCommand() - { + public void runPostCommand() { } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java index 488b0d4..6950806 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java @@ -16,13 +16,11 @@ import java.util.Scanner; /** - * * @author jmarranz */ -public class JProxyShellProcessor -{ +public class JProxyShellProcessor { public static final int LINE_OFFSET = 2; // El índice en codeBuffer + este valor = al valor de la línea que se muestra al usuario, hay que tener en cuenta que contamos desde uno y la primera línea es siempre vacía - + protected JProxyShellInteractiveImpl parent; @NotNull protected Charset encoding = Charset.defaultCharset(); @@ -32,192 +30,166 @@ public class JProxyShellProcessor protected Keyboard keyboard = KeyboardNotUsingClipboard.create(encoding); protected int lastLine = -1; // Indice respecto a codeBuffer protected int lineEditing = -1; // Indice respecto a codeBuffer - protected long codeBufferModTimestamp = 0; - protected long lastCodeCompiledTimestamp = 0; - - public JProxyShellProcessor(JProxyShellInteractiveImpl parent) - { + protected long codeBufferModTimestamp = 0; + protected long lastCodeCompiledTimestamp = 0; + + public JProxyShellProcessor(JProxyShellInteractiveImpl parent) { this.parent = parent; } - + @NotNull - public Keyboard getKeyboard() - { + public Keyboard getKeyboard() { return keyboard; } - + @NotNull - public Charset getEncoding() - { + public Charset getEncoding() { return encoding; } - - public int getLastLine() - { + + public int getLastLine() { return lastLine; } - - public void setLineEditing(int lineEditing) - { + + public void setLineEditing(int lineEditing) { this.lineEditing = lineEditing; } - - public void test() - { - try { Thread.sleep(2); } catch (InterruptedException ex){ } + + public void test() { + try { + Thread.sleep(2); + } catch (InterruptedException ex) { + } execute("System.out.println(\"Hello World\");"); // "Object o = null; o.equals(null);" } - - public void loop() - { + + public void loop() { System.out.println("RelProxy Java Shell v" + RelProxy.getVersion()); System.out.println("Write help for help"); - - Scanner sc = new Scanner(System.in,encoding.name()); // No encuentro nada interesante en http://docs.oracle.com/javase/6/docs/api/java/io/Console.html - System.out.print(">"); - while(true) - { + + Scanner sc = new Scanner(System.in, encoding.name()); // No encuentro nada interesante en http://docs.oracle.com/javase/6/docs/api/java/io/Console.html + System.out.print(">"); + while (true) { String line = sc.nextLine(); - Command command = Command.createCommand(this,line); - if (command != null) - { + Command command = Command.createCommand(this, line); + if (command != null) { if (command instanceof CommandError) // Era un comando pero con params erróneos { // Nada que hacer - System.out.print(">"); - } - else - { + System.out.print(">"); + } else { boolean success = command.run(); - System.out.print(">"); + System.out.print(">"); - if (success) - { + if (success) { command.runPostCommand(); // Lo normal es que no haga nada } } - } - else - { - if (lineEditing != -1) - { - setCodeBuffer(lineEditing, line); + } else { + if (lineEditing != -1) { + setCodeBuffer(lineEditing, line); this.lineEditing = -1; + } else { + addCodeBuffer(line); } - else - { - addCodeBuffer(line); - } - - System.out.print(">"); + + System.out.print(">"); } } - } - + } + @NotNull - public List getCodeBuffer() - { + public List getCodeBuffer() { return Collections.unmodifiableList(codeBuffer); - } - - public void setCodeBuffer(int index,String line) - { - codeBuffer.set(index, line); + } + + public void setCodeBuffer(int index, String line) { + codeBuffer.set(index, line); this.codeBufferModTimestamp = System.currentTimeMillis(); - this.lastLine = index; + this.lastLine = index; } - - public void setCodeBuffer(@NotNull LinkedList codeBuffer) - { + + public void setCodeBuffer(@NotNull LinkedList codeBuffer) { codeBuffer.clear(); - this.codeBuffer.addAll(codeBuffer); + this.codeBuffer.addAll(codeBuffer); this.codeBufferModTimestamp = System.currentTimeMillis(); - this.lastLine = codeBuffer.size() - 1; - } - - public void insertCodeBuffer(int index,String line) - { + this.lastLine = codeBuffer.size() - 1; + } + + public void insertCodeBuffer(int index, String line) { codeBuffer.add(index, line); this.codeBufferModTimestamp = System.currentTimeMillis(); - this.lastLine = index; - } - - public void addCodeBuffer(String line) - { - codeBuffer.add(line); + this.lastLine = index; + } + + public void addCodeBuffer(String line) { + codeBuffer.add(line); this.codeBufferModTimestamp = System.currentTimeMillis(); - this.lastLine = codeBuffer.size() - 1; - } - - public void removeCodeBuffer(int index) - { + this.lastLine = codeBuffer.size() - 1; + } + + public void removeCodeBuffer(int index) { codeBuffer.remove(index); this.codeBufferModTimestamp = System.currentTimeMillis(); this.lastLine = -1; // La hemos eliminado, no existe ya - } - - public void clearCodeBuffer() - { - codeBuffer.clear(); + } + + public void clearCodeBuffer() { + codeBuffer.clear(); this.codeBufferModTimestamp = System.currentTimeMillis(); - this.lastLine = - 1; - } - - public void executeCodeBuffer() - { + this.lastLine = -1; + } + + public void executeCodeBuffer() { StringBuilder code = new StringBuilder(); - for(String line : codeBuffer) - { + for (String line : codeBuffer) { code.append(line); - code.append("\n"); - } + code.append("\n"); + } execute(code.toString()); } - - private void execute(String code) - { + + private void execute(String code) { // Este código no es thread safe ni falta que hace. - + ClassDescriptorSourceScript classDescSourceScript = parent.getClassDescriptorSourceScript(); - + if (codeBufferModTimestamp > lastCodeCompiledTimestamp) // Incluimos el = por si acaso va todo muy seguido { - parent.getSourceScriptInMemory().setScriptCode(code,codeBufferModTimestamp); + parent.getSourceScriptInMemory().setScriptCode(code, codeBufferModTimestamp); // Recuerda que cada vez que se obtiene el timestamp se llama a System.currentTimeMillis(), es imposible que el usuario haga algo en menos de 1ms JProxyEngine engine = parent.getJProxyEngine(); ClassDescriptorSourceScript classDescSourceScript2 = null; - try - { + try { classDescSourceScript2 = engine.detectChangesInSourcesAndReload(); - } - catch(JProxyCompilationException ex) - { + } catch (JProxyCompilationException ex) { System.out.println("Compilation error"); return; } if (classDescSourceScript2 != classDescSourceScript) throw new RelProxyException("Internal Error"); - - this.lastCodeCompiledTimestamp = System.currentTimeMillis(); + + this.lastCodeCompiledTimestamp = System.currentTimeMillis(); if (lastCodeCompiledTimestamp == codeBufferModTimestamp) // Demasiado rápido compilando { // El ser humano es muy raro y es posible que a alguien se le ocurra usar el shell de forma automatizada y se genere un siguiente cambio en el // código fuente tan rápido que no cambie el ms, así nos aseguramos con total rotundidad que la modificación posterior de código fuente su timestamp es MAYOR que el de compilación último - try { Thread.sleep(1); } catch (InterruptedException ex) { throw new RelProxyException(ex); } + try { + Thread.sleep(1); + } catch (InterruptedException ex) { + throw new RelProxyException(ex); + } } } - - try - { - classDescSourceScript.callMainMethod(new LinkedList()); - } - catch(Throwable ex) - { + + try { + classDescSourceScript.callMainMethod(new LinkedList()); + } catch (Throwable ex) { ex.printStackTrace(System.out); } - } + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/Keyboard.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/Keyboard.java index b1cb22a..056f6fc 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/Keyboard.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/Keyboard.java @@ -3,23 +3,19 @@ import java.nio.charset.Charset; /** - * * @author jmarranz */ -public abstract class Keyboard -{ +public abstract class Keyboard { public abstract void type(CharSequence characters); - - public static Keyboard create(Charset cs) - { + + public static Keyboard create(Charset cs) { return KeyboardUsingClipboard.create(cs); //return KeyboardNotUsingClipboard.create(cs); - } - - public static void test(String arg) - { - Charset charset = Charset.defaultCharset(); - Keyboard kbd = create(charset); - kbd.type(arg); - } + } + + public static void test(String arg) { + Charset charset = Charset.defaultCharset(); + Keyboard kbd = create(charset); + kbd.type(arg); + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java index 1214e86..4f324a8 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java @@ -6,6 +6,7 @@ import java.awt.AWTException; import java.awt.Robot; + import static java.awt.event.KeyEvent.VK_0; import static java.awt.event.KeyEvent.VK_1; import static java.awt.event.KeyEvent.VK_2; @@ -54,6 +55,7 @@ import static java.awt.event.KeyEvent.VK_X; import static java.awt.event.KeyEvent.VK_Y; import static java.awt.event.KeyEvent.VK_Z; + import java.nio.ByteBuffer; import java.nio.charset.Charset; @@ -61,100 +63,107 @@ * http://stackoverflow.com/questions/1248510/convert-string-to-keyevents * http://en.wikipedia.org/wiki/Unicode_input#Hexadecimal_code_input * http://stackoverflow.com/questions/9814701/accent-with-robot-keypress - * + * * @author jmarranz */ -public abstract class KeyboardNotUsingClipboard extends Keyboard -{ +public abstract class KeyboardNotUsingClipboard extends Keyboard { @NotNull protected final Robot robot; protected Charset cs; - - - public KeyboardNotUsingClipboard(Charset cs) - { + + public KeyboardNotUsingClipboard(Charset cs) { this.cs = cs; - try - { + try { this.robot = new Robot(); - } - catch (AWTException ex) - { + } catch (AWTException ex) { throw new RelProxyException(ex); } } - public static KeyboardNotUsingClipboard create(Charset cs) - { + public static KeyboardNotUsingClipboard create(Charset cs) { String osName = System.getProperty("os.name").toLowerCase(); if (osName.contains("windows")) return new WindowUnicodeKeyboard(cs); - else if (osName.contains("os x")) return new MacOSXUnicodeKeyboard(cs);// https://developer.apple.com/library/mac/technotes/tn2002/tn2110.html + else if (osName.contains("os x")) + return new MacOSXUnicodeKeyboard(cs);// https://developer.apple.com/library/mac/technotes/tn2002/tn2110.html else return new LinuxUnicodeKeyboard(cs); - } + } @NotNull - private int[] getUnicodeInt(char character) - { - if (isUseCodePoint()) - { - char[] charArray = new char[]{character}; - int count = Character.codePointCount(charArray, 0,charArray.length); - int[] res = new int[count]; - for(int i = 0; i < count; i++) - res[i] = Character.codePointAt(charArray,i); - return res; - } - else - { + private int[] getUnicodeInt(char character) { + if (isUseCodePoint()) { + char[] charArray = new char[]{character}; + int count = Character.codePointCount(charArray, 0, charArray.length); + int[] res = new int[count]; + for (int i = 0; i < count; i++) + res[i] = Character.codePointAt(charArray, i); + return res; + } else { ByteBuffer buffer = cs.encode("" + character); int size = buffer.limit(); int[] res = new int[size]; - for(int i = 0; i < size; i++) - { - byte b = buffer.get(); - int bi = b & 0x000000FF; - res[i] = bi; + for (int i = 0; i < size; i++) { + byte b = buffer.get(); + int bi = b & 0x000000FF; + res[i] = bi; } return res; } } - + @NotNull - protected String getUnicodeDigits(char character, int radix) - { + protected String getUnicodeDigits(char character, int radix) { int[] uds = getUnicodeInt(character); StringBuilder res = new StringBuilder(); - for(int i = 0; i < uds.length; i++) - { - int ud = uds[i]; - String digits; - if (radix == 10) - digits = Integer.toString(ud); - else - digits = Integer.toString(ud,radix); // Si es 16 es hexadecimal - res.append(digits); + for (int i = 0; i < uds.length; i++) { + int ud = uds[i]; + String digits; + if (radix == 10) + digits = Integer.toString(ud); + else + digits = Integer.toString(ud, radix); // Si es 16 es hexadecimal + res.append(digits); } return res.toString(); - } + } protected void typeNumPad(int digit) { switch (digit) { - case 0: doType(VK_NUMPAD0); break; - case 1: doType(VK_NUMPAD1); break; - case 2: doType(VK_NUMPAD2); break; - case 3: doType(VK_NUMPAD3); break; - case 4: doType(VK_NUMPAD4); break; - case 5: doType(VK_NUMPAD5); break; - case 6: doType(VK_NUMPAD6); break; - case 7: doType(VK_NUMPAD7); break; - case 8: doType(VK_NUMPAD8); break; - case 9: doType(VK_NUMPAD9); break; - default: // Para que se calle el FindBugs + case 0: + doType(VK_NUMPAD0); + break; + case 1: + doType(VK_NUMPAD1); + break; + case 2: + doType(VK_NUMPAD2); + break; + case 3: + doType(VK_NUMPAD3); + break; + case 4: + doType(VK_NUMPAD4); + break; + case 5: + doType(VK_NUMPAD5); + break; + case 6: + doType(VK_NUMPAD6); + break; + case 7: + doType(VK_NUMPAD7); + break; + case 8: + doType(VK_NUMPAD8); + break; + case 9: + doType(VK_NUMPAD9); + break; + default: // Para que se calle el FindBugs } - } - - + } + + public void type(@NotNull CharSequence characters) { int length = characters.length(); for (int i = 0; i < length; i++) { @@ -164,75 +173,199 @@ public void type(@NotNull CharSequence characters) { } public boolean type(char character) { - + // He quitado todos los símbolos que son susceptibles de cambiar según el teclado pues hay que acertar exactamente la combinación de teclas del teclado // concreto o da error, ej no vale emitir VK_COLON únicamente si en el teclado concreto es necesario un SHIFT // En la clase derivada se procesan los caracteres no contemplados aquí - + switch (character) { - case 'a': doType(VK_A); break; - case 'b': doType(VK_B); break; - case 'c': doType(VK_C); break; - case 'd': doType(VK_D); break; - case 'e': doType(VK_E); break; - case 'f': doType(VK_F); break; - case 'g': doType(VK_G); break; - case 'h': doType(VK_H); break; - case 'i': doType(VK_I); break; - case 'j': doType(VK_J); break; - case 'k': doType(VK_K); break; - case 'l': doType(VK_L); break; - case 'm': doType(VK_M); break; - case 'n': doType(VK_N); break; - case 'o': doType(VK_O); break; - case 'p': doType(VK_P); break; - case 'q': doType(VK_Q); break; - case 'r': doType(VK_R); break; - case 's': doType(VK_S); break; - case 't': doType(VK_T); break; - case 'u': doType(VK_U); break; - case 'v': doType(VK_V); break; - case 'w': doType(VK_W); break; - case 'x': doType(VK_X); break; - case 'y': doType(VK_Y); break; - case 'z': doType(VK_Z); break; - case 'A': doType(VK_SHIFT, VK_A); break; - case 'B': doType(VK_SHIFT, VK_B); break; - case 'C': doType(VK_SHIFT, VK_C); break; - case 'D': doType(VK_SHIFT, VK_D); break; - case 'E': doType(VK_SHIFT, VK_E); break; - case 'F': doType(VK_SHIFT, VK_F); break; - case 'G': doType(VK_SHIFT, VK_G); break; - case 'H': doType(VK_SHIFT, VK_H); break; - case 'I': doType(VK_SHIFT, VK_I); break; - case 'J': doType(VK_SHIFT, VK_J); break; - case 'K': doType(VK_SHIFT, VK_K); break; - case 'L': doType(VK_SHIFT, VK_L); break; - case 'M': doType(VK_SHIFT, VK_M); break; - case 'N': doType(VK_SHIFT, VK_N); break; - case 'O': doType(VK_SHIFT, VK_O); break; - case 'P': doType(VK_SHIFT, VK_P); break; - case 'Q': doType(VK_SHIFT, VK_Q); break; - case 'R': doType(VK_SHIFT, VK_R); break; - case 'S': doType(VK_SHIFT, VK_S); break; - case 'T': doType(VK_SHIFT, VK_T); break; - case 'U': doType(VK_SHIFT, VK_U); break; - case 'V': doType(VK_SHIFT, VK_V); break; - case 'W': doType(VK_SHIFT, VK_W); break; - case 'X': doType(VK_SHIFT, VK_X); break; - case 'Y': doType(VK_SHIFT, VK_Y); break; - case 'Z': doType(VK_SHIFT, VK_Z); break; - // case '`': doType(VK_BACK_QUOTE); break; - case '0': doType(VK_0); break; - case '1': doType(VK_1); break; - case '2': doType(VK_2); break; - case '3': doType(VK_3); break; - case '4': doType(VK_4); break; - case '5': doType(VK_5); break; - case '6': doType(VK_6); break; - case '7': doType(VK_7); break; - case '8': doType(VK_8); break; - case '9': doType(VK_9); break; + case 'a': + doType(VK_A); + break; + case 'b': + doType(VK_B); + break; + case 'c': + doType(VK_C); + break; + case 'd': + doType(VK_D); + break; + case 'e': + doType(VK_E); + break; + case 'f': + doType(VK_F); + break; + case 'g': + doType(VK_G); + break; + case 'h': + doType(VK_H); + break; + case 'i': + doType(VK_I); + break; + case 'j': + doType(VK_J); + break; + case 'k': + doType(VK_K); + break; + case 'l': + doType(VK_L); + break; + case 'm': + doType(VK_M); + break; + case 'n': + doType(VK_N); + break; + case 'o': + doType(VK_O); + break; + case 'p': + doType(VK_P); + break; + case 'q': + doType(VK_Q); + break; + case 'r': + doType(VK_R); + break; + case 's': + doType(VK_S); + break; + case 't': + doType(VK_T); + break; + case 'u': + doType(VK_U); + break; + case 'v': + doType(VK_V); + break; + case 'w': + doType(VK_W); + break; + case 'x': + doType(VK_X); + break; + case 'y': + doType(VK_Y); + break; + case 'z': + doType(VK_Z); + break; + case 'A': + doType(VK_SHIFT, VK_A); + break; + case 'B': + doType(VK_SHIFT, VK_B); + break; + case 'C': + doType(VK_SHIFT, VK_C); + break; + case 'D': + doType(VK_SHIFT, VK_D); + break; + case 'E': + doType(VK_SHIFT, VK_E); + break; + case 'F': + doType(VK_SHIFT, VK_F); + break; + case 'G': + doType(VK_SHIFT, VK_G); + break; + case 'H': + doType(VK_SHIFT, VK_H); + break; + case 'I': + doType(VK_SHIFT, VK_I); + break; + case 'J': + doType(VK_SHIFT, VK_J); + break; + case 'K': + doType(VK_SHIFT, VK_K); + break; + case 'L': + doType(VK_SHIFT, VK_L); + break; + case 'M': + doType(VK_SHIFT, VK_M); + break; + case 'N': + doType(VK_SHIFT, VK_N); + break; + case 'O': + doType(VK_SHIFT, VK_O); + break; + case 'P': + doType(VK_SHIFT, VK_P); + break; + case 'Q': + doType(VK_SHIFT, VK_Q); + break; + case 'R': + doType(VK_SHIFT, VK_R); + break; + case 'S': + doType(VK_SHIFT, VK_S); + break; + case 'T': + doType(VK_SHIFT, VK_T); + break; + case 'U': + doType(VK_SHIFT, VK_U); + break; + case 'V': + doType(VK_SHIFT, VK_V); + break; + case 'W': + doType(VK_SHIFT, VK_W); + break; + case 'X': + doType(VK_SHIFT, VK_X); + break; + case 'Y': + doType(VK_SHIFT, VK_Y); + break; + case 'Z': + doType(VK_SHIFT, VK_Z); + break; + // case '`': doType(VK_BACK_QUOTE); break; + case '0': + doType(VK_0); + break; + case '1': + doType(VK_1); + break; + case '2': + doType(VK_2); + break; + case '3': + doType(VK_3); + break; + case '4': + doType(VK_4); + break; + case '5': + doType(VK_5); + break; + case '6': + doType(VK_6); + break; + case '7': + doType(VK_7); + break; + case '8': + doType(VK_8); + break; + case '9': + doType(VK_9); + break; /* case '-': doType(VK_MINUS); break; case '=': doType(VK_EQUALS); break; @@ -268,11 +401,13 @@ public boolean type(char character) { case '/': doType(VK_SLASH); break; case '?': doType(VK_SHIFT, VK_SLASH); break; */ - case ' ': doType(VK_SPACE); break; - default: - return false; + case ' ': + doType(VK_SPACE); + break; + default: + return false; } - + return true; } @@ -282,26 +417,23 @@ protected void doType(@NotNull int... keyCodes) { private void doTypeArr(@NotNull int[] keyCodes) { int length = keyCodes.length; - if (length == 1) - { - doType(keyCodes[0]); - } - else // 2 + if (length == 1) { + doType(keyCodes[0]); + } else // 2 { robot.keyPress(keyCodes[0]); robot.keyPress(keyCodes[1]); - - robot.keyRelease(keyCodes[1]); + + robot.keyRelease(keyCodes[1]); robot.keyRelease(keyCodes[0]); } } - - protected void doType(int keyCode) - { + + protected void doType(int keyCode) { robot.keyPress(keyCode); - robot.keyRelease(keyCode); - } - + robot.keyRelease(keyCode); + } + public abstract boolean isUseCodePoint(); - + } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java index 3999e14..5649500 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java @@ -18,40 +18,33 @@ * http://stackoverflow.com/questions/1248510/convert-string-to-keyevents * http://en.wikipedia.org/wiki/Unicode_input#Hexadecimal_code_input * http://stackoverflow.com/questions/9814701/accent-with-robot-keypress - * + * * @author jmarranz */ -public class KeyboardUsingClipboard extends Keyboard implements ClipboardOwner -{ +public class KeyboardUsingClipboard extends Keyboard implements ClipboardOwner { @NotNull protected final Robot robot; protected Charset cs; - - - public KeyboardUsingClipboard(Charset cs) - { + + + public KeyboardUsingClipboard(Charset cs) { this.cs = cs; - try - { + try { this.robot = new Robot(); - } - catch (AWTException ex) - { + } catch (AWTException ex) { throw new RelProxyException(ex); } } - public static KeyboardUsingClipboard create(Charset cs) - { + public static KeyboardUsingClipboard create(Charset cs) { return new KeyboardUsingClipboard(cs); - } + } + - @Override - public void type(@NotNull CharSequence characters) - { + public void type(@NotNull CharSequence characters) { Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); - StringSelection stringSelection = new StringSelection( characters.toString() ); + StringSelection stringSelection = new StringSelection(characters.toString()); clipboard.setContents(stringSelection, this); robot.keyPress(KeyEvent.VK_CONTROL); @@ -61,8 +54,7 @@ public void type(@NotNull CharSequence characters) } @Override - public void lostOwnership(Clipboard clipboard, Transferable contents) - { + public void lostOwnership(Clipboard clipboard, Transferable contents) { } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/LinuxUnicodeKeyboard.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/LinuxUnicodeKeyboard.java index b11f86b..2098142 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/LinuxUnicodeKeyboard.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/LinuxUnicodeKeyboard.java @@ -3,59 +3,51 @@ import static java.awt.event.KeyEvent.VK_CONTROL; import static java.awt.event.KeyEvent.VK_SHIFT; import static java.awt.event.KeyEvent.VK_U; + import java.nio.charset.Charset; /** - * * http://superuser.com/questions/59418/how-to-type-special-characters-in-linux - * + * * @author jmarranz */ -public class LinuxUnicodeKeyboard extends KeyboardNotUsingClipboard -{ - public LinuxUnicodeKeyboard(Charset cs) - { +public class LinuxUnicodeKeyboard extends KeyboardNotUsingClipboard { + public LinuxUnicodeKeyboard(Charset cs) { super(cs); } - + @Override - public boolean isUseCodePoint() - { + public boolean isUseCodePoint() { return true; } - + @Override - public boolean type(char character) - { + public boolean type(char character) { if (super.type(character)) return true; - String unicodeDigits = getUnicodeDigits(character,16); // En hexadecimal + String unicodeDigits = getUnicodeDigits(character, 16); // En hexadecimal - robot.keyPress(VK_CONTROL); + robot.keyPress(VK_CONTROL); robot.keyPress(VK_SHIFT); - + doType(VK_U); // 'u' indica que después viene un valor unicode hexadecimal - + // Pero dejamos pulsadas CTRL y SHIFT mientras // Ejemplo: 266A es una nota de solfeo - try - { - for (int i = 0; i < unicodeDigits.length(); i++) - { + try { + for (int i = 0; i < unicodeDigits.length(); i++) { char c = unicodeDigits.charAt(i); if (Character.isDigit(c)) typeNumPad(Integer.parseInt(unicodeDigits.substring(i, i + 1))); else - type(c); + type(c); } + } finally { + robot.keyRelease(VK_CONTROL); + robot.keyRelease(VK_SHIFT); } - finally - { - robot.keyRelease(VK_CONTROL); - robot.keyRelease(VK_SHIFT); - } - + return true; } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/MacOSXUnicodeKeyboard.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/MacOSXUnicodeKeyboard.java index 7a1caf5..a396418 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/MacOSXUnicodeKeyboard.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/MacOSXUnicodeKeyboard.java @@ -1,50 +1,43 @@ package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; import static java.awt.Event.ALT_MASK; + import java.nio.charset.Charset; /** - * * https://discussions.apple.com/thread/1899290 * http://superuser.com/questions/13086/how-do-you-type-unicode-characters-using-hexadecimal-codes (buscar OS X) * http://controlyourmac.com/2012/05/understanding-mac-keyboard.html - * + * * @author jmarranz */ -public class MacOSXUnicodeKeyboard extends KeyboardNotUsingClipboard -{ - public MacOSXUnicodeKeyboard(Charset cs) - { +public class MacOSXUnicodeKeyboard extends KeyboardNotUsingClipboard { + public MacOSXUnicodeKeyboard(Charset cs) { super(cs); } - + @Override - public boolean isUseCodePoint() - { + public boolean isUseCodePoint() { return true; - } - + } + @Override - public boolean type(char character) - { + public boolean type(char character) { if (super.type(character)) return true; - String unicodeDigits = getUnicodeDigits(character,16); // En hexadecimal + String unicodeDigits = getUnicodeDigits(character, 16); // En hexadecimal robot.keyPress(ALT_MASK); // "Since the ALT_MASK modifier is the Option key in OS X" https://developer.apple.com/library/mac/documentation/java/conceptual/java14development/07-NativePlatformIntegration/NativePlatformIntegration.html - - try - { + + try { for (int i = 0; i < unicodeDigits.length(); i++) { - type(unicodeDigits.charAt(i)); + type(unicodeDigits.charAt(i)); } + } finally { + robot.keyRelease(ALT_MASK); } - finally - { - robot.keyRelease(ALT_MASK); - } - + return true; } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/WindowUnicodeKeyboard.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/WindowUnicodeKeyboard.java index 35d4a47..52fc292 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/WindowUnicodeKeyboard.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/WindowUnicodeKeyboard.java @@ -1,49 +1,43 @@ package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; import static java.awt.event.KeyEvent.VK_ALT; + import java.nio.charset.Charset; /** * http://stackoverflow.com/questions/1248510/convert-string-to-keyevents - * + * * @author jmarranz */ -public class WindowUnicodeKeyboard extends KeyboardNotUsingClipboard -{ - public WindowUnicodeKeyboard(Charset cs) - { +public class WindowUnicodeKeyboard extends KeyboardNotUsingClipboard { + public WindowUnicodeKeyboard(Charset cs) { super(cs); } - + @Override - public boolean isUseCodePoint() - { + public boolean isUseCodePoint() { return false; - } - + } + @Override - public boolean type(char character) - { + public boolean type(char character) { if (super.type(character)) return true; // En Windows usar mintty porque usando la consola de MSYS por sí misma, que es realmente la de Windows, hay problemas con el set de caracteres, pues sería Cp1252 para Java pero Cp850 para la consola y salen mal por tanto los caracteres no ASCII - - - String unicodeDigits = getUnicodeDigits(character,10); // En DECIMAL - + + + String unicodeDigits = getUnicodeDigits(character, 10); // En DECIMAL + robot.keyPress(VK_ALT); - try - { + try { for (int i = 0; i < unicodeDigits.length(); i++) { typeNumPad(Integer.parseInt(unicodeDigits.substring(i, i + 1))); } + } finally { + robot.keyRelease(VK_ALT); } - finally - { - robot.keyRelease(VK_ALT); - } - + return true; } diff --git a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxy.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxy.java index 47c9838..1871adf 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxy.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxy.java @@ -8,115 +8,105 @@ /** * Is the class to create Java proxy objects based on Java objects and keep track of source code changes reloading classes when detected. - * + * * @author Jose Maria Arranz Santamaria */ -public class JProxy -{ +public class JProxy { /** * Creates a {@link JProxyConfig} object to be used to configure JProxy and {@link JProxyScriptEngineFactory}. - * + * * @return a new configuration object. * @see #init(JProxyConfig) */ - public static JProxyConfig createJProxyConfig() - { + public static JProxyConfig createJProxyConfig() { return JProxyDefaultImpl.createJProxyConfig(); - } - + } + /** * Initializes JProxy with the provided configuration object. - * - * @param config the configuration - */ - public static void init(JProxyConfig config) - { - JProxyDefaultImpl.initStatic((JProxyConfigImpl)config); + * + * @param config the configuration + */ + public static void init(JProxyConfig config) { + JProxyDefaultImpl.initStatic((JProxyConfigImpl) config); } - - - + + /** * Creates a proxy object using java.lang.reflect.Proxy based on the provided Java object and the class of the implemented Java interface. - * - *

This method is a simplification for a single interface (the most common case) of {@link #create(Object,Class[])} .

- * - * @param the interface implemented by the original object and proxy object returned. - * @param obj the original object to proxy. + *

+ *

This method is a simplification for a single interface (the most common case) of {@link #create(Object, Class[])} .

+ * + * @param the interface implemented by the original object and proxy object returned. + * @param obj the original object to proxy. * @param clasz the class of the interface implemented by the original object and proxy object returned. * @return the java.lang.reflect.Proxy object associated or the original object when GProxy is disabled. - */ + */ @Nullable - public static T create(T obj, Class clasz) - { + public static T create(T obj, Class clasz) { return JProxyDefaultImpl.createStatic(obj, clasz); } - + /** * Creates a proxy object using java.lang.reflect.Proxy based on the provided Java object and the classes of the implemented Java interfaces. - * - *

If JProxy has been configured and is enabled this method returns a java.lang.reflect.Proxy object implementing instead of + *

+ *

If JProxy has been configured and is enabled this method returns a java.lang.reflect.Proxy object implementing instead of * the original object provided. Methods called in proxy object are received by JProxy and forwarded to the original object, if source code * managed by JProxy has been changed, the class of the original object is reloaded based on the new source and the original object * is recreated with the new class and fields are re-set in the new object, then the method is called on the new original object.

- * + *

*

If JProxy is disabled returns the original object provided with no performance penalty.

- * - * @param obj the original object to proxy. + * + * @param obj the original object to proxy. * @param classes the classes of the interfaces implemented by the original object and proxy object returned. * @return the java.lang.reflect.Proxy object associated or the original object when JProxy is disabled. - */ + */ @Nullable - public static Object create(Object obj, @NotNull Class[] classes) - { + public static Object create(Object obj, @NotNull Class[] classes) { return JProxyDefaultImpl.createStatic(obj, classes); - } - + } + /** * Informs whether JProxy is configured and enabled. - * - * @return true if enabled. - */ - public static boolean isEnabled() - { + * + * @return true if enabled. + */ + public static boolean isEnabled() { return JProxyDefaultImpl.isEnabledStatic(); - } - + } + /** * Informs whether JProxy is enabled and started (timed checking for changes). - * - * @return true if running. - */ - public static boolean isRunning() - { + * + * @return true if running. + */ + public static boolean isRunning() { return JProxyDefaultImpl.isRunningStatic(); - } - + } + /** * Stops source code periodic change detection. - * + *

*

Periodicity of change detection is defined by {@link JProxyConfig#setScanPeriod(long)}

- * + * * @return true if source change detection has been stopped, false if it is already stopped or JProxy is not enabled or initialized. * @see #stop() */ - public static boolean stop() - { + public static boolean stop() { return JProxyDefaultImpl.stopStatic(); } - + /** * Starts source code periodic change detection. - * + *

*

Periodicity of change detection is defined by {@link JProxyConfig#setScanPeriod(long)}.

- * + *

*

By default when JProxy is initialized and enabled.

- * + * * @return true if source change detection has been started again, false if it is already started or cannot start because JProxy is not enabled or initialized or scan period is not positive. * @see #start() */ - public static boolean start() - { + public static boolean start() { return JProxyDefaultImpl.startStatic(); - } + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyCompilerListener.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyCompilerListener.java index 218f16e..d46d7fb 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyCompilerListener.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyCompilerListener.java @@ -4,12 +4,12 @@ /** * Is the interface to monitor the files being compiled. - * - * @see JProxyConfig#setJProxyCompilerListener(JProxyCompilerListener) + * * @author Jose Maria Arranz Santamaria + * @see JProxyConfig#setJProxyCompilerListener(JProxyCompilerListener) */ -public interface JProxyCompilerListener -{ +public interface JProxyCompilerListener { public void beforeCompile(File file); - public void afterCompile(File file); + + public void afterCompile(File file); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyConfig.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyConfig.java index 81e53ea..5e0b0f0 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyConfig.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyConfig.java @@ -6,19 +6,18 @@ /** * Interface implemented by the configuration object needed to initialize JProxy and {@link JProxyScriptEngineFactory}. - * - * @see JProxy#init(JProxyConfig) - * @see JProxyScriptEngine#init(JProxyConfig) + * * @author Jose Maria Arranz Santamaria + * @see JProxy#init(JProxyConfig) + * @see JProxyScriptEngine#init(JProxyConfig) */ -public interface JProxyConfig -{ +public interface JProxyConfig { /** * Sets whether automatic detection of source code changes is enabled. - * + *

*

If set to false other configuration parameters are ignored, there is no automatic source code change detection/reload and original objects are returned * instead of proxies, performance penalty is zero. Setting to false is recommended in production whether source code change detection/reload is not required.

- * + * * @param enabled whether automatic source code change detection and reload is enabled. By default is true. * @return this object for flow API use. */ @@ -27,86 +26,86 @@ public interface JProxyConfig /** * Sets the class reload listener. - * + * * @param relListener the class reload listener. By default is null. * @return this object for flow API use. - */ + */ @NotNull public JProxyConfig setRelProxyOnReloadListener(RelProxyOnReloadListener relListener); /** * Defines the folder root to locate source code Java files. - * + *

*

Structure of the source tree must be the same as a JavaSE application, the only difference is shell scripts, shell scripts must be - * located on the top level of the source tree (default package) and file extension is not required .

- * + * located on the top level of the source tree (default package) and file extension is not required .

+ *

*

Setting some input path is required.

- * + * * @param inputPath the folder root to locate source code Java files. * @return this object for flow API use. - * @see #setInputPaths(java.lang.String[]) + * @see #setInputPaths(java.lang.String[]) */ @NotNull public JProxyConfig setInputPath(String inputPath); - + /** * Defines the folder roots to locate source code Java files. - * + *

*

Structure of the source tree must be the same as a JavaSE application, the only difference is shell scripts, shell scripts must be - * located on the top level of the source tree (default package).

- * + * located on the top level of the source tree (default package).

+ *

*

Setting some input path is required.

- * + * * @param inputPaths the folder roots to locate source code Java files. * @return this object for flow API use. - * @see #setJProxyInputSourceFileExcludedListener(JProxyInputSourceFileExcludedListener) + * @see #setJProxyInputSourceFileExcludedListener(JProxyInputSourceFileExcludedListener) * @see #setRequiredExtraJarPaths(String[]) */ @NotNull public JProxyConfig setInputPaths(String[] inputPaths); - + /** * Defines the extra required jars providing the absolute paths to them. - * + *

*

In some circunstances RelProxy is not able to find some required classes by the compiler because the jar containing them is not found in spite of existing in classpath, * the reason may be due some conflictive configuration of META-INF/MANIFEST.MF of the jar. This problem can be fixed modifying accordingly the META-INF/MANIFEST.MF * file, or alternatively providing the paths to the conflictive jars calling to this method, in this case RelProxy will find the required classes searching on them by using brute force * avoiding the jar modification (not recommended). *

- * + * * @param inputJarPaths the paths of the required extra jars. * @return this object for flow API use. - * @see #setInputPaths(String[]) + * @see #setInputPaths(String[]) */ @NotNull public JProxyConfig setRequiredExtraJarPaths(String[] inputJarPaths); - + /** * Registers the listener implementing excluding rules to filter source files not to be part of the hot reloading system in spite of included in input paths. - * + * * @param listener the listener. By default is null. * @return this object for flow API use. - */ + */ @NotNull public JProxyConfig setJProxyInputSourceFileExcludedListener(JProxyInputSourceFileExcludedListener listener); - + /** * Registers the listener for monitoring files being compiled. - * + * * @param listener the listener. By default is null. * @return this object for flow API use. - */ + */ @NotNull - public JProxyConfig setJProxyCompilerListener(JProxyCompilerListener listener); - - + public JProxyConfig setJProxyCompilerListener(JProxyCompilerListener listener); + + /** * Sets the folder where to save .class files result of recompiling source code changed. - * + *

*

This setting is optional and the folder must be included in Java classpath because the objective is to avoid recompiling.

- * + *

*

Be careful when executing several Java scripts in the same time and source code has been changed, some file write collisions may happen.

- * + * * @param classFolder the folder where to save .class files. By default is null (not defined, .class files are not saved). * @return this object for flow API use. */ @@ -115,22 +114,22 @@ public interface JProxyConfig /** * Sets the delay between source code change checking. - * + *

*

If this value is set to 0 or negative, no periodic source code change detection is executed and only compilation on the fly happens in load time, * this is valid for one shot scripts but it has no sense when using proxies. - * + * * @param scanPeriod the delay between source code change checking. * @return this object for flow API use. */ @NotNull public JProxyConfig setScanPeriod(long scanPeriod); - + /** * Sets the compilation options to be provided to the compiler built-in in JDK like JavaCompiler.getTask() method and the same you would provide to javac. - * + *

*

Example of compilation options:

*

Iterable<String> compilationOptions = Arrays.asList(new String[]{"-source","1.6","-target","1.6"});

- * + * * @param compilationOptions compilation options passed to the internal compiler. By default is null (default compiler settings). * @return this object for flow API use. */ @@ -138,36 +137,36 @@ public interface JProxyConfig public JProxyConfig setCompilationOptions(Iterable compilationOptions); /** - * Sets the diagnostic listener to capture compilation errors and warnings thrown by the internal compiler. - * + * Sets the diagnostic listener to capture compilation errors and warnings thrown by the internal compiler. + *

*

The following is an example similar to the default behavior when this listener is not specified:

- * -
-        JProxyDiagnosticsListener diagnosticsListener = new JProxyDiagnosticsListener()
-        {
-            {@code @}Override
-            public void onDiagnostics(DiagnosticCollector<JavaFileObject> diagnostics)
-            {
-                List<Diagnostic<? extends JavaFileObject>> diagList = diagnostics.getDiagnostics();
-                int i = 1;
-                for (Diagnostic diagnostic : diagList)
-                {
-                   System.err.println("Diagnostic " + i);
-                   System.err.println("  code: " + diagnostic.getCode());
-                   System.err.println("  kind: " + diagnostic.getKind());
-                   System.err.println("  line number: " + diagnostic.getLineNumber());                   
-                   System.err.println("  column number: " + diagnostic.getColumnNumber());
-                   System.err.println("  start position: " + diagnostic.getStartPosition());
-                   System.err.println("  position: " + diagnostic.getPosition());                   
-                   System.err.println("  end position: " + diagnostic.getEndPosition());
-                   System.err.println("  source: " + diagnostic.getSource());
-                   System.err.println("  message: " + diagnostic.getMessage(null));
-                   i++;
-                }
-            }
-        };   
-     
- * + *

+ *

+     * JProxyDiagnosticsListener diagnosticsListener = new JProxyDiagnosticsListener()
+     * {
+     * {@code @}Override
+     * public void onDiagnostics(DiagnosticCollector<JavaFileObject> diagnostics)
+     * {
+     * List<Diagnostic<? extends JavaFileObject>> diagList = diagnostics.getDiagnostics();
+     * int i = 1;
+     * for (Diagnostic diagnostic : diagList)
+     * {
+     * System.err.println("Diagnostic " + i);
+     * System.err.println("  code: " + diagnostic.getCode());
+     * System.err.println("  kind: " + diagnostic.getKind());
+     * System.err.println("  line number: " + diagnostic.getLineNumber());
+     * System.err.println("  column number: " + diagnostic.getColumnNumber());
+     * System.err.println("  start position: " + diagnostic.getStartPosition());
+     * System.err.println("  position: " + diagnostic.getPosition());
+     * System.err.println("  end position: " + diagnostic.getEndPosition());
+     * System.err.println("  source: " + diagnostic.getSource());
+     * System.err.println("  message: " + diagnostic.getMessage(null));
+     * i++;
+     * }
+     * }
+     * };
+     * 
+ * * @param diagnosticsListener the diagnostic listener to capture compilation errors and warnings. By default is null, an internal listener is used logging to System.err. * @return this object for flow API use. */ diff --git a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyDiagnosticsListener.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyDiagnosticsListener.java index 6de8b26..ec01b55 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyDiagnosticsListener.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyDiagnosticsListener.java @@ -5,15 +5,14 @@ /** * Is the interface to implement diagnostic listeners to capture compilation errors and warnings. - * - * @see JProxyConfig#setJProxyDiagnosticsListener(JProxyDiagnosticsListener) + * * @author Jose Maria Arranz Santamaria + * @see JProxyConfig#setJProxyDiagnosticsListener(JProxyDiagnosticsListener) */ -public interface JProxyDiagnosticsListener -{ +public interface JProxyDiagnosticsListener { /** * This method is called when compilation Java code has generated diagnostics. - * + * * @param diagnostics the list of diagnostics. */ public void onDiagnostics(DiagnosticCollector diagnostics); diff --git a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java index def541e..ae16eb9 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java @@ -4,18 +4,17 @@ /** * This interface is provided to developers to implement excluding rules to filter source files not to be part of the hot reloading system in spite of included in input paths - * - * @see JProxyConfig#setJProxyInputSourceFileExcludedListener(JProxyInputSourceFileExcludedListener) + * * @author Jose Maria Arranz Santamaria + * @see JProxyConfig#setJProxyInputSourceFileExcludedListener(JProxyInputSourceFileExcludedListener) */ -public interface JProxyInputSourceFileExcludedListener -{ +public interface JProxyInputSourceFileExcludedListener { /** * This method is called per file when going to be managed by the hot reloading system. - * - * @param file the file to be managed. + * + * @param file the file to be managed. * @param rootFolderOfSources the folder root of sources where this file is located. * @return true whether the file must be ignored. */ - public boolean isExcluded(File file,File rootFolderOfSources); + public boolean isExcluded(File file, File rootFolderOfSources); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyScriptEngine.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyScriptEngine.java index ddc12c1..caa0756 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyScriptEngine.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyScriptEngine.java @@ -6,25 +6,24 @@ /** * Interface implemented by RelProxy to provide javax.script.ScriptEngine objects supporting Java as a scripting language. - * + *

*

The method {@link JProxyScriptEngineFactory#getScriptEngine()} returns an implementation of this interface.

- * + * * @author Jose Maria Arranz Santamaria */ -public interface JProxyScriptEngine extends ScriptEngine -{ +public interface JProxyScriptEngine extends ScriptEngine { /** * Initializes this JProxyScriptEngine instance with the provided configuration object. - * + * * @param config the configuration object. - */ + */ public void init(JProxyConfig config); - + /** * This method is the same as {@link JProxy#create(java.lang.Object, java.lang.Class)} but applied to this JProxyScriptEngine - * - * @param the interface implemented by the original object and proxy object returned. - * @param obj the original object to proxy. + * + * @param the interface implemented by the original object and proxy object returned. + * @param obj the original object to proxy. * @param clasz the class of the interface implemented by the original object and proxy object returned. * @return the java.lang.reflect.Proxy object associated or the original object when is disabled. */ @@ -33,41 +32,41 @@ public interface JProxyScriptEngine extends ScriptEngine /** * This method is the same as {@link JProxy#create(java.lang.Object, java.lang.Class[])} but applied to this JProxyScriptEngine - * - * @param obj the original object to proxy. + * + * @param obj the original object to proxy. * @param classes the classes of the interfaces implemented by the original object and proxy object returned. * @return the java.lang.reflect.Proxy object associated or the original object when is disabled. - */ + */ @Nullable public Object create(Object obj, Class[] classes); - + /** * This method is the same as {@link JProxy#isEnabled()} but applied to this JProxyScriptEngine - * - * @return true if enabled. - */ + * + * @return true if enabled. + */ public boolean isEnabled(); - + /** * This method is the same as {@link JProxy#isRunning()} but applied to this JProxyScriptEngine - * - * @return true if running. - */ - public boolean isRunning(); - + * + * @return true if running. + */ + public boolean isRunning(); + /** * This method is the same as {@link JProxy#stop()} but applied to this JProxyScriptEngine - * + * * @return true if source change detection has been stopped, false if it is already stopped or this JProxyScriptEngine is not enabled or initialized. * @see #stop() - */ + */ public boolean stop(); /** * This method is the same as {@link JProxy#start()} but applied to this JProxyScriptEngine - * + * * @return true if source change detection has been started again, false if it is already started or cannot start because this JProxyScriptEngine is not enabled or initialized or scan period is not positive. * @see #start() */ - public boolean start(); + public boolean start(); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyScriptEngineFactory.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyScriptEngineFactory.java index 175b320..ae22b72 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyScriptEngineFactory.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyScriptEngineFactory.java @@ -1,22 +1,21 @@ package com.sillelien.dollar.relproxy.jproxy; import com.sillelien.dollar.relproxy.impl.jproxy.screngine.JProxyScriptEngineFactoryImpl; + import javax.script.ScriptEngineFactory; /** * Is the root class of JSR-223 Java Scripting API support. - * + * * @author Jose Maria Arranz Santamaria */ -public abstract class JProxyScriptEngineFactory implements ScriptEngineFactory -{ +public abstract class JProxyScriptEngineFactory implements ScriptEngineFactory { /** * Factory method to create a JProxyScriptEngineFactory implementing ScriptEngineFactory. - * + * * @return the new factory. */ - public static JProxyScriptEngineFactory create() - { + public static JProxyScriptEngineFactory create() { return JProxyScriptEngineFactoryImpl.create(); } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyShell.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyShell.java index 3ea27a2..4cd6c2c 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyShell.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyShell.java @@ -5,20 +5,18 @@ /** * Is the main class to execute shell scripting based on Java. - * + *

*

You are not going to use directly this class, use instead jproxysh command line.

- * + * * @author Jose Maria Arranz Santamaria */ -public class JProxyShell -{ +public class JProxyShell { /** * The main method. - * + * * @param args arguments with the necessary data to initialize and executing the provided script. */ - public static void main(@NotNull String[] args) - { - JProxyShellImpl.main(args); + public static void main(@NotNull String[] args) { + JProxyShellImpl.main(args); } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/jproxy/package.html b/src/main/java/com/sillelien/dollar/relproxy/jproxy/package.html index 3a1f2ab..e8701f4 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/jproxy/package.html +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/package.html @@ -1,9 +1,9 @@ - + diff --git a/src/main/java/com/sillelien/dollar/relproxy/package.html b/src/main/java/com/sillelien/dollar/relproxy/package.html index d8f25f0..01103dd 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/package.html +++ b/src/main/java/com/sillelien/dollar/relproxy/package.html @@ -1,9 +1,9 @@ - + From a8d3bc0b3f92348fe44ed6e5793521fbb2637948 Mon Sep 17 00:00:00 2001 From: neilellis Date: Fri, 7 Jul 2017 22:14:35 +0100 Subject: [PATCH 029/135] Refactoring for Dollar project --- .idea/libraries/Maven__junit_junit_4_12.xml | 13 ++ .../Maven__org_hamcrest_hamcrest_core_1_3.xml | 13 ++ .../Maven__org_jetbrains_annotations_13_0.xml | 13 ++ .idea/libraries/annotations.xml | 9 + pom.xml | 23 +- .../example/javaex/JProxyExampleDocument.java | 5 +- .../javaex/JProxyExampleLoadListener.java | 4 +- .../dollar/relproxy/gproxy/GProxy.java | 8 +- .../dollar/relproxy/gproxy/GProxyConfig.java | 4 + .../gproxy/GProxyGroovyScriptEngine.java | 3 + .../dollar/relproxy/impl/FileExt.java | 8 +- .../relproxy/impl/GenericProxyImpl.java | 18 +- .../impl/GenericProxyInvocationHandler.java | 5 +- .../impl/GenericProxyVersionedObject.java | 12 +- .../impl/gproxy/GProxyConfigImpl.java | 4 + .../impl/gproxy/GProxyDefaultImpl.java | 10 +- .../relproxy/impl/gproxy/core/GProxyImpl.java | 6 +- .../gproxy/core/GProxyInvocationHandler.java | 4 +- .../gproxy/core/GProxyVersionedObject.java | 11 +- .../impl/jproxy/JProxyConfigImpl.java | 22 +- .../impl/jproxy/JProxyDefaultImpl.java | 13 +- .../relproxy/impl/jproxy/JProxyUtil.java | 22 +- .../relproxy/impl/jproxy/core/JProxyImpl.java | 12 +- .../jproxy/core/JProxyInvocationHandler.java | 4 +- .../jproxy/core/JProxyVersionedObject.java | 7 +- .../jproxy/core/clsmgr/FolderSourceList.java | 10 +- .../jproxy/core/clsmgr/JProxyClassLoader.java | 19 +- .../impl/jproxy/core/clsmgr/JProxyEngine.java | 22 +- ...JProxyEngineChangeDetectorAndCompiler.java | 19 +- .../jproxy/core/clsmgr/JavaSourcesSearch.java | 182 ++++++++-------- .../core/clsmgr/cldesc/ClassDescriptor.java | 23 +- .../clsmgr/cldesc/ClassDescriptorInner.java | 4 +- .../cldesc/ClassDescriptorSourceFileJava.java | 4 +- .../ClassDescriptorSourceFileRegistry.java | 15 +- .../cldesc/ClassDescriptorSourceScript.java | 17 +- .../cldesc/ClassDescriptorSourceUnit.java | 17 +- .../clsmgr/comp/JProxyCompilerInMemory.java | 11 +- .../clsmgr/comp/JavaFileManagerInMemory.java | 13 +- ...leObjectInputClassFinderByClassLoader.java | 13 +- .../jfo/JavaFileObjectInputClassInFile.java | 6 +- .../JavaFileObjectInputClassInFileSystem.java | 11 +- .../jfo/JavaFileObjectInputClassInJar.java | 5 +- .../jfo/JavaFileObjectInputClassInMemory.java | 6 +- .../jfo/JavaFileObjectInputSourceBase.java | 9 +- .../jfo/JavaFileObjectInputSourceInFile.java | 4 +- .../JavaFileObjectInputSourceInMemory.java | 4 +- .../comp/jfo/JavaFileObjectOutputClass.java | 5 +- .../clsmgr/srcunit/SourceFileJavaNormal.java | 5 +- .../clsmgr/srcunit/SourceScriptRootFile.java | 5 +- .../srcunit/SourceScriptRootFileJavaExt.java | 6 +- .../srcunit/SourceScriptRootFileOtherExt.java | 6 +- .../core/clsmgr/srcunit/SourceUnit.java | 8 +- .../JProxyScriptEngineDelegateImpl.java | 11 +- .../JProxyScriptEngineFactoryImpl.java | 23 +- .../screngine/JProxyScriptEngineImpl.java | 10 +- .../jproxy/shell/JProxyShellClassLoader.java | 8 +- .../shell/JProxyShellCodeSnippetImpl.java | 17 +- .../impl/jproxy/shell/JProxyShellImpl.java | 20 +- .../shell/JProxyShellInteractiveImpl.java | 20 +- .../shell/JProxyShellScriptFileImpl.java | 19 +- .../impl/jproxy/shell/inter/Command.java | 6 +- .../shell/inter/CommandCodeChangerBase.java | 4 +- .../jproxy/shell/inter/CommandDelete.java | 4 +- .../impl/jproxy/shell/inter/CommandEdit.java | 4 +- .../jproxy/shell/inter/CommandInsert.java | 4 +- .../impl/jproxy/shell/inter/CommandLoad.java | 4 +- .../impl/jproxy/shell/inter/CommandSave.java | 4 +- .../shell/inter/JProxyShellProcessor.java | 12 +- .../inter/KeyboardNotUsingClipboard.java | 13 +- .../shell/inter/KeyboardUsingClipboard.java | 5 +- .../dollar/relproxy/jproxy/JProxy.java | 8 +- .../dollar/relproxy/jproxy/JProxyConfig.java | 20 +- .../relproxy/jproxy/JProxyScriptEngine.java | 8 +- .../dollar/relproxy/jproxy/JProxyShell.java | 3 +- .../JProxyCodeSnippetCompleteClassTest.java | 74 +++++++ .../jproxy/JProxyCodeSnippetTest.java | 68 ++++++ .../JProxyJavaScriptEngineNoManagerTest.java | 183 ++++++++++++++++ .../jproxy/JProxyJavaScriptEngineTest.java | 201 ++++++++++++++++++ .../JProxyJavaShellCompleteClassTest.java | 72 +++++++ .../JProxyJavaShellInteractiveTest.java | 63 ++++++ .../JProxyJavaShellNormalClassTest.java | 69 ++++++ .../relproxy/jproxy/JProxyJavaShellTest.java | 74 +++++++ .../relproxy/jproxy/util/JProxyTestUtil.java | 16 ++ .../javashellex/JProxyShellExample.java | 44 ++-- .../test/resources/example_java_shell | 0 .../example_java_shell_complete_class | 0 .../test/resources/example_normal_class.java | 0 87 files changed, 1489 insertions(+), 304 deletions(-) create mode 100644 .idea/libraries/Maven__junit_junit_4_12.xml create mode 100644 .idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml create mode 100644 .idea/libraries/Maven__org_jetbrains_annotations_13_0.xml create mode 100644 .idea/libraries/annotations.xml create mode 100644 src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyCodeSnippetCompleteClassTest.java create mode 100644 src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyCodeSnippetTest.java create mode 100644 src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaScriptEngineNoManagerTest.java create mode 100644 src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaScriptEngineTest.java create mode 100644 src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaShellCompleteClassTest.java create mode 100644 src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaShellInteractiveTest.java create mode 100644 src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaShellNormalClassTest.java create mode 100644 src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaShellTest.java create mode 100644 src/test/java/com/sillelien/dollar/relproxy/jproxy/util/JProxyTestUtil.java rename {relproxy/src => src}/test/resources/example/javashellex/JProxyShellExample.java (96%) rename {relproxy/src => src}/test/resources/example_java_shell (100%) rename {relproxy/src => src}/test/resources/example_java_shell_complete_class (100%) rename {relproxy/src => src}/test/resources/example_normal_class.java (100%) diff --git a/.idea/libraries/Maven__junit_junit_4_12.xml b/.idea/libraries/Maven__junit_junit_4_12.xml new file mode 100644 index 0000000..d411041 --- /dev/null +++ b/.idea/libraries/Maven__junit_junit_4_12.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml b/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml new file mode 100644 index 0000000..f58bbc1 --- /dev/null +++ b/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_jetbrains_annotations_13_0.xml b/.idea/libraries/Maven__org_jetbrains_annotations_13_0.xml new file mode 100644 index 0000000..e2c8297 --- /dev/null +++ b/.idea/libraries/Maven__org_jetbrains_annotations_13_0.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/annotations.xml b/.idea/libraries/annotations.xml new file mode 100644 index 0000000..03e4ad1 --- /dev/null +++ b/.idea/libraries/annotations.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 51d3a7e..aaf4c19 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,9 @@ relproxy - Simple Java and Groovy hot class reloader,and Java based shell and scripting used by Dollar project, original project is https://github.com/jmarranz/relproxy + Simple Java and Groovy hot class reloader,and Java based shell and scripting used by Dollar project, + original project is https://github.com/jmarranz/relproxy + https://github.com/dollar-org/relproxy @@ -60,16 +62,31 @@ + 13.0 2.0.2 + 3.0.2 + 1.8 2.4 2.8 2.6 3.4 3.3.9 - 1.8 - 3.0.2 + + + org.jetbrains + annotations + ${annotations.version} + + + junit + junit + 4.12 + test + + + diff --git a/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleDocument.java b/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleDocument.java index f09bde7..f3d8267 100644 --- a/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleDocument.java +++ b/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleDocument.java @@ -8,6 +8,7 @@ import org.itsnat.comp.text.ItsNatHTMLInputText; import org.itsnat.core.ItsNatServletRequest; import org.itsnat.core.html.ItsNatHTMLDocument; +import org.jetbrains.annotations.NotNull; import org.w3c.dom.Element; import org.w3c.dom.events.Event; import org.w3c.dom.events.EventListener; @@ -32,7 +33,7 @@ public JProxyExampleDocument() // Requerido por el listener ejemplo anonymous in { } - public JProxyExampleDocument(ItsNatServletRequest request,ItsNatHTMLDocument itsNatDoc,FalseDB db) + public JProxyExampleDocument(ItsNatServletRequest request, @NotNull ItsNatHTMLDocument itsNatDoc, @NotNull FalseDB db) { class AuxMemberInMethod { @@ -59,7 +60,7 @@ public void log() } @Override - public void handleEvent(Event evt) + public void handleEvent(@NotNull Event evt) { String text = textInput.getText(); String comment = " YES I SAID THIS (" + evt.getType() + ")"; diff --git a/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleLoadListener.java b/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleLoadListener.java index 550320c..15314dc 100644 --- a/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleLoadListener.java +++ b/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleLoadListener.java @@ -8,10 +8,12 @@ import org.itsnat.core.ItsNatServletRequest; import org.itsnat.core.ItsNatServletResponse; import org.itsnat.core.html.ItsNatHTMLDocument; +import org.jetbrains.annotations.NotNull; public class JProxyExampleLoadListener implements ItsNatServletRequestListener { protected final FalseDB db; + @NotNull protected static Integer testStatic = 10; protected static final Integer testStaticFinal = 11; @@ -27,7 +29,7 @@ public JProxyExampleLoadListener(FalseDB db) @Override - public void processRequest(ItsNatServletRequest request, ItsNatServletResponse response) + public void processRequest(@NotNull ItsNatServletRequest request, ItsNatServletResponse response) { System.out.println("JProxyExampleLoadListener 1 " + this.getClass().getClassLoader().hashCode()); new example.javaex.JProxyExampleDocument(request,(ItsNatHTMLDocument)request.getItsNatDocument(),db); diff --git a/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxy.java b/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxy.java index 6fb5120..5ee51b4 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxy.java +++ b/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxy.java @@ -3,6 +3,8 @@ import com.sillelien.dollar.relproxy.impl.gproxy.GProxyConfigImpl; import com.sillelien.dollar.relproxy.impl.gproxy.GProxyDefaultImpl; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * Is the class to create Java proxy objects based on Groovy objects and keep track of Groovy source code changes reloading Groovy classes when detected. @@ -42,7 +44,8 @@ public static void init(GProxyConfig config) * @param clasz the class of the interface implemented by the original object and proxy object returned. * @return the java.lang.reflect.Proxy object associated or the original object when GProxy is disabled. */ - public static T create(T obj,Class clasz) + @Nullable + public static T create(T obj, Class clasz) { return GProxyDefaultImpl.createStatic(obj, clasz); } @@ -61,7 +64,8 @@ public static T create(T obj,Class clasz) * @param classes the classes of the interfaces implemented by the original object and proxy object returned. * @return the java.lang.reflect.Proxy object associated or the original object when GProxy is disabled. */ - public static Object create(Object obj,Class[] classes) + @Nullable + public static Object create(Object obj, @NotNull Class[] classes) { return GProxyDefaultImpl.createStatic(obj, classes); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyConfig.java b/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyConfig.java index ea57bcd..fd614e2 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyConfig.java +++ b/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyConfig.java @@ -2,6 +2,7 @@ package com.sillelien.dollar.relproxy.gproxy; import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; +import org.jetbrains.annotations.NotNull; /** * Interface implemented by the configuration object needed to initialize GProxy. @@ -21,6 +22,7 @@ public interface GProxyConfig * @param enabled whether automatic source code change detection and reload is enabled. By default is true. * @return this object for flow API use. */ + @NotNull public GProxyConfig setEnabled(boolean enabled); /** @@ -29,6 +31,7 @@ public interface GProxyConfig * @param relListener the class reload listener. By default is null. * @return this object for flow API use. */ + @NotNull public GProxyConfig setRelProxyOnReloadListener(RelProxyOnReloadListener relListener); /** @@ -39,5 +42,6 @@ public interface GProxyConfig * @param engine the GroovyScriptEngine wrapper. * @return this object for flow API use. */ + @NotNull public GProxyConfig setGProxyGroovyScriptEngine(GProxyGroovyScriptEngine engine); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyGroovyScriptEngine.java b/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyGroovyScriptEngine.java index 53957a5..714feeb 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyGroovyScriptEngine.java +++ b/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyGroovyScriptEngine.java @@ -1,5 +1,7 @@ package com.sillelien.dollar.relproxy.gproxy; +import org.jetbrains.annotations.NotNull; + /** * Interface to implement the object implementing the GroovyScriptEngine wrapper used to reload Groovy classes. * @@ -27,5 +29,6 @@ public interface GProxyGroovyScriptEngine * @param scriptName the name of the Groovy script/class. * @return the class associated to the specified Groovy script. */ + @NotNull public Class loadScriptByName(String scriptName); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/FileExt.java b/src/main/java/com/sillelien/dollar/relproxy/impl/FileExt.java index e3ab333..33c8866 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/FileExt.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/FileExt.java @@ -1,6 +1,8 @@ package com.sillelien.dollar.relproxy.impl; import com.sillelien.dollar.relproxy.RelProxyException; +import org.jetbrains.annotations.NotNull; + import java.io.File; import java.io.IOException; @@ -10,21 +12,25 @@ */ public class FileExt { + @NotNull protected final File file; + @NotNull protected final String cannonicalPath; // El obtener el cannonicalPath exige acceder al sistema de archivos, por eso nos inventamos esta clase, para evitar sucesivas llamadas a File.getCanonicalPath() - public FileExt(File file) + public FileExt(@NotNull File file) { this.file = file; try { this.cannonicalPath = file.getCanonicalPath(); } catch (IOException ex) { throw new RelProxyException(ex); } } + @NotNull public File getFile() { return file; } + @NotNull public String getCanonicalPath() { return cannonicalPath; diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyImpl.java index 53a8b3c..fa9a470 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyImpl.java @@ -2,6 +2,9 @@ import com.sillelien.dollar.relproxy.RelProxyException; import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; @@ -17,19 +20,19 @@ public GenericProxyImpl() { } - public static void checkSingletonNull(GenericProxyImpl singleton) + public static void checkSingletonNull(@Nullable GenericProxyImpl singleton) { if (singleton != null) throw new RelProxyException("Already initialized"); } - protected static void checkSingletonExists(GenericProxyImpl singleton) + protected static void checkSingletonExists(@Nullable GenericProxyImpl singleton) { if (singleton == null) throw new RelProxyException("Execute first the init method"); } - protected void init(GenericProxyConfigBaseImpl config) + protected void init(@NotNull GenericProxyConfigBaseImpl config) { this.reloadListener = config.getRelProxyOnReloadListener(); } @@ -39,14 +42,16 @@ public RelProxyOnReloadListener getRelProxyOnReloadListener() return reloadListener; } - public T create(T obj,Class clasz) + @Nullable + public T create(@Nullable T obj, Class clasz) { if (obj == null) return null; return (T)create(obj,new Class[] { clasz }); } - public Object create(Object obj,Class[] classes) + @Nullable + public Object create(@Nullable Object obj, @NotNull Class[] classes) { if (obj == null) return null; @@ -57,5 +62,6 @@ public Object create(Object obj,Class[] classes) } - public abstract GenericProxyInvocationHandler createGenericProxyInvocationHandler(Object obj); + @NotNull + public abstract GenericProxyInvocationHandler createGenericProxyInvocationHandler(Object obj); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyInvocationHandler.java b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyInvocationHandler.java index 76bf545..1c47def 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyInvocationHandler.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyInvocationHandler.java @@ -1,6 +1,9 @@ package com.sillelien.dollar.relproxy.impl; import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; @@ -30,7 +33,7 @@ private Object getNewVersion() throws Throwable } @Override - public synchronized Object invoke(Object proxy, Method method, Object[] args) throws Throwable + public synchronized Object invoke(Object proxy, @NotNull Method method, @Nullable Object[] args) throws Throwable { Object oldObj = getCurrent(); Object obj = getNewVersion(); diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyVersionedObject.java b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyVersionedObject.java index b941169..60a479c 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyVersionedObject.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyVersionedObject.java @@ -1,6 +1,9 @@ package com.sillelien.dollar.relproxy.impl; import com.sillelien.dollar.relproxy.RelProxyException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; @@ -22,7 +25,7 @@ public GenericProxyVersionedObject(Object obj,GenericProxyInvocationHandler pare this.parent = parent; } - protected static void getTreeFields(Class clasz,Object obj,ArrayList fieldList,ArrayList valueList) throws IllegalAccessException + protected static void getTreeFields(@NotNull Class clasz, Object obj, @NotNull ArrayList fieldList, ArrayList valueList) throws IllegalAccessException { getFields(clasz,obj,fieldList,valueList); Class superClass = clasz.getSuperclass(); @@ -30,7 +33,7 @@ protected static void getTreeFields(Class clasz,Object obj,ArrayList fiel getTreeFields(superClass,obj,fieldList,valueList); } - protected static void getFields(Class clasz,Object obj,ArrayList fieldList,ArrayList valueList) throws IllegalAccessException + protected static void getFields(@NotNull Class clasz, Object obj, @NotNull ArrayList fieldList, @Nullable ArrayList valueList) throws IllegalAccessException { Field[] fieldListClass = clasz.getDeclaredFields(); for(int i = 0; i < fieldListClass.length; i++) @@ -66,7 +69,7 @@ public Object getNewVersion() throws Throwable return obj; } - private Object copy(Class oldClass,Object oldObj,Class newClass) throws IllegalAccessException, InstantiationException, IllegalArgumentException, InvocationTargetException + private Object copy(@NotNull Class oldClass, Object oldObj, @NotNull Class newClass) throws IllegalAccessException, InstantiationException, IllegalArgumentException, InvocationTargetException { Object newObj; @@ -160,6 +163,7 @@ private Object copy(Class oldClass,Object oldObj,Class newClass) throws IllegalA return newObj; } - protected abstract Class reloadClass(); + @Nullable + protected abstract Class reloadClass(); protected abstract boolean ignoreField(Field field); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyConfigImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyConfigImpl.java index d549078..826cace 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyConfigImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyConfigImpl.java @@ -4,6 +4,7 @@ import com.sillelien.dollar.relproxy.gproxy.GProxyConfig; import com.sillelien.dollar.relproxy.gproxy.GProxyGroovyScriptEngine; import com.sillelien.dollar.relproxy.impl.GenericProxyConfigBaseImpl; +import org.jetbrains.annotations.NotNull; /** * @@ -13,18 +14,21 @@ public class GProxyConfigImpl extends GenericProxyConfigBaseImpl implements GPro { protected GProxyGroovyScriptEngine engine; + @NotNull public GProxyConfig setEnabled(boolean enabled) { this.enabled = enabled; return this; } + @NotNull public GProxyConfig setRelProxyOnReloadListener(RelProxyOnReloadListener relListener) { this.relListener = relListener; return this; } + @NotNull public GProxyConfig setGProxyGroovyScriptEngine(GProxyGroovyScriptEngine engine) { this.engine = engine; diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyDefaultImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyDefaultImpl.java index 03735ef..8f466a9 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyDefaultImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyDefaultImpl.java @@ -2,6 +2,8 @@ import com.sillelien.dollar.relproxy.gproxy.GProxyConfig; import com.sillelien.dollar.relproxy.impl.gproxy.core.GProxyImpl; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * @@ -14,7 +16,7 @@ public static GProxyConfig createGProxyConfig() return new GProxyConfigImpl(); } - public static void initStatic(GProxyConfigImpl config) + public static void initStatic(@NotNull GProxyConfigImpl config) { if (!config.isEnabled()) return; @@ -23,7 +25,8 @@ public static void initStatic(GProxyConfigImpl config) SINGLETON.init(config); } - public static T createStatic(T obj,Class clasz) + @Nullable + public static T createStatic(T obj, Class clasz) { if (SINGLETON == null) return obj; // No se ha llamado al init o enabled = false @@ -31,7 +34,8 @@ public static T createStatic(T obj,Class clasz) return SINGLETON.create(obj, clasz); } - public static Object createStatic(Object obj,Class[] classes) + @Nullable + public static Object createStatic(Object obj, @NotNull Class[] classes) { if (SINGLETON == null) return obj; // No se ha llamado al init o enabled = false diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyImpl.java index 40ab707..33de8ec 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyImpl.java @@ -4,6 +4,7 @@ import com.sillelien.dollar.relproxy.gproxy.GProxyGroovyScriptEngine; import com.sillelien.dollar.relproxy.impl.GenericProxyImpl; import com.sillelien.dollar.relproxy.impl.GenericProxyInvocationHandler; +import org.jetbrains.annotations.NotNull; /** @@ -15,7 +16,7 @@ public abstract class GProxyImpl extends GenericProxyImpl public static GProxyImpl SINGLETON; protected GProxyGroovyScriptEngine engine; - public void init(GProxyConfigImpl config) + public void init(@NotNull GProxyConfigImpl config) { super.init(config); this.engine = config.getGProxyGroovyScriptEngine(); @@ -26,8 +27,9 @@ public GProxyGroovyScriptEngine getGProxyGroovyScriptEngine() return engine; } + @NotNull @Override - public GenericProxyInvocationHandler createGenericProxyInvocationHandler(Object obj) + public GenericProxyInvocationHandler createGenericProxyInvocationHandler(@NotNull Object obj) { return new GProxyInvocationHandler(obj,this); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyInvocationHandler.java b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyInvocationHandler.java index 0bff93a..a1c54d3 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyInvocationHandler.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyInvocationHandler.java @@ -1,6 +1,7 @@ package com.sillelien.dollar.relproxy.impl.gproxy.core; import com.sillelien.dollar.relproxy.impl.GenericProxyInvocationHandler; +import org.jetbrains.annotations.NotNull; /** * @@ -8,12 +9,13 @@ */ public class GProxyInvocationHandler extends GenericProxyInvocationHandler { - public GProxyInvocationHandler(Object obj,GProxyImpl root) + public GProxyInvocationHandler(@NotNull Object obj, GProxyImpl root) { super(root); this.verObj = new GProxyVersionedObject(obj,this); } + @NotNull public GProxyImpl getGProxyImpl() { return (GProxyImpl)root; diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyVersionedObject.java b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyVersionedObject.java index c4edf28..f8cbc2a 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyVersionedObject.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyVersionedObject.java @@ -2,6 +2,9 @@ import com.sillelien.dollar.relproxy.gproxy.GProxyGroovyScriptEngine; import com.sillelien.dollar.relproxy.impl.GenericProxyVersionedObject; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.lang.reflect.Field; /** @@ -12,19 +15,21 @@ public class GProxyVersionedObject extends GenericProxyVersionedObject { protected String path; - public GProxyVersionedObject(Object obj,GProxyInvocationHandler parent) + public GProxyVersionedObject(@NotNull Object obj, GProxyInvocationHandler parent) { super(obj,parent); this.path = obj.getClass().getName().replace('.','/'); } + @NotNull public GProxyInvocationHandler getGProxyInvocationHandler() { return (GProxyInvocationHandler)parent; } - @Override + @Nullable + @Override protected Class reloadClass() { GProxyGroovyScriptEngine engine = getGProxyInvocationHandler().getGProxyImpl().getGProxyGroovyScriptEngine(); @@ -41,7 +46,7 @@ protected Class reloadClass() } @Override - protected boolean ignoreField(Field field) + protected boolean ignoreField(@NotNull Field field) { return field.getName().startsWith("__timeStamp__"); // Este atributo cambia de nombre en cada reload, no lo consideramos } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyConfigImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyConfigImpl.java index bd1fe4c..eb5c831 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyConfigImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyConfigImpl.java @@ -8,6 +8,9 @@ import com.sillelien.dollar.relproxy.jproxy.JProxyConfig; import com.sillelien.dollar.relproxy.jproxy.JProxyDiagnosticsListener; import com.sillelien.dollar.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.io.File; /** @@ -27,6 +30,7 @@ public class JProxyConfigImpl extends GenericProxyConfigBaseImpl implements JPro protected JProxyDiagnosticsListener diagnosticsListener; protected boolean test = false; + @NotNull @Override public JProxyConfig setEnabled(boolean enabled) { @@ -34,6 +38,7 @@ public JProxyConfig setEnabled(boolean enabled) return this; } + @NotNull @Override public JProxyConfig setRelProxyOnReloadListener(RelProxyOnReloadListener relListener) { @@ -41,13 +46,15 @@ public JProxyConfig setRelProxyOnReloadListener(RelProxyOnReloadListener relList return this; } + @NotNull @Override - public JProxyConfig setInputPath(String inputPath) + public JProxyConfig setInputPath(@Nullable String inputPath) { setInputPaths(inputPath != null ? new String[]{inputPath} : null); // inputPath es null en el caso de shell interactive return this; } + @NotNull @Override public JProxyConfig setInputPaths(String[] inputPaths) { @@ -55,27 +62,31 @@ public JProxyConfig setInputPaths(String[] inputPaths) return this; } - @Override + @NotNull + @Override public JProxyConfig setRequiredExtraJarPaths(String[] inputJarPaths) { this.requiredExtraJarPaths = new FolderSourceList(inputJarPaths,false); // inputPaths es null en el caso de shell interactive return this; } - @Override + @NotNull + @Override public JProxyConfig setJProxyInputSourceFileExcludedListener(JProxyInputSourceFileExcludedListener excludedListener) { this.excludedListener = excludedListener; return this; } - @Override + @NotNull + @Override public JProxyConfig setJProxyCompilerListener(JProxyCompilerListener compilerListener) { this.compilerListener = compilerListener; return this; } + @NotNull @Override public JProxyConfig setClassFolder(String classFolder) { @@ -83,6 +94,7 @@ public JProxyConfig setClassFolder(String classFolder) return this; } + @NotNull @Override public JProxyConfig setScanPeriod(long scanPeriod) { @@ -91,6 +103,7 @@ public JProxyConfig setScanPeriod(long scanPeriod) return this; } + @NotNull @Override public JProxyConfig setCompilationOptions(Iterable compilationOptions) { @@ -98,6 +111,7 @@ public JProxyConfig setCompilationOptions(Iterable compilationOptions) return this; } + @NotNull @Override public JProxyConfig setJProxyDiagnosticsListener(JProxyDiagnosticsListener diagnosticsListener) { diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyDefaultImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyDefaultImpl.java index a4ed4f5..83251da 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyDefaultImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyDefaultImpl.java @@ -2,6 +2,8 @@ import com.sillelien.dollar.relproxy.impl.jproxy.core.JProxyImpl; import com.sillelien.dollar.relproxy.jproxy.JProxyConfig; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * @@ -13,7 +15,8 @@ public JProxyDefaultImpl() { } - @Override + @Nullable + @Override public Class getMainParamClass() { return null; @@ -24,7 +27,7 @@ public static JProxyConfig createJProxyConfig() return new JProxyConfigImpl(); } - public static void initStatic(JProxyConfigImpl config) + public static void initStatic(@NotNull JProxyConfigImpl config) { if (!config.isEnabled()) return; @@ -34,7 +37,8 @@ public static void initStatic(JProxyConfigImpl config) } - public static T createStatic(T obj,Class clasz) + @Nullable + public static T createStatic(T obj, Class clasz) { if (SINGLETON == null) return obj; // No se ha llamado al init o enabled = false @@ -42,7 +46,8 @@ public static T createStatic(T obj,Class clasz) return SINGLETON.create(obj, clasz); } - public static Object createStatic(Object obj,Class[] classes) + @Nullable + public static Object createStatic(Object obj, @NotNull Class[] classes) { if (SINGLETON == null) return obj; // No se ha llamado al init o enabled = false diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyUtil.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyUtil.java index 86b3716..dcfa297 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyUtil.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyUtil.java @@ -1,6 +1,8 @@ package com.sillelien.dollar.relproxy.impl.jproxy; import com.sillelien.dollar.relproxy.RelProxyException; +import org.jetbrains.annotations.NotNull; + import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.File; @@ -20,7 +22,7 @@ */ public class JProxyUtil { - public static String getCanonicalPath(File file) + public static String getCanonicalPath(@NotNull File file) { try { @@ -32,7 +34,7 @@ public static String getCanonicalPath(File file) } } - public static String getFileExtension(File file) + public static String getFileExtension(@NotNull File file) { String path = file.getAbsolutePath(); int pos = path.lastIndexOf('.'); @@ -41,12 +43,12 @@ public static String getFileExtension(File file) return ""; } - public static File getParentDir(File file) + public static File getParentDir(@NotNull File file) { return file.getParentFile(); } - public static byte[] readURL(URL url) + public static byte[] readURL(@NotNull URL url) { URLConnection urlCon; try @@ -57,7 +59,7 @@ public static byte[] readURL(URL url) catch (IOException ex) { throw new RelProxyException(ex); } } - public static byte[] readFile(File file) + public static byte[] readFile(@NotNull File file) { FileInputStream fis = null; try @@ -72,12 +74,12 @@ public static byte[] readFile(File file) return readInputStream(fis); } - public static byte[] readInputStream(InputStream is) + public static byte[] readInputStream(@NotNull InputStream is) { return readInputStream(is,50); // 50Kb => unas 100 lecturas 5 Mb } - public static byte[] readInputStream(InputStream is,int bufferSizeKb) + public static byte[] readInputStream(@NotNull InputStream is, int bufferSizeKb) { ByteArrayOutputStream out = new ByteArrayOutputStream(); try @@ -102,7 +104,7 @@ public static byte[] readInputStream(InputStream is,int bufferSizeKb) return out.toByteArray(); } - public static void saveFile(File file,byte[] content) + public static void saveFile(@NotNull File file, @NotNull byte[] content) { File parent = getParentDir(file); if (parent != null) parent.mkdirs(); @@ -122,7 +124,7 @@ public static void saveFile(File file,byte[] content) } } - public static String readTextFile(File file,String encoding) + public static String readTextFile(@NotNull File file, @NotNull String encoding) { Reader reader = null; try @@ -134,7 +136,7 @@ public static String readTextFile(File file,String encoding) return readTextFile(reader); } - public static String readTextFile(Reader reader) + public static String readTextFile(@NotNull Reader reader) { BufferedReader br = null; try diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyImpl.java index 93c9fb9..8c9883c 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyImpl.java @@ -10,6 +10,8 @@ import com.sillelien.dollar.relproxy.jproxy.JProxyCompilerListener; import com.sillelien.dollar.relproxy.jproxy.JProxyDiagnosticsListener; import com.sillelien.dollar.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * @@ -30,12 +32,14 @@ public static ClassLoader getDefaultClassLoader() return Thread.currentThread().getContextClassLoader(); } - public ClassDescriptorSourceScript init(JProxyConfigImpl config) + @Nullable + public ClassDescriptorSourceScript init(@NotNull JProxyConfigImpl config) { return init(config,null,null); } - public ClassDescriptorSourceScript init(JProxyConfigImpl config,SourceScriptRoot scriptFile,ClassLoader classLoader) + @Nullable + public ClassDescriptorSourceScript init(@NotNull JProxyConfigImpl config, SourceScriptRoot scriptFile, ClassLoader classLoader) { super.init(config); @@ -80,11 +84,13 @@ public boolean start() return engine.start(); } + @NotNull @Override - public GenericProxyInvocationHandler createGenericProxyInvocationHandler(Object obj) + public GenericProxyInvocationHandler createGenericProxyInvocationHandler(@NotNull Object obj) { return new JProxyInvocationHandler(obj,this); } + @Nullable public abstract Class getMainParamClass(); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyInvocationHandler.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyInvocationHandler.java index 2cb390e..d4223e5 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyInvocationHandler.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyInvocationHandler.java @@ -2,6 +2,7 @@ package com.sillelien.dollar.relproxy.impl.jproxy.core; import com.sillelien.dollar.relproxy.impl.GenericProxyInvocationHandler; +import org.jetbrains.annotations.NotNull; /** * @@ -9,12 +10,13 @@ */ public class JProxyInvocationHandler extends GenericProxyInvocationHandler { - public JProxyInvocationHandler(Object obj,JProxyImpl root) + public JProxyInvocationHandler(@NotNull Object obj, JProxyImpl root) { super(root); this.verObj = new JProxyVersionedObject(obj,this); } + @NotNull public JProxyImpl getJProxyImpl() { return (JProxyImpl)root; diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyVersionedObject.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyVersionedObject.java index d3b07ca..2951dd4 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyVersionedObject.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyVersionedObject.java @@ -2,6 +2,9 @@ import com.sillelien.dollar.relproxy.impl.GenericProxyVersionedObject; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.lang.reflect.Field; /** @@ -12,17 +15,19 @@ public class JProxyVersionedObject extends GenericProxyVersionedObject { protected String className; - public JProxyVersionedObject(Object obj,JProxyInvocationHandler parent) + public JProxyVersionedObject(@NotNull Object obj, JProxyInvocationHandler parent) { super(obj,parent); this.className = obj.getClass().getName(); } + @NotNull public JProxyInvocationHandler getJProxyInvocationHandler() { return (JProxyInvocationHandler)parent; } + @Nullable @Override protected Class reloadClass() { diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java index d9b48e7..9e54d35 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java @@ -2,6 +2,9 @@ import com.sillelien.dollar.relproxy.RelProxyException; import com.sillelien.dollar.relproxy.impl.FileExt; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.io.File; /** @@ -12,7 +15,7 @@ public class FolderSourceList { protected FileExt[] sourceList; - public FolderSourceList(String[] sourcePathList,boolean expectedDirectory) + public FolderSourceList(@Nullable String[] sourcePathList, boolean expectedDirectory) { if (sourcePathList != null) // En el caso de shell interactivo es null { @@ -44,7 +47,8 @@ public FileExt[] getArray() return sourceList; } - public String buildClassNameFromFile(FileExt sourceFile) + @Nullable + public String buildClassNameFromFile(@NotNull FileExt sourceFile) { for(FileExt rootFolderOfSources : sourceList) { @@ -55,7 +59,7 @@ public String buildClassNameFromFile(FileExt sourceFile) throw new RelProxyException("File not found in source folders: " + sourceFile.getFile().getAbsolutePath()); } - public static String buildClassNameFromFile(FileExt sourceFile,FileExt rootFolderOfSources) + public static String buildClassNameFromFile(@NotNull FileExt sourceFile, @NotNull FileExt rootFolderOfSources) { String path = sourceFile.getCanonicalPath(); diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java index 328b1b9..8552bbc 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java @@ -3,6 +3,9 @@ import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.net.URL; /** @@ -11,16 +14,17 @@ */ public class JProxyClassLoader extends ClassLoader { + @NotNull protected final JProxyEngine engine; - public JProxyClassLoader(JProxyEngine engine) + public JProxyClassLoader(@NotNull JProxyEngine engine) { super(engine.getRootClassLoader()); this.engine = engine; } - public Class defineClass(ClassDescriptor classDesc) + public Class defineClass(@NotNull ClassDescriptor classDesc) { Object monitor = engine.getMonitor(); synchronized(monitor) @@ -34,7 +38,7 @@ public Class defineClass(ClassDescriptor classDesc) } @Override - protected Class findClass(String name) throws ClassNotFoundException + protected Class findClass(@NotNull String name) throws ClassNotFoundException { Object monitor = engine.getMonitor(); synchronized(monitor) @@ -54,7 +58,7 @@ protected Class findClass(String name) throws ClassNotFoundException } } - public Class loadClass(ClassDescriptor classDesc,boolean resolve) + public Class loadClass(@NotNull ClassDescriptor classDesc, boolean resolve) { Object monitor = engine.getMonitor(); synchronized(monitor) @@ -69,7 +73,8 @@ public Class loadClass(ClassDescriptor classDesc,boolean resolve) } } - public Class loadInnerClass(ClassDescriptorSourceUnit parentDesc,String innerClassName) + @Nullable + public Class loadInnerClass(@NotNull ClassDescriptorSourceUnit parentDesc, @NotNull String innerClassName) { Object monitor = engine.getMonitor(); synchronized(monitor) @@ -88,7 +93,7 @@ public Class loadInnerClass(ClassDescriptorSourceUnit parentDesc,String innerCla } @Override - protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException + protected Class loadClass(@NotNull String name, boolean resolve) throws ClassNotFoundException { // Inspiraciones en URLClassLoader.findClass y en el propio análisis de ClassLoader.loadClass // Lo redefinimos por si acaso porque el objetivo es recargar todas las clases hot-reloaded en este ClassLoader y no delegar en el parent @@ -140,7 +145,7 @@ protected Class loadClass(String name, boolean resolve) throws ClassNotFoundE } } - private byte[] getClassBytesFromResource(String className) + private byte[] getClassBytesFromResource(@NotNull String className) { String relClassPath = ClassDescriptor.getRelativeClassFilePathFromClassName(className); URL urlClass = getResource(relClassPath); diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java index 8fc57ad..efdfdd7 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java @@ -10,6 +10,9 @@ import com.sillelien.dollar.relproxy.jproxy.JProxyCompilerListener; import com.sillelien.dollar.relproxy.jproxy.JProxyDiagnosticsListener; import com.sillelien.dollar.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.util.LinkedList; import java.util.Timer; import java.util.TimerTask; @@ -22,12 +25,15 @@ public class JProxyEngine { protected final Object monitor = new Object(); // Podríamos usar este objeto JProxyEngine directamente pero el monitor es mejor para análisis de dependencias protected final JProxyImpl parent; + @NotNull protected final JProxyEngineChangeDetectorAndCompiler delegateChangeDetector; protected final ClassLoader rootClassLoader; + @Nullable protected JProxyClassLoader customClassLoader; protected final long scanPeriod; protected final String sourceEncoding = "UTF-8"; // Por ahora, provisional public volatile boolean stop = false; + @Nullable protected TimerTask task; protected boolean pendingReload = false; protected final boolean enabled; @@ -44,6 +50,7 @@ public JProxyEngine(JProxyImpl parent,boolean enabled,SourceScriptRoot scriptFil this.customClassLoader = null; //new JProxyClassLoader(this); } + @NotNull public Object getMonitor() { return monitor; @@ -59,6 +66,7 @@ public boolean isEnabled() return enabled; } + @Nullable public ClassDescriptorSourceScript init() { synchronized(getMonitor()) @@ -80,6 +88,7 @@ public JProxyClassLoader getJProxyClassLoader() } */ + @Nullable public ClassLoader getCurrentClassLoader() { if (customClassLoader != null) @@ -133,6 +142,7 @@ public ClassLoader getRootClassLoader() return rootClassLoader; } + @NotNull public String getSourceEncoding() { return sourceEncoding; @@ -179,7 +189,8 @@ public boolean start() - public ClassDescriptor getClassDescriptor(String className) + @Nullable + public ClassDescriptor getClassDescriptor(@NotNull String className) { synchronized(getMonitor()) { @@ -187,7 +198,8 @@ public ClassDescriptor getClassDescriptor(String className) } } - public Class findClass(String className) + @Nullable + public Class findClass(@NotNull String className) { // Si ya está cargada la devuelve, y si no se cargó por ningún JProxyClassLoader se intenta cargar por el parent ClassLoader, por lo que siempre devolverá distinto de null si la clase está en el classpath, que debería ser lo normal synchronized(getMonitor()) @@ -220,14 +232,14 @@ private void addNewClassLoader() - private Class reloadSource(ClassDescriptorSourceUnit sourceFile) + private Class reloadSource(@NotNull ClassDescriptorSourceUnit sourceFile) { Class clasz = customClassLoader.loadClass(sourceFile,true); reloadInnerClassesOnly(sourceFile,clasz); return clasz; } - private void reloadInnerClassesOnly(ClassDescriptorSourceUnit sourceFile,Class classParent) + private void reloadInnerClassesOnly(@NotNull ClassDescriptorSourceUnit sourceFile, @NotNull Class classParent) { LinkedList innerClassDescList = sourceFile.getInnerClassDescriptors(); @@ -262,11 +274,13 @@ private void reloadInnerClassesOnly(ClassDescriptorSourceUnit sourceFile,Class c } } + @Nullable public ClassDescriptorSourceScript detectChangesInSources() { return delegateChangeDetector.detectChangesInSources(); } + @Nullable public ClassDescriptorSourceScript detectChangesInSourcesAndReload() { ClassDescriptorSourceScript res = detectChangesInSources(); diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java index 4460e33..4e6f179 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java @@ -16,6 +16,9 @@ import com.sillelien.dollar.relproxy.jproxy.JProxyCompilerListener; import com.sillelien.dollar.relproxy.jproxy.JProxyDiagnosticsListener; import com.sillelien.dollar.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.io.File; import java.util.ArrayList; import java.util.LinkedList; @@ -27,12 +30,14 @@ public class JProxyEngineChangeDetectorAndCompiler { protected final JProxyEngine engine; - protected final JProxyCompilerInMemory compiler; + @NotNull + protected final JProxyCompilerInMemory compiler; protected final FolderSourceList folderSourceList; protected final FolderSourceList requiredExtraJarPaths; protected final SourceScriptRoot scriptFile; // Puede ser nulo protected final String folderClasses; // Puede ser nulo (es decir NO salvar como .class los cambios) protected final JProxyInputSourceFileExcludedListener excludedListener; + @NotNull protected final JavaSourcesSearch sourcesSearch; protected final JProxyCompilerListener compilerListener; protected volatile ClassDescriptorSourceFileRegistry sourceRegistry; @@ -77,7 +82,8 @@ public ClassDescriptorSourceFileRegistry getClassDescriptorSourceFileRegistry() return sourceRegistry; } - public ClassDescriptor getClassDescriptor(String className) + @Nullable + public ClassDescriptor getClassDescriptor(@NotNull String className) { return sourceRegistry.getClassDescriptor(className); } @@ -92,7 +98,7 @@ private JProxyCompilerListener getJProxyCompilerListener() return compilerListener; } - private void cleanBeforeCompile(ClassDescriptorSourceUnit sourceFile) + private void cleanBeforeCompile(@NotNull ClassDescriptorSourceUnit sourceFile) { if (isSaveClassesMode()) deleteClasses(sourceFile); // Antes de que nos las carguemos en memoria la clase principal y las inner tras recompilar @@ -100,7 +106,7 @@ private void cleanBeforeCompile(ClassDescriptorSourceUnit sourceFile) sourceFile.cleanOnSourceCodeChanged(); // El código fuente nuevo puede haber cambiado totalmente las innerclasses antiguas (añadido, eliminado) y por supuesto el bytecode necesita olvidarse } - private void compile(ClassDescriptorSourceUnit sourceFile,JProxyCompilerContext context) + private void compile(@NotNull ClassDescriptorSourceUnit sourceFile, @NotNull JProxyCompilerContext context) { if (sourceFile.getClassBytes() != null) return; // Ya ha sido compilado seguramente por dependencia de un archivo compilado inmediatamente antes, recuerda que el atributo classBytes se pone a null antes de compilar los archivos cambiados/nuevos @@ -108,6 +114,7 @@ private void compile(ClassDescriptorSourceUnit sourceFile,JProxyCompilerContext compiler.compileSourceFile(sourceFile,context,engine.getCurrentClassLoader(),sourceRegistry); } + @Nullable public ClassDescriptorSourceScript detectChangesInSources() { Object monitor = getJProxyEngine().getMonitor(); @@ -251,7 +258,7 @@ else if (srcUnit instanceof SourceScriptRootInMemory) // Caso de shell interacti return scriptFileDesc; } - private void saveClasses(ClassDescriptorSourceUnit sourceFile) + private void saveClasses(@NotNull ClassDescriptorSourceUnit sourceFile) { // Salvamos la clase principal { @@ -271,7 +278,7 @@ private void saveClasses(ClassDescriptorSourceUnit sourceFile) } } - private void deleteClasses(ClassDescriptorSourceUnit sourceFile) + private void deleteClasses(@NotNull ClassDescriptorSourceUnit sourceFile) { // Puede ocurrir que esta clase nunca se haya cargado y se ha modificado el código fuente y queramos limpiar los .class correspondientes pues se van a recrear // como no conocemos qué inner clases están asociadas para saber que .class hay que eliminar, pues lo que hacemos es directamente obtener los .class que hay diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java index 536113b..459278f 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JavaSourcesSearch.java @@ -13,75 +13,79 @@ import com.sillelien.dollar.relproxy.impl.FileExt; import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; import com.sillelien.dollar.relproxy.jproxy.JProxyInputSourceFileExcludedListener; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.io.File; import java.net.URL; import java.util.LinkedList; /** + * Additions hello@neilellis.me * * @author jmarranz */ -public class JavaSourcesSearch -{ +public class JavaSourcesSearch { + @NotNull protected final JProxyEngineChangeDetectorAndCompiler parent; - - public JavaSourcesSearch(JProxyEngineChangeDetectorAndCompiler parent) - { + + public JavaSourcesSearch(@NotNull JProxyEngineChangeDetectorAndCompiler parent) { + if (parent == null) { + throw new IllegalArgumentException("JProxyEngineChangeDetectorAndCompiler parent was null"); + } this.parent = parent; } - public JProxyEngineChangeDetectorAndCompiler getJProxyEngineChangeDetectorAndCompiler() - { + @NotNull + public JProxyEngineChangeDetectorAndCompiler getJProxyEngineChangeDetectorAndCompiler() { return parent; } - - public ClassDescriptorSourceScript sourceFileSearch(boolean firstTime,SourceScriptRoot scriptFile,ClassDescriptorSourceFileRegistry sourceRegistry,LinkedList updatedSourceFiles,LinkedList newSourceFiles) - { - ClassDescriptorSourceScript scriptFileDesc = (scriptFile == null) ? null : processSourceFileScript(firstTime,scriptFile,sourceRegistry,updatedSourceFiles,newSourceFiles); - FileExt[] folderSourceList = parent.getFolderSourceList().getArray(); - if (folderSourceList == null) // Es el caso de shell interactivo o code snippet + + @Nullable + public ClassDescriptorSourceScript sourceFileSearch(boolean firstTime, @Nullable SourceScriptRoot scriptFile, @NotNull ClassDescriptorSourceFileRegistry sourceRegistry, @NotNull LinkedList updatedSourceFiles, @NotNull LinkedList newSourceFiles) { + ClassDescriptorSourceScript scriptFileDesc = (scriptFile == null) ? null : processSourceFileScript(firstTime, scriptFile, sourceRegistry, updatedSourceFiles, newSourceFiles); + @NotNull FolderSourceList folderSourceList = parent.getFolderSourceList(); + FileExt[] folderSourceArray = folderSourceList.getArray(); + // Es el caso de shell interactivo o code snippet + if (folderSourceArray == null) { return scriptFileDesc; - + } + boolean allEmpty = true; - String scriptFileJavaCannonPath = (scriptFile != null && (scriptFile instanceof SourceScriptRootFileJavaExt)) ? ((SourceScriptRootFileJavaExt)scriptFile).getFileExt().getCanonicalPath() : null; + String scriptFileJavaCannonPath = (scriptFile != null && (scriptFile instanceof SourceScriptRootFileJavaExt)) ? ((SourceScriptRootFileJavaExt) scriptFile).getFileExt().getCanonicalPath() : null; - for(int i = 0; i < folderSourceList.length; i++) - { - FileExt rootFolderOfSources = folderSourceList[i]; - String[] children = rootFolderOfSources.getFile().list(); - if (children == null) continue; // El que ha configurado los rootFolders es tonto y ha puesto alguno nulo o no es válido el path + for (int i = 0; i < folderSourceArray.length; i++) { + FileExt rootFolderOfSources = folderSourceArray[i]; + String[] children = rootFolderOfSources.getFile().list(); + if (children == null) + continue; // El que ha configurado los rootFolders es tonto y ha puesto alguno nulo o no es válido el path if (children.length == 0) continue; // Empty if (allEmpty) allEmpty = false; - recursiveSourceFileJavaSearch(firstTime,scriptFileJavaCannonPath, i ,rootFolderOfSources,children,sourceRegistry,updatedSourceFiles,newSourceFiles); - } - + recursiveSourceFileJavaSearch(firstTime, scriptFileJavaCannonPath, i, rootFolderOfSources, children, sourceRegistry, updatedSourceFiles, newSourceFiles); + } + if (allEmpty) throw new RelProxyException("All specified input source folders are empty"); return scriptFileDesc; } - - private void recursiveSourceFileJavaSearch(boolean firstTime,String scriptFileJavaCannonPath,int rootFolderOfSourcesIndex,FileExt parentPath,String[] relPathList,ClassDescriptorSourceFileRegistry sourceRegistry,LinkedList updatedSourceFiles,LinkedList newSourceFiles) - { - FileExt rootFolderOfSources = parent.getFolderSourceList().getArray()[rootFolderOfSourcesIndex]; - JProxyInputSourceFileExcludedListener listener = parent.getJProxyInputSourceFileExcludedListener(); - - for(String relPath : relPathList) - { + + private void recursiveSourceFileJavaSearch(boolean firstTime, @Nullable String scriptFileJavaCannonPath, int rootFolderOfSourcesIndex, @NotNull FileExt parentPath, @NotNull String[] relPathList, @NotNull ClassDescriptorSourceFileRegistry sourceRegistry, @NotNull LinkedList updatedSourceFiles, @NotNull LinkedList newSourceFiles) { + FileExt rootFolderOfSources = parent.getFolderSourceList().getArray()[rootFolderOfSourcesIndex]; + JProxyInputSourceFileExcludedListener listener = parent.getJProxyInputSourceFileExcludedListener(); + + for (String relPath : relPathList) { File file = new File(parentPath.getCanonicalPath() + "/" + relPath); - FileExt fileExt = new FileExt(file); - if (file.isDirectory()) - { - if (listener != null && listener.isExcluded(file,rootFolderOfSources.getFile())) - continue; - + FileExt fileExt = new FileExt(file); + if (file.isDirectory()) { + if (listener != null && listener.isExcluded(file, rootFolderOfSources.getFile())) + continue; + String[] children = file.list(); // Si está vacío el array está vacío pero existe - recursiveSourceFileJavaSearch(firstTime,scriptFileJavaCannonPath,rootFolderOfSourcesIndex,fileExt,children,sourceRegistry,updatedSourceFiles,newSourceFiles); - } - else - { + recursiveSourceFileJavaSearch(firstTime, scriptFileJavaCannonPath, rootFolderOfSourcesIndex, fileExt, children, sourceRegistry, updatedSourceFiles, newSourceFiles); + } else { String ext = JProxyUtil.getFileExtension(file); // Si no tiene extensión devuelve "" if (!"java".equals(ext)) continue; //if (!"jsh".equals(ext)) continue; @@ -89,105 +93,93 @@ private void recursiveSourceFileJavaSearch(boolean firstTime,String scriptFileJa String cannonPath = JProxyUtil.getCanonicalPath(file); if (scriptFileJavaCannonPath != null && scriptFileJavaCannonPath.equals(cannonPath)) continue; // Es el propio archivo script inicial que es .java, así evitamos considerarlo dos veces - - if (listener != null && listener.isExcluded(file,rootFolderOfSources.getFile())) + + if (listener != null && listener.isExcluded(file, rootFolderOfSources.getFile())) continue; - - SourceFileJavaNormal sourceFile = new SourceFileJavaNormal(fileExt,rootFolderOfSources); - processSourceFileJava(firstTime,sourceFile,sourceRegistry,updatedSourceFiles,newSourceFiles); + + SourceFileJavaNormal sourceFile = new SourceFileJavaNormal(fileExt, rootFolderOfSources); + processSourceFileJava(firstTime, sourceFile, sourceRegistry, updatedSourceFiles, newSourceFiles); } } - } - - private ClassDescriptorSourceScript processSourceFileScript(boolean firstTime,SourceScriptRoot file,ClassDescriptorSourceFileRegistry sourceRegistry,LinkedList updatedSourceFiles,LinkedList newSourceFiles) - { - return (ClassDescriptorSourceScript)processSourceFile(firstTime,file,true,sourceRegistry,updatedSourceFiles,newSourceFiles); - } - - private ClassDescriptorSourceFileJava processSourceFileJava(boolean firstTime,SourceFileJavaNormal file,ClassDescriptorSourceFileRegistry sourceRegistry,LinkedList updatedSourceFiles,LinkedList newSourceFiles) - { - return (ClassDescriptorSourceFileJava)processSourceFile(firstTime,file,false,sourceRegistry,updatedSourceFiles,newSourceFiles); } - - private ClassDescriptorSourceUnit processSourceFile(boolean firstTime,SourceUnit file,boolean script,ClassDescriptorSourceFileRegistry sourceRegistry,LinkedList updatedSourceFiles,LinkedList newSourceFiles) - { + + @NotNull + private ClassDescriptorSourceScript processSourceFileScript(boolean firstTime, @NotNull SourceScriptRoot file, @NotNull ClassDescriptorSourceFileRegistry sourceRegistry, @NotNull LinkedList updatedSourceFiles, @NotNull LinkedList newSourceFiles) { + return (ClassDescriptorSourceScript) processSourceFile(firstTime, file, true, sourceRegistry, updatedSourceFiles, newSourceFiles); + } + + @NotNull + private ClassDescriptorSourceFileJava processSourceFileJava(boolean firstTime, @NotNull SourceFileJavaNormal file, @NotNull ClassDescriptorSourceFileRegistry sourceRegistry, @NotNull LinkedList updatedSourceFiles, @NotNull LinkedList newSourceFiles) { + return (ClassDescriptorSourceFileJava) processSourceFile(firstTime, file, false, sourceRegistry, updatedSourceFiles, newSourceFiles); + } + + @Nullable + private ClassDescriptorSourceUnit processSourceFile(boolean firstTime, @NotNull SourceUnit file, boolean script, @NotNull ClassDescriptorSourceFileRegistry sourceRegistry, @NotNull LinkedList updatedSourceFiles, @NotNull LinkedList newSourceFiles) { JProxyEngine engine = parent.getJProxyEngine(); - String className = file.getClassName(); - + String className = file.getClassName(); + long timestampSourceFile = file.lastModified(); ClassDescriptorSourceUnit sourceFile; - if (!firstTime) - { + if (!firstTime) { Object monitor = engine.getMonitor(); - synchronized(monitor) - { + synchronized (monitor) { sourceFile = sourceRegistry.getClassDescriptorSourceUnit(className); } - + if (sourceFile != null) // Cambiado { long oldTimestamp = sourceFile.getTimestamp(); - - if (timestampSourceFile > oldTimestamp) - { - synchronized(monitor) - { + + if (timestampSourceFile > oldTimestamp) { + synchronized (monitor) { sourceFile.updateTimestamp(timestampSourceFile); } updatedSourceFiles.add(sourceFile); } - sourceFile.setPendingToRemove( false ); // Encontrado, no se elimina porque sigue existiendo - } - else // Clase nueva + sourceFile.setPendingToRemove(false); // Encontrado, no se elimina porque sigue existiendo + } else // Clase nueva { - sourceFile = ClassDescriptorSourceUnit.create(script,engine,className,file,timestampSourceFile); - sourceFile.setPendingToRemove( false ); // Está ya por defecto pero para que quede claro + sourceFile = ClassDescriptorSourceUnit.create(script, engine, className, file, timestampSourceFile); + sourceFile.setPendingToRemove(false); // Está ya por defecto pero para que quede claro newSourceFiles.add(sourceFile); } - } - else // Primera vez, vemos si el código fuente se ha cambiado respecto a los .class en el sistema de archivos + } else // Primera vez, vemos si el código fuente se ha cambiado respecto a los .class en el sistema de archivos { String relClassPath = ClassDescriptor.getRelativeClassFilePathFromClassName(className); ClassLoader parentClassLoader = engine.getRootClassLoader(); URL urlClass = parentClassLoader.getResource(relClassPath); - if (urlClass != null) - { + if (urlClass != null) { String urlClassExt = urlClass.toExternalForm(); // Si el .class está en un JAR podríamos obtener el timestamp del archivo dentro del jar pero que haya un .java "fuera" reloadable indica que queremos "reemplazar" el del jar por lo que siempre se considerará que el archivo fuente ha sido modificado más reciente long timestampCompiledClass = urlClassExt.startsWith("file:") ? new File(urlClass.getPath()).lastModified() : 0; // 0 cuando está en un JAR - if (timestampSourceFile > timestampCompiledClass) - { - sourceFile = ClassDescriptorSourceUnit.create(script,engine,className,file,timestampSourceFile); + if (timestampSourceFile > timestampCompiledClass) { + sourceFile = ClassDescriptorSourceUnit.create(script, engine, className, file, timestampSourceFile); updatedSourceFiles.add(sourceFile); // Hay que recompilar //System.out.println("UPDATED: " + className + " " + urlClass.toExternalForm() + " " + (timestampSourceFile - timestampCompiledClass)); - } - else - { + } else { // Esto es lo normal en carga si no hemos tocado el código tras el deploy, que el .class sea más reciente que el .java - sourceFile = ClassDescriptorSourceUnit.create(script,engine,className,file,timestampCompiledClass); + sourceFile = ClassDescriptorSourceUnit.create(script, engine, className, file, timestampCompiledClass); byte[] classBytes = JProxyUtil.readURL(urlClass); - sourceFile.setClassBytes(classBytes); + sourceFile.setClassBytes(classBytes); // Falta cargar las posibles inner classes, hay que tener en cuenta que este archivo NO se va a compilar porque no ha cambiado respecto a .class conocido //System.out.println("NOT UPDATED: " + className + " " + urlClass.toExternalForm() + " " + (timestampSourceFile - timestampCompiledClass)); } - } - else // No hay .class, es un archivo fuente nuevo creado antes de cargar la app web, hay que compilar si o si + } else // No hay .class, es un archivo fuente nuevo creado antes de cargar la app web, hay que compilar si o si { - sourceFile = ClassDescriptorSourceUnit.create(script,engine,className,file,timestampSourceFile); + sourceFile = ClassDescriptorSourceUnit.create(script, engine, className, file, timestampSourceFile); newSourceFiles.add(sourceFile); } - + Object monitor = engine.getMonitor(); - synchronized(monitor) - { + synchronized (monitor) { sourceRegistry.addClassDescriptorSourceUnit(sourceFile); // El registro de archivos se hace por primera vez por lo que hay que añadirlos todos inicialmente, updatedSourceFiles y newSourceFiles indicarán en este caso los que hay que recompilar además } } return sourceFile; - } + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java index 99bc7ac..3633838 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java @@ -1,5 +1,7 @@ package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc; +import org.jetbrains.annotations.NotNull; + import java.io.File; /** @@ -8,13 +10,16 @@ */ public abstract class ClassDescriptor { + @NotNull protected final String className; // El nombre basado en puntos pero usando $ en el caso de innerclasses + @NotNull protected final String simpleClassName; // className sin el package + @NotNull protected final String packageName; // El package pero acabado en un "." o bien "" si no hay package, el motivo de acabar en un punto es simplemente para poder concatenar ciegamente el package y el simpleClassName protected byte[] classBytes; protected Class clasz; - public ClassDescriptor(String className) + public ClassDescriptor(@NotNull String className) { this.className = className; int pos = className.lastIndexOf('.'); @@ -24,16 +29,19 @@ public ClassDescriptor(String className) public abstract boolean isInnerClass(); - public String getClassName() + @NotNull + public String getClassName() { return className; } + @NotNull public String getSimpleClassName() { return simpleClassName; } + @NotNull public String getPackageName() { return packageName; @@ -71,7 +79,7 @@ public String getClassFileNameFromClassName() } */ - public static String getClassFileNameFromClassName(String className) + public static String getClassFileNameFromClassName(@NotNull String className) { // Es válido también para las innerclasses (ej Nombre$Otro => Nombre$Otro.class, Nombre$1 => Nombre$1.class, Nombre$1Nombre => Nombre$1Nombre.class int pos = className.lastIndexOf("."); @@ -79,12 +87,13 @@ public static String getClassFileNameFromClassName(String className) return className + ".class"; } - public static String getRelativeClassFilePathFromClassName(String className) + public static String getRelativeClassFilePathFromClassName(@NotNull String className) { return className.replace('.','/') + ".class"; // alternativa: className.replaceAll("\\.", "/") + ".class" } - public static String getRelativePackagePathFromClassName(String className) + @NotNull + public static String getRelativePackagePathFromClassName(@NotNull String className) { String packageName = className.replace('.','/'); int pos = packageName.lastIndexOf('/'); @@ -92,7 +101,7 @@ public static String getRelativePackagePathFromClassName(String className) return packageName.substring(0,pos); } - public static File getAbsoluteClassFilePathFromClassNameAndClassPath(String className,String classPath) + public static File getAbsoluteClassFilePathFromClassNameAndClassPath(@NotNull String className, String classPath) { String relativePath = getRelativeClassFilePathFromClassName(className); classPath = classPath.trim(); @@ -100,7 +109,7 @@ public static File getAbsoluteClassFilePathFromClassNameAndClassPath(String clas return new File(classPath + relativePath); } - public static String getClassNameFromRelativeClassFilePath(String path) + public static String getClassNameFromRelativeClassFilePath(@NotNull String path) { // Ej. org/w3c/dom/Element.class => org.w3c.dom.Element String binaryName = path.replaceAll("/", "."); diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java index 7190866..118e81b 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java @@ -1,5 +1,7 @@ package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc; +import org.jetbrains.annotations.NotNull; + /** * * @author jmarranz @@ -8,7 +10,7 @@ public class ClassDescriptorInner extends ClassDescriptor { protected final ClassDescriptorSourceUnit parent; - public ClassDescriptorInner(String className,ClassDescriptorSourceUnit parent) + public ClassDescriptorInner(@NotNull String className, ClassDescriptorSourceUnit parent) { super(className); this.parent = parent; diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java index 1300fea..351d73b 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java @@ -3,6 +3,7 @@ import com.sillelien.dollar.relproxy.impl.FileExt; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; +import org.jetbrains.annotations.NotNull; /** * @@ -10,11 +11,12 @@ */ public class ClassDescriptorSourceFileJava extends ClassDescriptorSourceUnit { - public ClassDescriptorSourceFileJava(JProxyEngine engine,String className, SourceFileJavaNormal sourceFile, long timestamp) + public ClassDescriptorSourceFileJava(JProxyEngine engine, @NotNull String className, SourceFileJavaNormal sourceFile, long timestamp) { super(engine,className, sourceFile, timestamp); } + @NotNull public SourceFileJavaNormal getSourceFileJavaNormal() { return (SourceFileJavaNormal)sourceUnit; diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java index bf0b64b..a532809 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java @@ -1,5 +1,8 @@ package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.util.Collection; import java.util.HashMap; import java.util.LinkedList; @@ -11,6 +14,7 @@ */ public class ClassDescriptorSourceFileRegistry { + @NotNull protected final Map sourceUnitMapByClassName; public ClassDescriptorSourceFileRegistry() @@ -18,7 +22,7 @@ public ClassDescriptorSourceFileRegistry() this.sourceUnitMapByClassName = new HashMap(); } - public ClassDescriptorSourceFileRegistry(ClassDescriptorSourceFileRegistry origin) + public ClassDescriptorSourceFileRegistry(@NotNull ClassDescriptorSourceFileRegistry origin) { this.sourceUnitMapByClassName = new HashMap( origin.sourceUnitMapByClassName ); } @@ -28,6 +32,7 @@ public boolean isEmpty() return sourceUnitMapByClassName.isEmpty(); } + @NotNull public Collection getClassDescriptorSourceFileColl() { return sourceUnitMapByClassName.values(); @@ -43,7 +48,7 @@ public ClassDescriptorSourceUnit removeClassDescriptorSourceUnit(String classNam return sourceUnitMapByClassName.remove(className); } - public void addClassDescriptorSourceUnit(ClassDescriptorSourceUnit sourceFile) + public void addClassDescriptorSourceUnit(@NotNull ClassDescriptorSourceUnit sourceFile) { sourceUnitMapByClassName.put(sourceFile.getClassName(), sourceFile); } @@ -54,7 +59,8 @@ public void setAllClassDescriptorSourceFilesPendingToRemove(boolean pending) entries.getValue().setPendingToRemove(pending); } - public LinkedList getAllClassDescriptorSourceFilesPendingToRemove(LinkedList deletedSourceFiles) + @NotNull + public LinkedList getAllClassDescriptorSourceFilesPendingToRemove(@NotNull LinkedList deletedSourceFiles) { for(Map.Entry entries : sourceUnitMapByClassName.entrySet()) { @@ -66,7 +72,8 @@ public LinkedList getAllClassDescriptorSourceFilesPen return deletedSourceFiles; } - public ClassDescriptor getClassDescriptor(String className) + @Nullable + public ClassDescriptor getClassDescriptor(@NotNull String className) { // Puede ser el de una innerclass // Las innerclasses no están como tales en sourceFileMap pues sólo está la clase contenedora pero también la consideramos hotloadable diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java index 0dda05d..8b76640 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java @@ -4,6 +4,8 @@ import com.sillelien.dollar.relproxy.impl.jproxy.core.JProxyImpl; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import org.jetbrains.annotations.NotNull; + import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.LinkedList; @@ -18,7 +20,7 @@ public class ClassDescriptorSourceScript extends ClassDescriptorSourceUnit { protected String source; - public ClassDescriptorSourceScript(JProxyEngine engine,String className,SourceScriptRoot sourceFile,long timestamp) + public ClassDescriptorSourceScript(JProxyEngine engine, @NotNull String className, SourceScriptRoot sourceFile, long timestamp) { super(engine,className, sourceFile, timestamp); @@ -26,6 +28,7 @@ public ClassDescriptorSourceScript(JProxyEngine engine,String className,SourceSc } + @NotNull public SourceScriptRoot getSourceScript() { return (SourceScriptRoot)sourceUnit; @@ -73,7 +76,7 @@ else if (mainParamClass.equals(ScriptContext.class)) this.source = finalCode.toString(); } - private boolean isCompleteClass(String code) + private boolean isCompleteClass(@NotNull String code) { // Buscamos si hay un " class ..." o un "import..." al comienzo para soportar la definición de una clase completa como script int pos = code.indexOf("class"); @@ -96,7 +99,7 @@ private boolean isCompleteClass(String code) return ("private".equals(visibility) || "public".equals(visibility) || "protected".equals(visibility)); } - private int getFirstPosIgnoringCommentsAndSeparators(String code) + private int getFirstPosIgnoringCommentsAndSeparators(@NotNull String code) { int i = -1; for(i = 0; i < code.length(); i++) @@ -122,12 +125,12 @@ else if (c2 == '*') return i; } - private int getFirstPosIgnoringOneLineComment(String code,int start) + private int getFirstPosIgnoringOneLineComment(@NotNull String code, int start) { return code.indexOf('\n',start); } - private int getFirstPosIgnoringMultiLineComment(String code,int start) + private int getFirstPosIgnoringMultiLineComment(@NotNull String code, int start) { return code.indexOf("*/", start); } @@ -146,7 +149,7 @@ public String getSourceCode() return source; } - public void callMainMethod(LinkedList argsToScript) throws Throwable + public void callMainMethod(@NotNull LinkedList argsToScript) throws Throwable { try { @@ -168,7 +171,7 @@ public Object callMainMethod(ScriptEngine engine,ScriptContext context) throws T return callMainMethod(scriptClass,engine,context); } - public static Object callMainMethod(Class scriptClass,ScriptEngine engine,ScriptContext context) throws Throwable + public static Object callMainMethod(@NotNull Class scriptClass, ScriptEngine engine, ScriptContext context) throws Throwable { try { diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java index 4896ee1..fa8287e 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java @@ -4,6 +4,9 @@ import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceFileJavaNormal; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceUnit; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.util.LinkedList; /** @@ -18,7 +21,7 @@ public abstract class ClassDescriptorSourceUnit extends ClassDescriptor protected LinkedList innerClasses; protected boolean pendingToRemove = false; // Se usa como monohilo, no hay problemas de sincronización - public ClassDescriptorSourceUnit(JProxyEngine engine,String className,SourceUnit sourceFile, long timestamp) + public ClassDescriptorSourceUnit(JProxyEngine engine, @NotNull String className, SourceUnit sourceFile, long timestamp) { super(className); this.engine = engine; @@ -26,7 +29,8 @@ public ClassDescriptorSourceUnit(JProxyEngine engine,String className,SourceUnit this.timestamp = timestamp; } - public static ClassDescriptorSourceUnit create(boolean script,JProxyEngine engine,String className,SourceUnit sourceFile, long timestamp) + @Nullable + public static ClassDescriptorSourceUnit create(boolean script, JProxyEngine engine, @NotNull String className, SourceUnit sourceFile, long timestamp) { if (sourceFile instanceof SourceScriptRoot) return new ClassDescriptorSourceScript(engine,className,(SourceScriptRoot)sourceFile,timestamp); @@ -41,6 +45,7 @@ public SourceUnit getSourceUnit() return sourceUnit; } + @NotNull public String getEncoding() { return engine.getSourceEncoding(); @@ -81,7 +86,7 @@ public void cleanOnSourceCodeChanged() clearInnerClassDescriptors(); // El código fuente nuevo puede haber cambiado totalmente las innerclasses antiguas (añadido, eliminado) } - public boolean isInnerClass(String className) + public boolean isInnerClass(@NotNull String className) { int pos = className.lastIndexOf('$'); if (pos == -1) @@ -101,7 +106,8 @@ public void clearInnerClassDescriptors() innerClasses.clear(); } - public ClassDescriptorInner getInnerClassDescriptor(String className,boolean addWhenMissing) + @Nullable + public ClassDescriptorInner getInnerClassDescriptor(@NotNull String className, boolean addWhenMissing) { if (innerClasses != null) { @@ -117,7 +123,8 @@ public ClassDescriptorInner getInnerClassDescriptor(String className,boolean add return addInnerClassDescriptor(className); } - public ClassDescriptorInner addInnerClassDescriptor(String className) + @Nullable + public ClassDescriptorInner addInnerClassDescriptor(@NotNull String className) { if (!isInnerClass(className)) return null; diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java index c8b20c8..8900a12 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java @@ -12,6 +12,8 @@ import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.JProxyEngineChangeDetectorAndCompiler; import com.sillelien.dollar.relproxy.jproxy.JProxyDiagnosticsListener; +import org.jetbrains.annotations.NotNull; + import java.io.File; import java.util.ArrayList; import java.util.LinkedList; @@ -42,14 +44,15 @@ public JProxyCompilerInMemory(JProxyEngineChangeDetectorAndCompiler engine,Itera this.compiler = ToolProvider.getSystemJavaCompiler(); } - public JProxyCompilerContext createJProxyCompilerContext() + @NotNull + public JProxyCompilerContext createJProxyCompilerContext() { DiagnosticCollector diagnostics = new DiagnosticCollector(); StandardJavaFileManager standardFileManager = compiler.getStandardFileManager(diagnostics, null, null); return new JProxyCompilerContext(standardFileManager,diagnostics,diagnosticsListener); } - public void compileSourceFile(ClassDescriptorSourceUnit sourceFileDesc,JProxyCompilerContext context,ClassLoader currentClassLoader,ClassDescriptorSourceFileRegistry sourceRegistry) + public void compileSourceFile(@NotNull ClassDescriptorSourceUnit sourceFileDesc, @NotNull JProxyCompilerContext context, ClassLoader currentClassLoader, @NotNull ClassDescriptorSourceFileRegistry sourceRegistry) { //File sourceFile = sourceFileDesc.getSourceFile(); LinkedList outClassList = compile(sourceFileDesc,context,currentClassLoader,sourceRegistry); @@ -104,7 +107,7 @@ public void compileSourceFile(ClassDescriptorSourceUnit sourceFileDesc,JProxyCom } } - private LinkedList compile(ClassDescriptorSourceUnit sourceFileDesc,JProxyCompilerContext context,ClassLoader currentClassLoader,ClassDescriptorSourceFileRegistry sourceRegistry) + private LinkedList compile(ClassDescriptorSourceUnit sourceFileDesc, @NotNull JProxyCompilerContext context, ClassLoader currentClassLoader, ClassDescriptorSourceFileRegistry sourceRegistry) { // http://stackoverflow.com/questions/12173294/compiling-fully-in-memory-with-javax-tools-javacompiler // http://www.accordess.com/wpblog/an-overview-of-java-compilation-api-jsr-199/ @@ -151,7 +154,7 @@ else if (sourceFileDesc instanceof ClassDescriptorSourceScript) return classObj; } - private boolean compile(Iterable compilationUnits,JavaFileManager fileManager,JProxyCompilerContext context) + private boolean compile(Iterable compilationUnits, JavaFileManager fileManager, @NotNull JProxyCompilerContext context) { /* String systemClassPath = System.getProperty("java.class.path"); diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java index 7de7a8e..0385854 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java @@ -7,6 +7,8 @@ import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceFileRegistry; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import org.jetbrains.annotations.NotNull; + import java.io.IOException; import java.util.Collection; import java.util.Collections; @@ -33,23 +35,26 @@ public class JavaFileManagerInMemory extends ForwardingJavaFileManager { private final LinkedList outputClassList = new LinkedList(); - private final JavaFileObjectInputClassFinderByClassLoader classFinder; + @NotNull + private final JavaFileObjectInputClassFinderByClassLoader classFinder; private final ClassDescriptorSourceFileRegistry sourceRegistry; - public JavaFileManagerInMemory(StandardJavaFileManager standardFileManager,ClassLoader classLoader,ClassDescriptorSourceFileRegistry sourceRegistry,FolderSourceList requiredExtraJarPaths) + public JavaFileManagerInMemory(@NotNull StandardJavaFileManager standardFileManager, ClassLoader classLoader, ClassDescriptorSourceFileRegistry sourceRegistry, FolderSourceList requiredExtraJarPaths) { super(standardFileManager); this.sourceRegistry = sourceRegistry; this.classFinder = new JavaFileObjectInputClassFinderByClassLoader(classLoader,requiredExtraJarPaths); } + @NotNull public LinkedList getJavaFileObjectOutputClassList() { return outputClassList; } + @NotNull @Override - public JavaFileObject getJavaFileForOutput(Location location,String className, Kind kind, FileObject sibling) throws IOException + public JavaFileObject getJavaFileForOutput(Location location, @NotNull String className, @NotNull Kind kind, FileObject sibling) throws IOException { // Normalmente sólo habrá un resultado pero se da el caso de compilar una clase con una o varias inner classes, el compilador las compila de una vez JavaFileObjectOutputClass outClass = new JavaFileObjectOutputClass(className, kind); @@ -58,7 +63,7 @@ public JavaFileObject getJavaFileForOutput(Location location,String className, K } @Override - public Iterable list(Location location, String packageName, Set kinds, boolean recurse) throws IOException + public Iterable list(Location location, @NotNull String packageName, @NotNull Set kinds, boolean recurse) throws IOException { if (location == StandardLocation.PLATFORM_CLASS_PATH) // let standard manager hanfle return super.list(location, packageName, kinds, recurse); // En este caso nunca (con PLATFORM_CLASS_PATH) va a encontrar nuestros sources ni .class diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java index 62f950f..da16537 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java @@ -7,6 +7,8 @@ import com.sillelien.dollar.relproxy.impl.FileExt; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import org.jetbrains.annotations.NotNull; + import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; @@ -41,7 +43,8 @@ public JavaFileObjectInputClassFinderByClassLoader(ClassLoader classLoader,Folde this.requiredExtraJarPaths = requiredExtraJarPaths; } - public List find(String packageName) throws IOException + @NotNull + public List find(@NotNull String packageName) throws IOException { // http://www.dzone.com/snippets/get-all-classes-within-package // http://sourceforge.net/p/scannotation/code/HEAD/tree/scannotation/src/main/java/org/scannotation/ClasspathUrlFinder.java#l124 @@ -87,7 +90,7 @@ public List find(String packageName) throw } - private void listUnder(String packageName, URL packageFolderURL,Collection result) + private void listUnder(String packageName, @NotNull URL packageFolderURL, @NotNull Collection result) { String pkgPath = packageFolderURL.toExternalForm(); //packageFolderURL.getFile(); El problema de getFile es que también está URL-encoded (un espacio es %20) lo cual no es compatible con File @@ -101,7 +104,7 @@ private void listUnder(String packageName, URL packageFolderURL,Collection result) + private void listUnderDir(String packageName, String pkgPath, @NotNull Collection result) { pkgPath = pkgPath.substring("file:".length()); @@ -129,7 +132,7 @@ private void listUnderDir(String packageName,String pkgPath,Collection result) + private void listUnderJar(@NotNull URL packageFolderURL, @NotNull Collection result) { try { @@ -160,7 +163,7 @@ private void listUnderJar(URL packageFolderURL,Collection result) + private void listUnderJarCustom(@NotNull String packagePath, @NotNull FileExt jarFile, @NotNull Collection result) { String normalizedPath = jarFile.getCanonicalPath(); if (normalizedPath.contains("\\")) // Windows diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java index eeb1b23..3152dac 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java @@ -1,5 +1,7 @@ package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo; +import org.jetbrains.annotations.NotNull; + import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; @@ -15,12 +17,13 @@ public class JavaFileObjectInputClassInFile extends JavaFileObjectInputClassInFi { protected File file; - public JavaFileObjectInputClassInFile(File file,String binaryName, URI uri) + public JavaFileObjectInputClassInFile(File file, String binaryName, @NotNull URI uri) { super(binaryName,uri,uri.getPath()); this.file = file; } + @NotNull @Override public InputStream openInputStream() throws IOException { @@ -34,6 +37,7 @@ public long getLastModified() return file.lastModified(); } + @NotNull @Override public String toString() { return "JavaFileObjectInputClassInFile{uri=" + uri + '}'; diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java index 62bf61e..afbf586 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java @@ -1,5 +1,7 @@ package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo; +import org.jetbrains.annotations.NotNull; + import java.io.IOException; import java.io.OutputStream; import java.io.Reader; @@ -41,21 +43,25 @@ public String getBinaryName() { return binaryName; } + @NotNull @Override public OutputStream openOutputStream() throws IOException { throw new UnsupportedOperationException(); } + @NotNull @Override public Reader openReader(boolean ignoreEncodingErrors) throws IOException { throw new UnsupportedOperationException(); } + @NotNull @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { throw new UnsupportedOperationException(); } + @NotNull @Override public Writer openWriter() throws IOException { throw new UnsupportedOperationException(); @@ -66,24 +72,27 @@ public boolean delete() { throw new UnsupportedOperationException(); } + @NotNull @Override public Kind getKind() { return Kind.CLASS; } @Override // copied from SimpleJavaFileManager - public boolean isNameCompatible(String simpleName, Kind kind) { + public boolean isNameCompatible(String simpleName, @NotNull Kind kind) { String baseName = simpleName + kind.extension; return kind.equals(getKind()) && (baseName.equals(getName()) || getName().endsWith("/" + baseName)); } + @NotNull @Override public NestingKind getNestingKind() { throw new UnsupportedOperationException(); } + @NotNull @Override public Modifier getAccessLevel() { throw new UnsupportedOperationException(); diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java index 4dee882..dfe3757 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java @@ -1,5 +1,7 @@ package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo; +import org.jetbrains.annotations.NotNull; + import java.io.IOException; import java.io.InputStream; import java.net.URI; @@ -12,7 +14,7 @@ public class JavaFileObjectInputClassInJar extends JavaFileObjectInputClassInFil { protected long timestamp; - public JavaFileObjectInputClassInJar(String binaryName, URI uri,long timestamp) + public JavaFileObjectInputClassInJar(String binaryName, @NotNull URI uri, long timestamp) { super(binaryName,uri,uri.getSchemeSpecificPart()); this.timestamp = timestamp; @@ -30,6 +32,7 @@ public long getLastModified() return timestamp; } + @NotNull @Override public String toString() { diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java index d4d764c..c632d7a 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java @@ -1,5 +1,7 @@ package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo; +import org.jetbrains.annotations.NotNull; + import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; @@ -18,7 +20,7 @@ public class JavaFileObjectInputClassInMemory extends SimpleJavaFileObject imple protected byte[] byteCode; protected long timestamp; - public JavaFileObjectInputClassInMemory(String name,byte[] byteCode,long timestamp) + public JavaFileObjectInputClassInMemory(@NotNull String name, byte[] byteCode, long timestamp) { super(URI.create("string:///" + name.replace('.', '/') + Kind.CLASS.extension), Kind.CLASS); @@ -38,12 +40,14 @@ public long getLastModified() return timestamp; } + @NotNull @Override public InputStream openInputStream() throws IOException { return new ByteArrayInputStream(getBytes()); } + @NotNull @Override public OutputStream openOutputStream() throws IOException { diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java index cf40ca1..8e2c67a 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java @@ -1,6 +1,8 @@ package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo; import com.sillelien.dollar.relproxy.RelProxyException; +import org.jetbrains.annotations.NotNull; + import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; @@ -19,7 +21,7 @@ public abstract class JavaFileObjectInputSourceBase extends SimpleJavaFileObject protected String binaryName; protected String encoding; - public JavaFileObjectInputSourceBase(String name,String encoding) + public JavaFileObjectInputSourceBase(@NotNull String name, String encoding) { super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE); // La extensión .java es necesaria aunque sea falsa sino da error @@ -36,7 +38,8 @@ public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOExcept return getSource(); } - public byte[] getBytes() + @NotNull + public byte[] getBytes() { try { @@ -45,12 +48,14 @@ public byte[] getBytes() catch (UnsupportedEncodingException ex) { throw new RelProxyException(ex); } } + @NotNull @Override public InputStream openInputStream() throws IOException { return new ByteArrayInputStream(getBytes()); } + @NotNull @Override public OutputStream openOutputStream() throws IOException { diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java index 8683f69..801d10a 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java @@ -1,6 +1,8 @@ package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo; import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; +import org.jetbrains.annotations.NotNull; + import java.io.File; /** @@ -13,7 +15,7 @@ public class JavaFileObjectInputSourceInFile extends JavaFileObjectInputSourceBa protected File file; protected String source; - public JavaFileObjectInputSourceInFile(String name,File file,String encoding) + public JavaFileObjectInputSourceInFile(@NotNull String name, File file, String encoding) { super(name,encoding); this.file = file; diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java index dca46cd..b613805 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java @@ -1,5 +1,7 @@ package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo; +import org.jetbrains.annotations.NotNull; + /** * http://www.javablogging.com/dynamic-in-memory-compilation/ * @@ -10,7 +12,7 @@ public class JavaFileObjectInputSourceInMemory extends JavaFileObjectInputSource protected String source; protected long timestamp; - public JavaFileObjectInputSourceInMemory(String name,String source,String encoding,long timestamp) + public JavaFileObjectInputSourceInMemory(@NotNull String name, String source, String encoding, long timestamp) { super(name,encoding); this.source = source; diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java index 6fa68d0..62a90aa 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java @@ -1,6 +1,8 @@ package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo; import com.sillelien.dollar.relproxy.RelProxyException; +import org.jetbrains.annotations.NotNull; + import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; @@ -32,7 +34,7 @@ public class JavaFileObjectOutputClass extends SimpleJavaFileObject { * @param kind * Kind of the data. It will be CLASS in our case */ - public JavaFileObjectOutputClass(String name, Kind kind) + public JavaFileObjectOutputClass(@NotNull String name, @NotNull Kind kind) { super(URI.create("string:///" + name.replace('.', '/') + kind.extension), kind); @@ -50,6 +52,7 @@ public byte[] getBytes() return bos.toByteArray(); } + @NotNull @Override public OutputStream openOutputStream() throws IOException { diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java index b4432cf..836c2b0 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java @@ -1,6 +1,7 @@ package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit; import com.sillelien.dollar.relproxy.impl.FileExt; +import org.jetbrains.annotations.NotNull; /** * @@ -8,9 +9,10 @@ */ public class SourceFileJavaNormal extends SourceUnit { + @NotNull protected final FileExt sourceFile; - public SourceFileJavaNormal(FileExt sourceFile,FileExt rootFolderOfSources) + public SourceFileJavaNormal(@NotNull FileExt sourceFile, @NotNull FileExt rootFolderOfSources) { super(buildClassNameFromFile(sourceFile,rootFolderOfSources)); this.sourceFile = sourceFile; @@ -22,6 +24,7 @@ public long lastModified() return sourceFile.getFile().lastModified(); } + @NotNull public FileExt getFileExt() { return sourceFile; diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java index 60b46bb..5456fa3 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java @@ -3,6 +3,7 @@ import com.sillelien.dollar.relproxy.impl.FileExt; import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import org.jetbrains.annotations.NotNull; /** * @@ -12,13 +13,13 @@ public abstract class SourceScriptRootFile extends SourceScriptRoot { protected FileExt sourceFile; - public SourceScriptRootFile(FileExt sourceFile,FolderSourceList folderSourceList) + public SourceScriptRootFile(@NotNull FileExt sourceFile, @NotNull FolderSourceList folderSourceList) { super(buildClassNameFromFile(sourceFile,folderSourceList)); this.sourceFile = sourceFile; } - public static SourceScriptRootFile createSourceScriptRootFile(FileExt sourceFile,FolderSourceList folderSourceList) + public static SourceScriptRootFile createSourceScriptRootFile(@NotNull FileExt sourceFile, @NotNull FolderSourceList folderSourceList) { String ext = JProxyUtil.getFileExtension(sourceFile.getFile()); // Si no tiene extensión devuelve "" if ("java".equals(ext)) diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java index 4aeb091..5e22815 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java @@ -3,6 +3,7 @@ import com.sillelien.dollar.relproxy.impl.FileExt; import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import org.jetbrains.annotations.NotNull; /** * @@ -10,13 +11,14 @@ */ public class SourceScriptRootFileJavaExt extends SourceScriptRootFile { - public SourceScriptRootFileJavaExt(FileExt sourceFile,FolderSourceList folderSourceList) + public SourceScriptRootFileJavaExt(@NotNull FileExt sourceFile, @NotNull FolderSourceList folderSourceList) { super(sourceFile,folderSourceList); } + @NotNull @Override - public String getScriptCode(String encoding,boolean[] hasHashBang) + public String getScriptCode(@NotNull String encoding, boolean[] hasHashBang) { hasHashBang[0] = false; return JProxyUtil.readTextFile(sourceFile.getFile(),encoding); diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java index 154b757..84530c3 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java @@ -3,6 +3,7 @@ import com.sillelien.dollar.relproxy.impl.FileExt; import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import org.jetbrains.annotations.NotNull; /** * @@ -10,13 +11,14 @@ */ public class SourceScriptRootFileOtherExt extends SourceScriptRootFile { - public SourceScriptRootFileOtherExt(FileExt sourceFile,FolderSourceList folderSourceList) + public SourceScriptRootFileOtherExt(@NotNull FileExt sourceFile, @NotNull FolderSourceList folderSourceList) { super(sourceFile,folderSourceList); } + @NotNull @Override - public String getScriptCode(String encoding,boolean[] hasHashBang) + public String getScriptCode(@NotNull String encoding, boolean[] hasHashBang) { String codeBody = JProxyUtil.readTextFile(sourceFile.getFile(),encoding); // Eliminamos la primera línea #! (debe estar en la primera línea y sin espacios antes) diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java index f0b55e2..fd33113 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java @@ -2,6 +2,8 @@ import com.sillelien.dollar.relproxy.impl.FileExt; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * @@ -18,12 +20,14 @@ public SourceUnit(String className) public abstract long lastModified(); - protected static String buildClassNameFromFile(FileExt sourceFile,FolderSourceList sourceList) + @Nullable + protected static String buildClassNameFromFile(@NotNull FileExt sourceFile, @NotNull FolderSourceList sourceList) { return sourceList.buildClassNameFromFile(sourceFile); } - protected static String buildClassNameFromFile(FileExt sourceFile,FileExt rootFolderOfSources) + @Nullable + protected static String buildClassNameFromFile(@NotNull FileExt sourceFile, @NotNull FileExt rootFolderOfSources) { return FolderSourceList.buildClassNameFromFile(sourceFile,rootFolderOfSources); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java index 461c2d5..e658569 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java @@ -9,6 +9,9 @@ import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootInMemory; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.JProxyCompilationException; import com.sillelien.dollar.relproxy.impl.jproxy.shell.JProxyShellClassLoader; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.io.File; import javax.script.ScriptContext; import javax.script.ScriptException; @@ -20,6 +23,7 @@ public class JProxyScriptEngineDelegateImpl extends JProxyImpl { protected JProxyScriptEngineImpl parent; + @Nullable protected ClassDescriptorSourceScript classDescSourceScript; protected long codeBufferModTimestamp = 0; protected long lastCodeCompiledTimestamp = 0; @@ -29,8 +33,9 @@ public JProxyScriptEngineDelegateImpl(JProxyScriptEngineImpl parent) this.parent = parent; } - @Override - public ClassDescriptorSourceScript init(JProxyConfigImpl config) + @Nullable + @Override + public ClassDescriptorSourceScript init(@NotNull JProxyConfigImpl config) { SourceScriptRoot sourceFileScript = SourceScriptRootInMemory.createSourceScriptInMemory(""); @@ -43,12 +48,14 @@ public ClassDescriptorSourceScript init(JProxyConfigImpl config) return classDescSourceScript; } + @NotNull @Override public Class getMainParamClass() { return ScriptContext.class; } + @NotNull private SourceScriptRootInMemory getSourceScriptInMemory() { return (SourceScriptRootInMemory)classDescSourceScript.getSourceScript(); diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java index aab0f23..4c657b3 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java @@ -2,6 +2,8 @@ import com.sillelien.dollar.relproxy.RelProxy; import com.sillelien.dollar.relproxy.jproxy.JProxyScriptEngineFactory; +import org.jetbrains.annotations.NotNull; + import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -17,8 +19,11 @@ public class JProxyScriptEngineFactoryImpl extends JProxyScriptEngineFactory protected static final String SHORT_NAME = "java"; protected static final String LANGUAGE_NAME = "Java"; - protected static final List names; + @NotNull + protected static final List names; + @NotNull protected static final List extensions; + @NotNull protected static final List mimeTypes; static @@ -49,36 +54,42 @@ public static JProxyScriptEngineFactory create() return new JProxyScriptEngineFactoryImpl(); } + @NotNull @Override public String getEngineName() { return "RelProxy Java Script Engine"; } + @NotNull @Override public String getEngineVersion() { return RelProxy.getVersion(); } + @NotNull @Override public List getExtensions() { return extensions; } + @NotNull @Override public List getMimeTypes() { return mimeTypes; } + @NotNull @Override public List getNames() { return names; } + @NotNull @Override public String getLanguageName() { @@ -111,8 +122,9 @@ public Object getParameter(String key) } } + @NotNull @Override - public String getMethodCallSyntax(String obj, String method, String... args) + public String getMethodCallSyntax(String obj, String method, @NotNull String... args) { StringBuilder ret = new StringBuilder(); ret.append(obj + "." + method + "("); @@ -133,8 +145,9 @@ public String getMethodCallSyntax(String obj, String method, String... args) return ret.toString(); } + @NotNull @Override - public String getOutputStatement(String toDisplay) + public String getOutputStatement(@NotNull String toDisplay) { StringBuilder buf = new StringBuilder(); buf.append("System.out.println(\""); @@ -158,8 +171,9 @@ public String getOutputStatement(String toDisplay) return buf.toString(); } + @NotNull @Override - public String getProgram(String... statements) + public String getProgram(@NotNull String... statements) { StringBuilder ret = new StringBuilder(); int len = statements.length; @@ -171,6 +185,7 @@ public String getProgram(String... statements) return ret.toString(); } + @NotNull @Override public ScriptEngine getScriptEngine() { diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java index eab9862..8781e61 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java @@ -6,6 +6,9 @@ import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; import com.sillelien.dollar.relproxy.jproxy.JProxyConfig; import com.sillelien.dollar.relproxy.jproxy.JProxyScriptEngine; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.io.Reader; import javax.script.AbstractScriptEngine; import javax.script.Bindings; @@ -50,12 +53,13 @@ public Object eval(String script, ScriptContext context) throws ScriptException } @Override - public Object eval(Reader reader, ScriptContext context) throws ScriptException + public Object eval(@NotNull Reader reader, ScriptContext context) throws ScriptException { String script = JProxyUtil.readTextFile(reader); return eval(script,context); } + @NotNull @Override public Bindings createBindings() { @@ -68,6 +72,7 @@ public ScriptEngineFactory getFactory() return factory; } + @Nullable @Override public T create(T obj,Class clasz) { @@ -76,8 +81,9 @@ public T create(T obj,Class clasz) return jproxy.create(obj, clasz); } + @Nullable @Override - public Object create(Object obj,Class[] classes) + public Object create(Object obj, @NotNull Class[] classes) { if (jproxy == null) return obj; // No se ha llamado al init o enabled = false diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java index 1941300..6cd7faf 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java @@ -2,6 +2,8 @@ import com.sillelien.dollar.relproxy.RelProxyException; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptor; +import org.jetbrains.annotations.NotNull; + import java.io.File; import java.net.MalformedURLException; import java.net.URL; @@ -13,12 +15,12 @@ */ public class JProxyShellClassLoader extends URLClassLoader { - public JProxyShellClassLoader(ClassLoader parent,File classFolder) + public JProxyShellClassLoader(ClassLoader parent, @NotNull File classFolder) { super(toURLArray(classFolder),parent); } - private static URL[] toURLArray(File file) + private static URL[] toURLArray(@NotNull File file) { try { return new URL[]{file.toURI().toURL()}; } catch (MalformedURLException ex) { throw new RelProxyException(ex); } @@ -36,7 +38,7 @@ protected synchronized Class loadClass(String name, boolean resolve) throws C return super.loadClass(name, resolve); } - public synchronized Class defineClass(ClassDescriptor classDesc) + public synchronized Class defineClass(@NotNull ClassDescriptor classDesc) { String className = classDesc.getClassName(); byte[] classBytes = classDesc.getClassBytes(); diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java index 220909a..df4510a 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java @@ -6,6 +6,9 @@ import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootInMemory; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.util.LinkedList; /** @@ -14,13 +17,13 @@ */ public class JProxyShellCodeSnippetImpl extends JProxyShellImpl { - public void init(String[] args) + public void init(@NotNull String[] args) { super.init(args, null); } @Override - protected void executeFirstTime(ClassDescriptorSourceScript scriptFileDesc,LinkedList argsToScript,JProxyShellClassLoader classLoader) + protected void executeFirstTime(@NotNull ClassDescriptorSourceScript scriptFileDesc, @NotNull LinkedList argsToScript, JProxyShellClassLoader classLoader) { try { @@ -33,7 +36,7 @@ protected void executeFirstTime(ClassDescriptorSourceScript scriptFileDesc,Linke } @Override - protected void processConfigParams(String[] args,LinkedList argsToScript,JProxyConfigImpl config) + protected void processConfigParams(@NotNull String[] args, @NotNull LinkedList argsToScript, @NotNull JProxyConfigImpl config) { super.processConfigParams(args, argsToScript, config); @@ -41,8 +44,9 @@ protected void processConfigParams(String[] args,LinkedList argsToScript if (classFolder != null && !classFolder.trim().isEmpty()) throw new RelProxyException("cacheClassFolder is useless to execute a code snippet"); } - @Override - protected SourceScriptRoot createSourceScriptRoot(String[] args,LinkedList argsToScript,FolderSourceList folderSourceList) + @NotNull + @Override + protected SourceScriptRoot createSourceScriptRoot(String[] args, @NotNull LinkedList argsToScript, FolderSourceList folderSourceList) { // En argsToScript no está el args[0] ni falta que hace porque es el flag "-c" StringBuilder code = new StringBuilder(); @@ -51,7 +55,8 @@ protected SourceScriptRoot createSourceScriptRoot(String[] args,LinkedList no hay necesidad de nuevo ClassLoader diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellImpl.java index adba4a7..e88a295 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellImpl.java @@ -7,6 +7,9 @@ import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.lang.reflect.Method; import java.util.LinkedList; @@ -18,7 +21,7 @@ public abstract class JProxyShellImpl extends JProxyImpl { - public static void main(String[] args) + public static void main(@NotNull String[] args) { if (args[0].isEmpty()) { @@ -43,7 +46,8 @@ public static void main(String[] args) } } - protected ClassDescriptorSourceScript init(String[] args,String inputPath) + @Nullable + protected ClassDescriptorSourceScript init(@NotNull String[] args, String inputPath) { // Esto quizás necesite una opción en plan "verbose" o "log" para mostrar por pantalla o nada RelProxyOnReloadListener proxyListener = new RelProxyOnReloadListener() { @@ -75,6 +79,7 @@ public void onReload(Object objOld, Object objNew, Object proxy, Method method, return scriptFileDesc; } + @NotNull @Override public Class getMainParamClass() { @@ -82,11 +87,14 @@ public Class getMainParamClass() } - protected abstract SourceScriptRoot createSourceScriptRoot(String[] args,LinkedList argsToScript,FolderSourceList folderSourceList); - protected abstract JProxyShellClassLoader getJProxyShellClassLoader(JProxyConfigImpl config); + @NotNull + protected abstract SourceScriptRoot createSourceScriptRoot(String[] args, LinkedList argsToScript, FolderSourceList folderSourceList); + @Nullable + protected abstract JProxyShellClassLoader getJProxyShellClassLoader(JProxyConfigImpl config); protected abstract void executeFirstTime(ClassDescriptorSourceScript scriptFileDesc,LinkedList argsToScript,JProxyShellClassLoader classLoader); - private static Iterable parseCompilationOptions(String value) + @NotNull + private static Iterable parseCompilationOptions(@NotNull String value) { // Ej -source 1.6 -target 1.6 se convertiría en Arrays.asList(new String[]{"-source","1.6","-target","1.6"}); String[] options = value.split(" "); @@ -101,7 +109,7 @@ private static Iterable parseCompilationOptions(String value) } - protected void processConfigParams(String[] args,LinkedList argsToScript,JProxyConfigImpl config) + protected void processConfigParams(@NotNull String[] args, @NotNull LinkedList argsToScript, @NotNull JProxyConfigImpl config) { String classFolder = null; long scanPeriod = -1; diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java index 1a72f62..7ab2f67 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java @@ -7,6 +7,9 @@ import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootInMemory; import com.sillelien.dollar.relproxy.impl.jproxy.shell.inter.JProxyShellProcessor; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.util.LinkedList; /** @@ -17,10 +20,12 @@ public class JProxyShellInteractiveImpl extends JProxyShellImpl { protected boolean test = false; + @NotNull protected JProxyShellProcessor processor = new JProxyShellProcessor(this); + @Nullable protected ClassDescriptorSourceScript classDescSourceScript; - public void init(String[] args) + public void init(@NotNull String[] args) { this.classDescSourceScript = super.init(args, null); @@ -33,18 +38,21 @@ public void init(String[] args) processor.loop(); } + @Nullable public ClassDescriptorSourceScript getClassDescriptorSourceScript() { return classDescSourceScript; } + @NotNull public SourceScriptRootInMemory getSourceScriptInMemory() { return (SourceScriptRootInMemory)classDescSourceScript.getSourceScript(); } + @Nullable @Override - public ClassDescriptorSourceScript init(JProxyConfigImpl config,SourceScriptRoot scriptFile,ClassLoader classLoader) + public ClassDescriptorSourceScript init(@NotNull JProxyConfigImpl config, SourceScriptRoot scriptFile, ClassLoader classLoader) { ClassDescriptorSourceScript script = super.init(config,scriptFile, classLoader); @@ -60,7 +68,7 @@ protected void executeFirstTime(ClassDescriptorSourceScript scriptFileDesc,Linke } @Override - protected void processConfigParams(String[] args,LinkedList argsToScript,JProxyConfigImpl config) + protected void processConfigParams(@NotNull String[] args, @NotNull LinkedList argsToScript, @NotNull JProxyConfigImpl config) { super.processConfigParams(args, argsToScript, config); @@ -68,13 +76,15 @@ protected void processConfigParams(String[] args,LinkedList argsToScript if (classFolder != null && !classFolder.trim().isEmpty()) throw new RelProxyException("cacheClassFolder is useless to execute in interactive mode"); } - @Override + @NotNull + @Override protected SourceScriptRoot createSourceScriptRoot(String[] args,LinkedList argsToScript,FolderSourceList folderSourceList) { return SourceScriptRootInMemory.createSourceScriptInMemory(""); // La primera vez no hace nada, sirve para "calentar" la app } - @Override + @Nullable + @Override protected JProxyShellClassLoader getJProxyShellClassLoader(JProxyConfigImpl config) { // No hay classFolder => no hay necesidad de nuevo ClassLoader diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java index b19d3bb..821fde7 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java @@ -8,6 +8,9 @@ import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.FolderSourceList; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.io.File; import java.util.LinkedList; @@ -19,7 +22,7 @@ public class JProxyShellScriptFileImpl extends JProxyShellImpl { protected FileExt scriptFile; - public void init(String[] args) + public void init(@NotNull String[] args) { File scriptFile = new File(args[0]); if (!scriptFile.exists()) @@ -33,7 +36,7 @@ public void init(String[] args) } @Override - protected void executeFirstTime(ClassDescriptorSourceScript scriptFileDesc,LinkedList argsToScript,JProxyShellClassLoader classLoader) + protected void executeFirstTime(@NotNull ClassDescriptorSourceScript scriptFileDesc, @NotNull LinkedList argsToScript, JProxyShellClassLoader classLoader) { fixLastLoadedClass(scriptFileDesc,classLoader); @@ -47,14 +50,16 @@ protected void executeFirstTime(ClassDescriptorSourceScript scriptFileDesc,Linke } } - @Override - protected SourceScriptRoot createSourceScriptRoot(String[] args,LinkedList argsToScript,FolderSourceList folderSourceList) + @NotNull + @Override + protected SourceScriptRoot createSourceScriptRoot(String[] args, LinkedList argsToScript, @NotNull FolderSourceList folderSourceList) { return SourceScriptRootFile.createSourceScriptRootFile(scriptFile,folderSourceList); } - @Override - protected JProxyShellClassLoader getJProxyShellClassLoader(JProxyConfigImpl config) + @Nullable + @Override + protected JProxyShellClassLoader getJProxyShellClassLoader(@NotNull JProxyConfigImpl config) { String classFolder = config.getClassFolder(); if (classFolder != null) @@ -63,7 +68,7 @@ protected JProxyShellClassLoader getJProxyShellClassLoader(JProxyConfigImpl conf return null; } - protected void fixLastLoadedClass(ClassDescriptorSourceScript scriptFileDesc,JProxyShellClassLoader classLoader) + protected void fixLastLoadedClass(@NotNull ClassDescriptorSourceScript scriptFileDesc, @Nullable JProxyShellClassLoader classLoader) { Class scriptClass = scriptFileDesc.getLastLoadedClass(); if (scriptClass != null) return; diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/Command.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/Command.java index b41f3bb..06b0ebc 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/Command.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/Command.java @@ -1,5 +1,7 @@ package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; +import org.jetbrains.annotations.NotNull; + /** * * @author jmarranz @@ -15,7 +17,7 @@ public Command(JProxyShellProcessor parent,String name) this.name = name; } - public static Command createCommand(JProxyShellProcessor parent,String cmd) + public static Command createCommand(@NotNull JProxyShellProcessor parent, String cmd) { cmd = cmd.trim(); if (cmd.equals("clear")) @@ -86,7 +88,7 @@ else if (cmd.startsWith("save")) return null; // No es un comando } - protected static String getParameter(String cmdName,String cmd) + protected static String getParameter(String cmdName, @NotNull String cmd) { int pos = cmd.indexOf(cmdName + " "); if (pos != 0) diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java index 5884b0c..3ecd2e3 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java @@ -1,6 +1,8 @@ package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; +import org.jetbrains.annotations.NotNull; + /** * * @author jmarranz @@ -23,7 +25,7 @@ public CommandCodeChangerBase(JProxyShellProcessor parent,String name,int line) this.line = line; } - public static int getLineFromParam(JProxyShellProcessor parent,String name,String cmd) + public static int getLineFromParam(@NotNull JProxyShellProcessor parent, String name, @NotNull String cmd) { String param = getParameter(name,cmd); if (param == null) diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandDelete.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandDelete.java index f4d6b29..956501f 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandDelete.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandDelete.java @@ -1,6 +1,8 @@ package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; +import org.jetbrains.annotations.NotNull; + /** * * @author jmarranz @@ -14,7 +16,7 @@ public CommandDelete(JProxyShellProcessor parent,int line) super(parent,NAME,line); } - public static CommandDelete createCommandDelete(JProxyShellProcessor parent,String cmd) + public static CommandDelete createCommandDelete(@NotNull JProxyShellProcessor parent, @NotNull String cmd) { int line = getLineFromParam(parent,NAME,cmd); if (line < 0) diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandEdit.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandEdit.java index d86f854..6ddb775 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandEdit.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandEdit.java @@ -1,6 +1,8 @@ package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; +import org.jetbrains.annotations.NotNull; + /** * * @author jmarranz @@ -16,7 +18,7 @@ public CommandEdit(JProxyShellProcessor parent,int line,String codeLine) this.codeLine = codeLine; } - public static CommandEdit createCommandEdit(JProxyShellProcessor parent,String cmd) + public static CommandEdit createCommandEdit(@NotNull JProxyShellProcessor parent, @NotNull String cmd) { int line = getLineFromParam(parent,NAME,cmd); if (line < 0) diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandInsert.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandInsert.java index cf36e4f..5fe5983 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandInsert.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandInsert.java @@ -1,6 +1,8 @@ package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; +import org.jetbrains.annotations.NotNull; + /** * * @author jmarranz @@ -14,7 +16,7 @@ public CommandInsert(JProxyShellProcessor parent,int line) super(parent,NAME,line); } - public static CommandInsert createCommandInsert(JProxyShellProcessor parent,String cmd) + public static CommandInsert createCommandInsert(@NotNull JProxyShellProcessor parent, @NotNull String cmd) { int line = getLineFromParam(parent,NAME,cmd); if (line < 0) diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandLoad.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandLoad.java index cf4e7b8..7afdaf0 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandLoad.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandLoad.java @@ -1,6 +1,8 @@ package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; +import org.jetbrains.annotations.NotNull; + import java.io.File; import java.net.URI; import java.net.URL; @@ -22,7 +24,7 @@ public CommandLoad(JProxyShellProcessor parent,String url) this.url = url; } - public static CommandLoad createCommandLoad(JProxyShellProcessor parent,String cmd) + public static CommandLoad createCommandLoad(JProxyShellProcessor parent, @NotNull String cmd) { String url = getParameter(NAME,cmd); if (url == null) diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandSave.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandSave.java index b19f83c..5797667 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandSave.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandSave.java @@ -1,6 +1,8 @@ package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; import com.sillelien.dollar.relproxy.impl.jproxy.JProxyUtil; +import org.jetbrains.annotations.NotNull; + import java.io.File; import java.util.List; @@ -19,7 +21,7 @@ public CommandSave(JProxyShellProcessor parent,String url) this.path = url; } - public static CommandSave createCommandSave(JProxyShellProcessor parent,String cmd) + public static CommandSave createCommandSave(JProxyShellProcessor parent, @NotNull String cmd) { String url = getParameter(NAME,cmd); if (url == null) diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java index 4f14985..488b0d4 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java @@ -6,6 +6,8 @@ import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.JProxyEngine; import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.JProxyCompilationException; import com.sillelien.dollar.relproxy.impl.jproxy.shell.JProxyShellInteractiveImpl; +import org.jetbrains.annotations.NotNull; + import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collections; @@ -22,8 +24,11 @@ public class JProxyShellProcessor public static final int LINE_OFFSET = 2; // El índice en codeBuffer + este valor = al valor de la línea que se muestra al usuario, hay que tener en cuenta que contamos desde uno y la primera línea es siempre vacía protected JProxyShellInteractiveImpl parent; + @NotNull protected Charset encoding = Charset.defaultCharset(); - protected ArrayList codeBuffer = new ArrayList(20); + @NotNull + protected ArrayList codeBuffer = new ArrayList(20); + @NotNull protected Keyboard keyboard = KeyboardNotUsingClipboard.create(encoding); protected int lastLine = -1; // Indice respecto a codeBuffer protected int lineEditing = -1; // Indice respecto a codeBuffer @@ -35,11 +40,13 @@ public JProxyShellProcessor(JProxyShellInteractiveImpl parent) this.parent = parent; } + @NotNull public Keyboard getKeyboard() { return keyboard; } + @NotNull public Charset getEncoding() { return encoding; @@ -108,6 +115,7 @@ public void loop() } } + @NotNull public List getCodeBuffer() { return Collections.unmodifiableList(codeBuffer); @@ -120,7 +128,7 @@ public void setCodeBuffer(int index,String line) this.lastLine = index; } - public void setCodeBuffer(LinkedList codeBuffer) + public void setCodeBuffer(@NotNull LinkedList codeBuffer) { codeBuffer.clear(); this.codeBuffer.addAll(codeBuffer); diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java index bef7800..1214e86 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java @@ -2,6 +2,8 @@ import com.sillelien.dollar.relproxy.RelProxyException; +import org.jetbrains.annotations.NotNull; + import java.awt.AWTException; import java.awt.Robot; import static java.awt.event.KeyEvent.VK_0; @@ -64,6 +66,7 @@ */ public abstract class KeyboardNotUsingClipboard extends Keyboard { + @NotNull protected final Robot robot; protected Charset cs; @@ -90,6 +93,7 @@ public static KeyboardNotUsingClipboard create(Charset cs) else return new LinuxUnicodeKeyboard(cs); } + @NotNull private int[] getUnicodeInt(char character) { if (isUseCodePoint()) @@ -116,7 +120,8 @@ private int[] getUnicodeInt(char character) } } - protected String getUnicodeDigits(char character,int radix) + @NotNull + protected String getUnicodeDigits(char character, int radix) { int[] uds = getUnicodeInt(character); StringBuilder res = new StringBuilder(); @@ -150,7 +155,7 @@ protected void typeNumPad(int digit) { } - public void type(CharSequence characters) { + public void type(@NotNull CharSequence characters) { int length = characters.length(); for (int i = 0; i < length; i++) { char character = characters.charAt(i); @@ -271,11 +276,11 @@ public boolean type(char character) { return true; } - protected void doType(int... keyCodes) { + protected void doType(@NotNull int... keyCodes) { doTypeArr(keyCodes); } - private void doTypeArr(int[] keyCodes) { + private void doTypeArr(@NotNull int[] keyCodes) { int length = keyCodes.length; if (length == 1) { diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java index 0f42d3b..3999e14 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java @@ -2,6 +2,8 @@ import com.sillelien.dollar.relproxy.RelProxyException; +import org.jetbrains.annotations.NotNull; + import java.awt.AWTException; import java.awt.Robot; import java.awt.Toolkit; @@ -21,6 +23,7 @@ */ public class KeyboardUsingClipboard extends Keyboard implements ClipboardOwner { + @NotNull protected final Robot robot; protected Charset cs; @@ -45,7 +48,7 @@ public static KeyboardUsingClipboard create(Charset cs) @Override - public void type(CharSequence characters) + public void type(@NotNull CharSequence characters) { Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); StringSelection stringSelection = new StringSelection( characters.toString() ); diff --git a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxy.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxy.java index a101b83..47c9838 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxy.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxy.java @@ -3,6 +3,8 @@ import com.sillelien.dollar.relproxy.impl.jproxy.JProxyConfigImpl; import com.sillelien.dollar.relproxy.impl.jproxy.JProxyDefaultImpl; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * Is the class to create Java proxy objects based on Java objects and keep track of source code changes reloading classes when detected. @@ -44,7 +46,8 @@ public static void init(JProxyConfig config) * @param clasz the class of the interface implemented by the original object and proxy object returned. * @return the java.lang.reflect.Proxy object associated or the original object when GProxy is disabled. */ - public static T create(T obj,Class clasz) + @Nullable + public static T create(T obj, Class clasz) { return JProxyDefaultImpl.createStatic(obj, clasz); } @@ -63,7 +66,8 @@ public static T create(T obj,Class clasz) * @param classes the classes of the interfaces implemented by the original object and proxy object returned. * @return the java.lang.reflect.Proxy object associated or the original object when JProxy is disabled. */ - public static Object create(Object obj,Class[] classes) + @Nullable + public static Object create(Object obj, @NotNull Class[] classes) { return JProxyDefaultImpl.createStatic(obj, classes); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyConfig.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyConfig.java index 1c8a235..81e53ea 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyConfig.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyConfig.java @@ -2,6 +2,7 @@ package com.sillelien.dollar.relproxy.jproxy; import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; +import org.jetbrains.annotations.NotNull; /** * Interface implemented by the configuration object needed to initialize JProxy and {@link JProxyScriptEngineFactory}. @@ -21,6 +22,7 @@ public interface JProxyConfig * @param enabled whether automatic source code change detection and reload is enabled. By default is true. * @return this object for flow API use. */ + @NotNull public JProxyConfig setEnabled(boolean enabled); /** @@ -29,6 +31,7 @@ public interface JProxyConfig * @param relListener the class reload listener. By default is null. * @return this object for flow API use. */ + @NotNull public JProxyConfig setRelProxyOnReloadListener(RelProxyOnReloadListener relListener); /** @@ -43,6 +46,7 @@ public interface JProxyConfig * @return this object for flow API use. * @see #setInputPaths(java.lang.String[]) */ + @NotNull public JProxyConfig setInputPath(String inputPath); /** @@ -58,7 +62,8 @@ public interface JProxyConfig * @see #setJProxyInputSourceFileExcludedListener(JProxyInputSourceFileExcludedListener) * @see #setRequiredExtraJarPaths(String[]) */ - public JProxyConfig setInputPaths(String[] inputPaths); + @NotNull + public JProxyConfig setInputPaths(String[] inputPaths); /** * Defines the extra required jars providing the absolute paths to them. @@ -73,7 +78,8 @@ public interface JProxyConfig * @return this object for flow API use. * @see #setInputPaths(String[]) */ - public JProxyConfig setRequiredExtraJarPaths(String[] inputJarPaths); + @NotNull + public JProxyConfig setRequiredExtraJarPaths(String[] inputJarPaths); /** * Registers the listener implementing excluding rules to filter source files not to be part of the hot reloading system in spite of included in input paths. @@ -81,7 +87,8 @@ public interface JProxyConfig * @param listener the listener. By default is null. * @return this object for flow API use. */ - public JProxyConfig setJProxyInputSourceFileExcludedListener(JProxyInputSourceFileExcludedListener listener); + @NotNull + public JProxyConfig setJProxyInputSourceFileExcludedListener(JProxyInputSourceFileExcludedListener listener); /** * Registers the listener for monitoring files being compiled. @@ -89,7 +96,8 @@ public interface JProxyConfig * @param listener the listener. By default is null. * @return this object for flow API use. */ - public JProxyConfig setJProxyCompilerListener(JProxyCompilerListener listener); + @NotNull + public JProxyConfig setJProxyCompilerListener(JProxyCompilerListener listener); /** @@ -102,6 +110,7 @@ public interface JProxyConfig * @param classFolder the folder where to save .class files. By default is null (not defined, .class files are not saved). * @return this object for flow API use. */ + @NotNull public JProxyConfig setClassFolder(String classFolder); /** @@ -113,6 +122,7 @@ public interface JProxyConfig * @param scanPeriod the delay between source code change checking. * @return this object for flow API use. */ + @NotNull public JProxyConfig setScanPeriod(long scanPeriod); /** @@ -124,6 +134,7 @@ public interface JProxyConfig * @param compilationOptions compilation options passed to the internal compiler. By default is null (default compiler settings). * @return this object for flow API use. */ + @NotNull public JProxyConfig setCompilationOptions(Iterable compilationOptions); /** @@ -160,5 +171,6 @@ public interface JProxyConfig * @param diagnosticsListener the diagnostic listener to capture compilation errors and warnings. By default is null, an internal listener is used logging to System.err. * @return this object for flow API use. */ + @NotNull public JProxyConfig setJProxyDiagnosticsListener(JProxyDiagnosticsListener diagnosticsListener); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyScriptEngine.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyScriptEngine.java index ea1ae96..ddc12c1 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyScriptEngine.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyScriptEngine.java @@ -1,5 +1,7 @@ package com.sillelien.dollar.relproxy.jproxy; +import org.jetbrains.annotations.Nullable; + import javax.script.ScriptEngine; /** @@ -26,7 +28,8 @@ public interface JProxyScriptEngine extends ScriptEngine * @param clasz the class of the interface implemented by the original object and proxy object returned. * @return the java.lang.reflect.Proxy object associated or the original object when is disabled. */ - public T create(T obj,Class clasz); + @Nullable + public T create(T obj, Class clasz); /** * This method is the same as {@link JProxy#create(java.lang.Object, java.lang.Class[])} but applied to this JProxyScriptEngine @@ -35,7 +38,8 @@ public interface JProxyScriptEngine extends ScriptEngine * @param classes the classes of the interfaces implemented by the original object and proxy object returned. * @return the java.lang.reflect.Proxy object associated or the original object when is disabled. */ - public Object create(Object obj,Class[] classes); + @Nullable + public Object create(Object obj, Class[] classes); /** * This method is the same as {@link JProxy#isEnabled()} but applied to this JProxyScriptEngine diff --git a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyShell.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyShell.java index 0afa40a..3ea27a2 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyShell.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyShell.java @@ -1,6 +1,7 @@ package com.sillelien.dollar.relproxy.jproxy; import com.sillelien.dollar.relproxy.impl.jproxy.shell.JProxyShellImpl; +import org.jetbrains.annotations.NotNull; /** * Is the main class to execute shell scripting based on Java. @@ -16,7 +17,7 @@ public class JProxyShell * * @param args arguments with the necessary data to initialize and executing the provided script. */ - public static void main(String[] args) + public static void main(@NotNull String[] args) { JProxyShellImpl.main(args); } diff --git a/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyCodeSnippetCompleteClassTest.java b/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyCodeSnippetCompleteClassTest.java new file mode 100644 index 0000000..1d859cf --- /dev/null +++ b/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyCodeSnippetCompleteClassTest.java @@ -0,0 +1,74 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package com.sillelien.dollar.relproxy.jproxy; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +/** + * + * @author jmarranz + */ +public class JProxyCodeSnippetCompleteClassTest +{ + public static boolean RESULT; + + public JProxyCodeSnippetCompleteClassTest() + { + } + + @BeforeClass + public static void setUpClass() + { + } + + @AfterClass + public static void tearDownClass() + { + } + + @Before + public void setUp() + { + RESULT = false; + } + + @After + public void tearDown() + { + RESULT = false; + } + + @Test + public void test_code_snippet_complete_class() + { + String compilationOptions = "-source 1.6 -target 1.6"; + + String[] args = new String[] + { + "-c", + "public class _jproxyMainClass_ { ", + " public static void main(String[] args) { ", + " System.out.print(\"This code snippet says: \");", + " System.out.println(\"Hello World!!\");", + JProxyCodeSnippetCompleteClassTest.class.getName() + ".RESULT = true;", + " }", + "}", + "-DcompilationOptions=" + compilationOptions + }; + + JProxyShell.main(args); + + assertTrue(RESULT); + + } +} diff --git a/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyCodeSnippetTest.java b/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyCodeSnippetTest.java new file mode 100644 index 0000000..e9902eb --- /dev/null +++ b/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyCodeSnippetTest.java @@ -0,0 +1,68 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package com.sillelien.dollar.relproxy.jproxy; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * + * @author jmarranz + */ +public class JProxyCodeSnippetTest +{ + public static boolean RESULT; + + public JProxyCodeSnippetTest() + { + } + + @BeforeClass + public static void setUpClass() + { + } + + @AfterClass + public static void tearDownClass() + { + } + + @Before + public void setUp() + { + RESULT = false; + } + + @After + public void tearDown() + { + RESULT = false; + } + + @Test + public void test_code_snippet() + { + String compilationOptions = "-source 1.6 -target 1.6"; + + String[] args = new String[] + { + "-c", + "System.out.print(\"This code snippet says: \");", + "System.out.println(\"Hello World!!\");", + JProxyCodeSnippetTest.class.getName() + ".RESULT = true;", + "-DcompilationOptions=" + compilationOptions + }; + + JProxyShell.main(args); + + assertTrue(RESULT); + } +} diff --git a/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaScriptEngineNoManagerTest.java b/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaScriptEngineNoManagerTest.java new file mode 100644 index 0000000..a4b6f1c --- /dev/null +++ b/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaScriptEngineNoManagerTest.java @@ -0,0 +1,183 @@ +package com.sillelien.dollar.relproxy.jproxy; + +import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import javax.script.Bindings; +import javax.script.ScriptEngine; +import javax.script.ScriptException; +import javax.tools.Diagnostic; +import javax.tools.DiagnosticCollector; +import javax.tools.JavaFileObject; +import java.io.File; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.List; + +import static com.sillelien.dollar.relproxy.jproxy.util.JProxyTestUtil.RESOURCES_FOLDER; +import static com.sillelien.dollar.relproxy.jproxy.util.JProxyTestUtil.getProjectFolder; +import static org.junit.Assert.*; + +/** + * + * @author jmarranz + */ +public class JProxyJavaScriptEngineNoManagerTest +{ + + public JProxyJavaScriptEngineNoManagerTest() + { + } + + @BeforeClass + public static void setUpClass() + { + } + + @AfterClass + public static void tearDownClass() + { + } + + @Before + public void setUp() + { + + } + + @After + public void tearDown() + { + + } + + + @Test + public void test_java_script_engine() + { + File projectFolder = getProjectFolder(); + + File inputFolderFile = new File(projectFolder,RESOURCES_FOLDER); + // File classFolderFile = new File(projectFolder,"tmp/java_shell_test_classes"); + String inputPath = inputFolderFile.getAbsolutePath(); + String classFolder = null; // Optional + Iterable compilationOptions = Arrays.asList(new String[]{"-source","1.6","-target","1.6"}); + long scanPeriod = 300; + + RelProxyOnReloadListener proxyListener = new RelProxyOnReloadListener() { + @Override + public void onReload(Object objOld, Object objNew, Object proxy, Method method, Object[] args) { + System.out.println("Reloaded " + objNew + " Calling method: " + method); + } + }; + + JProxyCompilerListener compilerListener = new JProxyCompilerListener(){ + @Override + public void beforeCompile(File file) + { + System.out.println("Before compile: " + file); + } + + @Override + public void afterCompile(File file) + { + System.out.println("After compile: " + file); + } + }; + + JProxyDiagnosticsListener diagnosticsListener = new JProxyDiagnosticsListener() + { + @Override + public void onDiagnostics(DiagnosticCollector diagnostics) + { + List> diagList = diagnostics.getDiagnostics(); + int i = 1; + for (Diagnostic diagnostic : diagList) + { + System.err.println("Diagnostic " + i); + System.err.println(" code: " + diagnostic.getCode()); + System.err.println(" kind: " + diagnostic.getKind()); + System.err.println(" line number: " + diagnostic.getLineNumber()); + System.err.println(" column number: " + diagnostic.getColumnNumber()); + System.err.println(" start position: " + diagnostic.getStartPosition()); + System.err.println(" position: " + diagnostic.getPosition()); + System.err.println(" end position: " + diagnostic.getEndPosition()); + System.err.println(" source: " + diagnostic.getSource()); + System.err.println(" message: " + diagnostic.getMessage(null)); + i++; + } + } + }; + + JProxyConfig jpConfig = JProxy.createJProxyConfig(); + jpConfig.setEnabled(true) + .setRelProxyOnReloadListener(proxyListener) + .setInputPath(inputPath) + .setJProxyInputSourceFileExcludedListener(null) + .setJProxyCompilerListener(compilerListener) + .setScanPeriod(scanPeriod) + .setClassFolder(classFolder) + .setCompilationOptions(compilationOptions) + .setJProxyDiagnosticsListener(diagnosticsListener); + + JProxyScriptEngineFactory factory = JProxyScriptEngineFactory.create(); + + ScriptEngine engine = factory.getScriptEngine(); + + ((JProxyScriptEngine)engine).init(jpConfig); + + assertNotNull(engine); + + try + { + + // El javax.script.ScriptContext.GLOBAL_SCOPE no está disponible porque no hemos usado el ScriptEngineManager para obtener el JProxyScriptEngine + // pero si podemos crear un javax.script.ScriptContext.ENGINE_SCOPE: + + Bindings bindings = engine.createBindings(); + bindings.put("msg","HELLO ENGINE SCOPE WORLD!"); + + + StringBuilder code = new StringBuilder(); + code.append( " javax.script.Bindings bindings = context.getBindings(javax.script.ScriptContext.ENGINE_SCOPE); \n"); + code.append( " String msg = (String)bindings.get(\"msg\"); \n"); + code.append( " System.out.println(msg); \n"); + code.append( " example.javashellex.JProxyShellExample.exec(engine); \n"); + code.append( " return \"SUCCESS\";"); + + String result = (String)engine.eval( code.toString() , bindings); + assertEquals("SUCCESS",result); + + bindings = engine.createBindings(); + bindings.put("msg","HELLO ENGINE SCOPE WORLD 2!"); + + code = new StringBuilder(); + code.append( "public class _jproxyMainClass_ { \n"); + code.append( " public static Object main(javax.script.ScriptEngine engine,javax.script.ScriptContext context) { \n"); + code.append( " javax.script.Bindings bindings = context.getBindings(javax.script.ScriptContext.ENGINE_SCOPE); \n"); + code.append( " String msg = (String)bindings.get(\"msg\"); \n"); + code.append( " System.out.println(msg); \n"); + code.append( " example.javashellex.JProxyShellExample.exec(engine); \n"); + code.append( " return \"SUCCESS 2\";"); + code.append( " }"); + code.append( "}"); + + result = (String)engine.eval( code.toString() , bindings); + assertEquals("SUCCESS 2",result); + } + catch(ScriptException ex) + { + ex.printStackTrace(); + assertTrue(false); + } + finally + { + boolean res = ((JProxyScriptEngine)engine).stop(); // Necessary if scanPeriod > 0 was defined + assertTrue(res); + } + } +} diff --git a/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaScriptEngineTest.java b/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaScriptEngineTest.java new file mode 100644 index 0000000..2249dab --- /dev/null +++ b/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaScriptEngineTest.java @@ -0,0 +1,201 @@ +package com.sillelien.dollar.relproxy.jproxy; + +import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; +import static com.sillelien.dollar.relproxy.jproxy.util.JProxyTestUtil.RESOURCES_FOLDER; +import static com.sillelien.dollar.relproxy.jproxy.util.JProxyTestUtil.getProjectFolder; + + +import java.io.File; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.List; +import javax.script.Bindings; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +import javax.script.ScriptException; +import javax.tools.Diagnostic; +import javax.tools.DiagnosticCollector; +import javax.tools.JavaFileObject; + +import com.sillelien.dollar.relproxy.jproxy.JProxy; +import com.sillelien.dollar.relproxy.jproxy.JProxyCompilerListener; +import com.sillelien.dollar.relproxy.jproxy.JProxyConfig; +import com.sillelien.dollar.relproxy.jproxy.JProxyDiagnosticsListener; +import com.sillelien.dollar.relproxy.jproxy.JProxyScriptEngine; +import com.sillelien.dollar.relproxy.jproxy.JProxyScriptEngineFactory; +import org.junit.After; +import org.junit.AfterClass; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +/** + * + * @author jmarranz + */ +public class JProxyJavaScriptEngineTest +{ + + public JProxyJavaScriptEngineTest() + { + } + + @BeforeClass + public static void setUpClass() + { + } + + @AfterClass + public static void tearDownClass() + { + } + + @Before + public void setUp() + { + + } + + @After + public void tearDown() + { + + } + + + @Test + public void test_java_script_engine() + { + File projectFolder = getProjectFolder(); + + File inputFolderFile = new File(projectFolder,RESOURCES_FOLDER); + // File classFolderFile = new File(projectFolder,"tmp/java_shell_test_classes"); + String inputPath = inputFolderFile.getAbsolutePath(); + String classFolder = null; // Optional + Iterable compilationOptions = Arrays.asList(new String[]{"-source","1.6","-target","1.6"}); + long scanPeriod = 300; + + RelProxyOnReloadListener proxyListener = new RelProxyOnReloadListener() { + @Override + public void onReload(Object objOld, Object objNew, Object proxy, Method method, Object[] args) { + System.out.println("Reloaded " + objNew + " Calling method: " + method); + } + }; + + JProxyCompilerListener compilerListener = new JProxyCompilerListener(){ + @Override + public void beforeCompile(File file) + { + System.out.println("Before compile: " + file); + } + + @Override + public void afterCompile(File file) + { + System.out.println("After compile: " + file); + } + }; + + JProxyDiagnosticsListener diagnosticsListener = new JProxyDiagnosticsListener() + { + @Override + public void onDiagnostics(DiagnosticCollector diagnostics) + { + List> diagList = diagnostics.getDiagnostics(); + int i = 1; + for (Diagnostic diagnostic : diagList) + { + System.err.println("Diagnostic " + i); + System.err.println(" code: " + diagnostic.getCode()); + System.err.println(" kind: " + diagnostic.getKind()); + System.err.println(" line number: " + diagnostic.getLineNumber()); + System.err.println(" column number: " + diagnostic.getColumnNumber()); + System.err.println(" start position: " + diagnostic.getStartPosition()); + System.err.println(" position: " + diagnostic.getPosition()); + System.err.println(" end position: " + diagnostic.getEndPosition()); + System.err.println(" source: " + diagnostic.getSource()); + System.err.println(" message: " + diagnostic.getMessage(null)); + i++; + } + } + }; + + JProxyConfig jpConfig = JProxy.createJProxyConfig(); + jpConfig.setEnabled(true) + .setRelProxyOnReloadListener(proxyListener) + .setInputPath(inputPath) + .setJProxyInputSourceFileExcludedListener(null) + .setJProxyCompilerListener(compilerListener) + .setScanPeriod(scanPeriod) + .setClassFolder(classFolder) + .setCompilationOptions(compilationOptions) + .setJProxyDiagnosticsListener(diagnosticsListener); + + JProxyScriptEngineFactory factory = JProxyScriptEngineFactory.create(); + + ScriptEngineManager manager = new ScriptEngineManager(); + manager.registerEngineName("Java", factory); + + manager.getBindings().put("msg","HELLO GLOBAL WORLD!"); + + ScriptEngine engine = manager.getEngineByName("Java"); + + ((JProxyScriptEngine)engine).init(jpConfig); + + assertNotNull(engine); + + try + { + + Bindings bindings = engine.createBindings(); + bindings.put("msg","HELLO ENGINE SCOPE WORLD!"); + + + StringBuilder code = new StringBuilder(); + code.append( " javax.script.Bindings bindings = context.getBindings(javax.script.ScriptContext.ENGINE_SCOPE); \n"); + code.append( " String msg = (String)bindings.get(\"msg\"); \n"); + code.append( " System.out.println(msg); \n"); + code.append( " bindings = context.getBindings(javax.script.ScriptContext.GLOBAL_SCOPE); \n"); + code.append( " msg = (String)bindings.get(\"msg\"); \n"); + code.append( " System.out.println(msg); \n"); + code.append( " example.javashellex.JProxyShellExample.exec(engine); \n"); + code.append( " return \"SUCCESS\";"); + + String result = (String)engine.eval( code.toString() , bindings); + assertEquals("SUCCESS",result); + + bindings = engine.createBindings(); + bindings.put("msg","HELLO ENGINE SCOPE WORLD 2!"); + + code = new StringBuilder(); + code.append( "public class _jproxyMainClass_ { \n"); + code.append( " public static Object main(javax.script.ScriptEngine engine,javax.script.ScriptContext context) { \n"); + code.append( " javax.script.Bindings bindings = context.getBindings(javax.script.ScriptContext.ENGINE_SCOPE); \n"); + code.append( " String msg = (String)bindings.get(\"msg\"); \n"); + code.append( " System.out.println(msg); \n"); + code.append( " bindings = context.getBindings(javax.script.ScriptContext.GLOBAL_SCOPE); \n"); + code.append( " msg = (String)bindings.get(\"msg\"); \n"); + code.append( " System.out.println(msg); \n"); + code.append( " example.javashellex.JProxyShellExample.exec(engine); \n"); + code.append( " return \"SUCCESS 2\";"); + code.append( " }"); + code.append( "}"); + + result = (String)engine.eval( code.toString() , bindings); + assertEquals("SUCCESS 2",result); + } + catch(ScriptException ex) + { + ex.printStackTrace(); + assertTrue(false); + } + finally + { + boolean res = ((JProxyScriptEngine)engine).stop(); // Necessary if scanPeriod > 0 was defined + assertTrue(res); + } + } +} diff --git a/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaShellCompleteClassTest.java b/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaShellCompleteClassTest.java new file mode 100644 index 0000000..b9c8110 --- /dev/null +++ b/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaShellCompleteClassTest.java @@ -0,0 +1,72 @@ +package com.sillelien.dollar.relproxy.jproxy; + +import com.sillelien.dollar.relproxy.jproxy.JProxyShell; +import com.sillelien.dollar.relproxy.jproxy.util.JProxyTestUtil; +import java.io.File; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +/** + * + * @author jmarranz + */ +public class JProxyJavaShellCompleteClassTest +{ + + + + public JProxyJavaShellCompleteClassTest() + { + } + + @BeforeClass + public static void setUpClass() + { + } + + @AfterClass + public static void tearDownClass() + { + } + + @Before + public void setUp() + { + + } + + @After + public void tearDown() + { + + } + + + @Test + public void test_java_shell() + { + File projectFolder = JProxyTestUtil.getProjectFolder(); + File inputFolderFile = new File(projectFolder,JProxyTestUtil.RESOURCES_FOLDER); + File cacheClassFolderFile = new File(projectFolder,JProxyTestUtil.CACHE_CLASS_FOLDER); + + String inputPath = inputFolderFile.getAbsolutePath(); + String cacheClassFolder = cacheClassFolderFile.getAbsolutePath(); + String compilationOptions = "-source 1.6 -target 1.6"; + + String[] args = new String[] + { + inputPath + "/example_java_shell_complete_class", + "HELLO ", + "WORLD!", + "-DcacheClassFolder=" + cacheClassFolder, + "-DcompilationOptions=" + compilationOptions, + }; + + JProxyShell.main(args); + } + + +} diff --git a/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaShellInteractiveTest.java b/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaShellInteractiveTest.java new file mode 100644 index 0000000..08b7772 --- /dev/null +++ b/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaShellInteractiveTest.java @@ -0,0 +1,63 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package com.sillelien.dollar.relproxy.jproxy; + +import com.sillelien.dollar.relproxy.jproxy.JProxyShell; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * + * @author jmarranz + */ +public class JProxyJavaShellInteractiveTest +{ + public JProxyJavaShellInteractiveTest() + { + } + + @BeforeClass + public static void setUpClass() + { + } + + @AfterClass + public static void tearDownClass() + { + } + + @Before + public void setUp() + { + + } + + @After + public void tearDown() + { + + } + + @Test + public void test_java_shell_interactive() + { + String compilationOptions = "-source 1.6 -target 1.6"; + + String[] args = new String[] + { + "", // El args[0] esperado + "-DcompilationOptions=" + compilationOptions, + "-Dtest=true" + }; + + JProxyShell.main(args); + } +} diff --git a/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaShellNormalClassTest.java b/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaShellNormalClassTest.java new file mode 100644 index 0000000..2c3df46 --- /dev/null +++ b/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaShellNormalClassTest.java @@ -0,0 +1,69 @@ +package com.sillelien.dollar.relproxy.jproxy; + +import com.sillelien.dollar.relproxy.jproxy.JProxyShell; +import com.sillelien.dollar.relproxy.jproxy.util.JProxyTestUtil; +import java.io.File; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +/** + * + * @author jmarranz + */ +public class JProxyJavaShellNormalClassTest +{ + public JProxyJavaShellNormalClassTest() + { + } + + @BeforeClass + public static void setUpClass() + { + } + + @AfterClass + public static void tearDownClass() + { + } + + @Before + public void setUp() + { + + } + + @After + public void tearDown() + { + + } + + + @Test + public void test_java_shell() + { + File projectFolder = JProxyTestUtil.getProjectFolder(); + File inputFolderFile = new File(projectFolder,JProxyTestUtil.RESOURCES_FOLDER); + File cacheClassFolderFile = new File(projectFolder,JProxyTestUtil.CACHE_CLASS_FOLDER); + + String inputPath = inputFolderFile.getAbsolutePath(); + String cacheClassFolder = cacheClassFolderFile.getAbsolutePath(); + String compilationOptions = "-source 1.6 -target 1.6"; + + String[] args = new String[] + { + inputPath + "/example_normal_class.java", + "HELLO ", + "WORLD!", + "-DcacheClassFolder=" + cacheClassFolder, + "-DcompilationOptions=" + compilationOptions + }; + + JProxyShell.main(args); + } + + +} diff --git a/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaShellTest.java b/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaShellTest.java new file mode 100644 index 0000000..94abc8f --- /dev/null +++ b/src/test/java/com/sillelien/dollar/relproxy/jproxy/JProxyJavaShellTest.java @@ -0,0 +1,74 @@ +package com.sillelien.dollar.relproxy.jproxy; + +import com.sillelien.dollar.relproxy.jproxy.JProxyShell; +import com.sillelien.dollar.relproxy.jproxy.util.JProxyTestUtil; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.File; + +/** + * + * @author jmarranz + */ +public class JProxyJavaShellTest +{ + + + + public JProxyJavaShellTest() + { + } + + @BeforeClass + public static void setUpClass() + { + } + + @AfterClass + public static void tearDownClass() + { + } + + @Before + public void setUp() + { + + } + + @After + public void tearDown() + { + + } + + + @Test + public void test_java_shell() + { + File projectFolder = JProxyTestUtil.getProjectFolder(); + File inputFolderFile = new File(projectFolder,JProxyTestUtil.RESOURCES_FOLDER); + File cacheClassFolderFile = new File(projectFolder,JProxyTestUtil.CACHE_CLASS_FOLDER); + + String inputPath = inputFolderFile.getAbsolutePath(); + String cacheClassFolder = cacheClassFolderFile.getAbsolutePath(); + String compilationOptions = "-source 1.6 -target 1.6"; + + + String[] args = new String[] + { + inputPath + "/example_java_shell", + "HELLO ", + "WORLD!", + "-DcacheClassFolder=" + cacheClassFolder, + "-DcompilationOptions=" + compilationOptions + }; + + JProxyShell.main(args); + } + + +} diff --git a/src/test/java/com/sillelien/dollar/relproxy/jproxy/util/JProxyTestUtil.java b/src/test/java/com/sillelien/dollar/relproxy/jproxy/util/JProxyTestUtil.java new file mode 100644 index 0000000..d4d51df --- /dev/null +++ b/src/test/java/com/sillelien/dollar/relproxy/jproxy/util/JProxyTestUtil.java @@ -0,0 +1,16 @@ +package com.sillelien.dollar.relproxy.jproxy.util; + +import java.io.File; + +/** + * @author jmarranz + */ +public class JProxyTestUtil { + public static final String RESOURCES_FOLDER = "src/test/resources"; + public static final String CACHE_CLASS_FOLDER = "tmp/java_shell_test_classes"; + + public static File getProjectFolder() { + + return new File(".").getAbsoluteFile(); + } +} diff --git a/relproxy/src/test/resources/example/javashellex/JProxyShellExample.java b/src/test/resources/example/javashellex/JProxyShellExample.java similarity index 96% rename from relproxy/src/test/resources/example/javashellex/JProxyShellExample.java rename to src/test/resources/example/javashellex/JProxyShellExample.java index b0b5dcf..0da7133 100644 --- a/relproxy/src/test/resources/example/javashellex/JProxyShellExample.java +++ b/src/test/resources/example/javashellex/JProxyShellExample.java @@ -1,22 +1,22 @@ -package example.javashellex; - -import javax.script.ScriptEngine; -import com.sillelien.dollar.relproxy.jproxy.JProxyScriptEngine; - -/** - * - * @author jmarranz - */ -public class JProxyShellExample -{ - public static void exec() - { - System.out.println("JProxyShellExample exec() 1 "); - } - - public static void exec(ScriptEngine engine) - { - JProxyScriptEngine jengine = ((JProxyScriptEngine)engine); // Just to show that ScriptEngine is a JProxyScriptEngine object - System.out.println("JProxyShellExample exec(ScriptEngine) 1 "); - } -} +package example.javashellex; + +import javax.script.ScriptEngine; +import com.sillelien.dollar.relproxy.jproxy.JProxyScriptEngine; + +/** + * + * @author jmarranz + */ +public class JProxyShellExample +{ + public static void exec() + { + System.out.println("JProxyShellExample exec() 1 "); + } + + public static void exec(ScriptEngine engine) + { + JProxyScriptEngine jengine = ((JProxyScriptEngine)engine); // Just to show that ScriptEngine is a JProxyScriptEngine object + System.out.println("JProxyShellExample exec(ScriptEngine) 1 "); + } +} diff --git a/relproxy/src/test/resources/example_java_shell b/src/test/resources/example_java_shell similarity index 100% rename from relproxy/src/test/resources/example_java_shell rename to src/test/resources/example_java_shell diff --git a/relproxy/src/test/resources/example_java_shell_complete_class b/src/test/resources/example_java_shell_complete_class similarity index 100% rename from relproxy/src/test/resources/example_java_shell_complete_class rename to src/test/resources/example_java_shell_complete_class diff --git a/relproxy/src/test/resources/example_normal_class.java b/src/test/resources/example_normal_class.java similarity index 100% rename from relproxy/src/test/resources/example_normal_class.java rename to src/test/resources/example_normal_class.java From 726a3ec649398f1972adf60e4c3723251476b991 Mon Sep 17 00:00:00 2001 From: "hello@neilellis.me" Date: Fri, 7 Jul 2017 22:16:54 +0100 Subject: [PATCH 030/135] Release 0.9.29 [29/963bc5ff5e05bb4e56d0ad0d3a3482a39b0756a6] (tangly-caller-wits) --- .release | 2 +- .release.details | 2 +- README.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release b/.release index 46e7a71..017ccd0 100644 --- a/.release +++ b/.release @@ -1 +1 @@ -0.9.26 +0.9.29 diff --git a/.release.details b/.release.details index d4ffea5..14de863 100644 --- a/.release.details +++ b/.release.details @@ -1 +1 @@ -0.9.26 26 85d846629a8114e3e6634ae3b43f80e47f60d078 bally-spoilt-flutes +0.9.29 29 963bc5ff5e05bb4e56d0ad0d3a3482a39b0756a6 tangly-caller-wits diff --git a/README.md b/README.md index b4e2b5f..f1cf4ca 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ RelProxy is a simple Java and Groovy hot class reloader for Java and Groovy prov com.sillelien dollar-relproxy -0.9.26 +0.9.29 jar ``` From 931857eb1372f8e0b335350e6a1bc912576e47de Mon Sep 17 00:00:00 2001 From: neilellis Date: Fri, 7 Jul 2017 22:15:49 +0100 Subject: [PATCH 031/135] Reformatting only --- .../sillelien/dollar/relproxy/RelProxy.java | 10 +- .../dollar/relproxy/RelProxyException.java | 36 +- .../relproxy/RelProxyOnReloadListener.java | 18 +- .../dollar/relproxy/gproxy/GProxy.java | 57 ++- .../dollar/relproxy/gproxy/GProxyConfig.java | 18 +- .../gproxy/GProxyGroovyScriptEngine.java | 24 +- .../dollar/relproxy/gproxy/package.html | 6 +- .../dollar/relproxy/impl/FileExt.java | 26 +- .../impl/GenericProxyConfigBaseImpl.java | 10 +- .../relproxy/impl/GenericProxyImpl.java | 67 ++- .../impl/GenericProxyInvocationHandler.java | 48 +- .../impl/GenericProxyVersionedObject.java | 150 +++---- .../impl/gproxy/GProxyConfigImpl.java | 28 +- .../impl/gproxy/GProxyDefaultImpl.java | 44 +- .../relproxy/impl/gproxy/core/GProxyImpl.java | 25 +- .../gproxy/core/GProxyInvocationHandler.java | 14 +- .../gproxy/core/GProxyVersionedObject.java | 41 +- .../impl/jproxy/JProxyConfigImpl.java | 129 +++--- .../impl/jproxy/JProxyDefaultImpl.java | 98 ++-- .../relproxy/impl/jproxy/JProxyUtil.java | 177 ++++---- .../relproxy/impl/jproxy/core/JProxyImpl.java | 82 ++-- .../jproxy/core/JProxyInvocationHandler.java | 18 +- .../jproxy/core/JProxyVersionedObject.java | 36 +- .../jproxy/core/clsmgr/FolderSourceList.java | 68 ++- .../jproxy/core/clsmgr/JProxyClassLoader.java | 111 ++--- .../impl/jproxy/core/clsmgr/JProxyEngine.java | 281 +++++------- ...JProxyEngineChangeDetectorAndCompiler.java | 249 +++++------ .../core/clsmgr/cldesc/ClassDescriptor.java | 103 ++--- .../clsmgr/cldesc/ClassDescriptorInner.java | 23 +- .../cldesc/ClassDescriptorSourceFileJava.java | 25 +- .../ClassDescriptorSourceFileRegistry.java | 94 ++-- .../cldesc/ClassDescriptorSourceScript.java | 217 +++++---- .../cldesc/ClassDescriptorSourceUnit.java | 117 ++--- .../comp/JProxyCompilationException.java | 16 +- .../clsmgr/comp/JProxyCompilerContext.java | 71 ++- .../clsmgr/comp/JProxyCompilerInMemory.java | 130 +++--- .../clsmgr/comp/JavaFileManagerInMemory.java | 73 ++- ...leObjectInputClassFinderByClassLoader.java | 198 ++++----- .../comp/jfo/JProxyJavaFileObjectInput.java | 4 +- .../jfo/JavaFileObjectInputClassInFile.java | 21 +- .../JavaFileObjectInputClassInFileSystem.java | 29 +- .../jfo/JavaFileObjectInputClassInJar.java | 20 +- .../jfo/JavaFileObjectInputClassInMemory.java | 43 +- .../jfo/JavaFileObjectInputSourceBase.java | 53 +-- .../jfo/JavaFileObjectInputSourceInFile.java | 24 +- .../JavaFileObjectInputSourceInMemory.java | 26 +- .../comp/jfo/JavaFileObjectOutputClass.java | 44 +- .../clsmgr/srcunit/SourceFileJavaNormal.java | 21 +- .../core/clsmgr/srcunit/SourceScriptRoot.java | 11 +- .../clsmgr/srcunit/SourceScriptRootFile.java | 32 +- .../srcunit/SourceScriptRootFileJavaExt.java | 22 +- .../srcunit/SourceScriptRootFileOtherExt.java | 30 +- .../srcunit/SourceScriptRootInMemory.java | 47 +- .../core/clsmgr/srcunit/SourceUnit.java | 36 +- .../impl/jproxy/screngine/BindingsImpl.java | 4 +- .../JProxyScriptEngineDelegateImpl.java | 83 ++-- .../JProxyScriptEngineFactoryImpl.java | 124 +++--- .../screngine/JProxyScriptEngineImpl.java | 95 ++-- .../jproxy/shell/JProxyShellClassLoader.java | 36 +- .../shell/JProxyShellCodeSnippetImpl.java | 57 +-- .../impl/jproxy/shell/JProxyShellImpl.java | 113 ++--- .../shell/JProxyShellInteractiveImpl.java | 73 ++- .../shell/JProxyShellScriptFileImpl.java | 64 ++- .../impl/jproxy/shell/inter/Command.java | 114 ++--- .../shell/inter/CommandCodeChangerBase.java | 85 ++-- .../jproxy/shell/inter/CommandDelete.java | 55 +-- .../impl/jproxy/shell/inter/CommandEdit.java | 63 ++- .../impl/jproxy/shell/inter/CommandError.java | 15 +- .../jproxy/shell/inter/CommandInsert.java | 61 ++- .../impl/jproxy/shell/inter/CommandLoad.java | 60 +-- .../impl/jproxy/shell/inter/CommandOther.java | 139 +++--- .../impl/jproxy/shell/inter/CommandSave.java | 55 +-- .../shell/inter/JProxyShellProcessor.java | 214 ++++----- .../impl/jproxy/shell/inter/Keyboard.java | 24 +- .../inter/KeyboardNotUsingClipboard.java | 420 ++++++++++++------ .../shell/inter/KeyboardUsingClipboard.java | 34 +- .../shell/inter/LinuxUnicodeKeyboard.java | 46 +- .../shell/inter/MacOSXUnicodeKeyboard.java | 39 +- .../shell/inter/WindowUnicodeKeyboard.java | 40 +- .../dollar/relproxy/jproxy/JProxy.java | 112 +++-- .../jproxy/JProxyCompilerListener.java | 10 +- .../dollar/relproxy/jproxy/JProxyConfig.java | 139 +++--- .../jproxy/JProxyDiagnosticsListener.java | 9 +- ...JProxyInputSourceFileExcludedListener.java | 13 +- .../relproxy/jproxy/JProxyScriptEngine.java | 53 ++- .../jproxy/JProxyScriptEngineFactory.java | 11 +- .../dollar/relproxy/jproxy/JProxyShell.java | 14 +- .../dollar/relproxy/jproxy/package.html | 6 +- .../sillelien/dollar/relproxy/package.html | 6 +- 89 files changed, 2603 insertions(+), 3284 deletions(-) diff --git a/src/main/java/com/sillelien/dollar/relproxy/RelProxy.java b/src/main/java/com/sillelien/dollar/relproxy/RelProxy.java index 8b2ee78..ec16e4b 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/RelProxy.java +++ b/src/main/java/com/sillelien/dollar/relproxy/RelProxy.java @@ -2,18 +2,16 @@ /** * Is the root of RelProxy - * + * * @author Jose Maria Arranz Santamaria */ -public class RelProxy -{ +public class RelProxy { /** * Returns the version of this RelProxy library. - * + * * @return the version of the library. */ - public static String getVersion() - { + public static String getVersion() { return "0.8.8"; } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/RelProxyException.java b/src/main/java/com/sillelien/dollar/relproxy/RelProxyException.java index 1d0e5d4..d4bbf09 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/RelProxyException.java +++ b/src/main/java/com/sillelien/dollar/relproxy/RelProxyException.java @@ -2,45 +2,41 @@ /** * Internal checked exceptions thrown by RelProxy and library specific errors are wrapped into this exception class. - * + * * @author Jose Maria Arranz Santamaria */ -public class RelProxyException extends RuntimeException -{ +public class RelProxyException extends RuntimeException { /** * Constructs a new exception with the specified message and cause. - * + *

*

Parameters are passed to the super constructor.

- * + * * @param message the detail message - * @param cause the cause + * @param cause the cause */ - public RelProxyException(String message, Throwable cause) - { + public RelProxyException(String message, Throwable cause) { super(message, cause); } - + /** * Constructs a new exception with the specified message. - * + *

*

Parameter is passed to the super constructor.

- * + * * @param message the detail message */ - public RelProxyException(String message) - { + public RelProxyException(String message) { super(message); - } - + } + /** * Constructs a new exception with the specified cause. - * + *

*

Parameter is passed to the super constructor.

- * + * * @param cause the cause */ - public RelProxyException(Throwable cause) - { + public RelProxyException(Throwable cause) { super(cause); - } + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/RelProxyOnReloadListener.java b/src/main/java/com/sillelien/dollar/relproxy/RelProxyOnReloadListener.java index 1750bf3..d84ad4b 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/RelProxyOnReloadListener.java +++ b/src/main/java/com/sillelien/dollar/relproxy/RelProxyOnReloadListener.java @@ -4,26 +4,24 @@ /** * Is the interface needed to register a class reload listener. - * + *

*

An object implementing this interface can optionally be registered on RelProxy to listen when the method of a proxy object has been called * and the class of the original object associated has been reloaded (and a new "original" object based on the new class was created to replace it). *

- * - * + * + * @author Jose Maria Arranz Santamaria * @see com.sillelien.dollar.relproxy.jproxy.JProxyConfig#setRelProxyOnReloadListener(com.sillelien.dollar.relproxy.RelProxyOnReloadListener) * @see com.sillelien.dollar.relproxy.gproxy.GProxyConfig#setRelProxyOnReloadListener(com.sillelien.dollar.relproxy.RelProxyOnReloadListener) - * @author Jose Maria Arranz Santamaria */ -public interface RelProxyOnReloadListener -{ +public interface RelProxyOnReloadListener { /** * Called when some source code change has happened and a new class has been compiled and reloaded. - * + * * @param objOld the old object before class reload. * @param objNew the new object based on the new class loaded by the new class loader. - * @param proxy the proxy object created by {@link java.lang.reflect.Proxy} being used. + * @param proxy the proxy object created by {@link java.lang.reflect.Proxy} being used. * @param method the method being called through the proxy object. - * @param args the parameters being used in the method call. + * @param args the parameters being used in the method call. */ - public void onReload(Object objOld,Object objNew,Object proxy, Method method, Object[] args); + public void onReload(Object objOld, Object objNew, Object proxy, Method method, Object[] args); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxy.java b/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxy.java index 5ee51b4..1f084ed 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxy.java +++ b/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxy.java @@ -8,65 +8,60 @@ /** * Is the class to create Java proxy objects based on Groovy objects and keep track of Groovy source code changes reloading Groovy classes when detected. - * + * * @author Jose Maria Arranz Santamaria */ -public class GProxy -{ +public class GProxy { /** * Creates a {@link GProxyConfig} object to be used to configure GProxy. - * + * * @return a new configuration object. * @see #init(GProxyConfig) */ - public static GProxyConfig createGProxyConfig() - { + public static GProxyConfig createGProxyConfig() { return GProxyDefaultImpl.createGProxyConfig(); - } - + } + /** * Initializes GProxy with the provided configuration object. - * + * * @param config config */ - public static void init(GProxyConfig config) - { - GProxyDefaultImpl.initStatic((GProxyConfigImpl)config); - } - + public static void init(GProxyConfig config) { + GProxyDefaultImpl.initStatic((GProxyConfigImpl) config); + } + /** * Creates a proxy object using java.lang.reflect.Proxy based on the provided Groovy object and the class of the implemented Java interface. - * - *

This method is a simplification for a single interface (the most common case) of {@link #create(Object,Class[])} .

- * - * @param the interface implemented by the original object and proxy object returned. - * @param obj the original object to proxy. + *

+ *

This method is a simplification for a single interface (the most common case) of {@link #create(Object, Class[])} .

+ * + * @param the interface implemented by the original object and proxy object returned. + * @param obj the original object to proxy. * @param clasz the class of the interface implemented by the original object and proxy object returned. * @return the java.lang.reflect.Proxy object associated or the original object when GProxy is disabled. */ @Nullable - public static T create(T obj, Class clasz) - { + public static T create(T obj, Class clasz) { return GProxyDefaultImpl.createStatic(obj, clasz); - } - + } + /** * Creates a proxy object using java.lang.reflect.Proxy based on the provided Groovy object and the classes of the implemented Java interfaces. - * - *

If GProxy has been configured and is enabled this method returns a java.lang.reflect.Proxy object implementing instead of + *

+ *

If GProxy has been configured and is enabled this method returns a java.lang.reflect.Proxy object implementing instead of * the original object provided. Methods called in proxy object are received by GProxy and forwarded to the original object, if source code * managed by GProxy has been changed, the class of the original object is reloaded based on the new source and the original object * is recreated with the new class and fields are re-set in the new object, then the method is called on the new original object.

- * + *

*

If GProxy is disabled returns the original object provided with no performance penalty.

- * - * @param obj the original object to proxy. + * + * @param obj the original object to proxy. * @param classes the classes of the interfaces implemented by the original object and proxy object returned. * @return the java.lang.reflect.Proxy object associated or the original object when GProxy is disabled. */ @Nullable - public static Object create(Object obj, @NotNull Class[] classes) - { + public static Object create(Object obj, @NotNull Class[] classes) { return GProxyDefaultImpl.createStatic(obj, classes); - } + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyConfig.java b/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyConfig.java index fd614e2..511ab75 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyConfig.java +++ b/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyConfig.java @@ -6,19 +6,17 @@ /** * Interface implemented by the configuration object needed to initialize GProxy. - * - * - * @see GProxy#init(GProxyConfig) + * * @author Jose Maria Arranz Santamaria + * @see GProxy#init(GProxyConfig) */ -public interface GProxyConfig -{ +public interface GProxyConfig { /** * Sets whether automatic detection of source code changes is enabled. - * + *

*

If set to false other configuration parameters are ignored, there is no automatic source code change detection/reload and original objects are returned * instead of proxies, performance penalty is zero. Setting to false is recommended in production whether source code change detection/reload is not required.

- * + * * @param enabled whether automatic source code change detection and reload is enabled. By default is true. * @return this object for flow API use. */ @@ -27,7 +25,7 @@ public interface GProxyConfig /** * Sets the class reload listener. - * + * * @param relListener the class reload listener. By default is null. * @return this object for flow API use. */ @@ -36,9 +34,9 @@ public interface GProxyConfig /** * Sets the object implementing the GroovyScriptEngine wrapper used to reload Groovy classes. - * + *

*

This parameter is required otherwise there is no bridge between RelProxy and Groovy because there is no explicit Groovy dependency in RelProxy. - * + * * @param engine the GroovyScriptEngine wrapper. * @return this object for flow API use. */ diff --git a/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyGroovyScriptEngine.java b/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyGroovyScriptEngine.java index 714feeb..02e4aa7 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyGroovyScriptEngine.java +++ b/src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyGroovyScriptEngine.java @@ -4,28 +4,26 @@ /** * Interface to implement the object implementing the GroovyScriptEngine wrapper used to reload Groovy classes. - * + *

*

The following is a very simple example of the required implementation, groovyEngine is the groovy.util.GroovyScriptEngine * object:

- - def gproxyGroovyEngine = { - String scriptName -> return (java.lang.Class)groovyEngine.loadScriptByName(scriptName) - } as GProxyGroovyScriptEngine; - - * - * - * @see GProxyConfig#setGProxyGroovyScriptEngine(GProxyGroovyScriptEngine) + * + * def gproxyGroovyEngine = { + * String scriptName -> return (java.lang.Class)groovyEngine.loadScriptByName(scriptName) + * } as GProxyGroovyScriptEngine; + * + * * @author Jose Maria Arranz Santamaria + * @see GProxyConfig#setGProxyGroovyScriptEngine(GProxyGroovyScriptEngine) */ -public interface GProxyGroovyScriptEngine -{ +public interface GProxyGroovyScriptEngine { /** * The class implementing this method must call the method groovy.util.GroovyScriptEngine.loadScriptByName(String scriptName) passing * the scriptName. - * + *

*

This method is called by GProxy when it needs to get the Class associated to the specified Groovy script/class to check if this class * has changed because Groovy has reloaded the class when a source code has been detected. - * + * * @param scriptName the name of the Groovy script/class. * @return the class associated to the specified Groovy script. */ diff --git a/src/main/java/com/sillelien/dollar/relproxy/gproxy/package.html b/src/main/java/com/sillelien/dollar/relproxy/gproxy/package.html index 3edbfbf..c6bd773 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/gproxy/package.html +++ b/src/main/java/com/sillelien/dollar/relproxy/gproxy/package.html @@ -1,9 +1,9 @@ - + diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/FileExt.java b/src/main/java/com/sillelien/dollar/relproxy/impl/FileExt.java index 33c8866..d5912f6 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/FileExt.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/FileExt.java @@ -7,32 +7,30 @@ import java.io.IOException; /** - * * @author jmarranz */ -public class FileExt -{ +public class FileExt { @NotNull protected final File file; @NotNull protected final String cannonicalPath; // El obtener el cannonicalPath exige acceder al sistema de archivos, por eso nos inventamos esta clase, para evitar sucesivas llamadas a File.getCanonicalPath() - - public FileExt(@NotNull File file) - { + + public FileExt(@NotNull File file) { this.file = file; - try { this.cannonicalPath = file.getCanonicalPath(); } - catch (IOException ex) { throw new RelProxyException(ex); } + try { + this.cannonicalPath = file.getCanonicalPath(); + } catch (IOException ex) { + throw new RelProxyException(ex); + } } - + @NotNull - public File getFile() - { + public File getFile() { return file; } - + @NotNull - public String getCanonicalPath() - { + public String getCanonicalPath() { return cannonicalPath; } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyConfigBaseImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyConfigBaseImpl.java index 2dd406d..483c142 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyConfigBaseImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyConfigBaseImpl.java @@ -3,21 +3,17 @@ import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; /** - * * @author jmarranz */ -public class GenericProxyConfigBaseImpl -{ +public class GenericProxyConfigBaseImpl { protected boolean enabled = true; protected RelProxyOnReloadListener relListener; - public boolean isEnabled() - { + public boolean isEnabled() { return enabled; } - public RelProxyOnReloadListener getRelProxyOnReloadListener() - { + public RelProxyOnReloadListener getRelProxyOnReloadListener() { return relListener; } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyImpl.java index fa9a470..47f1b12 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyImpl.java @@ -9,59 +9,50 @@ import java.lang.reflect.Proxy; /** - * * @author jmarranz */ -public abstract class GenericProxyImpl -{ +public abstract class GenericProxyImpl { protected RelProxyOnReloadListener reloadListener; - - public GenericProxyImpl() - { + + public GenericProxyImpl() { } - public static void checkSingletonNull(@Nullable GenericProxyImpl singleton) - { - if (singleton != null) + public static void checkSingletonNull(@Nullable GenericProxyImpl singleton) { + if (singleton != null) throw new RelProxyException("Already initialized"); } - - protected static void checkSingletonExists(@Nullable GenericProxyImpl singleton) - { - if (singleton == null) + + protected static void checkSingletonExists(@Nullable GenericProxyImpl singleton) { + if (singleton == null) throw new RelProxyException("Execute first the init method"); - } - - protected void init(@NotNull GenericProxyConfigBaseImpl config) - { - this.reloadListener = config.getRelProxyOnReloadListener(); - } - - public RelProxyOnReloadListener getRelProxyOnReloadListener() - { + } + + protected void init(@NotNull GenericProxyConfigBaseImpl config) { + this.reloadListener = config.getRelProxyOnReloadListener(); + } + + public RelProxyOnReloadListener getRelProxyOnReloadListener() { return reloadListener; } - + @Nullable - public T create(@Nullable T obj, Class clasz) - { - if (obj == null) return null; - - return (T)create(obj,new Class[] { clasz }); + public T create(@Nullable T obj, Class clasz) { + if (obj == null) return null; + + return (T) create(obj, new Class[]{clasz}); } - + @Nullable - public Object create(@Nullable Object obj, @NotNull Class[] classes) - { - if (obj == null) return null; - + public Object create(@Nullable Object obj, @NotNull Class[] classes) { + if (obj == null) return null; + InvocationHandler handler = createGenericProxyInvocationHandler(obj); - - Object proxy = Proxy.newProxyInstance(obj.getClass().getClassLoader(),classes, handler); + + Object proxy = Proxy.newProxyInstance(obj.getClass().getClassLoader(), classes, handler); return proxy; - } - - + } + + @NotNull public abstract GenericProxyInvocationHandler createGenericProxyInvocationHandler(Object obj); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyInvocationHandler.java b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyInvocationHandler.java index 1c47def..9761664 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyInvocationHandler.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyInvocationHandler.java @@ -9,61 +9,51 @@ import java.lang.reflect.Proxy; /** - * * @author jmarranz */ -public abstract class GenericProxyInvocationHandler implements InvocationHandler -{ +public abstract class GenericProxyInvocationHandler implements InvocationHandler { protected GenericProxyImpl root; protected GenericProxyVersionedObject verObj; - - public GenericProxyInvocationHandler(GenericProxyImpl root) - { + + public GenericProxyInvocationHandler(GenericProxyImpl root) { this.root = root; - } - - private Object getCurrent() - { + } + + private Object getCurrent() { return verObj.getCurrent(); } - - private Object getNewVersion() throws Throwable - { + + private Object getNewVersion() throws Throwable { return verObj.getNewVersion(); - } - + } + @Override - public synchronized Object invoke(Object proxy, @NotNull Method method, @Nullable Object[] args) throws Throwable - { + public synchronized Object invoke(Object proxy, @NotNull Method method, @Nullable Object[] args) throws Throwable { Object oldObj = getCurrent(); Object obj = getNewVersion(); RelProxyOnReloadListener reloadListener = root.getRelProxyOnReloadListener(); if (oldObj != obj && reloadListener != null) - reloadListener.onReload(oldObj,obj,proxy,method,args); + reloadListener.onReload(oldObj, obj, proxy, method, args); - if (args != null && args.length == 1) - { + if (args != null && args.length == 1) { // Conseguimos que en proxy1.equals(proxy2) se usen los objetos asociados no los propios proxies, para ello obtenemos el objeto asociado al parámetro // No hace falta que equals forme parte de la interface, pero está ahí implícitamente // hashCode() como no tiene params es llamado sin problema de conversiones Object param = args[0]; if (param instanceof Proxy && // Si es una clase generada com.sun.proxy.$ProxyN (N=1,2...) es también derivada de Proxy - method.getName().equals("equals") && - method.getReturnType().equals(boolean.class)) - { + method.getName().equals("equals") && + method.getReturnType().equals(boolean.class)) { Class[] paramTypes = method.getParameterTypes(); - if (paramTypes.length == 1 && paramTypes[0].equals(Object.class)) - { + if (paramTypes.length == 1 && paramTypes[0].equals(Object.class)) { InvocationHandler paramInvHandler = Proxy.getInvocationHandler(param); - if (paramInvHandler instanceof GenericProxyInvocationHandler) - { - args[0] = ((GenericProxyInvocationHandler)paramInvHandler).getCurrent(); // reemplazamos el Proxy por el objeto asociado + if (paramInvHandler instanceof GenericProxyInvocationHandler) { + args[0] = ((GenericProxyInvocationHandler) paramInvHandler).getCurrent(); // reemplazamos el Proxy por el objeto asociado } } } } return method.invoke(obj, args); - } + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyVersionedObject.java b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyVersionedObject.java index 60a479c..8fe21d1 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyVersionedObject.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/GenericProxyVersionedObject.java @@ -11,98 +11,79 @@ import java.util.ArrayList; /** - * * @author jmarranz */ -public abstract class GenericProxyVersionedObject -{ - protected Object obj; +public abstract class GenericProxyVersionedObject { + protected Object obj; protected GenericProxyInvocationHandler parent; - - public GenericProxyVersionedObject(Object obj,GenericProxyInvocationHandler parent) - { - this.obj = obj; + + public GenericProxyVersionedObject(Object obj, GenericProxyInvocationHandler parent) { + this.obj = obj; this.parent = parent; } - - protected static void getTreeFields(@NotNull Class clasz, Object obj, @NotNull ArrayList fieldList, ArrayList valueList) throws IllegalAccessException - { - getFields(clasz,obj,fieldList,valueList); + + protected static void getTreeFields(@NotNull Class clasz, Object obj, @NotNull ArrayList fieldList, ArrayList valueList) throws IllegalAccessException { + getFields(clasz, obj, fieldList, valueList); Class superClass = clasz.getSuperclass(); if (superClass != null) - getTreeFields(superClass,obj,fieldList,valueList); + getTreeFields(superClass, obj, fieldList, valueList); } - protected static void getFields(@NotNull Class clasz, Object obj, @NotNull ArrayList fieldList, @Nullable ArrayList valueList) throws IllegalAccessException - { - Field[] fieldListClass = clasz.getDeclaredFields(); - for(int i = 0; i < fieldListClass.length; i++) - { - Field field = fieldListClass[i]; + protected static void getFields(@NotNull Class clasz, Object obj, @NotNull ArrayList fieldList, @Nullable ArrayList valueList) throws IllegalAccessException { + Field[] fieldListClass = clasz.getDeclaredFields(); + for (int i = 0; i < fieldListClass.length; i++) { + Field field = fieldListClass[i]; fieldList.add(field); - if (valueList != null) - { - field.setAccessible(true); - Object value = field.get(obj); + if (valueList != null) { + field.setAccessible(true); + Object value = field.get(obj); valueList.add(value); } - } - } - - public Object getCurrent() - { + } + } + + public Object getCurrent() { return obj; - } - - public Object getNewVersion() throws Throwable - { + } + + public Object getNewVersion() throws Throwable { Class newClass = reloadClass(); if (newClass == null) return obj; - Class oldClass = obj.getClass(); - if (newClass != oldClass) - { - this.obj = copy(oldClass,obj,newClass); + Class oldClass = obj.getClass(); + if (newClass != oldClass) { + this.obj = copy(oldClass, obj, newClass); } - + return obj; - } - - private Object copy(@NotNull Class oldClass, Object oldObj, @NotNull Class newClass) throws IllegalAccessException, InstantiationException, IllegalArgumentException, InvocationTargetException - { + } + + private Object copy(@NotNull Class oldClass, Object oldObj, @NotNull Class newClass) throws IllegalAccessException, InstantiationException, IllegalArgumentException, InvocationTargetException { Object newObj; ArrayList fieldListOld = new ArrayList(); - ArrayList valueListOld = new ArrayList(); + ArrayList valueListOld = new ArrayList(); - getTreeFields(oldClass,oldObj,fieldListOld,valueListOld); + getTreeFields(oldClass, oldObj, fieldListOld, valueListOld); Class enclosingClassNew = newClass.getEnclosingClass(); - if (enclosingClassNew == null) - { + if (enclosingClassNew == null) { Constructor construc; - try - { + try { construc = newClass.getConstructor(new Class[0]); + } catch (NoSuchMethodException ex) { + throw new RelProxyException("Cannot reload " + newClass.getName() + " a default empty of params constructor is required", ex); } - catch(NoSuchMethodException ex) - { - throw new RelProxyException("Cannot reload " + newClass.getName() + " a default empty of params constructor is required",ex); - } - newObj = construc.newInstance(); - } - else - { + newObj = construc.newInstance(); + } else { // En el caso de inner class o anonymous inner class el constructor por defecto se obtiene de forma diferente, útil para los EventListener de ItsNat Constructor construc; - try + try { + construc = newClass.getDeclaredConstructor(new Class[]{enclosingClassNew}); + } catch (NoSuchMethodException ex) // Yo creo que nunca ocurre al menos no en anonymous inner classes pero por si acaso { - construc = newClass.getDeclaredConstructor(new Class[]{enclosingClassNew}); - } - catch(NoSuchMethodException ex) // Yo creo que nunca ocurre al menos no en anonymous inner classes pero por si acaso - { - throw new RelProxyException("Cannot reload " + newClass.getName() + " a default empty of params constructor is required",ex); + throw new RelProxyException("Cannot reload " + newClass.getName() + " a default empty of params constructor is required", ex); } construc.setAccessible(true); // Necesario @@ -110,60 +91,63 @@ private Object copy(@NotNull Class oldClass, Object oldObj, @NotNull Class newCl Field enclosingFieldOld; - try { enclosingFieldOld = oldClass.getDeclaredField("this$0"); } - catch (NoSuchFieldException ex) { throw new RelProxyException(ex); } + try { + enclosingFieldOld = oldClass.getDeclaredField("this$0"); + } catch (NoSuchFieldException ex) { + throw new RelProxyException(ex); + } enclosingFieldOld.setAccessible(true); - Object enclosingObjectOld = enclosingFieldOld.get(oldObj); - Object enclosingObjectNew = copy(enclosingObjectOld.getClass(),enclosingObjectOld,enclosingClassNew); + Object enclosingObjectOld = enclosingFieldOld.get(oldObj); + Object enclosingObjectNew = copy(enclosingObjectOld.getClass(), enclosingObjectOld, enclosingClassNew); - newObj = construc.newInstance(enclosingObjectNew); + newObj = construc.newInstance(enclosingObjectNew); } ArrayList fieldListNew = new ArrayList(); - getTreeFields(newClass,newObj,fieldListNew,null); + getTreeFields(newClass, newObj, fieldListNew, null); - if (fieldListOld.size() != fieldListNew.size()) throw new RelProxyException("Cannot reload " + newClass.getName() + " number of fields have changed, redeploy"); + if (fieldListOld.size() != fieldListNew.size()) + throw new RelProxyException("Cannot reload " + newClass.getName() + " number of fields have changed, redeploy"); - for(int i = 0; i < fieldListOld.size(); i++) - { + for (int i = 0; i < fieldListOld.size(); i++) { Field fieldOld = fieldListOld.get(i); Field fieldNew = fieldListNew.get(i); - if (enclosingClassNew != null && fieldOld.getName().equals("this$0") && fieldNew.getName().equals("this$0")) + if (enclosingClassNew != null && fieldOld.getName().equals("this$0") && fieldNew.getName().equals("this$0")) continue; // Ya están correctamente definidos - if ( (!ignoreField(fieldOld) && !fieldOld.getName().equals(fieldNew.getName())) || - !fieldOld.getType().equals(fieldNew.getType())) + if ((!ignoreField(fieldOld) && !fieldOld.getName().equals(fieldNew.getName())) || + !fieldOld.getType().equals(fieldNew.getType())) throw new RelProxyException("Cannot reload " + newClass.getName() + " fields have changed, redeploy"); Object fieldObj = valueListOld.get(i); fieldNew.setAccessible(true); - int modifiersNew = fieldNew.getModifiers(); + int modifiersNew = fieldNew.getModifiers(); boolean isStaticFinal = Modifier.isStatic(modifiersNew) && Modifier.isFinal(modifiersNew); Field modifiersField = null; - if (isStaticFinal) - { + if (isStaticFinal) { // http://stackoverflow.com/questions/3301635/change-private-static-final-field-using-java-reflection try { modifiersField = Field.class.getDeclaredField("modifiers"); + } catch (NoSuchFieldException ex) { + throw new RelProxyException(ex); } - catch (NoSuchFieldException ex) { throw new RelProxyException(ex); } modifiersField.setAccessible(true); modifiersField.setInt(fieldNew, fieldNew.getModifiers() & ~Modifier.FINAL); // Quitamos el modifier final - } + } fieldNew.set(newObj, fieldObj); - if (modifiersField != null) - { + if (modifiersField != null) { modifiersField.setInt(fieldNew, fieldNew.getModifiers() & ~Modifier.FINAL); // Restauramos el modifier final } - } + } return newObj; } - + @Nullable protected abstract Class reloadClass(); - protected abstract boolean ignoreField(Field field); + + protected abstract boolean ignoreField(Field field); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyConfigImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyConfigImpl.java index 826cace..0497adb 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyConfigImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyConfigImpl.java @@ -7,36 +7,30 @@ import org.jetbrains.annotations.NotNull; /** - * * @author jmarranz */ -public class GProxyConfigImpl extends GenericProxyConfigBaseImpl implements GProxyConfig -{ +public class GProxyConfigImpl extends GenericProxyConfigBaseImpl implements GProxyConfig { protected GProxyGroovyScriptEngine engine; @NotNull - public GProxyConfig setEnabled(boolean enabled) - { + public GProxyConfig setEnabled(boolean enabled) { this.enabled = enabled; return this; } @NotNull - public GProxyConfig setRelProxyOnReloadListener(RelProxyOnReloadListener relListener) - { - this.relListener = relListener; - return this; + public GProxyConfig setRelProxyOnReloadListener(RelProxyOnReloadListener relListener) { + this.relListener = relListener; + return this; } - + @NotNull - public GProxyConfig setGProxyGroovyScriptEngine(GProxyGroovyScriptEngine engine) - { - this.engine = engine; - return this; + public GProxyConfig setGProxyGroovyScriptEngine(GProxyGroovyScriptEngine engine) { + this.engine = engine; + return this; } - - public GProxyGroovyScriptEngine getGProxyGroovyScriptEngine() - { + + public GProxyGroovyScriptEngine getGProxyGroovyScriptEngine() { return engine; } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyDefaultImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyDefaultImpl.java index 8f466a9..25d0796 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyDefaultImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyDefaultImpl.java @@ -6,40 +6,34 @@ import org.jetbrains.annotations.Nullable; /** - * * @author jmarranz */ -public class GProxyDefaultImpl extends GProxyImpl -{ - public static GProxyConfig createGProxyConfig() - { +public class GProxyDefaultImpl extends GProxyImpl { + public static GProxyConfig createGProxyConfig() { return new GProxyConfigImpl(); - } - - public static void initStatic(@NotNull GProxyConfigImpl config) - { + } + + public static void initStatic(@NotNull GProxyConfigImpl config) { if (!config.isEnabled()) return; - - checkSingletonNull(SINGLETON); + + checkSingletonNull(SINGLETON); SINGLETON = new GProxyDefaultImpl(); SINGLETON.init(config); - } - + } + @Nullable - public static T createStatic(T obj, Class clasz) - { - if (SINGLETON == null) + public static T createStatic(T obj, Class clasz) { + if (SINGLETON == null) return obj; // No se ha llamado al init o enabled = false - + return SINGLETON.create(obj, clasz); - } - + } + @Nullable - public static Object createStatic(Object obj, @NotNull Class[] classes) - { - if (SINGLETON == null) + public static Object createStatic(Object obj, @NotNull Class[] classes) { + if (SINGLETON == null) return obj; // No se ha llamado al init o enabled = false - - return SINGLETON.create(obj, classes); - } + + return SINGLETON.create(obj, classes); + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyImpl.java index 33de8ec..0b07d79 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyImpl.java @@ -8,29 +8,24 @@ /** - * * @author jmarranz */ -public abstract class GProxyImpl extends GenericProxyImpl -{ - public static GProxyImpl SINGLETON; +public abstract class GProxyImpl extends GenericProxyImpl { + public static GProxyImpl SINGLETON; protected GProxyGroovyScriptEngine engine; - - public void init(@NotNull GProxyConfigImpl config) - { + + public void init(@NotNull GProxyConfigImpl config) { super.init(config); this.engine = config.getGProxyGroovyScriptEngine(); } - - public GProxyGroovyScriptEngine getGProxyGroovyScriptEngine() - { + + public GProxyGroovyScriptEngine getGProxyGroovyScriptEngine() { return engine; - } - + } + @NotNull @Override - public GenericProxyInvocationHandler createGenericProxyInvocationHandler(@NotNull Object obj) - { - return new GProxyInvocationHandler(obj,this); + public GenericProxyInvocationHandler createGenericProxyInvocationHandler(@NotNull Object obj) { + return new GProxyInvocationHandler(obj, this); } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyInvocationHandler.java b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyInvocationHandler.java index a1c54d3..9859dce 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyInvocationHandler.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyInvocationHandler.java @@ -4,21 +4,17 @@ import org.jetbrains.annotations.NotNull; /** - * * @author jmarranz */ -public class GProxyInvocationHandler extends GenericProxyInvocationHandler -{ - public GProxyInvocationHandler(@NotNull Object obj, GProxyImpl root) - { +public class GProxyInvocationHandler extends GenericProxyInvocationHandler { + public GProxyInvocationHandler(@NotNull Object obj, GProxyImpl root) { super(root); - this.verObj = new GProxyVersionedObject(obj,this); + this.verObj = new GProxyVersionedObject(obj, this); } @NotNull - public GProxyImpl getGProxyImpl() - { - return (GProxyImpl)root; + public GProxyImpl getGProxyImpl() { + return (GProxyImpl) root; } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyVersionedObject.java b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyVersionedObject.java index f8cbc2a..8f20b99 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyVersionedObject.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyVersionedObject.java @@ -8,46 +8,37 @@ import java.lang.reflect.Field; /** - * * @author jmarranz */ -public class GProxyVersionedObject extends GenericProxyVersionedObject -{ - protected String path; - - public GProxyVersionedObject(@NotNull Object obj, GProxyInvocationHandler parent) - { - super(obj,parent); - this.path = obj.getClass().getName().replace('.','/'); - } +public class GProxyVersionedObject extends GenericProxyVersionedObject { + protected String path; + + public GProxyVersionedObject(@NotNull Object obj, GProxyInvocationHandler parent) { + super(obj, parent); + this.path = obj.getClass().getName().replace('.', '/'); + } @NotNull - public GProxyInvocationHandler getGProxyInvocationHandler() - { - return (GProxyInvocationHandler)parent; + public GProxyInvocationHandler getGProxyInvocationHandler() { + return (GProxyInvocationHandler) parent; } @Nullable @Override - protected Class reloadClass() - { + protected Class reloadClass() { GProxyGroovyScriptEngine engine = getGProxyInvocationHandler().getGProxyImpl().getGProxyGroovyScriptEngine(); - - try - { + + try { return engine.loadScriptByName(path + ".groovy"); //Ej: example/groovyex/GroovyExampleLoadListener.groovy - } - catch(Exception ex) - { + } catch (Exception ex) { ex.printStackTrace(System.err); return null; - } + } } - + @Override - protected boolean ignoreField(@NotNull Field field) - { + protected boolean ignoreField(@NotNull Field field) { return field.getName().startsWith("__timeStamp__"); // Este atributo cambia de nombre en cada reload, no lo consideramos } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyConfigImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyConfigImpl.java index eb5c831..7b62e6f 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyConfigImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyConfigImpl.java @@ -14,12 +14,10 @@ import java.io.File; /** - * * @author jmarranz */ -public class JProxyConfigImpl extends GenericProxyConfigBaseImpl implements JProxyConfig -{ - protected File folderSources; +public class JProxyConfigImpl extends GenericProxyConfigBaseImpl implements JProxyConfig { + protected File folderSources; protected FolderSourceList folderSourceList; protected FolderSourceList requiredExtraJarPaths; protected JProxyInputSourceFileExcludedListener excludedListener; @@ -29,144 +27,123 @@ public class JProxyConfigImpl extends GenericProxyConfigBaseImpl implements JPro protected Iterable compilationOptions; protected JProxyDiagnosticsListener diagnosticsListener; protected boolean test = false; - + @NotNull @Override - public JProxyConfig setEnabled(boolean enabled) - { + public JProxyConfig setEnabled(boolean enabled) { this.enabled = enabled; return this; } @NotNull @Override - public JProxyConfig setRelProxyOnReloadListener(RelProxyOnReloadListener relListener) - { - this.relListener = relListener; - return this; - } - + public JProxyConfig setRelProxyOnReloadListener(RelProxyOnReloadListener relListener) { + this.relListener = relListener; + return this; + } + @NotNull @Override - public JProxyConfig setInputPath(@Nullable String inputPath) - { + public JProxyConfig setInputPath(@Nullable String inputPath) { setInputPaths(inputPath != null ? new String[]{inputPath} : null); // inputPath es null en el caso de shell interactive return this; } @NotNull @Override - public JProxyConfig setInputPaths(String[] inputPaths) - { - this.folderSourceList = new FolderSourceList(inputPaths,true); // inputPaths es null en el caso de shell interactive + public JProxyConfig setInputPaths(String[] inputPaths) { + this.folderSourceList = new FolderSourceList(inputPaths, true); // inputPaths es null en el caso de shell interactive return this; - } + } @NotNull @Override - public JProxyConfig setRequiredExtraJarPaths(String[] inputJarPaths) - { - this.requiredExtraJarPaths = new FolderSourceList(inputJarPaths,false); // inputPaths es null en el caso de shell interactive + public JProxyConfig setRequiredExtraJarPaths(String[] inputJarPaths) { + this.requiredExtraJarPaths = new FolderSourceList(inputJarPaths, false); // inputPaths es null en el caso de shell interactive return this; - } - + } + @NotNull @Override - public JProxyConfig setJProxyInputSourceFileExcludedListener(JProxyInputSourceFileExcludedListener excludedListener) - { + public JProxyConfig setJProxyInputSourceFileExcludedListener(JProxyInputSourceFileExcludedListener excludedListener) { this.excludedListener = excludedListener; return this; } - + @NotNull @Override - public JProxyConfig setJProxyCompilerListener(JProxyCompilerListener compilerListener) - { + public JProxyConfig setJProxyCompilerListener(JProxyCompilerListener compilerListener) { this.compilerListener = compilerListener; return this; - } - + } + @NotNull @Override - public JProxyConfig setClassFolder(String classFolder) - { - this.classFolder = classFolder; - return this; + public JProxyConfig setClassFolder(String classFolder) { + this.classFolder = classFolder; + return this; } @NotNull @Override - public JProxyConfig setScanPeriod(long scanPeriod) - { + public JProxyConfig setScanPeriod(long scanPeriod) { if (scanPeriod == 0) throw new RelProxyException("scanPeriod cannot be zero"); - this.scanPeriod = scanPeriod; - return this; + this.scanPeriod = scanPeriod; + return this; } @NotNull @Override - public JProxyConfig setCompilationOptions(Iterable compilationOptions) - { - this.compilationOptions = compilationOptions; - return this; + public JProxyConfig setCompilationOptions(Iterable compilationOptions) { + this.compilationOptions = compilationOptions; + return this; } @NotNull @Override - public JProxyConfig setJProxyDiagnosticsListener(JProxyDiagnosticsListener diagnosticsListener) - { + public JProxyConfig setJProxyDiagnosticsListener(JProxyDiagnosticsListener diagnosticsListener) { this.diagnosticsListener = diagnosticsListener; - return this; - } - - public FolderSourceList getFolderSourceList() - { + return this; + } + + public FolderSourceList getFolderSourceList() { return folderSourceList; } - - public FolderSourceList getRequiredExtraJarPaths() - { + + public FolderSourceList getRequiredExtraJarPaths() { return requiredExtraJarPaths; - } - - public JProxyInputSourceFileExcludedListener getJProxyInputSourceFileExcludedListener() - { + } + + public JProxyInputSourceFileExcludedListener getJProxyInputSourceFileExcludedListener() { return excludedListener; - } - - public JProxyCompilerListener getJProxyCompilerListener() - { + } + + public JProxyCompilerListener getJProxyCompilerListener() { return compilerListener; } - - public String getClassFolder() - { + + public String getClassFolder() { return classFolder; } - public long getScanPeriod() - { + public long getScanPeriod() { return scanPeriod; } - public Iterable getCompilationOptions() - { + public Iterable getCompilationOptions() { return compilationOptions; } - public JProxyDiagnosticsListener getJProxyDiagnosticsListener() - { + public JProxyDiagnosticsListener getJProxyDiagnosticsListener() { return diagnosticsListener; } - - public boolean isTest() - { + + public boolean isTest() { return test; } - public void setTest(boolean test) - { + public void setTest(boolean test) { this.test = test; } - + } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyDefaultImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyDefaultImpl.java index 83251da..d674f35 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyDefaultImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyDefaultImpl.java @@ -6,86 +6,74 @@ import org.jetbrains.annotations.Nullable; /** - * * @author jmarranz */ -public class JProxyDefaultImpl extends JProxyImpl -{ - public JProxyDefaultImpl() - { +public class JProxyDefaultImpl extends JProxyImpl { + public JProxyDefaultImpl() { } - + @Nullable @Override - public Class getMainParamClass() - { + public Class getMainParamClass() { return null; } - public static JProxyConfig createJProxyConfig() - { + public static JProxyConfig createJProxyConfig() { return new JProxyConfigImpl(); - } - - public static void initStatic(@NotNull JProxyConfigImpl config) - { + } + + public static void initStatic(@NotNull JProxyConfigImpl config) { if (!config.isEnabled()) return; - + checkSingletonNull(SINGLETON); SINGLETON = new JProxyDefaultImpl(); SINGLETON.init(config); - } - - + } + + @Nullable - public static T createStatic(T obj, Class clasz) - { - if (SINGLETON == null) + public static T createStatic(T obj, Class clasz) { + if (SINGLETON == null) return obj; // No se ha llamado al init o enabled = false - + return SINGLETON.create(obj, clasz); - } + } @Nullable - public static Object createStatic(Object obj, @NotNull Class[] classes) - { - if (SINGLETON == null) + public static Object createStatic(Object obj, @NotNull Class[] classes) { + if (SINGLETON == null) return obj; // No se ha llamado al init o enabled = false - - return SINGLETON.create(obj, classes); - } - - - public static boolean isEnabledStatic() - { - if (SINGLETON == null) + + return SINGLETON.create(obj, classes); + } + + + public static boolean isEnabledStatic() { + if (SINGLETON == null) return false; - + return SINGLETON.isEnabled(); - } - - - public static boolean isRunningStatic() - { - if (SINGLETON == null) + } + + + public static boolean isRunningStatic() { + if (SINGLETON == null) return false; - + return SINGLETON.isRunning(); - } - - public static boolean stopStatic() - { - if (SINGLETON == null) + } + + public static boolean stopStatic() { + if (SINGLETON == null) return false; - + return SINGLETON.stop(); - } - - public static boolean startStatic() - { - if (SINGLETON == null) + } + + public static boolean startStatic() { + if (SINGLETON == null) return false; - + return SINGLETON.start(); - } + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyUtil.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyUtil.java index dcfa297..ba850d0 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyUtil.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/JProxyUtil.java @@ -17,149 +17,126 @@ import java.net.URLConnection; /** - * * @author jmarranz */ -public class JProxyUtil -{ - public static String getCanonicalPath(@NotNull File file) - { - try - { +public class JProxyUtil { + public static String getCanonicalPath(@NotNull File file) { + try { return file.getCanonicalPath(); - } - catch (IOException ex) - { + } catch (IOException ex) { throw new RelProxyException(ex); } } - - public static String getFileExtension(@NotNull File file) - { + + public static String getFileExtension(@NotNull File file) { String path = file.getAbsolutePath(); - int pos = path.lastIndexOf('.'); - if (pos != -1) - return path.substring(pos + 1); + int pos = path.lastIndexOf('.'); + if (pos != -1) + return path.substring(pos + 1); return ""; - } - - public static File getParentDir(@NotNull File file) - { + } + + public static File getParentDir(@NotNull File file) { return file.getParentFile(); } - - public static byte[] readURL(@NotNull URL url) - { + + public static byte[] readURL(@NotNull URL url) { URLConnection urlCon; - try - { - urlCon = url.openConnection(); - return readInputStream(urlCon.getInputStream()); - } - catch (IOException ex) { throw new RelProxyException(ex); } + try { + urlCon = url.openConnection(); + return readInputStream(urlCon.getInputStream()); + } catch (IOException ex) { + throw new RelProxyException(ex); + } } - - public static byte[] readFile(@NotNull File file) - { + + public static byte[] readFile(@NotNull File file) { FileInputStream fis = null; - try - { - fis = new FileInputStream(file); - } - catch (FileNotFoundException ex) - { + try { + fis = new FileInputStream(file); + } catch (FileNotFoundException ex) { throw new RelProxyException(ex); - } + } return readInputStream(fis); - } + } - public static byte[] readInputStream(@NotNull InputStream is) - { - return readInputStream(is,50); // 50Kb => unas 100 lecturas 5 Mb + public static byte[] readInputStream(@NotNull InputStream is) { + return readInputStream(is, 50); // 50Kb => unas 100 lecturas 5 Mb } - public static byte[] readInputStream(@NotNull InputStream is, int bufferSizeKb) - { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - try - { - byte[] buffer = new byte[bufferSizeKb*1024]; + public static byte[] readInputStream(@NotNull InputStream is, int bufferSizeKb) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + try { + byte[] buffer = new byte[bufferSizeKb * 1024]; int size; - while( (size = is.read(buffer)) != -1 ) - { - out.write(buffer, 0, size); - } - } - catch (IOException ex) - { + while ((size = is.read(buffer)) != -1) { + out.write(buffer, 0, size); + } + } catch (IOException ex) { throw new RelProxyException(ex); - } - finally - { - try { is.close(); } catch (IOException ex2) { throw new RelProxyException(ex2); } + } finally { + try { + is.close(); + } catch (IOException ex2) { + throw new RelProxyException(ex2); + } } return out.toByteArray(); - } - - public static void saveFile(@NotNull File file, @NotNull byte[] content) - { + } + + public static void saveFile(@NotNull File file, @NotNull byte[] content) { File parent = getParentDir(file); if (parent != null) parent.mkdirs(); - FileOutputStream out = null; - try - { - out = new FileOutputStream(file); - out.write(content, 0, content.length); - } - catch (IOException ex) - { + FileOutputStream out = null; + try { + out = new FileOutputStream(file); + out.write(content, 0, content.length); + } catch (IOException ex) { throw new RelProxyException(ex); - } - finally - { - if (out != null) try { out.close(); } catch (IOException ex2) { throw new RelProxyException(ex2); } + } finally { + if (out != null) try { + out.close(); + } catch (IOException ex2) { + throw new RelProxyException(ex2); + } } - } + } - public static String readTextFile(@NotNull File file, @NotNull String encoding) - { + public static String readTextFile(@NotNull File file, @NotNull String encoding) { Reader reader = null; - try - { - reader = new InputStreamReader(new FileInputStream(file),encoding); // FileReader no permite especificar el encoding y total no hace nada que no haga InputStreamReader + try { + reader = new InputStreamReader(new FileInputStream(file), encoding); // FileReader no permite especificar el encoding y total no hace nada que no haga InputStreamReader + } catch (IOException ex) { + throw new RelProxyException(ex); } - catch(IOException ex) { throw new RelProxyException(ex); } - + return readTextFile(reader); - } - - public static String readTextFile(@NotNull Reader reader) - { + } + + public static String readTextFile(@NotNull Reader reader) { BufferedReader br = null; - try - { + try { br = new BufferedReader(reader); // FileReader no permite especificar el encoding y total no hace nada que no haga InputStreamReader StringBuilder sb = new StringBuilder(); String line = br.readLine(); - while (line != null) - { + while (line != null) { sb.append(line); sb.append('\n'); line = br.readLine(); } return sb.toString(); - } - catch(IOException ex) - { + } catch (IOException ex) { throw new RelProxyException(ex); + } finally { + if (br != null) try { + br.close(); + } catch (IOException ex) { + throw new RelProxyException(ex); + } } - finally - { - if (br != null) try { br.close(); } catch (IOException ex) { throw new RelProxyException(ex); } - } - } + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyImpl.java index 8c9883c..df213eb 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyImpl.java @@ -14,35 +14,29 @@ import org.jetbrains.annotations.Nullable; /** - * * @author jmarranz */ -public abstract class JProxyImpl extends GenericProxyImpl -{ - public static JProxyImpl SINGLETON; +public abstract class JProxyImpl extends GenericProxyImpl { + public static JProxyImpl SINGLETON; protected JProxyEngine engine; - - protected JProxyImpl() - { + + protected JProxyImpl() { } - - public static ClassLoader getDefaultClassLoader() - { + + public static ClassLoader getDefaultClassLoader() { return Thread.currentThread().getContextClassLoader(); } - + @Nullable - public ClassDescriptorSourceScript init(@NotNull JProxyConfigImpl config) - { - return init(config,null,null); - } - + public ClassDescriptorSourceScript init(@NotNull JProxyConfigImpl config) { + return init(config, null, null); + } + @Nullable - public ClassDescriptorSourceScript init(@NotNull JProxyConfigImpl config, SourceScriptRoot scriptFile, ClassLoader classLoader) - { + public ClassDescriptorSourceScript init(@NotNull JProxyConfigImpl config, SourceScriptRoot scriptFile, ClassLoader classLoader) { super.init(config); - + FolderSourceList folderSourceList = config.getFolderSourceList(); FolderSourceList requiredExtraJarPaths = config.getRequiredExtraJarPaths(); JProxyInputSourceFileExcludedListener excludedListener = config.getJProxyInputSourceFileExcludedListener(); @@ -52,45 +46,39 @@ public ClassDescriptorSourceScript init(@NotNull JProxyConfigImpl config, Source Iterable compilationOptions = config.getCompilationOptions(); JProxyDiagnosticsListener diagnosticsListener = config.getJProxyDiagnosticsListener(); boolean enabled = config.isEnabled(); - - classLoader = classLoader != null ? classLoader : getDefaultClassLoader(); - this.engine = new JProxyEngine(this,enabled,scriptFile,classLoader,folderSourceList,requiredExtraJarPaths,classFolder,scanPeriod,excludedListener,compilerListener,compilationOptions,diagnosticsListener); - + + classLoader = classLoader != null ? classLoader : getDefaultClassLoader(); + this.engine = new JProxyEngine(this, enabled, scriptFile, classLoader, folderSourceList, requiredExtraJarPaths, classFolder, scanPeriod, excludedListener, compilerListener, compilationOptions, diagnosticsListener); + return engine.init(); - } - - public JProxyEngine getJProxyEngine() - { + } + + public JProxyEngine getJProxyEngine() { return engine; } - - public boolean isEnabled() - { + + public boolean isEnabled() { return engine.isEnabled(); } - - public boolean isRunning() - { + + public boolean isRunning() { return engine.isRunning(); - } - - public boolean stop() - { + } + + public boolean stop() { return engine.stop(); - } - - public boolean start() - { + } + + public boolean start() { return engine.start(); - } - + } + @NotNull @Override - public GenericProxyInvocationHandler createGenericProxyInvocationHandler(@NotNull Object obj) - { - return new JProxyInvocationHandler(obj,this); + public GenericProxyInvocationHandler createGenericProxyInvocationHandler(@NotNull Object obj) { + return new JProxyInvocationHandler(obj, this); } - + @Nullable public abstract Class getMainParamClass(); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyInvocationHandler.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyInvocationHandler.java index d4223e5..4820f08 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyInvocationHandler.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyInvocationHandler.java @@ -5,21 +5,17 @@ import org.jetbrains.annotations.NotNull; /** - * * @author jmarranz */ -public class JProxyInvocationHandler extends GenericProxyInvocationHandler -{ - public JProxyInvocationHandler(@NotNull Object obj, JProxyImpl root) - { +public class JProxyInvocationHandler extends GenericProxyInvocationHandler { + public JProxyInvocationHandler(@NotNull Object obj, JProxyImpl root) { super(root); - this.verObj = new JProxyVersionedObject(obj,this); + this.verObj = new JProxyVersionedObject(obj, this); } @NotNull - public JProxyImpl getJProxyImpl() - { - return (JProxyImpl)root; - } - + public JProxyImpl getJProxyImpl() { + return (JProxyImpl) root; + } + } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyVersionedObject.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyVersionedObject.java index 2951dd4..55e2931 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyVersionedObject.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/JProxyVersionedObject.java @@ -8,37 +8,31 @@ import java.lang.reflect.Field; /** - * * @author jmarranz */ -public class JProxyVersionedObject extends GenericProxyVersionedObject -{ - protected String className; +public class JProxyVersionedObject extends GenericProxyVersionedObject { + protected String className; - public JProxyVersionedObject(@NotNull Object obj, JProxyInvocationHandler parent) - { - super(obj,parent); + public JProxyVersionedObject(@NotNull Object obj, JProxyInvocationHandler parent) { + super(obj, parent); this.className = obj.getClass().getName(); - } + } @NotNull - public JProxyInvocationHandler getJProxyInvocationHandler() - { - return (JProxyInvocationHandler)parent; - } - + public JProxyInvocationHandler getJProxyInvocationHandler() { + return (JProxyInvocationHandler) parent; + } + @Nullable @Override - protected Class reloadClass() - { - JProxyEngine engine = getJProxyInvocationHandler().getJProxyImpl().getJProxyEngine(); + protected Class reloadClass() { + JProxyEngine engine = getJProxyInvocationHandler().getJProxyImpl().getJProxyEngine(); engine.reloadWhenChanged(); - return (Class)engine.findClass(className); + return (Class) engine.findClass(className); } - + @Override - protected boolean ignoreField(Field field) - { + protected boolean ignoreField(Field field) { return false; // Todos cuentan (útil en Groovy no en Java) - } + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java index 9e54d35..925da6d 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java @@ -8,76 +8,64 @@ import java.io.File; /** - * * @author jmarranz */ -public class FolderSourceList -{ +public class FolderSourceList { protected FileExt[] sourceList; - - public FolderSourceList(@Nullable String[] sourcePathList, boolean expectedDirectory) - { + + public FolderSourceList(@Nullable String[] sourcePathList, boolean expectedDirectory) { if (sourcePathList != null) // En el caso de shell interactivo es null { // El convertir siempre a File los paths es para normalizar paths this.sourceList = new FileExt[sourcePathList.length]; - for(int i = 0; i < sourcePathList.length; i++) - { + for (int i = 0; i < sourcePathList.length; i++) { File folder = new File(sourcePathList[i]); if (!folder.exists()) throw new RelProxyException("Source folder does not exist: " + folder.getAbsolutePath()); boolean isDirectory = folder.isDirectory(); - if (expectedDirectory) - { + if (expectedDirectory) { if (!isDirectory) - throw new RelProxyException("Source folder is not a directory: " + folder.getAbsolutePath()); - } - else - { + throw new RelProxyException("Source folder is not a directory: " + folder.getAbsolutePath()); + } else { if (isDirectory) - throw new RelProxyException("Expected a file not a directory: " + folder.getAbsolutePath()); + throw new RelProxyException("Expected a file not a directory: " + folder.getAbsolutePath()); } - sourceList[i] = new FileExt(folder); + sourceList[i] = new FileExt(folder); } } - } - - public FileExt[] getArray() - { - return sourceList; } - + + public FileExt[] getArray() { + return sourceList; + } + @Nullable - public String buildClassNameFromFile(@NotNull FileExt sourceFile) - { - for(FileExt rootFolderOfSources : sourceList) - { - String className = buildClassNameFromFile(sourceFile,rootFolderOfSources); + public String buildClassNameFromFile(@NotNull FileExt sourceFile) { + for (FileExt rootFolderOfSources : sourceList) { + String className = buildClassNameFromFile(sourceFile, rootFolderOfSources); if (className != null) - return className; + return className; } throw new RelProxyException("File not found in source folders: " + sourceFile.getFile().getAbsolutePath()); - } - - public static String buildClassNameFromFile(@NotNull FileExt sourceFile, @NotNull FileExt rootFolderOfSources) - { + } + + public static String buildClassNameFromFile(@NotNull FileExt sourceFile, @NotNull FileExt rootFolderOfSources) { String path = sourceFile.getCanonicalPath(); String rootFolderOfSourcesAbsPath = rootFolderOfSources.getCanonicalPath(); - int pos = path.indexOf(rootFolderOfSourcesAbsPath); + int pos = path.indexOf(rootFolderOfSourcesAbsPath); if (pos == 0) // Está en este source folder { path = path.substring(rootFolderOfSourcesAbsPath.length() + 1); // Sumamos +1 para quitar también el / separador del pathInput y el path relativo de la clase // Puede no tener extensión (script) o bien ser .java o bien ser una inventada (ej .jsh), la quitamos si existe - pos = path.lastIndexOf('.'); - if (pos != -1) - path = path.substring(0, pos); + pos = path.lastIndexOf('.'); + if (pos != -1) + path = path.substring(0, pos); path = path.replace(File.separatorChar, '.'); // getAbsolutePath() normaliza con el caracter de la plataforma return path; } return null; - } - - - + } + + } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java index 8552bbc..4a14c6b 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyClassLoader.java @@ -9,42 +9,35 @@ import java.net.URL; /** - * * @author jmarranz */ -public class JProxyClassLoader extends ClassLoader -{ +public class JProxyClassLoader extends ClassLoader { @NotNull protected final JProxyEngine engine; - - public JProxyClassLoader(@NotNull JProxyEngine engine) - { + + public JProxyClassLoader(@NotNull JProxyEngine engine) { super(engine.getRootClassLoader()); - + this.engine = engine; } - - public Class defineClass(@NotNull ClassDescriptor classDesc) - { + + public Class defineClass(@NotNull ClassDescriptor classDesc) { Object monitor = engine.getMonitor(); - synchronized(monitor) - { + synchronized (monitor) { String className = classDesc.getClassName(); byte[] classBytes = classDesc.getClassBytes(); - Class clasz = defineClass(className,classBytes, 0, classBytes.length); + Class clasz = defineClass(className, classBytes, 0, classBytes.length); classDesc.setLastLoadedClass(clasz); - return clasz; + return clasz; } } - + @Override - protected Class findClass(@NotNull String name) throws ClassNotFoundException - { + protected Class findClass(@NotNull String name) throws ClassNotFoundException { Object monitor = engine.getMonitor(); - synchronized(monitor) - { - return loadClass(name,true); - + synchronized (monitor) { + return loadClass(name, true); + /* Class cls = findLoadedClass(name); if (cls == null) @@ -56,49 +49,43 @@ protected Class findClass(@NotNull String name) throws ClassNotFoundException return cls; */ } - } + } - public Class loadClass(@NotNull ClassDescriptor classDesc, boolean resolve) - { + public Class loadClass(@NotNull ClassDescriptor classDesc, boolean resolve) { Object monitor = engine.getMonitor(); - synchronized(monitor) - { + synchronized (monitor) { Class clasz = classDesc.getLastLoadedClass(); if (clasz != null && clasz.getClassLoader() == this) return clasz; // Glup, ya fue cargada - clasz = defineClass(classDesc); + clasz = defineClass(classDesc); if (resolve) { resolveClass(clasz); - } + } return clasz; } - } - + } + @Nullable - public Class loadInnerClass(@NotNull ClassDescriptorSourceUnit parentDesc, @NotNull String innerClassName) - { + public Class loadInnerClass(@NotNull ClassDescriptorSourceUnit parentDesc, @NotNull String innerClassName) { Object monitor = engine.getMonitor(); - synchronized(monitor) - { - ClassDescriptor classDesc = parentDesc.getInnerClassDescriptor(innerClassName,false); - if (classDesc == null || classDesc.getClassBytes() == null) - { - byte[] classBytes = getClassBytesFromResource(innerClassName); - if (classBytes == null) return null; + synchronized (monitor) { + ClassDescriptor classDesc = parentDesc.getInnerClassDescriptor(innerClassName, false); + if (classDesc == null || classDesc.getClassBytes() == null) { + byte[] classBytes = getClassBytesFromResource(innerClassName); + if (classBytes == null) return null; if (classDesc == null) classDesc = parentDesc.addInnerClassDescriptor(innerClassName); classDesc.setClassBytes(classBytes); - } + } - return defineClass(classDesc); + return defineClass(classDesc); } } - + @Override - protected Class loadClass(@NotNull String name, boolean resolve) throws ClassNotFoundException - { + protected Class loadClass(@NotNull String name, boolean resolve) throws ClassNotFoundException { // Inspiraciones en URLClassLoader.findClass y en el propio análisis de ClassLoader.loadClass // Lo redefinimos por si acaso porque el objetivo es recargar todas las clases hot-reloaded en este ClassLoader y no delegar en el parent // (el comportamiento por defecto de loadClass) pues las clases cargadas con el parent tenderán a cargar las clases vinculadas con dicho ClassLoader - + // En teoría este método redefinido no es necesario porque manualmente detectamos los cambios de código fuente, recompilamos y recargamos explícitamente // con defineClass el cual no carga también las innerclasses vinculadas, // pero si el código fuente tiene innerclasses y no ha sido cambiado nunca, las innerclasses pueden no ser conocidas como ClassDescriptor, @@ -110,32 +97,27 @@ protected Class loadClass(@NotNull String name, boolean resolve) throws Class // por lo que pasaremos por aquí y debemos cargarla aquí, luego no hay problema de recarga explícita porque sabemos que ha sido ya cargada // y tampoco hay problema de auto-salvado del .class o eliminación del mismo puesto que al ser un archivo fuente normal se tratará por si mismo // aunque la carga en el class loader se haya hecho a través de una clase derivada quizás antes - + Object monitor = engine.getMonitor(); - synchronized(monitor) - { + synchronized (monitor) { Class cls = findLoadedClass(name); - if (cls == null) - { + if (cls == null) { ClassDescriptor classDesc = engine.getClassDescriptor(name); // Si es una inner class se crea el descriptor y se añade al source file asociado automáticamente - if (classDesc != null) - { + if (classDesc != null) { byte[] classBytes = classDesc.getClassBytes(); - if (classBytes == null) - { + if (classBytes == null) { classBytes = getClassBytesFromResource(name); // No puede ser nulo classDesc.setClassBytes(classBytes); } - cls = defineClass(classDesc); + cls = defineClass(classDesc); } - - if (cls == null) - { + + if (cls == null) { cls = getParent().loadClass(name); // Dará un ClassNotFoundException si no puede cargarla } - } - + } + if (cls == null) throw new ClassNotFoundException(name); if (resolve) { @@ -144,12 +126,11 @@ protected Class loadClass(@NotNull String name, boolean resolve) throws Class return cls; } } - - private byte[] getClassBytesFromResource(@NotNull String className) - { - String relClassPath = ClassDescriptor.getRelativeClassFilePathFromClassName(className); + + private byte[] getClassBytesFromResource(@NotNull String className) { + String relClassPath = ClassDescriptor.getRelativeClassFilePathFromClassName(className); URL urlClass = getResource(relClassPath); if (urlClass == null) return null; - return JProxyUtil.readURL(urlClass); + return JProxyUtil.readURL(urlClass); } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java index efdfdd7..303706c 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngine.java @@ -18,11 +18,9 @@ import java.util.TimerTask; /** - * * @author jmarranz */ -public class JProxyEngine -{ +public class JProxyEngine { protected final Object monitor = new Object(); // Podríamos usar este objeto JProxyEngine directamente pero el monitor es mejor para análisis de dependencias protected final JProxyImpl parent; @NotNull @@ -30,47 +28,41 @@ public class JProxyEngine protected final ClassLoader rootClassLoader; @Nullable protected JProxyClassLoader customClassLoader; - protected final long scanPeriod; + protected final long scanPeriod; protected final String sourceEncoding = "UTF-8"; // Por ahora, provisional public volatile boolean stop = false; @Nullable protected TimerTask task; - protected boolean pendingReload = false; - protected final boolean enabled; - - public JProxyEngine(JProxyImpl parent,boolean enabled,SourceScriptRoot scriptFile,ClassLoader rootClassLoader,FolderSourceList folderSourceList,FolderSourceList requiredExtraJarPaths, - String folderClasses,long scanPeriod,JProxyInputSourceFileExcludedListener excludedListener, - JProxyCompilerListener compilerListener,Iterable compilationOptions,JProxyDiagnosticsListener diagnosticsListener) - { + protected boolean pendingReload = false; + protected final boolean enabled; + + public JProxyEngine(JProxyImpl parent, boolean enabled, SourceScriptRoot scriptFile, ClassLoader rootClassLoader, FolderSourceList folderSourceList, FolderSourceList requiredExtraJarPaths, + String folderClasses, long scanPeriod, JProxyInputSourceFileExcludedListener excludedListener, + JProxyCompilerListener compilerListener, Iterable compilationOptions, JProxyDiagnosticsListener diagnosticsListener) { this.parent = parent; - this.enabled = enabled; + this.enabled = enabled; this.rootClassLoader = rootClassLoader; this.scanPeriod = scanPeriod; - this.delegateChangeDetector = new JProxyEngineChangeDetectorAndCompiler(this,scriptFile,folderSourceList,requiredExtraJarPaths,folderClasses,excludedListener,compilationOptions,diagnosticsListener,compilerListener); + this.delegateChangeDetector = new JProxyEngineChangeDetectorAndCompiler(this, scriptFile, folderSourceList, requiredExtraJarPaths, folderClasses, excludedListener, compilationOptions, diagnosticsListener, compilerListener); this.customClassLoader = null; //new JProxyClassLoader(this); } - + @NotNull - public Object getMonitor() - { + public Object getMonitor() { return monitor; } - - public JProxyImpl getJProxy() - { + + public JProxyImpl getJProxy() { return parent; } - - public boolean isEnabled() - { + + public boolean isEnabled() { return enabled; - } - + } + @Nullable - public ClassDescriptorSourceScript init() - { - synchronized(getMonitor()) - { + public ClassDescriptorSourceScript init() { + synchronized (getMonitor()) { ClassDescriptorSourceScript scriptFileDesc = detectChangesInSources(); // Primera vez para detectar cambios en los .java respecto a los .class mientras el servidor estaba parado reloadWhenChanged(); // La primera vez cargamos pues el código fuente manda sobre los .class @@ -87,230 +79,185 @@ public JProxyClassLoader getJProxyClassLoader() return customClassLoader; } */ - + @Nullable - public ClassLoader getCurrentClassLoader() - { + public ClassLoader getCurrentClassLoader() { if (customClassLoader != null) return customClassLoader; return rootClassLoader; - } - - private boolean startScanner() - { + } + + private boolean startScanner() { if (scanPeriod > 0) // Si es 0 o negativo sólo se recargan una vez (la inicial ya ejecutada) - { - this.task = new TimerTask() - { + { + this.task = new TimerTask() { @Override - public void run() - { - if (stop) - { + public void run() { + if (stop) { cancel(); return; } - - try - { + + try { detectChangesInSources(); // Está sincronizado las partes que lo necesitan - } - catch(Exception ex) - { + } catch (Exception ex) { ex.printStackTrace(System.err); // Si dejamos subir la excepción se acabó el timer } } - }; - + }; + new Timer().schedule(task, scanPeriod, scanPeriod); // Ojo, después de la primera llamada a detectChangesInSources() return true; - } - else - { + } else { return false; } } - - public void setPendingReload() - { + + public void setPendingReload() { this.pendingReload = true; - } - - - public ClassLoader getRootClassLoader() - { + } + + + public ClassLoader getRootClassLoader() { return rootClassLoader; } - + @NotNull - public String getSourceEncoding() - { + public String getSourceEncoding() { return sourceEncoding; } - - public boolean isRunning() - { - synchronized(getMonitor()) - { + + public boolean isRunning() { + synchronized (getMonitor()) { return task != null && scanPeriod > 0; } } - - public boolean stop() - { - synchronized(getMonitor()) - { - if (task != null) - { + + public boolean stop() { + synchronized (getMonitor()) { + if (task != null) { this.stop = true; task.cancel(); this.task = null; return true; - } - else - { + } else { return false; } } - } - - public boolean start() - { - synchronized(getMonitor()) - { - if (task == null) - { + } + + public boolean start() { + synchronized (getMonitor()) { + if (task == null) { this.stop = false; return startScanner(); - } - else return false; + } else return false; } - } - + } + - @Nullable - public ClassDescriptor getClassDescriptor(@NotNull String className) - { - synchronized(getMonitor()) - { + public ClassDescriptor getClassDescriptor(@NotNull String className) { + synchronized (getMonitor()) { return delegateChangeDetector.getClassDescriptor(className); } } - + @Nullable - public Class findClass(@NotNull String className) - { + public Class findClass(@NotNull String className) { // Si ya está cargada la devuelve, y si no se cargó por ningún JProxyClassLoader se intenta cargar por el parent ClassLoader, por lo que siempre devolverá distinto de null si la clase está en el classpath, que debería ser lo normal - synchronized(getMonitor()) - { - try - { + synchronized (getMonitor()) { + try { if (customClassLoader != null) - return customClassLoader.findClass(className); + return customClassLoader.findClass(className); else return rootClassLoader.loadClass(className); - } - catch (ClassNotFoundException ex) - { + } catch (ClassNotFoundException ex) { return null; } } } - - private void addNewClassLoader() - { + + private void addNewClassLoader() { ClassDescriptorSourceFileRegistry sourceRegistry = delegateChangeDetector.getClassDescriptorSourceFileRegistry(); - - for(ClassDescriptorSourceUnit sourceFile : sourceRegistry.getClassDescriptorSourceFileColl()) - { + + for (ClassDescriptorSourceUnit sourceFile : sourceRegistry.getClassDescriptorSourceFileColl()) { sourceFile.resetLastLoadedClass(); // resetea también las innerclasses } - - this.customClassLoader = new JProxyClassLoader(this); + + this.customClassLoader = new JProxyClassLoader(this); } - - - private Class reloadSource(@NotNull ClassDescriptorSourceUnit sourceFile) - { - Class clasz = customClassLoader.loadClass(sourceFile,true); - reloadInnerClassesOnly(sourceFile,clasz); + + private Class reloadSource(@NotNull ClassDescriptorSourceUnit sourceFile) { + Class clasz = customClassLoader.loadClass(sourceFile, true); + reloadInnerClassesOnly(sourceFile, clasz); return clasz; } - - private void reloadInnerClassesOnly(@NotNull ClassDescriptorSourceUnit sourceFile, @NotNull Class classParent) - { - - LinkedList innerClassDescList = sourceFile.getInnerClassDescriptors(); - if (innerClassDescList != null && !innerClassDescList.isEmpty()) - { + + private void reloadInnerClassesOnly(@NotNull ClassDescriptorSourceUnit sourceFile, @NotNull Class classParent) { + + LinkedList innerClassDescList = sourceFile.getInnerClassDescriptors(); + if (innerClassDescList != null && !innerClassDescList.isEmpty()) { // En el caso de una clase que ha sido compilada, las inner classes se descubren todas - for(ClassDescriptorInner innerClassDesc : innerClassDescList) - { - customClassLoader.loadClass(innerClassDesc,true); + for (ClassDescriptorInner innerClassDesc : innerClassDescList) { + customClassLoader.loadClass(innerClassDesc, true); } - } - else // Auto-Detección de innerclasses: puede ser un archivo fuente que posiblemente nunca se hayan tocado desde la carga inicial y por tanto quizás se desconocen las innerclasses + } else // Auto-Detección de innerclasses: puede ser un archivo fuente que posiblemente nunca se hayan tocado desde la carga inicial y por tanto quizás se desconocen las innerclasses { // Aprovechando la carga de la clase, hacemos el esfuerzo de cargar todas las clases dependientes lo más posible classParent.getDeclaredClasses(); // Provoca que las inner clases miembro indirectamente se procesen y carguen a través del JProxyClassLoader de la clase padre clasz - + // Ahora bien, lo anterior NO sirve para las anonymous inner classes, afortunadamente en ese caso podemos conocer y cargar por fuerza bruta // http://stackoverflow.com/questions/1654889/java-reflection-how-can-i-retrieve-anonymous-inner-classes?rq=1 - - for(int i = 1; i < Integer.MAX_VALUE; i++) // No te asustes por el MAX_VALUE, se parará tras unos poquitos ciclos + + for (int i = 1; i < Integer.MAX_VALUE; i++) // No te asustes por el MAX_VALUE, se parará tras unos poquitos ciclos { - String anonClassName = sourceFile.getClassName() + "$" + i; - Class innerClasz = customClassLoader.loadInnerClass(sourceFile,anonClassName); + String anonClassName = sourceFile.getClassName() + "$" + i; + Class innerClasz = customClassLoader.loadInnerClass(sourceFile, anonClassName); if (innerClasz == null) break; // No hay más o no hay ninguna (si i es 1) - } - + } + // ¿Qué es lo que queda por cargar pero que no podemos hacer explícitamente? // 1) Las clases privadas autónomas que fueron definidas en el mismo archivo que la clase principal: no las soportamos pues no podemos identificar en el ClassLoader que es una clase "hot reloadable", no son inner classes en el sentido estricto // 2) Las clases privadas "inner" locales, es decir no anónimas declaradas dentro de un método, se cargarán la primera vez que se usen, no podemos conocerlas a priori // porque siguen la notación className$NclassName ej. JReloadExampleDocument$1AuxMemberInMethod. No hay problema con que se carguen con un class loader antiguo pues // el ClassLoader de la clase padre contenedora será el encargado de cargarla en cuanto se pase por el método que la declara. - } - } - + } + } + @Nullable - public ClassDescriptorSourceScript detectChangesInSources() - { - return delegateChangeDetector.detectChangesInSources(); - } - + public ClassDescriptorSourceScript detectChangesInSources() { + return delegateChangeDetector.detectChangesInSources(); + } + @Nullable - public ClassDescriptorSourceScript detectChangesInSourcesAndReload() - { - ClassDescriptorSourceScript res = detectChangesInSources(); + public ClassDescriptorSourceScript detectChangesInSourcesAndReload() { + ClassDescriptorSourceScript res = detectChangesInSources(); reloadWhenChanged(); - return res; - } - - public boolean reloadWhenChanged() - { - synchronized(getMonitor()) - { - if (pendingReload) - { + return res; + } + + public boolean reloadWhenChanged() { + synchronized (getMonitor()) { + if (pendingReload) { addNewClassLoader(); - ClassDescriptorSourceFileRegistry sourceRegistry = delegateChangeDetector.getClassDescriptorSourceFileRegistry(); + ClassDescriptorSourceFileRegistry sourceRegistry = delegateChangeDetector.getClassDescriptorSourceFileRegistry(); - for(ClassDescriptorSourceUnit sourceFile : sourceRegistry.getClassDescriptorSourceFileColl()) // sourceRegistry NUNCA es nulo pues se ejecuta una primera vez en tiempo de inicialización + for (ClassDescriptorSourceUnit sourceFile : sourceRegistry.getClassDescriptorSourceFileColl()) // sourceRegistry NUNCA es nulo pues se ejecuta una primera vez en tiempo de inicialización { - // if (sourceFilesCompiled.contains(sourceFile)) - // continue; + // if (sourceFilesCompiled.contains(sourceFile)) + // continue; // las clases deleted no están en sourceFileMap por lo que no hay que filtrarlas reloadSource(sourceFile); // Ponemos detectInnerClasses a true porque son archivos fuente que posiblemente nunca se hayan tocado desde la carga inicial y por tanto quizás se desconocen las innerclasses - } + } this.pendingReload = false; return true; } - return false; + return false; } } - + } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java index 4e6f179..90df143 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java @@ -24,225 +24,194 @@ import java.util.LinkedList; /** - * * @author jmarranz */ -public class JProxyEngineChangeDetectorAndCompiler -{ +public class JProxyEngineChangeDetectorAndCompiler { protected final JProxyEngine engine; @NotNull protected final JProxyCompilerInMemory compiler; - protected final FolderSourceList folderSourceList; + protected final FolderSourceList folderSourceList; protected final FolderSourceList requiredExtraJarPaths; protected final SourceScriptRoot scriptFile; // Puede ser nulo protected final String folderClasses; // Puede ser nulo (es decir NO salvar como .class los cambios) - protected final JProxyInputSourceFileExcludedListener excludedListener; + protected final JProxyInputSourceFileExcludedListener excludedListener; @NotNull protected final JavaSourcesSearch sourcesSearch; - protected final JProxyCompilerListener compilerListener; + protected final JProxyCompilerListener compilerListener; protected volatile ClassDescriptorSourceFileRegistry sourceRegistry; - - public JProxyEngineChangeDetectorAndCompiler(JProxyEngine engine,SourceScriptRoot scriptFile,FolderSourceList folderSourceList,FolderSourceList requiredExtraJarPaths, - String folderClasses, JProxyInputSourceFileExcludedListener excludedListener,Iterable compilationOptions,JProxyDiagnosticsListener diagnosticsListener, - JProxyCompilerListener compilerListener) - { + + public JProxyEngineChangeDetectorAndCompiler(JProxyEngine engine, SourceScriptRoot scriptFile, FolderSourceList folderSourceList, FolderSourceList requiredExtraJarPaths, + String folderClasses, JProxyInputSourceFileExcludedListener excludedListener, Iterable compilationOptions, JProxyDiagnosticsListener diagnosticsListener, + JProxyCompilerListener compilerListener) { this.engine = engine; this.scriptFile = scriptFile; - this.folderSourceList = folderSourceList; + this.folderSourceList = folderSourceList; this.requiredExtraJarPaths = requiredExtraJarPaths; this.folderClasses = folderClasses; this.excludedListener = excludedListener; - this.compiler = new JProxyCompilerInMemory(this,compilationOptions,diagnosticsListener); - this.sourcesSearch = new JavaSourcesSearch(this); + this.compiler = new JProxyCompilerInMemory(this, compilationOptions, diagnosticsListener); + this.sourcesSearch = new JavaSourcesSearch(this); this.compilerListener = compilerListener; } - - public JProxyEngine getJProxyEngine() - { + + public JProxyEngine getJProxyEngine() { return engine; } - - public FolderSourceList getFolderSourceList() - { + + public FolderSourceList getFolderSourceList() { return folderSourceList; - } - - public FolderSourceList getRequiredExtraJarPaths() - { + } + + public FolderSourceList getRequiredExtraJarPaths() { return requiredExtraJarPaths; - } - - public JProxyInputSourceFileExcludedListener getJProxyInputSourceFileExcludedListener() - { + } + + public JProxyInputSourceFileExcludedListener getJProxyInputSourceFileExcludedListener() { return excludedListener; - } - - public ClassDescriptorSourceFileRegistry getClassDescriptorSourceFileRegistry() - { + } + + public ClassDescriptorSourceFileRegistry getClassDescriptorSourceFileRegistry() { return sourceRegistry; - } - + } + @Nullable - public ClassDescriptor getClassDescriptor(@NotNull String className) - { + public ClassDescriptor getClassDescriptor(@NotNull String className) { return sourceRegistry.getClassDescriptor(className); - } - - private boolean isSaveClassesMode() - { + } + + private boolean isSaveClassesMode() { return (folderClasses != null); - } - - private JProxyCompilerListener getJProxyCompilerListener() - { + } + + private JProxyCompilerListener getJProxyCompilerListener() { return compilerListener; } - - private void cleanBeforeCompile(@NotNull ClassDescriptorSourceUnit sourceFile) - { - if (isSaveClassesMode()) + + private void cleanBeforeCompile(@NotNull ClassDescriptorSourceUnit sourceFile) { + if (isSaveClassesMode()) deleteClasses(sourceFile); // Antes de que nos las carguemos en memoria la clase principal y las inner tras recompilar - + sourceFile.cleanOnSourceCodeChanged(); // El código fuente nuevo puede haber cambiado totalmente las innerclasses antiguas (añadido, eliminado) y por supuesto el bytecode necesita olvidarse } - - private void compile(@NotNull ClassDescriptorSourceUnit sourceFile, @NotNull JProxyCompilerContext context) - { + + private void compile(@NotNull ClassDescriptorSourceUnit sourceFile, @NotNull JProxyCompilerContext context) { if (sourceFile.getClassBytes() != null) return; // Ya ha sido compilado seguramente por dependencia de un archivo compilado inmediatamente antes, recuerda que el atributo classBytes se pone a null antes de compilar los archivos cambiados/nuevos - - compiler.compileSourceFile(sourceFile,context,engine.getCurrentClassLoader(),sourceRegistry); - } - + + compiler.compileSourceFile(sourceFile, context, engine.getCurrentClassLoader(), sourceRegistry); + } + @Nullable - public ClassDescriptorSourceScript detectChangesInSources() - { + public ClassDescriptorSourceScript detectChangesInSources() { Object monitor = getJProxyEngine().getMonitor(); - + boolean firstTime; - - synchronized(monitor) - { + + synchronized (monitor) { if (this.sourceRegistry == null) // Es null la primera vez { firstTime = true; this.sourceRegistry = new ClassDescriptorSourceFileRegistry(); - } - else - { + } else { firstTime = false; - sourceRegistry.setAllClassDescriptorSourceFilesPendingToRemove( true ); // A medida que los vamos encontrando ponemos a false, es mucho más rápido que recrear el registro si no ha cambiado nada (lo normal) + sourceRegistry.setAllClassDescriptorSourceFilesPendingToRemove(true); // A medida que los vamos encontrando ponemos a false, es mucho más rápido que recrear el registro si no ha cambiado nada (lo normal) } - } + } LinkedList updatedSourceFiles = new LinkedList(); - LinkedList newSourceFiles = new LinkedList(); - - ClassDescriptorSourceScript scriptFileDesc = sourcesSearch.sourceFileSearch(firstTime,scriptFile,sourceRegistry,updatedSourceFiles,newSourceFiles); + LinkedList newSourceFiles = new LinkedList(); + + ClassDescriptorSourceScript scriptFileDesc = sourcesSearch.sourceFileSearch(firstTime, scriptFile, sourceRegistry, updatedSourceFiles, newSourceFiles); LinkedList deletedSourceFiles = new LinkedList(); - - if (!firstTime) - { - synchronized(monitor) - { + + if (!firstTime) { + synchronized (monitor) { // Obtenemos los deletedSourceFiles detectados (si es firstTime no tiene sentido hacer esto no haría nada pero nos ahorramos synchronized y llamada) sourceRegistry.getAllClassDescriptorSourceFilesPendingToRemove(deletedSourceFiles); } } - + if (updatedSourceFiles.isEmpty() && newSourceFiles.isEmpty() && deletedSourceFiles.isEmpty()) return scriptFileDesc; // También el hecho de eliminar una clase debe implicar crear un ClassLoader nuevo para que dicha clase desaparezca de las clases cargadas aunque será muy raro que sólo eliminemos un .java y no añadamos/cambiemos otros, otro motico es porque si tenemos configurado el autosalvado de .class tenemos que eliminar en ese caso - synchronized(monitor) - { - if (!firstTime) - { + synchronized (monitor) { + if (!firstTime) { if (!deletedSourceFiles.isEmpty()) // En firstTime no tiene sentido que haya eliminados { - for(ClassDescriptorSourceUnit classDesc : deletedSourceFiles) + for (ClassDescriptorSourceUnit classDesc : deletedSourceFiles) sourceRegistry.removeClassDescriptorSourceUnit(classDesc.getClassName()); } if (!newSourceFiles.isEmpty()) // En firstTime ya están añadidos en sourceRegistry explícitamente al recorrer los sources { - for(ClassDescriptorSourceUnit classDesc : newSourceFiles) + for (ClassDescriptorSourceUnit classDesc : newSourceFiles) sourceRegistry.addClassDescriptorSourceUnit(classDesc); - } + } } - + ArrayList sourceFilesToCompile = new ArrayList(updatedSourceFiles.size() + newSourceFiles.size()); sourceFilesToCompile.addAll(updatedSourceFiles); - sourceFilesToCompile.addAll(newSourceFiles); + sourceFilesToCompile.addAll(newSourceFiles); updatedSourceFiles = null; // Ya no se necesita newSourceFiles = null; // Ya no se necesita - if (!sourceFilesToCompile.isEmpty()) - { + if (!sourceFilesToCompile.isEmpty()) { // Eliminamos el estado de la anterior compilación de todas las clases que van a recompilarse antes de compilarlas porque al compilar una clase es posible que // se necesite recompilar al mismo tiempo una dependiente de otra (ej clase base) y luego se intente compilar la dependiente y sería un problema que limpiáramos antes de compilar cada archivo - for(ClassDescriptorSourceUnit sourceFile : sourceFilesToCompile) - cleanBeforeCompile(sourceFile); + for (ClassDescriptorSourceUnit sourceFile : sourceFilesToCompile) + cleanBeforeCompile(sourceFile); JProxyCompilerContext context = compiler.createJProxyCompilerContext(); JProxyCompilerListener compilerListener = getJProxyCompilerListener(); - try - { + try { - for(ClassDescriptorSourceUnit sourceFile : sourceFilesToCompile) - { + for (ClassDescriptorSourceUnit sourceFile : sourceFilesToCompile) { File file = null; - if (compilerListener != null) - { + if (compilerListener != null) { SourceUnit srcUnit = sourceFile.getSourceUnit(); if (srcUnit instanceof SourceFileJavaNormal) - file = ((SourceFileJavaNormal)srcUnit).getFileExt().getFile(); + file = ((SourceFileJavaNormal) srcUnit).getFileExt().getFile(); else if (srcUnit instanceof SourceScriptRootFile) - file = ((SourceScriptRootFile)srcUnit).getFileExt().getFile(); + file = ((SourceScriptRootFile) srcUnit).getFileExt().getFile(); else if (srcUnit instanceof SourceScriptRootInMemory) // Caso de shell interactive y code snippet, en ese caso NO hay listener porque no hay forma de definirlo file = null; } if (compilerListener != null && file != null) - compilerListener.beforeCompile(file); + compilerListener.beforeCompile(file); - compile(sourceFile,context); + compile(sourceFile, context); if (compilerListener != null && file != null) - compilerListener.afterCompile(file); + compilerListener.afterCompile(file); } - } - finally - { + } finally { context.close(); } - if (isSaveClassesMode()) - { - for(ClassDescriptorSourceUnit sourceFile : sourceFilesToCompile) - { - saveClasses(sourceFile); - } + if (isSaveClassesMode()) { + for (ClassDescriptorSourceUnit sourceFile : sourceFilesToCompile) { + saveClasses(sourceFile); + } } } if (isSaveClassesMode() && !deletedSourceFiles.isEmpty()) - for(ClassDescriptorSourceUnit sourceFile : deletedSourceFiles) - deleteClasses(sourceFile); + for (ClassDescriptorSourceUnit sourceFile : deletedSourceFiles) + deleteClasses(sourceFile); deletedSourceFiles = null; // Ya no se necesita boolean setPendingReload = true; - if (sourceFilesToCompile.size() == 1) - { + if (sourceFilesToCompile.size() == 1) { ClassDescriptorSourceUnit sourceFile = sourceFilesToCompile.get(0); SourceUnit sourceUnit = sourceFile.getSourceUnit(); - if ((sourceUnit instanceof SourceScriptRootInMemory) && ((SourceScriptRootInMemory)sourceUnit).isEmptyCode()) - { + if ((sourceUnit instanceof SourceScriptRootInMemory) && ((SourceScriptRootInMemory) sourceUnit).isEmptyCode()) { // Leer notas en SourceScriptRootInMemory.isEmptyCode() de esta manera evitamos crear un ClassLoader nuevo inútilmente por culpa de una clase // root que no sirve para nada, ello impide que el registro/desregistro en colecciones funcione bien pues la instancia // en el proxy que añade se ha recreado y es diferente por tanto a la instancia del proxy que elimina pues hace lo mismo por su parte @@ -250,63 +219,57 @@ else if (srcUnit instanceof SourceScriptRootInMemory) // Caso de shell interacti setPendingReload = false; } } - + if (setPendingReload) engine.setPendingReload(); } return scriptFileDesc; - } - - private void saveClasses(@NotNull ClassDescriptorSourceUnit sourceFile) - { + } + + private void saveClasses(@NotNull ClassDescriptorSourceUnit sourceFile) { // Salvamos la clase principal { - File classFilePath = ClassDescriptor.getAbsoluteClassFilePathFromClassNameAndClassPath(sourceFile.getClassName(),folderClasses); - JProxyUtil.saveFile(classFilePath,sourceFile.getClassBytes()); + File classFilePath = ClassDescriptor.getAbsoluteClassFilePathFromClassNameAndClassPath(sourceFile.getClassName(), folderClasses); + JProxyUtil.saveFile(classFilePath, sourceFile.getClassBytes()); } // Salvamos las innerclasses si hay, no hay problema de clases inner no detectadas pues lo están todas pues sólo se salva tras una compilación - LinkedList innerClassDescList = sourceFile.getInnerClassDescriptors(); - if (innerClassDescList != null && !innerClassDescList.isEmpty()) - { - for(ClassDescriptorInner innerClassDesc : innerClassDescList) - { - File classFilePath = ClassDescriptor.getAbsoluteClassFilePathFromClassNameAndClassPath(innerClassDesc.getClassName(),folderClasses); - JProxyUtil.saveFile(classFilePath,innerClassDesc.getClassBytes()); + LinkedList innerClassDescList = sourceFile.getInnerClassDescriptors(); + if (innerClassDescList != null && !innerClassDescList.isEmpty()) { + for (ClassDescriptorInner innerClassDesc : innerClassDescList) { + File classFilePath = ClassDescriptor.getAbsoluteClassFilePathFromClassNameAndClassPath(innerClassDesc.getClassName(), folderClasses); + JProxyUtil.saveFile(classFilePath, innerClassDesc.getClassBytes()); } - } - } - - private void deleteClasses(@NotNull ClassDescriptorSourceUnit sourceFile) - { + } + } + + private void deleteClasses(@NotNull ClassDescriptorSourceUnit sourceFile) { // Puede ocurrir que esta clase nunca se haya cargado y se ha modificado el código fuente y queramos limpiar los .class correspondientes pues se van a recrear // como no conocemos qué inner clases están asociadas para saber que .class hay que eliminar, pues lo que hacemos es directamente obtener los .class que hay // en el directorio con el fin de eliminar todos .class que tengan el patrón de ser inner classes del source file de acuerdo a su nombre // así conseguimos por ejemplo también eliminar las local classes (inner clases con nombre declaradas dentro de un método) que no hay manera de conocer // a través de la carga de la clase - + // Hay un caso en el que puede haber .class que ya no están en el código fuente y es cuando tocamos el código fuente ANTES de cargar y eliminamos algún .java, // al cargar como no existe el archivo no lo relacionamos con los .class // La solución sería en tiempo de carga forzar una carga de todas las clases y de ahí deducir todos los .class que deben existir (excepto las clases locales // que no podríamos detectarlas), pero el que haya .class sobrantes antiguos no es gran problema. - - File classFilePath = ClassDescriptor.getAbsoluteClassFilePathFromClassNameAndClassPath(sourceFile.getClassName(),folderClasses); + + File classFilePath = ClassDescriptor.getAbsoluteClassFilePathFromClassNameAndClassPath(sourceFile.getClassName(), folderClasses); File parentDir = JProxyUtil.getParentDir(classFilePath); String[] fileNameList = parentDir.list(); // Es más ligero que listFiles() que crea File por cada resultado if (fileNameList != null) // Si es null es que el directorio no está creado { - for (String fileName : fileNameList) - { + for (String fileName : fileNameList) { int pos = fileName.lastIndexOf(".class"); if (pos == -1) continue; String simpleClassName = fileName.substring(0, pos); if (sourceFile.getSimpleClassName().equals(simpleClassName) || - sourceFile.isInnerClass(sourceFile.getPackageName() + simpleClassName)) - { - new File(parentDir,fileName).delete(); + sourceFile.isInnerClass(sourceFile.getPackageName() + simpleClassName)) { + new File(parentDir, fileName).delete(); } } } - } + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java index 3633838..15bdf65 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java @@ -5,11 +5,9 @@ import java.io.File; /** - * * @author jmarranz */ -public abstract class ClassDescriptor -{ +public abstract class ClassDescriptor { @NotNull protected final String className; // El nombre basado en puntos pero usando $ en el caso de innerclasses @NotNull @@ -17,59 +15,50 @@ public abstract class ClassDescriptor @NotNull protected final String packageName; // El package pero acabado en un "." o bien "" si no hay package, el motivo de acabar en un punto es simplemente para poder concatenar ciegamente el package y el simpleClassName protected byte[] classBytes; - protected Class clasz; - - public ClassDescriptor(@NotNull String className) - { + protected Class clasz; + + public ClassDescriptor(@NotNull String className) { this.className = className; int pos = className.lastIndexOf('.'); this.simpleClassName = (pos != -1) ? className.substring(pos + 1) : className; - this.packageName = (pos != -1) ? className.substring(0,pos + 1) : ""; // SE INCLUYE EL . en el caso de existir package + this.packageName = (pos != -1) ? className.substring(0, pos + 1) : ""; // SE INCLUYE EL . en el caso de existir package } - + public abstract boolean isInnerClass(); - + @NotNull - public String getClassName() - { + public String getClassName() { return className; } - + @NotNull - public String getSimpleClassName() - { + public String getSimpleClassName() { return simpleClassName; } - + @NotNull - public String getPackageName() - { + public String getPackageName() { return packageName; - } - - public byte[] getClassBytes() - { + } + + public byte[] getClassBytes() { return classBytes; } - - public void setClassBytes(byte[] classBytes) - { + + public void setClassBytes(byte[] classBytes) { this.classBytes = classBytes; } - public Class getLastLoadedClass() - { + public Class getLastLoadedClass() { return clasz; } - public void setLastLoadedClass(Class clasz) - { + public void setLastLoadedClass(Class clasz) { this.clasz = clasz; - } + } - public void resetLastLoadedClass() - { - setLastLoadedClass(null); + public void resetLastLoadedClass() { + setLastLoadedClass(null); } /* @@ -78,46 +67,40 @@ public String getClassFileNameFromClassName() return getClassFileNameFromClassName(className); } */ - - public static String getClassFileNameFromClassName(@NotNull String className) - { + + public static String getClassFileNameFromClassName(@NotNull String className) { // Es válido también para las innerclasses (ej Nombre$Otro => Nombre$Otro.class, Nombre$1 => Nombre$1.class, Nombre$1Nombre => Nombre$1Nombre.class int pos = className.lastIndexOf("."); - if(pos != -1) className = className.substring(pos + 1); - return className + ".class"; + if (pos != -1) className = className.substring(pos + 1); + return className + ".class"; } - - public static String getRelativeClassFilePathFromClassName(@NotNull String className) - { - return className.replace('.','/') + ".class"; // alternativa: className.replaceAll("\\.", "/") + ".class" + + public static String getRelativeClassFilePathFromClassName(@NotNull String className) { + return className.replace('.', '/') + ".class"; // alternativa: className.replaceAll("\\.", "/") + ".class" } - + @NotNull - public static String getRelativePackagePathFromClassName(@NotNull String className) - { - String packageName = className.replace('.','/'); + public static String getRelativePackagePathFromClassName(@NotNull String className) { + String packageName = className.replace('.', '/'); int pos = packageName.lastIndexOf('/'); if (pos == -1) return packageName; - return packageName.substring(0,pos); - } - - public static File getAbsoluteClassFilePathFromClassNameAndClassPath(@NotNull String className, String classPath) - { + return packageName.substring(0, pos); + } + + public static File getAbsoluteClassFilePathFromClassNameAndClassPath(@NotNull String className, String classPath) { String relativePath = getRelativeClassFilePathFromClassName(className); classPath = classPath.trim(); - if (!classPath.endsWith("/") && !classPath.endsWith("\\")) classPath += File.separatorChar; - return new File(classPath + relativePath); - } - - public static String getClassNameFromRelativeClassFilePath(@NotNull String path) - { + if (!classPath.endsWith("/") && !classPath.endsWith("\\")) classPath += File.separatorChar; + return new File(classPath + relativePath); + } + + public static String getClassNameFromRelativeClassFilePath(@NotNull String path) { // Ej. org/w3c/dom/Element.class => org.w3c.dom.Element String binaryName = path.replaceAll("/", "."); return binaryName.replaceAll(".class$", ""); // El $ indica "el .class del final" } - - public static String getClassNameFromPackageAndClassFileName(String packageName,String fileName) - { + + public static String getClassNameFromPackageAndClassFileName(String packageName, String fileName) { String className = packageName + "." + fileName; return className.replaceAll(".class$", ""); // El $ indica "el .class del final" } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java index 118e81b..190c067 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java @@ -3,27 +3,22 @@ import org.jetbrains.annotations.NotNull; /** - * * @author jmarranz */ -public class ClassDescriptorInner extends ClassDescriptor -{ +public class ClassDescriptorInner extends ClassDescriptor { protected final ClassDescriptorSourceUnit parent; - - public ClassDescriptorInner(@NotNull String className, ClassDescriptorSourceUnit parent) - { + + public ClassDescriptorInner(@NotNull String className, ClassDescriptorSourceUnit parent) { super(className); this.parent = parent; - } - + } + @Override - public boolean isInnerClass() - { + public boolean isInnerClass() { return true; - } - - public ClassDescriptorSourceUnit getClassDescriptorSourceUnit() - { + } + + public ClassDescriptorSourceUnit getClassDescriptorSourceUnit() { return parent; } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java index 351d73b..4e87460 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java @@ -6,25 +6,20 @@ import org.jetbrains.annotations.NotNull; /** - * * @author jmarranz */ -public class ClassDescriptorSourceFileJava extends ClassDescriptorSourceUnit -{ - public ClassDescriptorSourceFileJava(JProxyEngine engine, @NotNull String className, SourceFileJavaNormal sourceFile, long timestamp) - { - super(engine,className, sourceFile, timestamp); +public class ClassDescriptorSourceFileJava extends ClassDescriptorSourceUnit { + public ClassDescriptorSourceFileJava(JProxyEngine engine, @NotNull String className, SourceFileJavaNormal sourceFile, long timestamp) { + super(engine, className, sourceFile, timestamp); } - + @NotNull - public SourceFileJavaNormal getSourceFileJavaNormal() - { - return (SourceFileJavaNormal)sourceUnit; + public SourceFileJavaNormal getSourceFileJavaNormal() { + return (SourceFileJavaNormal) sourceUnit; } - - public FileExt getSourceFile() - { + + public FileExt getSourceFile() { return getSourceFileJavaNormal().getFileExt(); - } - + } + } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java index a532809..53fb273 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java @@ -9,91 +9,75 @@ import java.util.Map; /** - * * @author jmarranz */ -public class ClassDescriptorSourceFileRegistry -{ +public class ClassDescriptorSourceFileRegistry { @NotNull - protected final Map sourceUnitMapByClassName; - - public ClassDescriptorSourceFileRegistry() - { - this.sourceUnitMapByClassName = new HashMap(); + protected final Map sourceUnitMapByClassName; + + public ClassDescriptorSourceFileRegistry() { + this.sourceUnitMapByClassName = new HashMap(); + } + + public ClassDescriptorSourceFileRegistry(@NotNull ClassDescriptorSourceFileRegistry origin) { + this.sourceUnitMapByClassName = new HashMap(origin.sourceUnitMapByClassName); } - public ClassDescriptorSourceFileRegistry(@NotNull ClassDescriptorSourceFileRegistry origin) - { - this.sourceUnitMapByClassName = new HashMap( origin.sourceUnitMapByClassName ); - } - - public boolean isEmpty() - { + public boolean isEmpty() { return sourceUnitMapByClassName.isEmpty(); } - + @NotNull - public Collection getClassDescriptorSourceFileColl() - { + public Collection getClassDescriptorSourceFileColl() { return sourceUnitMapByClassName.values(); } - - public ClassDescriptorSourceUnit getClassDescriptorSourceUnit(String className) - { + + public ClassDescriptorSourceUnit getClassDescriptorSourceUnit(String className) { return sourceUnitMapByClassName.get(className); - } - - public ClassDescriptorSourceUnit removeClassDescriptorSourceUnit(String className) - { + } + + public ClassDescriptorSourceUnit removeClassDescriptorSourceUnit(String className) { return sourceUnitMapByClassName.remove(className); - } - - public void addClassDescriptorSourceUnit(@NotNull ClassDescriptorSourceUnit sourceFile) - { + } + + public void addClassDescriptorSourceUnit(@NotNull ClassDescriptorSourceUnit sourceFile) { sourceUnitMapByClassName.put(sourceFile.getClassName(), sourceFile); } - - public void setAllClassDescriptorSourceFilesPendingToRemove(boolean pending) - { - for(Map.Entry entries : sourceUnitMapByClassName.entrySet()) - entries.getValue().setPendingToRemove(pending); + + public void setAllClassDescriptorSourceFilesPendingToRemove(boolean pending) { + for (Map.Entry entries : sourceUnitMapByClassName.entrySet()) + entries.getValue().setPendingToRemove(pending); } - + @NotNull - public LinkedList getAllClassDescriptorSourceFilesPendingToRemove(@NotNull LinkedList deletedSourceFiles) - { - for(Map.Entry entries : sourceUnitMapByClassName.entrySet()) - { + public LinkedList getAllClassDescriptorSourceFilesPendingToRemove(@NotNull LinkedList deletedSourceFiles) { + for (Map.Entry entries : sourceUnitMapByClassName.entrySet()) { ClassDescriptorSourceUnit classDesc = entries.getValue(); - boolean pending = classDesc.isPendingToRemove(); + boolean pending = classDesc.isPendingToRemove(); if (pending) - deletedSourceFiles.add(classDesc); + deletedSourceFiles.add(classDesc); } return deletedSourceFiles; - } - + } + @Nullable - public ClassDescriptor getClassDescriptor(@NotNull String className) - { + public ClassDescriptor getClassDescriptor(@NotNull String className) { // Puede ser el de una innerclass // Las innerclasses no están como tales en sourceFileMap pues sólo está la clase contenedora pero también la consideramos hotloadable String parentClassName; - int pos = className.lastIndexOf('$'); - boolean inner; - if (pos != -1) - { + int pos = className.lastIndexOf('$'); + boolean inner; + if (pos != -1) { parentClassName = className.substring(0, pos); inner = true; - } - else - { + } else { parentClassName = className; inner = false; } - ClassDescriptorSourceUnit sourceDesc = sourceUnitMapByClassName.get(parentClassName); + ClassDescriptorSourceUnit sourceDesc = sourceUnitMapByClassName.get(parentClassName); if (sourceDesc == null) return null; if (!inner) return sourceDesc; - return sourceDesc.getInnerClassDescriptor(className,true); - } + return sourceDesc.getInnerClassDescriptor(className, true); + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java index 8b76640..2dea6f9 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java @@ -13,81 +13,70 @@ import javax.script.ScriptEngine; /** - * * @author jmarranz */ -public class ClassDescriptorSourceScript extends ClassDescriptorSourceUnit -{ - protected String source; - - public ClassDescriptorSourceScript(JProxyEngine engine, @NotNull String className, SourceScriptRoot sourceFile, long timestamp) - { - super(engine,className, sourceFile, timestamp); +public class ClassDescriptorSourceScript extends ClassDescriptorSourceUnit { + protected String source; + + public ClassDescriptorSourceScript(JProxyEngine engine, @NotNull String className, SourceScriptRoot sourceFile, long timestamp) { + super(engine, className, sourceFile, timestamp); generateSourceCode(); } - + @NotNull - public SourceScriptRoot getSourceScript() - { - return (SourceScriptRoot)sourceUnit; + public SourceScriptRoot getSourceScript() { + return (SourceScriptRoot) sourceUnit; } - - private void generateSourceCode() - { + + private void generateSourceCode() { boolean[] hasHashBang = new boolean[1]; - - String scriptCode = getSourceScript().getScriptCode(getEncoding(),hasHashBang); - + + String scriptCode = getSourceScript().getScriptCode(getEncoding(), hasHashBang); + boolean completeClass = isCompleteClass(scriptCode); - - StringBuilder finalCode = new StringBuilder(); - if (completeClass) - { - if (hasHashBang[0]) finalCode.append("\n"); // Como hemos quitado la línea #! añadimos una nueva para que los números de línea en caso de error coincidan con el original - finalCode.append(scriptCode); - } - else - { - JProxyImpl jproxy = engine.getJProxy(); - String mainParamsDec = null; - String mainReturnType = null; - + + StringBuilder finalCode = new StringBuilder(); + if (completeClass) { + if (hasHashBang[0]) + finalCode.append("\n"); // Como hemos quitado la línea #! añadimos una nueva para que los números de línea en caso de error coincidan con el original + finalCode.append(scriptCode); + } else { + JProxyImpl jproxy = engine.getJProxy(); + String mainParamsDec = null; + String mainReturnType = null; + Class mainParamClass = jproxy.getMainParamClass(); - if (mainParamClass.equals(String[].class)) - { + if (mainParamClass.equals(String[].class)) { mainParamsDec = "String[] args"; mainReturnType = "void"; - } - else if (mainParamClass.equals(ScriptContext.class)) - { + } else if (mainParamClass.equals(ScriptContext.class)) { mainParamsDec = ScriptEngine.class.getName() + " engine," + ScriptContext.class.getName() + " context"; mainReturnType = "Object"; - + if (scriptCode.equals("")) scriptCode = "return null;"; } - + finalCode.append("public class " + className + " { public static " + mainReturnType + " main(" + mainParamsDec + ") {\n"); // Lo ponemos todo en una línea para que en caso de error la línea de error coincida con el script original pues hemos quitado la primera línea #! - finalCode.append(scriptCode); - finalCode.append(" }\n"); - finalCode.append("}\n"); + finalCode.append(scriptCode); + finalCode.append(" }\n"); + finalCode.append("}\n"); } - this.source = finalCode.toString(); + this.source = finalCode.toString(); } - - private boolean isCompleteClass(@NotNull String code) - { + + private boolean isCompleteClass(@NotNull String code) { // Buscamos si hay un " class ..." o un "import..." al comienzo para soportar la definición de una clase completa como script - int pos = code.indexOf("class"); - if (pos == -1) return false; + int pos = code.indexOf("class"); + if (pos == -1) return false; // Hay al menos un "class", ojo que puede ser parte de una variable o dentro de un comentario, pero si no existiera desde luego que no es clase completa - + pos = getFirstPosIgnoringCommentsAndSeparators(code); if (pos == -1) return false; - + // Lo primero que nos tenemos encontrar es un import o una declaración de class - int pos2 = code.indexOf("import",pos); + int pos2 = code.indexOf("import", pos); if (pos2 == pos) return true; // Si hay un import hay declaración de clase @@ -96,92 +85,86 @@ private boolean isCompleteClass(@NotNull String code) String visibility = code.substring(pos, posClass); visibility = visibility.trim(); // No consideramos \n hay que ser retorcido poner un \n entre el public y el class por ejemplo if (visibility.isEmpty()) return true; // No hay visibilidad, que no compile no es cosa nuestra - return ("private".equals(visibility) || "public".equals(visibility) || "protected".equals(visibility)); + return ("private".equals(visibility) || "public".equals(visibility) || "protected".equals(visibility)); } - - private int getFirstPosIgnoringCommentsAndSeparators(@NotNull String code) - { + + private int getFirstPosIgnoringCommentsAndSeparators(@NotNull String code) { int i = -1; - for(i = 0; i < code.length(); i++) - { + for (i = 0; i < code.length(); i++) { char c = code.charAt(i); if (c == ' ' || c == '\n' || c == '\t') continue; - else if (c == '/' && i + 1 < code.length()) - { + else if (c == '/' && i + 1 < code.length()) { char c2 = code.charAt(i + 1); - if (c2 == '/') - { - i = getFirstPosIgnoringOneLineComment(code,i); + if (c2 == '/') { + i = getFirstPosIgnoringOneLineComment(code, i); if (i == -1) return -1; // Comentario mal formado - } - else if (c2 == '*') - { - i = getFirstPosIgnoringMultiLineComment(code,i); + } else if (c2 == '*') { + i = getFirstPosIgnoringMultiLineComment(code, i); if (i == -1) return -1; // Comentario mal formado } - } - else break; + } else break; } return i; } - - private int getFirstPosIgnoringOneLineComment(@NotNull String code, int start) - { - return code.indexOf('\n',start); - } - - private int getFirstPosIgnoringMultiLineComment(@NotNull String code, int start) - { + + private int getFirstPosIgnoringOneLineComment(@NotNull String code, int start) { + return code.indexOf('\n', start); + } + + private int getFirstPosIgnoringMultiLineComment(@NotNull String code, int start) { return code.indexOf("*/", start); - } - + } + @Override - public void updateTimestamp(long timestamp) - { + public void updateTimestamp(long timestamp) { long oldTimestamp = this.timestamp; if (oldTimestamp != timestamp) - generateSourceCode(); + generateSourceCode(); super.updateTimestamp(timestamp); } - - public String getSourceCode() - { + + public String getSourceCode() { return source; } - - public void callMainMethod(@NotNull LinkedList argsToScript) throws Throwable - { - try - { - Class scriptClass = getLastLoadedClass(); - Method method = scriptClass.getDeclaredMethod("main",new Class[]{ String[].class }); + + public void callMainMethod(@NotNull LinkedList argsToScript) throws Throwable { + try { + Class scriptClass = getLastLoadedClass(); + Method method = scriptClass.getDeclaredMethod("main", new Class[]{String[].class}); String[] argsToScriptArr = argsToScript.size() > 0 ? argsToScript.toArray(new String[argsToScript.size()]) : new String[0]; - method.invoke(null, new Object[]{ argsToScriptArr }); - } - catch (IllegalAccessException ex) { throw new RelProxyException(ex); } - catch (NoSuchMethodException ex) { throw new RelProxyException(ex); } - catch (SecurityException ex) { throw new RelProxyException(ex); } - catch (IllegalArgumentException ex) { throw new RelProxyException(ex); } - catch (InvocationTargetException ex) { throw ex.getCause(); } // Los errores de ejecución se envuelven en un InvocationTargetException - } - - public Object callMainMethod(ScriptEngine engine,ScriptContext context) throws Throwable - { - Class scriptClass = getLastLoadedClass(); - return callMainMethod(scriptClass,engine,context); + method.invoke(null, new Object[]{argsToScriptArr}); + } catch (IllegalAccessException ex) { + throw new RelProxyException(ex); + } catch (NoSuchMethodException ex) { + throw new RelProxyException(ex); + } catch (SecurityException ex) { + throw new RelProxyException(ex); + } catch (IllegalArgumentException ex) { + throw new RelProxyException(ex); + } catch (InvocationTargetException ex) { + throw ex.getCause(); + } // Los errores de ejecución se envuelven en un InvocationTargetException + } + + public Object callMainMethod(ScriptEngine engine, ScriptContext context) throws Throwable { + Class scriptClass = getLastLoadedClass(); + return callMainMethod(scriptClass, engine, context); + } + + public static Object callMainMethod(@NotNull Class scriptClass, ScriptEngine engine, ScriptContext context) throws Throwable { + try { + Method method = scriptClass.getDeclaredMethod("main", new Class[]{ScriptEngine.class, ScriptContext.class}); + return method.invoke(null, new Object[]{engine, context}); + } catch (IllegalAccessException ex) { + throw new RelProxyException(ex); + } catch (NoSuchMethodException ex) { + throw new RelProxyException(ex); + } catch (SecurityException ex) { + throw new RelProxyException(ex); + } catch (IllegalArgumentException ex) { + throw new RelProxyException(ex); + } catch (InvocationTargetException ex) { + throw ex.getCause(); + } // Los errores de ejecución se envuelven en un InvocationTargetException } - - public static Object callMainMethod(@NotNull Class scriptClass, ScriptEngine engine, ScriptContext context) throws Throwable - { - try - { - Method method = scriptClass.getDeclaredMethod("main",new Class[]{ ScriptEngine.class,ScriptContext.class }); - return method.invoke(null, new Object[]{ engine, context }); - } - catch (IllegalAccessException ex) { throw new RelProxyException(ex); } - catch (NoSuchMethodException ex) { throw new RelProxyException(ex); } - catch (SecurityException ex) { throw new RelProxyException(ex); } - catch (IllegalArgumentException ex) { throw new RelProxyException(ex); } - catch (InvocationTargetException ex) { throw ex.getCause(); } // Los errores de ejecución se envuelven en un InvocationTargetException - } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java index fa8287e..3e112d9 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java @@ -10,19 +10,16 @@ import java.util.LinkedList; /** - * * @author jmarranz */ -public abstract class ClassDescriptorSourceUnit extends ClassDescriptor -{ +public abstract class ClassDescriptorSourceUnit extends ClassDescriptor { protected final JProxyEngine engine; protected volatile long timestamp; - protected final SourceUnit sourceUnit; + protected final SourceUnit sourceUnit; protected LinkedList innerClasses; protected boolean pendingToRemove = false; // Se usa como monohilo, no hay problemas de sincronización - - public ClassDescriptorSourceUnit(JProxyEngine engine, @NotNull String className, SourceUnit sourceFile, long timestamp) - { + + public ClassDescriptorSourceUnit(JProxyEngine engine, @NotNull String className, SourceUnit sourceFile, long timestamp) { super(className); this.engine = engine; this.sourceUnit = sourceFile; @@ -30,124 +27,106 @@ public ClassDescriptorSourceUnit(JProxyEngine engine, @NotNull String className, } @Nullable - public static ClassDescriptorSourceUnit create(boolean script, JProxyEngine engine, @NotNull String className, SourceUnit sourceFile, long timestamp) - { + public static ClassDescriptorSourceUnit create(boolean script, JProxyEngine engine, @NotNull String className, SourceUnit sourceFile, long timestamp) { if (sourceFile instanceof SourceScriptRoot) - return new ClassDescriptorSourceScript(engine,className,(SourceScriptRoot)sourceFile,timestamp); + return new ClassDescriptorSourceScript(engine, className, (SourceScriptRoot) sourceFile, timestamp); else if (sourceFile instanceof SourceFileJavaNormal) - return new ClassDescriptorSourceFileJava(engine,className,(SourceFileJavaNormal)sourceFile,timestamp); + return new ClassDescriptorSourceFileJava(engine, className, (SourceFileJavaNormal) sourceFile, timestamp); else return null; // WTF!! } - - public SourceUnit getSourceUnit() - { + + public SourceUnit getSourceUnit() { return sourceUnit; } - + @NotNull - public String getEncoding() - { + public String getEncoding() { return engine.getSourceEncoding(); } - + @Override - public boolean isInnerClass() - { + public boolean isInnerClass() { return false; - } - - public long getTimestamp() - { + } + + public long getTimestamp() { return timestamp; } - public void updateTimestamp(long timestamp) - { + public void updateTimestamp(long timestamp) { this.timestamp = timestamp; } - public boolean isPendingToRemove() - { + public boolean isPendingToRemove() { return pendingToRemove; } - public void setPendingToRemove(boolean pendingToRemove) - { + public void setPendingToRemove(boolean pendingToRemove) { this.pendingToRemove = pendingToRemove; } - - - public void cleanOnSourceCodeChanged() - { + + + public void cleanOnSourceCodeChanged() { // Como ha cambiado la clase, reseteamos las dependencias setClassBytes(null); setLastLoadedClass(null); clearInnerClassDescriptors(); // El código fuente nuevo puede haber cambiado totalmente las innerclasses antiguas (añadido, eliminado) } - - public boolean isInnerClass(@NotNull String className) - { + + public boolean isInnerClass(@NotNull String className) { int pos = className.lastIndexOf('$'); if (pos == -1) return false; // No es innerclass String baseClassName = className.substring(0, pos); return this.className.equals(baseClassName); // Si es false es que es una innerclass pero de otra clase } - - public LinkedList getInnerClassDescriptors() - { + + public LinkedList getInnerClassDescriptors() { return innerClasses; } - - public void clearInnerClassDescriptors() - { + + public void clearInnerClassDescriptors() { if (innerClasses != null) - innerClasses.clear(); + innerClasses.clear(); } - + @Nullable - public ClassDescriptorInner getInnerClassDescriptor(@NotNull String className, boolean addWhenMissing) - { - if (innerClasses != null) - { - for(ClassDescriptorInner classDesc : innerClasses) - { + public ClassDescriptorInner getInnerClassDescriptor(@NotNull String className, boolean addWhenMissing) { + if (innerClasses != null) { + for (ClassDescriptorInner classDesc : innerClasses) { if (classDesc.getClassName().equals(className)) return classDesc; } } - + if (!addWhenMissing) return null; - + return addInnerClassDescriptor(className); } - + @Nullable - public ClassDescriptorInner addInnerClassDescriptor(@NotNull String className) - { + public ClassDescriptorInner addInnerClassDescriptor(@NotNull String className) { if (!isInnerClass(className)) return null; - + if (innerClasses == null) innerClasses = new LinkedList(); - - ClassDescriptorInner classDesc = new ClassDescriptorInner(className,this); + + ClassDescriptorInner classDesc = new ClassDescriptorInner(className, this); innerClasses.add(classDesc); return classDesc; - } - + } + @Override - public void resetLastLoadedClass() - { + public void resetLastLoadedClass() { super.resetLastLoadedClass(); LinkedList innerClassDescList = getInnerClassDescriptors(); - if (innerClassDescList != null) - { - for(ClassDescriptorInner innerClassDesc : innerClassDescList) - innerClassDesc.resetLastLoadedClass(); - } + if (innerClassDescList != null) { + for (ClassDescriptorInner innerClassDesc : innerClassDescList) + innerClassDesc.resetLastLoadedClass(); + } } - + } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java index dd43381..cf0c86e 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java @@ -5,21 +5,17 @@ import com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceUnit; /** - * * @author jmarranz */ -public class JProxyCompilationException extends RelProxyException -{ +public class JProxyCompilationException extends RelProxyException { protected ClassDescriptorSourceUnit sourceUnit; - - public JProxyCompilationException(ClassDescriptorSourceUnit sourceUnit) - { + + public JProxyCompilationException(ClassDescriptorSourceUnit sourceUnit) { super("Compilation error"); this.sourceUnit = sourceUnit; - } - - public ClassDescriptorSourceUnit getClassDescriptorSourceUnit() - { + } + + public ClassDescriptorSourceUnit getClassDescriptorSourceUnit() { return sourceUnit; } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java index 2ad1bd7..c5d4f0e 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java @@ -2,6 +2,7 @@ import com.sillelien.dollar.relproxy.RelProxyException; import com.sillelien.dollar.relproxy.jproxy.JProxyDiagnosticsListener; + import java.io.IOException; import java.util.List; import javax.tools.Diagnostic; @@ -10,62 +11,54 @@ import javax.tools.StandardJavaFileManager; /** - * * @author jmarranz */ -public class JProxyCompilerContext -{ - protected StandardJavaFileManager standardFileManager; +public class JProxyCompilerContext { + protected StandardJavaFileManager standardFileManager; protected DiagnosticCollector diagnostics; protected JProxyDiagnosticsListener diagnosticsListener; - - public JProxyCompilerContext(StandardJavaFileManager standardFileManager,DiagnosticCollector diagnostics,JProxyDiagnosticsListener diagnosticsListener) - { + + public JProxyCompilerContext(StandardJavaFileManager standardFileManager, DiagnosticCollector diagnostics, JProxyDiagnosticsListener diagnosticsListener) { this.standardFileManager = standardFileManager; this.diagnostics = diagnostics; this.diagnosticsListener = diagnosticsListener; } - public StandardJavaFileManager getStandardFileManager() - { + public StandardJavaFileManager getStandardFileManager() { return standardFileManager; - } + } - public DiagnosticCollector getDiagnosticCollector() - { + public DiagnosticCollector getDiagnosticCollector() { return diagnostics; } - - public void close() - { - try { this.standardFileManager.close(); } - catch (IOException ex) { throw new RelProxyException(ex); } - + + public void close() { + try { + this.standardFileManager.close(); + } catch (IOException ex) { + throw new RelProxyException(ex); + } + List> diagList = diagnostics.getDiagnostics(); - if (!diagList.isEmpty()) - { - if (diagnosticsListener != null) - { + if (!diagList.isEmpty()) { + if (diagnosticsListener != null) { diagnosticsListener.onDiagnostics(diagnostics); - } - else - { + } else { int i = 1; - for (Diagnostic diagnostic : diagList) - { - System.err.println("Diagnostic " + i); - System.err.println(" code: " + diagnostic.getCode()); - System.err.println(" kind: " + diagnostic.getKind()); - System.err.println(" line number: " + diagnostic.getLineNumber()); - System.err.println(" column number: " + diagnostic.getColumnNumber()); - System.err.println(" start position: " + diagnostic.getStartPosition()); - System.err.println(" position: " + diagnostic.getPosition()); - System.err.println(" end position: " + diagnostic.getEndPosition()); - System.err.println(" source: " + diagnostic.getSource()); - System.err.println(" message: " + diagnostic.getMessage(null)); - i++; + for (Diagnostic diagnostic : diagList) { + System.err.println("Diagnostic " + i); + System.err.println(" code: " + diagnostic.getCode()); + System.err.println(" kind: " + diagnostic.getKind()); + System.err.println(" line number: " + diagnostic.getLineNumber()); + System.err.println(" column number: " + diagnostic.getColumnNumber()); + System.err.println(" start position: " + diagnostic.getStartPosition()); + System.err.println(" position: " + diagnostic.getPosition()); + System.err.println(" end position: " + diagnostic.getEndPosition()); + System.err.println(" source: " + diagnostic.getSource()); + System.err.println(" message: " + diagnostic.getMessage(null)); + i++; } } - } + } } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java index 8900a12..f1757bc 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java @@ -26,74 +26,59 @@ import javax.tools.ToolProvider; /** - * * @author jmarranz */ -public class JProxyCompilerInMemory -{ +public class JProxyCompilerInMemory { protected JProxyEngineChangeDetectorAndCompiler parent; protected JavaCompiler compiler; protected Iterable compilationOptions; // puede ser null protected JProxyDiagnosticsListener diagnosticsListener; // puede ser null - public JProxyCompilerInMemory(JProxyEngineChangeDetectorAndCompiler engine,Iterable compilationOptions,JProxyDiagnosticsListener diagnosticsListener) - { + public JProxyCompilerInMemory(JProxyEngineChangeDetectorAndCompiler engine, Iterable compilationOptions, JProxyDiagnosticsListener diagnosticsListener) { this.parent = engine; this.compilationOptions = compilationOptions; this.diagnosticsListener = diagnosticsListener; - this.compiler = ToolProvider.getSystemJavaCompiler(); + this.compiler = ToolProvider.getSystemJavaCompiler(); } - + @NotNull - public JProxyCompilerContext createJProxyCompilerContext() - { + public JProxyCompilerContext createJProxyCompilerContext() { DiagnosticCollector diagnostics = new DiagnosticCollector(); - StandardJavaFileManager standardFileManager = compiler.getStandardFileManager(diagnostics, null, null); - return new JProxyCompilerContext(standardFileManager,diagnostics,diagnosticsListener); + StandardJavaFileManager standardFileManager = compiler.getStandardFileManager(diagnostics, null, null); + return new JProxyCompilerContext(standardFileManager, diagnostics, diagnosticsListener); } - - public void compileSourceFile(@NotNull ClassDescriptorSourceUnit sourceFileDesc, @NotNull JProxyCompilerContext context, ClassLoader currentClassLoader, @NotNull ClassDescriptorSourceFileRegistry sourceRegistry) - { + + public void compileSourceFile(@NotNull ClassDescriptorSourceUnit sourceFileDesc, @NotNull JProxyCompilerContext context, ClassLoader currentClassLoader, @NotNull ClassDescriptorSourceFileRegistry sourceRegistry) { //File sourceFile = sourceFileDesc.getSourceFile(); - LinkedList outClassList = compile(sourceFileDesc,context,currentClassLoader,sourceRegistry); - - if (outClassList == null) + LinkedList outClassList = compile(sourceFileDesc, context, currentClassLoader, sourceRegistry); + + if (outClassList == null) throw new JProxyCompilationException(sourceFileDesc); - - String className = sourceFileDesc.getClassName(); - + + String className = sourceFileDesc.getClassName(); + // Puede haber más de un resultado cuando hay inner classes y/o clase privada en el mismo archivo o bien simplemente clases dependientes - for(JavaFileObjectOutputClass outClass : outClassList) - { + for (JavaFileObjectOutputClass outClass : outClassList) { String currClassName = outClass.binaryName(); - byte[] classBytes = outClass.getBytes(); - if (className.equals(currClassName)) - { - sourceFileDesc.setClassBytes(classBytes); - } - else - { - ClassDescriptorInner innerClass = sourceFileDesc.getInnerClassDescriptor(currClassName,true); - if (innerClass != null) - { - innerClass.setClassBytes(classBytes); - } - else - { + byte[] classBytes = outClass.getBytes(); + if (className.equals(currClassName)) { + sourceFileDesc.setClassBytes(classBytes); + } else { + ClassDescriptorInner innerClass = sourceFileDesc.getInnerClassDescriptor(currClassName, true); + if (innerClass != null) { + innerClass.setClassBytes(classBytes); + } else { // Lo mismo es un archivo dependiente e incluso una inner class pero de otra clase que está siendo usada en el archivo compilado ClassDescriptor dependentClass = sourceRegistry.getClassDescriptor(currClassName); - if (dependentClass != null) - { - dependentClass.setClassBytes(classBytes); - } - else - { + if (dependentClass != null) { + dependentClass.setClassBytes(classBytes); + } else { // Seguramente es debido a que el archivo java tiene una clase privada autónoma declarada en el mismo archivo .java (las que se ponen después de la clase principal pública normal), no permitimos estas clases porque sólo podemos // detectarlas cuando cambiamos el código fuente, pero no si el código fuente no se ha tocado, por ejemplo no tenemos // forma de conseguir que se recarguen de forma determinista y si posteriormente se cargara via ClassLoader al usarse no podemos reconocer que es una clase // "hot reloadable" (quizás a través del package respecto a las demás clases hot pero no es muy determinista pues nada impide la mezcla de hot y no hot en el mismo package) // Es una limitación mínima. - + // También puede ser un caso de clase excluida por el listener de exclusión, no debería ocurrir, tengo un caso de test en donde ocurre a posta // (caso de JProxyExampleAuxIgnored cuando se cambia la JProxyExampleDocument que la usa) pero en programación normal no. @@ -105,10 +90,9 @@ public void compileSourceFile(@NotNull ClassDescriptorSourceUnit sourceFileDesc, } } } - } - - private LinkedList compile(ClassDescriptorSourceUnit sourceFileDesc, @NotNull JProxyCompilerContext context, ClassLoader currentClassLoader, ClassDescriptorSourceFileRegistry sourceRegistry) - { + } + + private LinkedList compile(ClassDescriptorSourceUnit sourceFileDesc, @NotNull JProxyCompilerContext context, ClassLoader currentClassLoader, ClassDescriptorSourceFileRegistry sourceRegistry) { // http://stackoverflow.com/questions/12173294/compiling-fully-in-memory-with-javax-tools-javacompiler // http://www.accordess.com/wpblog/an-overview-of-java-compilation-api-jsr-199/ // http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/com/sun/tools/javac/util/JavacFileManager.java?av=h#JavacFileManager @@ -123,66 +107,58 @@ private LinkedList compile(ClassDescriptorSourceUnit StandardJavaFileManager standardFileManager = context.getStandardFileManager(); // recuerda que el StandardJavaFileManager puede reutilizarse entre varias compilaciones consecutivas mientras se cierre al final - + Iterable compilationUnits; - if (sourceFileDesc instanceof ClassDescriptorSourceFileJava) - { + if (sourceFileDesc instanceof ClassDescriptorSourceFileJava) { List sourceFileList = new ArrayList(); - sourceFileList.add(((ClassDescriptorSourceFileJava)sourceFileDesc).getSourceFile().getFile()); + sourceFileList.add(((ClassDescriptorSourceFileJava) sourceFileDesc).getSourceFile().getFile()); compilationUnits = standardFileManager.getJavaFileObjectsFromFiles(sourceFileList); - } - else if (sourceFileDesc instanceof ClassDescriptorSourceScript) - { - ClassDescriptorSourceScript sourceFileDescScript = (ClassDescriptorSourceScript)sourceFileDesc; - LinkedList compilationUnitsList = new LinkedList(); + } else if (sourceFileDesc instanceof ClassDescriptorSourceScript) { + ClassDescriptorSourceScript sourceFileDescScript = (ClassDescriptorSourceScript) sourceFileDesc; + LinkedList compilationUnitsList = new LinkedList(); String code = sourceFileDescScript.getSourceCode(); - compilationUnitsList.add(new JavaFileObjectInputSourceInMemory(sourceFileDescScript.getClassName(),code,sourceFileDescScript.getEncoding(),sourceFileDescScript.getTimestamp())); - compilationUnits = compilationUnitsList; - } - else - { + compilationUnitsList.add(new JavaFileObjectInputSourceInMemory(sourceFileDescScript.getClassName(), code, sourceFileDescScript.getEncoding(), sourceFileDescScript.getTimestamp())); + compilationUnits = compilationUnitsList; + } else { throw new RelProxyException("Internal error"); } - JavaFileManagerInMemory fileManagerInMemory = new JavaFileManagerInMemory(standardFileManager,currentClassLoader,sourceRegistry,parent.getRequiredExtraJarPaths()); + JavaFileManagerInMemory fileManagerInMemory = new JavaFileManagerInMemory(standardFileManager, currentClassLoader, sourceRegistry, parent.getRequiredExtraJarPaths()); - boolean success = compile(compilationUnits,fileManagerInMemory,context); + boolean success = compile(compilationUnits, fileManagerInMemory, context); if (!success) return null; LinkedList classObj = fileManagerInMemory.getJavaFileObjectOutputClassList(); return classObj; } - private boolean compile(Iterable compilationUnits, JavaFileManager fileManager, @NotNull JProxyCompilerContext context) - { + private boolean compile(Iterable compilationUnits, JavaFileManager fileManager, @NotNull JProxyCompilerContext context) { /* String systemClassPath = System.getProperty("java.class.path"); */ LinkedList finalCompilationOptions = new LinkedList(); - if (compilationOptions != null) - for(String option : compilationOptions) finalCompilationOptions.add(option); - + if (compilationOptions != null) + for (String option : compilationOptions) finalCompilationOptions.add(option); + FileExt[] folderSourceList = parent.getFolderSourceList().getArray(); - if (folderSourceList != null) - { + if (folderSourceList != null) { finalCompilationOptions.add("-classpath"); StringBuilder classPath = new StringBuilder(); - for(int i = 0; i < folderSourceList.length; i++) - { + for (int i = 0; i < folderSourceList.length; i++) { FileExt folderSources = folderSourceList[i]; classPath.append(folderSources.getCanonicalPath()); if (i < folderSourceList.length - 1) - classPath.append(File.pathSeparatorChar); + classPath.append(File.pathSeparatorChar); } - finalCompilationOptions.add(classPath.toString()); + finalCompilationOptions.add(classPath.toString()); } - + DiagnosticCollector diagnostics = context.getDiagnosticCollector(); - JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnostics, finalCompilationOptions,null, compilationUnits); + JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnostics, finalCompilationOptions, null, compilationUnits); boolean success = task.call(); - + return success; } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java index 0385854..d9d68f9 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java @@ -25,37 +25,32 @@ /** - * * http://www.javablogging.com/dynamic-in-memory-compilation/ * http://atamur.blogspot.com.es/2009/10/using-built-in-javacompiler-with-custom.html * http://grepcode.com/file/repo1.maven.org/maven2/org.st-js/generator/3.0.3/org/stjs/generator/javac/CustomClassloaderJavaFileManager.java - * + * * @author jmarranz */ -public class JavaFileManagerInMemory extends ForwardingJavaFileManager -{ +public class JavaFileManagerInMemory extends ForwardingJavaFileManager { private final LinkedList outputClassList = new LinkedList(); @NotNull private final JavaFileObjectInputClassFinderByClassLoader classFinder; private final ClassDescriptorSourceFileRegistry sourceRegistry; - - public JavaFileManagerInMemory(@NotNull StandardJavaFileManager standardFileManager, ClassLoader classLoader, ClassDescriptorSourceFileRegistry sourceRegistry, FolderSourceList requiredExtraJarPaths) - { + + public JavaFileManagerInMemory(@NotNull StandardJavaFileManager standardFileManager, ClassLoader classLoader, ClassDescriptorSourceFileRegistry sourceRegistry, FolderSourceList requiredExtraJarPaths) { super(standardFileManager); this.sourceRegistry = sourceRegistry; - this.classFinder = new JavaFileObjectInputClassFinderByClassLoader(classLoader,requiredExtraJarPaths); + this.classFinder = new JavaFileObjectInputClassFinderByClassLoader(classLoader, requiredExtraJarPaths); } @NotNull - public LinkedList getJavaFileObjectOutputClassList() - { + public LinkedList getJavaFileObjectOutputClassList() { return outputClassList; } - + @NotNull @Override - public JavaFileObject getJavaFileForOutput(Location location, @NotNull String className, @NotNull Kind kind, FileObject sibling) throws IOException - { + public JavaFileObject getJavaFileForOutput(Location location, @NotNull String className, @NotNull Kind kind, FileObject sibling) throws IOException { // Normalmente sólo habrá un resultado pero se da el caso de compilar una clase con una o varias inner classes, el compilador las compila de una vez JavaFileObjectOutputClass outClass = new JavaFileObjectOutputClass(className, kind); outputClassList.add(outClass); @@ -63,57 +58,46 @@ public JavaFileObject getJavaFileForOutput(Location location, @NotNull String cl } @Override - public Iterable list(Location location, @NotNull String packageName, @NotNull Set kinds, boolean recurse) throws IOException - { + public Iterable list(Location location, @NotNull String packageName, @NotNull Set kinds, boolean recurse) throws IOException { if (location == StandardLocation.PLATFORM_CLASS_PATH) // let standard manager hanfle return super.list(location, packageName, kinds, recurse); // En este caso nunca (con PLATFORM_CLASS_PATH) va a encontrar nuestros sources ni .class - else if (location == StandardLocation.CLASS_PATH && kinds.contains(JavaFileObject.Kind.CLASS)) - { + else if (location == StandardLocation.CLASS_PATH && kinds.contains(JavaFileObject.Kind.CLASS)) { if (packageName.equals("java") || packageName.startsWith("java.")) // a hack to let standard manager handle locations like "java.lang" or "java.util", clases sólo cargables por el system class loader. Estrictamente no es necesario pero derivamos la inmensa mayoría de las clases estándar al método por defecto, NO añadimos "javax." pues hay extensiones tal y como el estándar servlet que no forma parte del Java core return super.list(location, packageName, kinds, recurse); - else - { + else { // El StandardJavaFileManager al que hacemos forward es "configurado" por el compilador al que está asociado cuando hay una tarea de compilación // dicha configuración es por ejemplo el classpath tanto para encontrar .class como .java // En nuestro caso no disponemos del classpath de los .class, disponemos del ClassLoader a través del cual podemos obtener "a mano" via resources los // JavaFileObject de los .class que necesitamos. // Ahora bien, no es el caso de los archivos fuente en donde sí tenemos un path claro el cual pasamos como classpath al compilador y por tanto un super.list(location, packageName, kinds, recurse) // nos devolverá los .java (como JavaFileObject claro) si encuentra archivos correspondientes al package buscado. - - LinkedList result = new LinkedList(); - + + LinkedList result = new LinkedList(); + Iterable inFileMgr = super.list(location, packageName, kinds, recurse); // Esperamos o archivos fuente o .class de clases no recargables - if (inFileMgr instanceof Collection) - { - result.addAll((Collection)inFileMgr); - } - else - { - for(Iterator it = inFileMgr.iterator(); it.hasNext(); ) - { - JavaFileObject file = (JavaFileObject)it.next(); + if (inFileMgr instanceof Collection) { + result.addAll((Collection) inFileMgr); + } else { + for (Iterator it = inFileMgr.iterator(); it.hasNext(); ) { + JavaFileObject file = (JavaFileObject) it.next(); result.add(file); } } - + List classList = classFinder.find(packageName); - + // Reemplazamos los .class de classList que son los que están en archivo "deployados" que pueden ser más antiguos que los que están en memoria - for(JavaFileObjectInputClassInFileSystem fileObj : classList) - { + for (JavaFileObjectInputClassInFileSystem fileObj : classList) { String className = fileObj.getBinaryName(); ClassDescriptorSourceUnit sourceFileDesc = sourceRegistry.getClassDescriptorSourceUnit(className); - if (sourceFileDesc != null && sourceFileDesc.getClassBytes() != null) - { - JavaFileObjectInputClassInMemory fileInput = new JavaFileObjectInputClassInMemory(className,sourceFileDesc.getClassBytes(),sourceFileDesc.getTimestamp()); + if (sourceFileDesc != null && sourceFileDesc.getClassBytes() != null) { + JavaFileObjectInputClassInMemory fileInput = new JavaFileObjectInputClassInMemory(className, sourceFileDesc.getClassBytes(), sourceFileDesc.getTimestamp()); result.add(fileInput); - } - else - { + } else { result.add(fileObj); } } - + // Los JavaFileObject de archivos fuente pueden ser los mimas clases que los de .class, el compilador se encargará de comparar los timestamp y elegir el .class o el source return result; @@ -123,10 +107,9 @@ else if (location == StandardLocation.CLASS_PATH && kinds.contains(JavaFileObjec } @Override - public String inferBinaryName(Location location, JavaFileObject file) - { + public String inferBinaryName(Location location, JavaFileObject file) { if (file instanceof JProxyJavaFileObjectInput) - return ((JProxyJavaFileObjectInput)file).getBinaryName(); + return ((JProxyJavaFileObjectInput) file).getBinaryName(); return super.inferBinaryName(location, file); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java index da16537..cadabc2 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java @@ -30,40 +30,33 @@ * * @author jmarranz */ -public class JavaFileObjectInputClassFinderByClassLoader -{ +public class JavaFileObjectInputClassFinderByClassLoader { private static final String CLASS_FILE_EXTENSION = ".class"; - private final ClassLoader classLoader; + private final ClassLoader classLoader; private final FolderSourceList requiredExtraJarPaths; - - public JavaFileObjectInputClassFinderByClassLoader(ClassLoader classLoader,FolderSourceList requiredExtraJarPaths) - { + + public JavaFileObjectInputClassFinderByClassLoader(ClassLoader classLoader, FolderSourceList requiredExtraJarPaths) { this.classLoader = classLoader; this.requiredExtraJarPaths = requiredExtraJarPaths; } @NotNull - public List find(@NotNull String packageName) throws IOException - { - // http://www.dzone.com/snippets/get-all-classes-within-package - // http://sourceforge.net/p/scannotation/code/HEAD/tree/scannotation/src/main/java/org/scannotation/ClasspathUrlFinder.java#l124 + public List find(@NotNull String packageName) throws IOException { + // http://www.dzone.com/snippets/get-all-classes-within-package + // http://sourceforge.net/p/scannotation/code/HEAD/tree/scannotation/src/main/java/org/scannotation/ClasspathUrlFinder.java#l124 String packagePath = packageName.replaceAll("\\.", "/"); List result = new ArrayList(); Enumeration urlEnumeration = classLoader.getResources(packagePath); - if (urlEnumeration.hasMoreElements()) - { - while (urlEnumeration.hasMoreElements()) - { // one URL for each jar on the classpath that has the given package + if (urlEnumeration.hasMoreElements()) { + while (urlEnumeration.hasMoreElements()) { // one URL for each jar on the classpath that has the given package URL packageFolderURL = urlEnumeration.nextElement(); - listUnder(packageName,packageFolderURL,result); + listUnder(packageName, packageFolderURL, result); } - } - else - { + } else { // Enumeration vacía, chungo, esto nos ha ocurrido con el jar lib/ext/portlet.jar del Tomcat 6.2 del bundle liferay-portal-6.2-ce-ga3 // daba un error de de javax.portlet.PortletRquest not found. // En teoría debería responder a la búsqueda classLoader.getResources("javax/portlet") devolviendo el jar, pero devuelve un Enumeration vacío @@ -73,145 +66,132 @@ public List find(@NotNull String packageNa // requerido en el parámetro de este método find() y le evitamos modificar un jar de infraestructura que queda muy feo e inmantenible respecto a una solución // basada en configuración del usuario. - if (requiredExtraJarPaths != null) - { + if (requiredExtraJarPaths != null) { FileExt[] jarFileList = requiredExtraJarPaths.getArray(); - if (jarFileList != null) - { - for (FileExt jarFile : jarFileList) - { - listUnderJarCustom(packagePath,jarFile,result); + if (jarFileList != null) { + for (FileExt jarFile : jarFileList) { + listUnderJarCustom(packagePath, jarFile, result); } } } } - + return result; } - - private void listUnder(String packageName, @NotNull URL packageFolderURL, @NotNull Collection result) - { - String pkgPath = packageFolderURL.toExternalForm(); //packageFolderURL.getFile(); El problema de getFile es que también está URL-encoded (un espacio es %20) lo cual no es compatible con File - if (pkgPath.startsWith("file:")) - { - listUnderDir(packageName,pkgPath,result); - } - else - { // browse a jar file - listUnderJar(packageFolderURL,result); + private void listUnder(String packageName, @NotNull URL packageFolderURL, @NotNull Collection result) { + String pkgPath = packageFolderURL.toExternalForm(); //packageFolderURL.getFile(); El problema de getFile es que también está URL-encoded (un espacio es %20) lo cual no es compatible con File + + if (pkgPath.startsWith("file:")) { + listUnderDir(packageName, pkgPath, result); + } else { // browse a jar file + listUnderJar(packageFolderURL, result); } // maybe there can be something else for more involved class loaders } - private void listUnderDir(String packageName, String pkgPath, @NotNull Collection result) - { + private void listUnderDir(String packageName, String pkgPath, @NotNull Collection result) { pkgPath = pkgPath.substring("file:".length()); - try { pkgPath = URLDecoder.decode(pkgPath, "UTF-8"); } // Detecté el problema con Vaadin en un path con "Documents%20and%20Settings" con %20 obviamente no es un path correcto, deben ser espacios - catch (UnsupportedEncodingException ex) { throw new RelProxyException(ex); } + try { + pkgPath = URLDecoder.decode(pkgPath, "UTF-8"); + } // Detecté el problema con Vaadin en un path con "Documents%20and%20Settings" con %20 obviamente no es un path correcto, deben ser espacios + catch (UnsupportedEncodingException ex) { + throw new RelProxyException(ex); + } - File directory = new File(pkgPath); - if (!directory.isDirectory()) + File directory = new File(pkgPath); + if (!directory.isDirectory()) throw new RelProxyException("Internal Error:" + pkgPath); - + // browse local .class files - useful for local execution - + File[] childFiles = directory.listFiles(); - for (File childFile : childFiles) - { + for (File childFile : childFiles) { if (!childFile.isFile()) continue; - + // We only want the .class files. String name = childFile.getName(); - if (name.endsWith(CLASS_FILE_EXTENSION)) - { - String binaryName = ClassDescriptor.getClassNameFromPackageAndClassFileName(packageName,name); - result.add(new JavaFileObjectInputClassInFile(childFile,binaryName, childFile.toURI())); - } - } - } - - private void listUnderJar(@NotNull URL packageFolderURL, @NotNull Collection result) - { - try - { + if (name.endsWith(CLASS_FILE_EXTENSION)) { + String binaryName = ClassDescriptor.getClassNameFromPackageAndClassFileName(packageName, name); + result.add(new JavaFileObjectInputClassInFile(childFile, binaryName, childFile.toURI())); + } + } + } + + private void listUnderJar(@NotNull URL packageFolderURL, @NotNull Collection result) { + try { String jarUri = packageFolderURL.toExternalForm().split("!")[0]; - + JarURLConnection jarConn = (JarURLConnection) packageFolderURL.openConnection(); String rootEntryName = jarConn.getEntryName(); int rootEnd = rootEntryName.length() + 1; Enumeration entryEnum = jarConn.getJarFile().entries(); - while (entryEnum.hasMoreElements()) - { + while (entryEnum.hasMoreElements()) { JarEntry jarEntry = entryEnum.nextElement(); String name = jarEntry.getName(); // Empieza por packagePath y no hay más folders siguientes, terminando en un .class (una clase concreta) - if (name.startsWith(rootEntryName) && name.indexOf('/', rootEnd) == -1 && name.endsWith(CLASS_FILE_EXTENSION)) - { + if (name.startsWith(rootEntryName) && name.indexOf('/', rootEnd) == -1 && name.endsWith(CLASS_FILE_EXTENSION)) { URI uri = URI.create(jarUri + "!/" + name); String binaryName = ClassDescriptor.getClassNameFromRelativeClassFilePath(name); - result.add(new JavaFileObjectInputClassInJar(binaryName, uri,jarEntry.getTime())); + result.add(new JavaFileObjectInputClassInJar(binaryName, uri, jarEntry.getTime())); } } - } - catch (Exception e) - { + } catch (Exception e) { throw new RelProxyException("Wasn't able to open " + packageFolderURL + " as a jar file", e); } } - - private void listUnderJarCustom(@NotNull String packagePath, @NotNull FileExt jarFile, @NotNull Collection result) - { - String normalizedPath = jarFile.getCanonicalPath(); - if (normalizedPath.contains("\\")) // Windows - { + + private void listUnderJarCustom(@NotNull String packagePath, @NotNull FileExt jarFile, @NotNull Collection result) { + String normalizedPath = jarFile.getCanonicalPath(); + if (normalizedPath.contains("\\")) // Windows + { // No estoy seguro de que sea necesario normalizar pero por si acaso - normalizedPath = normalizedPath.replace("\\","/"); // "C:/folder" + normalizedPath = normalizedPath.replace("\\", "/"); // "C:/folder" normalizedPath = "/" + normalizedPath; // "/C:/folder" - } - - String urlPath = "file:" + normalizedPath; - - URL packageFolderURL; - try { packageFolderURL = new URL(urlPath); } - catch (MalformedURLException ex) { throw new RelProxyException(ex); } - - String jarUri = "jar:" + packageFolderURL.toExternalForm(); - - int posEnd = packagePath.length() + 1; - + } + + String urlPath = "file:" + normalizedPath; + + URL packageFolderURL; + try { + packageFolderURL = new URL(urlPath); + } catch (MalformedURLException ex) { + throw new RelProxyException(ex); + } + + String jarUri = "jar:" + packageFolderURL.toExternalForm(); + + int posEnd = packagePath.length() + 1; + ZipInputStream zip = null; - - try - { + + try { zip = new ZipInputStream(packageFolderURL.openStream()); ZipEntry zipEntry = zip.getNextEntry(); - while(zipEntry != null) - { - String name = zipEntry.getName(); + while (zipEntry != null) { + String name = zipEntry.getName(); // Empieza por packagePath y no hay más folders siguientes, terminando en un .class (una clase concreta) - if (name.startsWith(packagePath) && name.indexOf('/', posEnd) == -1 && name.endsWith(CLASS_FILE_EXTENSION)) - { + if (name.startsWith(packagePath) && name.indexOf('/', posEnd) == -1 && name.endsWith(CLASS_FILE_EXTENSION)) { URI uri = URI.create(jarUri + "!/" + name); String binaryName = ClassDescriptor.getClassNameFromRelativeClassFilePath(name); - result.add(new JavaFileObjectInputClassInJar(binaryName, uri,zipEntry.getTime())); - } + result.add(new JavaFileObjectInputClassInJar(binaryName, uri, zipEntry.getTime())); + } zipEntry = zip.getNextEntry(); - } - } - catch(IOException ex) - { + } + } catch (IOException ex) { throw new RelProxyException(ex); + } finally { + if (zip != null) try { + zip.close(); + } catch (IOException ex) { + throw new RelProxyException(ex); + } } - finally - { - if (zip != null) try { zip.close(); } catch (IOException ex) { throw new RelProxyException(ex); } - } - } - - + } + + } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JProxyJavaFileObjectInput.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JProxyJavaFileObjectInput.java index 8faf5a6..af404f9 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JProxyJavaFileObjectInput.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JProxyJavaFileObjectInput.java @@ -1,10 +1,8 @@ package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.comp.jfo; /** - * * @author jmarranz */ -public interface JProxyJavaFileObjectInput -{ +public interface JProxyJavaFileObjectInput { public String getBinaryName(); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java index 3152dac..db32523 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java @@ -10,30 +10,25 @@ import java.net.URI; /** - * * @author jmarranz */ -public class JavaFileObjectInputClassInFile extends JavaFileObjectInputClassInFileSystem -{ +public class JavaFileObjectInputClassInFile extends JavaFileObjectInputClassInFileSystem { protected File file; - - public JavaFileObjectInputClassInFile(File file, String binaryName, @NotNull URI uri) - { - super(binaryName,uri,uri.getPath()); + + public JavaFileObjectInputClassInFile(File file, String binaryName, @NotNull URI uri) { + super(binaryName, uri, uri.getPath()); this.file = file; } @NotNull @Override - public InputStream openInputStream() throws IOException - { + public InputStream openInputStream() throws IOException { // Podríamos hacer uri.toURL().openStream() pero si tenemos el File es para algo - return new BufferedInputStream(new FileInputStream(file),10 * 1024); + return new BufferedInputStream(new FileInputStream(file), 10 * 1024); } - + @Override - public long getLastModified() - { + public long getLastModified() { return file.lastModified(); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java index afbf586..c59610c 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java @@ -12,37 +12,34 @@ import javax.tools.JavaFileObject; /** - * * @author jmarranz */ -public abstract class JavaFileObjectInputClassInFileSystem implements JavaFileObject,JProxyJavaFileObjectInput -{ +public abstract class JavaFileObjectInputClassInFileSystem implements JavaFileObject, JProxyJavaFileObjectInput { protected final String binaryName; protected final URI uri; protected final String name; - - public JavaFileObjectInputClassInFileSystem(String binaryName, URI uri,String name) - { + + public JavaFileObjectInputClassInFileSystem(String binaryName, URI uri, String name) { this.uri = uri; this.binaryName = binaryName; this.name = name; - } - + } + @Override public URI toUri() { return uri; } - + @Override public String getName() { return name; } - - @Override + + @Override public String getBinaryName() { return binaryName; - } - + } + @NotNull @Override public OutputStream openOutputStream() throws IOException { @@ -70,8 +67,8 @@ public Writer openWriter() throws IOException { @Override public boolean delete() { throw new UnsupportedOperationException(); - } - + } + @NotNull @Override public Kind getKind() { @@ -97,5 +94,5 @@ public NestingKind getNestingKind() { public Modifier getAccessLevel() { throw new UnsupportedOperationException(); } - + } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java index dfe3757..9f24cce 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java @@ -7,35 +7,29 @@ import java.net.URI; /** - * * @author jmarranz */ -public class JavaFileObjectInputClassInJar extends JavaFileObjectInputClassInFileSystem -{ +public class JavaFileObjectInputClassInJar extends JavaFileObjectInputClassInFileSystem { protected long timestamp; - - public JavaFileObjectInputClassInJar(String binaryName, @NotNull URI uri, long timestamp) - { - super(binaryName,uri,uri.getSchemeSpecificPart()); + + public JavaFileObjectInputClassInJar(String binaryName, @NotNull URI uri, long timestamp) { + super(binaryName, uri, uri.getSchemeSpecificPart()); this.timestamp = timestamp; } @Override - public InputStream openInputStream() throws IOException - { + public InputStream openInputStream() throws IOException { return uri.toURL().openStream(); // easy way to handle any URI! } @Override - public long getLastModified() - { + public long getLastModified() { return timestamp; } @NotNull @Override - public String toString() - { + public String toString() { return "JavaFileObjectInputClassInJar{uri=" + uri + '}'; } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java index c632d7a..480d393 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java @@ -11,52 +11,45 @@ /** * http://www.javablogging.com/dynamic-in-memory-compilation/ - * + * * @author jmarranz */ -public class JavaFileObjectInputClassInMemory extends SimpleJavaFileObject implements JProxyJavaFileObjectInput -{ +public class JavaFileObjectInputClassInMemory extends SimpleJavaFileObject implements JProxyJavaFileObjectInput { protected String binaryName; protected byte[] byteCode; protected long timestamp; - - public JavaFileObjectInputClassInMemory(@NotNull String name, byte[] byteCode, long timestamp) - { + + public JavaFileObjectInputClassInMemory(@NotNull String name, byte[] byteCode, long timestamp) { super(URI.create("string:///" + name.replace('.', '/') + Kind.CLASS.extension), Kind.CLASS); - + this.binaryName = name; this.byteCode = byteCode; this.timestamp = timestamp; } - public byte[] getBytes() - { + public byte[] getBytes() { return byteCode; } - - @Override - public long getLastModified() - { + + @Override + public long getLastModified() { return timestamp; - } - + } + @NotNull @Override - public InputStream openInputStream() throws IOException - { + public InputStream openInputStream() throws IOException { return new ByteArrayInputStream(getBytes()); - } - + } + @NotNull @Override - public OutputStream openOutputStream() throws IOException - { + public OutputStream openOutputStream() throws IOException { throw new UnsupportedOperationException(); } - - @Override - public String getBinaryName() - { + + @Override + public String getBinaryName() { return binaryName; } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java index 8e2c67a..5e9b250 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java @@ -13,57 +13,50 @@ /** * http://www.javablogging.com/dynamic-in-memory-compilation/ - * + * * @author jmarranz */ -public abstract class JavaFileObjectInputSourceBase extends SimpleJavaFileObject implements JProxyJavaFileObjectInput -{ +public abstract class JavaFileObjectInputSourceBase extends SimpleJavaFileObject implements JProxyJavaFileObjectInput { protected String binaryName; protected String encoding; - - public JavaFileObjectInputSourceBase(@NotNull String name, String encoding) - { + + public JavaFileObjectInputSourceBase(@NotNull String name, String encoding) { super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE); // La extensión .java es necesaria aunque sea falsa sino da error - + this.binaryName = name; this.encoding = encoding; } - + protected abstract String getSource(); - - + + @Override - public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException - { + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { return getSource(); - } - + } + @NotNull - public byte[] getBytes() - { - try - { + public byte[] getBytes() { + try { return getSource().getBytes(encoding); + } catch (UnsupportedEncodingException ex) { + throw new RelProxyException(ex); } - catch (UnsupportedEncodingException ex) { throw new RelProxyException(ex); } - } - + } + @NotNull @Override - public InputStream openInputStream() throws IOException - { + public InputStream openInputStream() throws IOException { return new ByteArrayInputStream(getBytes()); - } - + } + @NotNull @Override - public OutputStream openOutputStream() throws IOException - { + public OutputStream openOutputStream() throws IOException { throw new UnsupportedOperationException(); } - - public String getBinaryName() - { + + public String getBinaryName() { return binaryName; } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java index 801d10a..28505a1 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java @@ -7,32 +7,28 @@ /** * http://www.javablogging.com/dynamic-in-memory-compilation/ - * + * * @author jmarranz */ -public class JavaFileObjectInputSourceInFile extends JavaFileObjectInputSourceBase -{ +public class JavaFileObjectInputSourceInFile extends JavaFileObjectInputSourceBase { protected File file; protected String source; - - public JavaFileObjectInputSourceInFile(@NotNull String name, File file, String encoding) - { - super(name,encoding); + + public JavaFileObjectInputSourceInFile(@NotNull String name, File file, String encoding) { + super(name, encoding); this.file = file; } @Override - protected String getSource() - { + protected String getSource() { if (source != null) return source; this.source = JProxyUtil.readTextFile(file, encoding); return source; - } - + } + @Override - public long getLastModified() - { + public long getLastModified() { return file.lastModified(); - } + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java index b613805..6e6aacc 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java @@ -4,30 +4,26 @@ /** * http://www.javablogging.com/dynamic-in-memory-compilation/ - * + * * @author jmarranz */ -public class JavaFileObjectInputSourceInMemory extends JavaFileObjectInputSourceBase -{ +public class JavaFileObjectInputSourceInMemory extends JavaFileObjectInputSourceBase { protected String source; protected long timestamp; - - public JavaFileObjectInputSourceInMemory(@NotNull String name, String source, String encoding, long timestamp) - { - super(name,encoding); + + public JavaFileObjectInputSourceInMemory(@NotNull String name, String source, String encoding, long timestamp) { + super(name, encoding); this.source = source; this.timestamp = timestamp; } @Override - protected String getSource() - { + protected String getSource() { return source; - } - - @Override - public long getLastModified() - { + } + + @Override + public long getLastModified() { return timestamp; - } + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java index 62a90aa..a49056b 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java @@ -11,51 +11,45 @@ /** * http://www.javablogging.com/dynamic-in-memory-compilation/ - * + * * @author jmarranz */ public class JavaFileObjectOutputClass extends SimpleJavaFileObject { /** - * Byte code created by the compiler will be stored in this - * ByteArrayOutputStream so that we can later get the - * byte array out of it - * and put it in the memory as an instance of our class. - */ + * Byte code created by the compiler will be stored in this + * ByteArrayOutputStream so that we can later get the + * byte array out of it + * and put it in the memory as an instance of our class. + */ protected final ByteArrayOutputStream bos = new ByteArrayOutputStream(); protected String binaryName; - + /** - * Registers the compiled class object under URI - * containing the class full name - * - * @param name - * Full name of the compiled class - * @param kind - * Kind of the data. It will be CLASS in our case - */ - public JavaFileObjectOutputClass(@NotNull String name, @NotNull Kind kind) - { + * Registers the compiled class object under URI + * containing the class full name + * + * @param name Full name of the compiled class + * @param kind Kind of the data. It will be CLASS in our case + */ + public JavaFileObjectOutputClass(@NotNull String name, @NotNull Kind kind) { super(URI.create("string:///" + name.replace('.', '/') + kind.extension), kind); - + if (!Kind.CLASS.equals(kind)) throw new RelProxyException("Unexpected"); this.binaryName = name; } - public String binaryName() - { + public String binaryName() { return binaryName; } - - public byte[] getBytes() - { + + public byte[] getBytes() { return bos.toByteArray(); } @NotNull @Override - public OutputStream openOutputStream() throws IOException - { + public OutputStream openOutputStream() throws IOException { return bos; } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java index 836c2b0..3ae32ba 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java @@ -4,29 +4,24 @@ import org.jetbrains.annotations.NotNull; /** - * * @author jmarranz */ -public class SourceFileJavaNormal extends SourceUnit -{ +public class SourceFileJavaNormal extends SourceUnit { @NotNull protected final FileExt sourceFile; - - public SourceFileJavaNormal(@NotNull FileExt sourceFile, @NotNull FileExt rootFolderOfSources) - { - super(buildClassNameFromFile(sourceFile,rootFolderOfSources)); - this.sourceFile = sourceFile; + + public SourceFileJavaNormal(@NotNull FileExt sourceFile, @NotNull FileExt rootFolderOfSources) { + super(buildClassNameFromFile(sourceFile, rootFolderOfSources)); + this.sourceFile = sourceFile; } @Override - public long lastModified() - { + public long lastModified() { return sourceFile.getFile().lastModified(); } - + @NotNull - public FileExt getFileExt() - { + public FileExt getFileExt() { return sourceFile; } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRoot.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRoot.java index 5d81119..3907af1 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRoot.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRoot.java @@ -1,15 +1,12 @@ package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit; /** - * * @author jmarranz */ -public abstract class SourceScriptRoot extends SourceUnit -{ - public SourceScriptRoot(String className) - { +public abstract class SourceScriptRoot extends SourceUnit { + public SourceScriptRoot(String className) { super(className); } - - public abstract String getScriptCode(String encoding,boolean[] hasHashBang); + + public abstract String getScriptCode(String encoding, boolean[] hasHashBang); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java index 5456fa3..a8add45 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java @@ -6,36 +6,30 @@ import org.jetbrains.annotations.NotNull; /** - * * @author jmarranz */ -public abstract class SourceScriptRootFile extends SourceScriptRoot -{ +public abstract class SourceScriptRootFile extends SourceScriptRoot { protected FileExt sourceFile; - - public SourceScriptRootFile(@NotNull FileExt sourceFile, @NotNull FolderSourceList folderSourceList) - { - super(buildClassNameFromFile(sourceFile,folderSourceList)); - this.sourceFile = sourceFile; + + public SourceScriptRootFile(@NotNull FileExt sourceFile, @NotNull FolderSourceList folderSourceList) { + super(buildClassNameFromFile(sourceFile, folderSourceList)); + this.sourceFile = sourceFile; } - - public static SourceScriptRootFile createSourceScriptRootFile(@NotNull FileExt sourceFile, @NotNull FolderSourceList folderSourceList) - { + + public static SourceScriptRootFile createSourceScriptRootFile(@NotNull FileExt sourceFile, @NotNull FolderSourceList folderSourceList) { String ext = JProxyUtil.getFileExtension(sourceFile.getFile()); // Si no tiene extensión devuelve "" if ("java".equals(ext)) - return new SourceScriptRootFileJavaExt(sourceFile,folderSourceList); + return new SourceScriptRootFileJavaExt(sourceFile, folderSourceList); else - return new SourceScriptRootFileOtherExt(sourceFile,folderSourceList); // Caso de archivo script inicial sin extensión .java (puede ser sin extensión) + return new SourceScriptRootFileOtherExt(sourceFile, folderSourceList); // Caso de archivo script inicial sin extensión .java (puede ser sin extensión) } - + @Override - public long lastModified() - { + public long lastModified() { return sourceFile.getFile().lastModified(); - } + } - public FileExt getFileExt() - { + public FileExt getFileExt() { return sourceFile; } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java index 5e22815..3fc69a2 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java @@ -6,21 +6,17 @@ import org.jetbrains.annotations.NotNull; /** - * * @author jmarranz */ -public class SourceScriptRootFileJavaExt extends SourceScriptRootFile -{ - public SourceScriptRootFileJavaExt(@NotNull FileExt sourceFile, @NotNull FolderSourceList folderSourceList) - { - super(sourceFile,folderSourceList); - } - +public class SourceScriptRootFileJavaExt extends SourceScriptRootFile { + public SourceScriptRootFileJavaExt(@NotNull FileExt sourceFile, @NotNull FolderSourceList folderSourceList) { + super(sourceFile, folderSourceList); + } + @NotNull @Override - public String getScriptCode(@NotNull String encoding, boolean[] hasHashBang) - { - hasHashBang[0] = false; - return JProxyUtil.readTextFile(sourceFile.getFile(),encoding); - } + public String getScriptCode(@NotNull String encoding, boolean[] hasHashBang) { + hasHashBang[0] = false; + return JProxyUtil.readTextFile(sourceFile.getFile(), encoding); + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java index 84530c3..cbc97bf 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java @@ -6,32 +6,26 @@ import org.jetbrains.annotations.NotNull; /** - * * @author jmarranz */ -public class SourceScriptRootFileOtherExt extends SourceScriptRootFile -{ - public SourceScriptRootFileOtherExt(@NotNull FileExt sourceFile, @NotNull FolderSourceList folderSourceList) - { - super(sourceFile,folderSourceList); - } - +public class SourceScriptRootFileOtherExt extends SourceScriptRootFile { + public SourceScriptRootFileOtherExt(@NotNull FileExt sourceFile, @NotNull FolderSourceList folderSourceList) { + super(sourceFile, folderSourceList); + } + @NotNull @Override - public String getScriptCode(@NotNull String encoding, boolean[] hasHashBang) - { - String codeBody = JProxyUtil.readTextFile(sourceFile.getFile(),encoding); + public String getScriptCode(@NotNull String encoding, boolean[] hasHashBang) { + String codeBody = JProxyUtil.readTextFile(sourceFile.getFile(), encoding); // Eliminamos la primera línea #! (debe estar en la primera línea y sin espacios antes) - if (codeBody.startsWith("#!")) - { - hasHashBang[0] = true; + if (codeBody.startsWith("#!")) { + hasHashBang[0] = true; int pos = codeBody.indexOf('\n'); if (pos != -1) // Rarísimo que sólo esté el hash bang (script vacío) { codeBody = codeBody.substring(pos + 1); - } - } - else hasHashBang[0] = false; + } + } else hasHashBang[0] = false; return codeBody; - } + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootInMemory.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootInMemory.java index 9ad61e0..a258205 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootInMemory.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootInMemory.java @@ -1,56 +1,47 @@ package com.sillelien.dollar.relproxy.impl.jproxy.core.clsmgr.srcunit; /** - * * @author jmarranz */ -public class SourceScriptRootInMemory extends SourceScriptRoot -{ +public class SourceScriptRootInMemory extends SourceScriptRoot { public static final String DEFAULT_CLASS_NAME = "_jproxyMainClass_"; // OJO NO CAMBIAR, está ya documentada - + protected String code; protected long timestamp; - - private SourceScriptRootInMemory(String className,String code) - { + + private SourceScriptRootInMemory(String className, String code) { super(className); - setScriptCode(code,System.currentTimeMillis()); + setScriptCode(code, System.currentTimeMillis()); } - - public static SourceScriptRootInMemory createSourceScriptInMemory(String code) - { - return new SourceScriptRootInMemory(DEFAULT_CLASS_NAME,code); + + public static SourceScriptRootInMemory createSourceScriptInMemory(String code) { + return new SourceScriptRootInMemory(DEFAULT_CLASS_NAME, code); } - + @Override - public long lastModified() - { + public long lastModified() { return timestamp; // Siempre ha sido modificado - } + } @Override - public String getScriptCode(String encoding,boolean[] hasHashBang) - { + public String getScriptCode(String encoding, boolean[] hasHashBang) { hasHashBang[0] = false; return code; } - - public boolean isEmptyCode() - { + + public boolean isEmptyCode() { // Si code es "" la clase especial se genera pero no hace nada simplemente devuelve un null. // Este es el caso en el que utilizamos RelProxy embebido en un framework utilizando la API ScriptEngine pero únicamente porque se usa una API basada // en interfaces, pero tiene el inconveniente de generarse un SourceScriptRootInMemory inútil que no hace nada return code.isEmpty(); } - - public String getScriptCode() - { + + public String getScriptCode() { return code; } - - public final void setScriptCode(String code,long timestamp) - { + + public final void setScriptCode(String code, long timestamp) { this.code = code; this.timestamp = timestamp; - } + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java index fd33113..16818ea 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java @@ -6,35 +6,29 @@ import org.jetbrains.annotations.Nullable; /** - * * @author jmarranz */ -public abstract class SourceUnit -{ +public abstract class SourceUnit { protected final String className; - - public SourceUnit(String className) - { + + public SourceUnit(String className) { this.className = className; } - + public abstract long lastModified(); - + @Nullable - protected static String buildClassNameFromFile(@NotNull FileExt sourceFile, @NotNull FolderSourceList sourceList) - { + protected static String buildClassNameFromFile(@NotNull FileExt sourceFile, @NotNull FolderSourceList sourceList) { return sourceList.buildClassNameFromFile(sourceFile); - } - + } + @Nullable - protected static String buildClassNameFromFile(@NotNull FileExt sourceFile, @NotNull FileExt rootFolderOfSources) - { - return FolderSourceList.buildClassNameFromFile(sourceFile,rootFolderOfSources); - } - - public String getClassName() - { + protected static String buildClassNameFromFile(@NotNull FileExt sourceFile, @NotNull FileExt rootFolderOfSources) { + return FolderSourceList.buildClassNameFromFile(sourceFile, rootFolderOfSources); + } + + public String getClassName() { return className; - } - + } + } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/BindingsImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/BindingsImpl.java index e960b2a..536f81a 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/BindingsImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/BindingsImpl.java @@ -5,10 +5,8 @@ import javax.script.Bindings; /** - * * @author jmarranz */ -public class BindingsImpl extends HashMap implements Bindings -{ +public class BindingsImpl extends HashMap implements Bindings { } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java index e658569..2877591 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java @@ -17,96 +17,85 @@ import javax.script.ScriptException; /** - * * @author jmarranz */ -public class JProxyScriptEngineDelegateImpl extends JProxyImpl -{ +public class JProxyScriptEngineDelegateImpl extends JProxyImpl { protected JProxyScriptEngineImpl parent; @Nullable protected ClassDescriptorSourceScript classDescSourceScript; - protected long codeBufferModTimestamp = 0; + protected long codeBufferModTimestamp = 0; protected long lastCodeCompiledTimestamp = 0; - - public JProxyScriptEngineDelegateImpl(JProxyScriptEngineImpl parent) - { - this.parent = parent; - } - + + public JProxyScriptEngineDelegateImpl(JProxyScriptEngineImpl parent) { + this.parent = parent; + } + @Nullable @Override - public ClassDescriptorSourceScript init(@NotNull JProxyConfigImpl config) - { + public ClassDescriptorSourceScript init(@NotNull JProxyConfigImpl config) { SourceScriptRoot sourceFileScript = SourceScriptRootInMemory.createSourceScriptInMemory(""); JProxyShellClassLoader classLoader = null; String classFolder = config.getClassFolder(); if (classFolder != null) - classLoader = new JProxyShellClassLoader(getDefaultClassLoader(),new File(classFolder)); + classLoader = new JProxyShellClassLoader(getDefaultClassLoader(), new File(classFolder)); - this.classDescSourceScript = init(config,sourceFileScript,classLoader); + this.classDescSourceScript = init(config, sourceFileScript, classLoader); return classDescSourceScript; } - + @NotNull @Override - public Class getMainParamClass() - { + public Class getMainParamClass() { return ScriptContext.class; } - + @NotNull - private SourceScriptRootInMemory getSourceScriptInMemory() - { - return (SourceScriptRootInMemory)classDescSourceScript.getSourceScript(); - } - - public Object execute(String code,ScriptContext context) throws ScriptException - { + private SourceScriptRootInMemory getSourceScriptInMemory() { + return (SourceScriptRootInMemory) classDescSourceScript.getSourceScript(); + } + + public Object execute(String code, ScriptContext context) throws ScriptException { Class scriptClass; JProxyEngine jproxyEngine = getJProxyEngine(); Object monitor = jproxyEngine.getMonitor(); - synchronized(monitor) - { - if (!getSourceScriptInMemory().getScriptCode().equals(code)) - { + synchronized (monitor) { + if (!getSourceScriptInMemory().getScriptCode().equals(code)) { this.codeBufferModTimestamp = System.currentTimeMillis(); - getSourceScriptInMemory().setScriptCode(code,codeBufferModTimestamp); + getSourceScriptInMemory().setScriptCode(code, codeBufferModTimestamp); // Recuerda que cada vez que se obtiene el timestamp se llama a System.currentTimeMillis(), es imposible que el usuario haga algo en menos de 1ms ClassDescriptorSourceScript classDescSourceScript2 = null; - try - { + try { classDescSourceScript2 = jproxyEngine.detectChangesInSourcesAndReload(); - } - catch(JProxyCompilationException ex) - { + } catch (JProxyCompilationException ex) { throw new ScriptException(ex); } if (classDescSourceScript2 != classDescSourceScript) throw new RelProxyException("Internal Error"); - this.lastCodeCompiledTimestamp = System.currentTimeMillis(); + this.lastCodeCompiledTimestamp = System.currentTimeMillis(); if (lastCodeCompiledTimestamp == codeBufferModTimestamp) // Demasiado rápido compilando { // Aseguramos que el siguiente código se ejecuta si o si con un codeBufferModTimestamp mayor que el timestamp de la compilación - try { Thread.sleep(1); } catch (InterruptedException ex) { throw new RelProxyException(ex); } + try { + Thread.sleep(1); + } catch (InterruptedException ex) { + throw new RelProxyException(ex); + } } } scriptClass = classDescSourceScript.getLastLoadedClass(); } - - try - { - return ClassDescriptorSourceScript.callMainMethod(scriptClass,parent,context); - } - catch(Throwable ex) - { - Exception ex2 = (ex instanceof Exception) ? (Exception)ex : new RelProxyException(ex); + + try { + return ClassDescriptorSourceScript.callMainMethod(scriptClass, parent, context); + } catch (Throwable ex) { + Exception ex2 = (ex instanceof Exception) ? (Exception) ex : new RelProxyException(ex); throw new ScriptException(ex2); - } - } + } + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java index 4c657b3..1ff0969 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java @@ -11,108 +11,98 @@ /** * Ideas: http://grepcode.com/file/repo1.maven.org/maven2/org.codehaus.groovy/groovy/1.6.0/org/codehaus/groovy/jsr223/GroovyScriptEngineFactory.java - * + * * @author jmarranz */ -public class JProxyScriptEngineFactoryImpl extends JProxyScriptEngineFactory -{ - protected static final String SHORT_NAME = "java"; - protected static final String LANGUAGE_NAME = "Java"; - +public class JProxyScriptEngineFactoryImpl extends JProxyScriptEngineFactory { + protected static final String SHORT_NAME = "java"; + protected static final String LANGUAGE_NAME = "Java"; + @NotNull protected static final List names; @NotNull protected static final List extensions; @NotNull protected static final List mimeTypes; - - static - { + + static { ArrayList n; - + n = new ArrayList(2); n.add(SHORT_NAME); n.add(LANGUAGE_NAME); - names = Collections.unmodifiableList(n); + names = Collections.unmodifiableList(n); n = new ArrayList(1); n.add("java"); - extensions = Collections.unmodifiableList(n); - - n = new ArrayList(2); http://reference.sitepoint.com/html/mime-types-full + extensions = Collections.unmodifiableList(n); + + n = new ArrayList(2); + http: +//reference.sitepoint.com/html/mime-types-full n.add("text/x-java-source"); - n.add("text/plain"); - mimeTypes = Collections.unmodifiableList(n); + n.add("text/plain"); + mimeTypes = Collections.unmodifiableList(n); } - public JProxyScriptEngineFactoryImpl() - { + public JProxyScriptEngineFactoryImpl() { } - - public static JProxyScriptEngineFactory create() - { + + public static JProxyScriptEngineFactory create() { return new JProxyScriptEngineFactoryImpl(); - } - + } + @NotNull @Override - public String getEngineName() - { + public String getEngineName() { return "RelProxy Java Script Engine"; } @NotNull @Override - public String getEngineVersion() - { + public String getEngineVersion() { return RelProxy.getVersion(); } @NotNull @Override - public List getExtensions() - { + public List getExtensions() { return extensions; } @NotNull @Override - public List getMimeTypes() - { + public List getMimeTypes() { return mimeTypes; } @NotNull @Override - public List getNames() - { + public List getNames() { return names; } @NotNull @Override - public String getLanguageName() - { + public String getLanguageName() { return LANGUAGE_NAME; } @Override - public String getLanguageVersion() - { + public String getLanguageVersion() { return System.getProperty("java.version"); // Ej 1.6.0_18 } @Override - public Object getParameter(String key) - { - if (ScriptEngine.NAME.equals(key)) { - return SHORT_NAME; - } else if (ScriptEngine.ENGINE.equals(key)) { - return getEngineName(); - } else if (ScriptEngine.ENGINE_VERSION.equals(key)) { - return getEngineVersion(); - } else if (ScriptEngine.LANGUAGE.equals(key)) { - return getLanguageName(); + public Object getParameter(String key) { + if (ScriptEngine.NAME.equals(key)) { + return SHORT_NAME; + } else if (ScriptEngine.ENGINE.equals(key)) { + return getEngineName(); + } else if (ScriptEngine.ENGINE_VERSION.equals(key)) { + return getEngineVersion(); + } else if (ScriptEngine.LANGUAGE.equals(key)) { + return getLanguageName(); } else if (ScriptEngine.LANGUAGE_VERSION.equals(key)) { return getLanguageVersion(); } else if ("THREADING".equals(key)) { @@ -124,8 +114,7 @@ public Object getParameter(String key) @NotNull @Override - public String getMethodCallSyntax(String obj, String method, @NotNull String... args) - { + public String getMethodCallSyntax(String obj, String method, @NotNull String... args) { StringBuilder ret = new StringBuilder(); ret.append(obj + "." + method + "("); int len = args.length; @@ -133,7 +122,7 @@ public String getMethodCallSyntax(String obj, String method, @NotNull String... ret.append(")"); return ret.toString(); } - + for (int i = 0; i < len; i++) { ret.append(args[i]); if (i != len - 1) { @@ -147,24 +136,22 @@ public String getMethodCallSyntax(String obj, String method, @NotNull String... @NotNull @Override - public String getOutputStatement(@NotNull String toDisplay) - { + public String getOutputStatement(@NotNull String toDisplay) { StringBuilder buf = new StringBuilder(); buf.append("System.out.println(\""); int len = toDisplay.length(); - for (int i = 0; i < len; i++) - { + for (int i = 0; i < len; i++) { char ch = toDisplay.charAt(i); switch (ch) { - case '"': - buf.append("\\\""); - break; - case '\\': - buf.append("\\\\"); - break; - default: - buf.append(ch); - break; + case '"': + buf.append("\\\""); + break; + case '\\': + buf.append("\\\\"); + break; + default: + buf.append(ch); + break; } } buf.append("\")"); @@ -173,12 +160,10 @@ public String getOutputStatement(@NotNull String toDisplay) @NotNull @Override - public String getProgram(@NotNull String... statements) - { + public String getProgram(@NotNull String... statements) { StringBuilder ret = new StringBuilder(); int len = statements.length; - for (int i = 0; i < len; i++) - { + for (int i = 0; i < len; i++) { ret.append(statements[i]); ret.append('\n'); } @@ -187,8 +172,7 @@ public String getProgram(@NotNull String... statements) @NotNull @Override - public ScriptEngine getScriptEngine() - { + public ScriptEngine getScriptEngine() { return new JProxyScriptEngineImpl(this); - } + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java index 8781e61..aeda178 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java @@ -18,111 +18,98 @@ /** * Methods of this class are similar to JProxyDefaultImpl - * + * * @author jmarranz */ -public class JProxyScriptEngineImpl extends AbstractScriptEngine implements JProxyScriptEngine -{ +public class JProxyScriptEngineImpl extends AbstractScriptEngine implements JProxyScriptEngine { protected JProxyScriptEngineDelegateImpl jproxy; protected JProxyScriptEngineFactoryImpl factory; - public JProxyScriptEngineImpl(JProxyScriptEngineFactoryImpl factory) - { + public JProxyScriptEngineImpl(JProxyScriptEngineFactoryImpl factory) { this.factory = factory; } - @Override - public void init(JProxyConfig config) - { - JProxyConfigImpl configImpl = (JProxyConfigImpl)config; + @Override + public void init(JProxyConfig config) { + JProxyConfigImpl configImpl = (JProxyConfigImpl) config; if (!configImpl.isEnabled()) return; // jproxy quedará null - GenericProxyImpl.checkSingletonNull(jproxy); + GenericProxyImpl.checkSingletonNull(jproxy); this.jproxy = new JProxyScriptEngineDelegateImpl(this); - jproxy.init(configImpl); + jproxy.init(configImpl); } - + @Override - public Object eval(String script, ScriptContext context) throws ScriptException - { - if (jproxy == null) + public Object eval(String script, ScriptContext context) throws ScriptException { + if (jproxy == null) throw new RelProxyException("Engine is disabled"); - - return jproxy.execute(script,context); + + return jproxy.execute(script, context); } @Override - public Object eval(@NotNull Reader reader, ScriptContext context) throws ScriptException - { + public Object eval(@NotNull Reader reader, ScriptContext context) throws ScriptException { String script = JProxyUtil.readTextFile(reader); - return eval(script,context); + return eval(script, context); } @NotNull @Override - public Bindings createBindings() - { + public Bindings createBindings() { return new BindingsImpl(); } @Override - public ScriptEngineFactory getFactory() - { + public ScriptEngineFactory getFactory() { return factory; } @Nullable @Override - public T create(T obj,Class clasz) - { - if (jproxy == null) + public T create(T obj, Class clasz) { + if (jproxy == null) return obj; // No se ha llamado al init o enabled = false return jproxy.create(obj, clasz); } @Nullable @Override - public Object create(Object obj, @NotNull Class[] classes) - { - if (jproxy == null) + public Object create(Object obj, @NotNull Class[] classes) { + if (jproxy == null) return obj; // No se ha llamado al init o enabled = false return jproxy.create(obj, classes); - } - - @Override - public boolean isEnabled() - { - if (jproxy == null) + } + + @Override + public boolean isEnabled() { + if (jproxy == null) return false; - + return jproxy.isEnabled(); - } - - @Override - public boolean isRunning() - { - if (jproxy == null) + } + + @Override + public boolean isRunning() { + if (jproxy == null) return false; - + return jproxy.isRunning(); - } - + } + @Override - public boolean start() - { - if (jproxy == null) + public boolean start() { + if (jproxy == null) return false; - + return jproxy.start(); } @Override - public boolean stop() - { - if (jproxy == null) + public boolean stop() { + if (jproxy == null) return false; - + return jproxy.stop(); } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java index 6cd7faf..4055ffd 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellClassLoader.java @@ -10,40 +10,36 @@ import java.net.URLClassLoader; /** - * * @author jmarranz */ -public class JProxyShellClassLoader extends URLClassLoader -{ - public JProxyShellClassLoader(ClassLoader parent, @NotNull File classFolder) - { - super(toURLArray(classFolder),parent); +public class JProxyShellClassLoader extends URLClassLoader { + public JProxyShellClassLoader(ClassLoader parent, @NotNull File classFolder) { + super(toURLArray(classFolder), parent); } - private static URL[] toURLArray(@NotNull File file) - { - try { return new URL[]{file.toURI().toURL()}; } - catch (MalformedURLException ex) { throw new RelProxyException(ex); } + private static URL[] toURLArray(@NotNull File file) { + try { + return new URL[]{file.toURI().toURL()}; + } catch (MalformedURLException ex) { + throw new RelProxyException(ex); + } } @Override - protected Class findClass(String name) throws ClassNotFoundException - { - return super.findClass(name); + protected Class findClass(String name) throws ClassNotFoundException { + return super.findClass(name); } @Override - protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException - { - return super.loadClass(name, resolve); + protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + return super.loadClass(name, resolve); } - public synchronized Class defineClass(@NotNull ClassDescriptor classDesc) - { + public synchronized Class defineClass(@NotNull ClassDescriptor classDesc) { String className = classDesc.getClassName(); byte[] classBytes = classDesc.getClassBytes(); - Class clasz = defineClass(className,classBytes, 0, classBytes.length); + Class clasz = defineClass(className, classBytes, 0, classBytes.length); classDesc.setLastLoadedClass(clasz); return clasz; - } + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java index df4510a..b362a4c 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java @@ -12,55 +12,46 @@ import java.util.LinkedList; /** - * * @author jmarranz */ -public class JProxyShellCodeSnippetImpl extends JProxyShellImpl -{ - public void init(@NotNull String[] args) - { +public class JProxyShellCodeSnippetImpl extends JProxyShellImpl { + public void init(@NotNull String[] args) { super.init(args, null); - } - - @Override - protected void executeFirstTime(@NotNull ClassDescriptorSourceScript scriptFileDesc, @NotNull LinkedList argsToScript, JProxyShellClassLoader classLoader) - { - try - { - scriptFileDesc.callMainMethod(argsToScript); - } - catch(Throwable ex) - { + } + + @Override + protected void executeFirstTime(@NotNull ClassDescriptorSourceScript scriptFileDesc, @NotNull LinkedList argsToScript, JProxyShellClassLoader classLoader) { + try { + scriptFileDesc.callMainMethod(argsToScript); + } catch (Throwable ex) { ex.printStackTrace(System.out); - } - } - + } + } + @Override - protected void processConfigParams(@NotNull String[] args, @NotNull LinkedList argsToScript, @NotNull JProxyConfigImpl config) - { + protected void processConfigParams(@NotNull String[] args, @NotNull LinkedList argsToScript, @NotNull JProxyConfigImpl config) { super.processConfigParams(args, argsToScript, config); - + String classFolder = config.getClassFolder(); - if (classFolder != null && !classFolder.trim().isEmpty()) throw new RelProxyException("cacheClassFolder is useless to execute a code snippet"); - } - + if (classFolder != null && !classFolder.trim().isEmpty()) + throw new RelProxyException("cacheClassFolder is useless to execute a code snippet"); + } + @NotNull @Override - protected SourceScriptRoot createSourceScriptRoot(String[] args, @NotNull LinkedList argsToScript, FolderSourceList folderSourceList) - { + protected SourceScriptRoot createSourceScriptRoot(String[] args, @NotNull LinkedList argsToScript, FolderSourceList folderSourceList) { // En argsToScript no está el args[0] ni falta que hace porque es el flag "-c" StringBuilder code = new StringBuilder(); - for(String chunk : argsToScript) + for (String chunk : argsToScript) code.append(chunk); return SourceScriptRootInMemory.createSourceScriptInMemory(code.toString()); - } - + } + @Nullable @Override - protected JProxyShellClassLoader getJProxyShellClassLoader(JProxyConfigImpl config) - { + protected JProxyShellClassLoader getJProxyShellClassLoader(JProxyConfigImpl config) { // No hay classFolder => no hay necesidad de nuevo ClassLoader - return null; + return null; } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellImpl.java index e88a295..bfaef31 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellImpl.java @@ -18,37 +18,28 @@ * * @author jmarranz */ -public abstract class JProxyShellImpl extends JProxyImpl -{ - - public static void main(@NotNull String[] args) - { - if (args[0].isEmpty()) - { +public abstract class JProxyShellImpl extends JProxyImpl { + + public static void main(@NotNull String[] args) { + if (args[0].isEmpty()) { // Esto tiene explicación: cuando invocamos jproxysh sin parámetros (o espacios da igual) invocamos dentro jproxysh con com.sillelien.dollar.relproxy.jproxy.JProxyShell "$@" // el parámetro "$@" se convierte en "" que es un parámetro de verdad que recibimos pero de cadena vacía, lo cual nos viene GENIAL para distinguir el caso shell interactive - SINGLETON = new JProxyShellInteractiveImpl(); - ((JProxyShellInteractiveImpl)SINGLETON).init(args); - } - else - { - if (args[0].equals("-c")) - { + SINGLETON = new JProxyShellInteractiveImpl(); + ((JProxyShellInteractiveImpl) SINGLETON).init(args); + } else { + if (args[0].equals("-c")) { SINGLETON = new JProxyShellCodeSnippetImpl(); - ((JProxyShellCodeSnippetImpl)SINGLETON).init(args); - } - else - { - SINGLETON = new JProxyShellScriptFileImpl(); - ((JProxyShellScriptFileImpl)SINGLETON).init(args); + ((JProxyShellCodeSnippetImpl) SINGLETON).init(args); + } else { + SINGLETON = new JProxyShellScriptFileImpl(); + ((JProxyShellScriptFileImpl) SINGLETON).init(args); } } } - + @Nullable - protected ClassDescriptorSourceScript init(@NotNull String[] args, String inputPath) - { + protected ClassDescriptorSourceScript init(@NotNull String[] args, String inputPath) { // Esto quizás necesite una opción en plan "verbose" o "log" para mostrar por pantalla o nada RelProxyOnReloadListener proxyListener = new RelProxyOnReloadListener() { @Override @@ -61,91 +52,79 @@ public void onReload(Object objOld, Object objNew, Object proxy, Method method, config.setEnabled(true); config.setRelProxyOnReloadListener(proxyListener); config.setInputPath(inputPath); - config.setJProxyInputSourceFileExcludedListener(null); + config.setJProxyInputSourceFileExcludedListener(null); config.setJProxyCompilerListener(null); config.setJProxyDiagnosticsListener(null); // Nos vale el log por defecto y no hay manera de espeficar otra cosa via comando - + LinkedList argsToScript = new LinkedList(); - processConfigParams(args,argsToScript,config); - - SourceScriptRoot sourceFileScript = createSourceScriptRoot(args,argsToScript,config.getFolderSourceList()); + processConfigParams(args, argsToScript, config); + + SourceScriptRoot sourceFileScript = createSourceScriptRoot(args, argsToScript, config.getFolderSourceList()); JProxyShellClassLoader classLoader = getJProxyShellClassLoader(config); - ClassDescriptorSourceScript scriptFileDesc = init(config,sourceFileScript,classLoader); + ClassDescriptorSourceScript scriptFileDesc = init(config, sourceFileScript, classLoader); + + executeFirstTime(scriptFileDesc, argsToScript, classLoader); - executeFirstTime(scriptFileDesc,argsToScript,classLoader); - return scriptFileDesc; - } + } @NotNull @Override - public Class getMainParamClass() - { + public Class getMainParamClass() { return String[].class; } - - + + @NotNull protected abstract SourceScriptRoot createSourceScriptRoot(String[] args, LinkedList argsToScript, FolderSourceList folderSourceList); + @Nullable protected abstract JProxyShellClassLoader getJProxyShellClassLoader(JProxyConfigImpl config); - protected abstract void executeFirstTime(ClassDescriptorSourceScript scriptFileDesc,LinkedList argsToScript,JProxyShellClassLoader classLoader); - + + protected abstract void executeFirstTime(ClassDescriptorSourceScript scriptFileDesc, LinkedList argsToScript, JProxyShellClassLoader classLoader); + @NotNull - private static Iterable parseCompilationOptions(@NotNull String value) - { + private static Iterable parseCompilationOptions(@NotNull String value) { // Ej -source 1.6 -target 1.6 se convertiría en Arrays.asList(new String[]{"-source","1.6","-target","1.6"}); String[] options = value.split(" "); LinkedList opCol = new LinkedList(); - for (String option : options) - { + for (String option : options) { String op = option.trim(); // Por si hubiera dos espacios if (op.isEmpty()) continue; opCol.add(op); } return opCol; } - - - protected void processConfigParams(@NotNull String[] args, @NotNull LinkedList argsToScript, @NotNull JProxyConfigImpl config) - { + + + protected void processConfigParams(@NotNull String[] args, @NotNull LinkedList argsToScript, @NotNull JProxyConfigImpl config) { String classFolder = null; long scanPeriod = -1; Iterable compilationOptions = null; boolean test = false; - - for(int i = 1; i < args.length; i++) - { + + for (int i = 1; i < args.length; i++) { String arg = args[i]; - if (arg.startsWith("-D")) - { + if (arg.startsWith("-D")) { String param = arg.substring(2); int pos = param.indexOf('='); if (pos == -1) throw new RelProxyException("Bad parameter format: " + arg); - String name = param.substring(0,pos); + String name = param.substring(0, pos); String value = param.substring(pos + 1); - if ("cacheClassFolder".equals(name)) - { + if ("cacheClassFolder".equals(name)) { classFolder = value; - } - else if ("compilationOptions".equals(name)) - { + } else if ("compilationOptions".equals(name)) { compilationOptions = parseCompilationOptions(value); - } - else if ("test".equals(name)) - { + } else if ("test".equals(name)) { test = Boolean.parseBoolean(value); - } - else throw new RelProxyException("Unknown parameter: " + arg); - } - else - { + } else throw new RelProxyException("Unknown parameter: " + arg); + } else { argsToScript.add(arg); } } @@ -153,8 +132,8 @@ else if ("test".equals(name)) config.setClassFolder(classFolder); config.setScanPeriod(scanPeriod); config.setCompilationOptions(compilationOptions); - config.setTest(test); + config.setTest(test); } - + } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java index 7ab2f67..f42955b 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java @@ -14,80 +14,71 @@ /** * Alguna inspiración: http://groovy.codehaus.org/Groovy+Shell - * + * * @author jmarranz */ -public class JProxyShellInteractiveImpl extends JProxyShellImpl -{ +public class JProxyShellInteractiveImpl extends JProxyShellImpl { protected boolean test = false; @NotNull protected JProxyShellProcessor processor = new JProxyShellProcessor(this); @Nullable protected ClassDescriptorSourceScript classDescSourceScript; - - public void init(@NotNull String[] args) - { + + public void init(@NotNull String[] args) { this.classDescSourceScript = super.init(args, null); - if (test) - { + if (test) { processor.test(); return; } - + processor.loop(); - } - + } + @Nullable - public ClassDescriptorSourceScript getClassDescriptorSourceScript() - { + public ClassDescriptorSourceScript getClassDescriptorSourceScript() { return classDescSourceScript; } - + @NotNull - public SourceScriptRootInMemory getSourceScriptInMemory() - { - return (SourceScriptRootInMemory)classDescSourceScript.getSourceScript(); + public SourceScriptRootInMemory getSourceScriptInMemory() { + return (SourceScriptRootInMemory) classDescSourceScript.getSourceScript(); } - + @Nullable @Override - public ClassDescriptorSourceScript init(@NotNull JProxyConfigImpl config, SourceScriptRoot scriptFile, ClassLoader classLoader) - { - ClassDescriptorSourceScript script = super.init(config,scriptFile, classLoader); - + public ClassDescriptorSourceScript init(@NotNull JProxyConfigImpl config, SourceScriptRoot scriptFile, ClassLoader classLoader) { + ClassDescriptorSourceScript script = super.init(config, scriptFile, classLoader); + this.test = config.isTest(); - + return script; } - + @Override - protected void executeFirstTime(ClassDescriptorSourceScript scriptFileDesc,LinkedList argsToScript,JProxyShellClassLoader classLoader) - { + protected void executeFirstTime(ClassDescriptorSourceScript scriptFileDesc, LinkedList argsToScript, JProxyShellClassLoader classLoader) { // La primera vez el script es vacío, no hay nada que ejecutar - } - + } + @Override - protected void processConfigParams(@NotNull String[] args, @NotNull LinkedList argsToScript, @NotNull JProxyConfigImpl config) - { + protected void processConfigParams(@NotNull String[] args, @NotNull LinkedList argsToScript, @NotNull JProxyConfigImpl config) { super.processConfigParams(args, argsToScript, config); - + String classFolder = config.getClassFolder(); - if (classFolder != null && !classFolder.trim().isEmpty()) throw new RelProxyException("cacheClassFolder is useless to execute in interactive mode"); - } + if (classFolder != null && !classFolder.trim().isEmpty()) + throw new RelProxyException("cacheClassFolder is useless to execute in interactive mode"); + } @NotNull @Override - protected SourceScriptRoot createSourceScriptRoot(String[] args,LinkedList argsToScript,FolderSourceList folderSourceList) - { + protected SourceScriptRoot createSourceScriptRoot(String[] args, LinkedList argsToScript, FolderSourceList folderSourceList) { return SourceScriptRootInMemory.createSourceScriptInMemory(""); // La primera vez no hace nada, sirve para "calentar" la app - } - + } + @Nullable @Override - protected JProxyShellClassLoader getJProxyShellClassLoader(JProxyConfigImpl config) - { + protected JProxyShellClassLoader getJProxyShellClassLoader(JProxyConfigImpl config) { // No hay classFolder => no hay necesidad de nuevo ClassLoader - return null; - } + return null; + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java index 821fde7..ffc45c6 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java @@ -15,69 +15,59 @@ import java.util.LinkedList; /** - * * @author jmarranz */ -public class JProxyShellScriptFileImpl extends JProxyShellImpl -{ +public class JProxyShellScriptFileImpl extends JProxyShellImpl { protected FileExt scriptFile; - - public void init(@NotNull String[] args) - { + + public void init(@NotNull String[] args) { File scriptFile = new File(args[0]); - if (!scriptFile.exists()) + if (!scriptFile.exists()) throw new RelProxyException("File " + args[0] + " does not exist"); - + this.scriptFile = new FileExt(scriptFile); - + File parentDir = JProxyUtil.getParentDir(scriptFile); - String inputPath = parentDir.getAbsolutePath(); + String inputPath = parentDir.getAbsolutePath(); super.init(args, inputPath); - } - + } + @Override - protected void executeFirstTime(@NotNull ClassDescriptorSourceScript scriptFileDesc, @NotNull LinkedList argsToScript, JProxyShellClassLoader classLoader) - { - fixLastLoadedClass(scriptFileDesc,classLoader); - - try - { - scriptFileDesc.callMainMethod(argsToScript); - } - catch(Throwable ex) - { + protected void executeFirstTime(@NotNull ClassDescriptorSourceScript scriptFileDesc, @NotNull LinkedList argsToScript, JProxyShellClassLoader classLoader) { + fixLastLoadedClass(scriptFileDesc, classLoader); + + try { + scriptFileDesc.callMainMethod(argsToScript); + } catch (Throwable ex) { ex.printStackTrace(System.out); - } + } } - + @NotNull @Override - protected SourceScriptRoot createSourceScriptRoot(String[] args, LinkedList argsToScript, @NotNull FolderSourceList folderSourceList) - { - return SourceScriptRootFile.createSourceScriptRootFile(scriptFile,folderSourceList); - } - + protected SourceScriptRoot createSourceScriptRoot(String[] args, LinkedList argsToScript, @NotNull FolderSourceList folderSourceList) { + return SourceScriptRootFile.createSourceScriptRootFile(scriptFile, folderSourceList); + } + @Nullable @Override - protected JProxyShellClassLoader getJProxyShellClassLoader(@NotNull JProxyConfigImpl config) - { + protected JProxyShellClassLoader getJProxyShellClassLoader(@NotNull JProxyConfigImpl config) { String classFolder = config.getClassFolder(); if (classFolder != null) - return new JProxyShellClassLoader(getDefaultClassLoader(),new File(classFolder)); + return new JProxyShellClassLoader(getDefaultClassLoader(), new File(classFolder)); else return null; } - - protected void fixLastLoadedClass(@NotNull ClassDescriptorSourceScript scriptFileDesc, @Nullable JProxyShellClassLoader classLoader) - { + + protected void fixLastLoadedClass(@NotNull ClassDescriptorSourceScript scriptFileDesc, @Nullable JProxyShellClassLoader classLoader) { Class scriptClass = scriptFileDesc.getLastLoadedClass(); if (scriptClass != null) return; - + // Esto es esperable cuando especificamos un classFolder en donde está ya compilado el script lanzador y es más actual que el fuente // no ha habido necesidad de crear un class loader "reloader" ni de recargar todos los archivos fuente con él if (classLoader == null) throw new RelProxyException("INTERNAL ERROR"); if (scriptFileDesc.getClassBytes() == null) throw new RelProxyException("INTERNAL ERROR"); scriptClass = classLoader.defineClass(scriptFileDesc); - scriptFileDesc.setLastLoadedClass(scriptClass); + scriptFileDesc.setLastLoadedClass(scriptClass); } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/Command.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/Command.java index 06b0ebc..f331c17 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/Command.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/Command.java @@ -3,103 +3,77 @@ import org.jetbrains.annotations.NotNull; /** - * * @author jmarranz */ -public abstract class Command -{ - protected JProxyShellProcessor parent; +public abstract class Command { + protected JProxyShellProcessor parent; protected String name; - - public Command(JProxyShellProcessor parent,String name) - { + + public Command(JProxyShellProcessor parent, String name) { this.parent = parent; this.name = name; } - - public static Command createCommand(@NotNull JProxyShellProcessor parent, String cmd) - { + + public static Command createCommand(@NotNull JProxyShellProcessor parent, String cmd) { cmd = cmd.trim(); - if (cmd.equals("clear")) - { - return new CommandOther(parent,cmd); - } - else if (cmd.startsWith("delete")) - { - CommandDelete command = CommandDelete.createCommandDelete(parent,cmd); + if (cmd.equals("clear")) { + return new CommandOther(parent, cmd); + } else if (cmd.startsWith("delete")) { + CommandDelete command = CommandDelete.createCommandDelete(parent, cmd); if (command != null) return command; else - return new CommandError(parent); - } - else if (cmd.equals("display")) - { - return new CommandOther(parent,cmd); - } - else if (cmd.startsWith("edit")) - { - CommandEdit command = CommandEdit.createCommandEdit(parent,cmd); + return new CommandError(parent); + } else if (cmd.equals("display")) { + return new CommandOther(parent, cmd); + } else if (cmd.startsWith("edit")) { + CommandEdit command = CommandEdit.createCommandEdit(parent, cmd); if (command != null) return command; else - return new CommandError(parent); - } - else if (cmd.equals("exec")) - { - return new CommandOther(parent,cmd); - } - else if (cmd.equals("exit")) - { - return new CommandOther(parent,cmd); - } - else if (cmd.equals("help")) - { - return new CommandOther(parent,cmd); - } - else if (cmd.startsWith("insert")) - { - CommandInsert command = CommandInsert.createCommandInsert(parent,cmd); + return new CommandError(parent); + } else if (cmd.equals("exec")) { + return new CommandOther(parent, cmd); + } else if (cmd.equals("exit")) { + return new CommandOther(parent, cmd); + } else if (cmd.equals("help")) { + return new CommandOther(parent, cmd); + } else if (cmd.startsWith("insert")) { + CommandInsert command = CommandInsert.createCommandInsert(parent, cmd); if (command != null) return command; else - return new CommandError(parent); - } - else if (cmd.startsWith("load")) - { - CommandLoad command = CommandLoad.createCommandLoad(parent,cmd); + return new CommandError(parent); + } else if (cmd.startsWith("load")) { + CommandLoad command = CommandLoad.createCommandLoad(parent, cmd); if (command != null) return command; else - return new CommandError(parent); - } - else if (cmd.equals("quit")) - { - return new CommandOther(parent,cmd); - } - else if (cmd.startsWith("save")) - { - CommandSave command = CommandSave.createCommandSave(parent,cmd); + return new CommandError(parent); + } else if (cmd.equals("quit")) { + return new CommandOther(parent, cmd); + } else if (cmd.startsWith("save")) { + CommandSave command = CommandSave.createCommandSave(parent, cmd); if (command != null) return command; else - return new CommandError(parent); - } - + return new CommandError(parent); + } + return null; // No es un comando - } - - protected static String getParameter(String cmdName, @NotNull String cmd) - { + } + + protected static String getParameter(String cmdName, @NotNull String cmd) { int pos = cmd.indexOf(cmdName + " "); if (pos != 0) return null; - pos = cmd.indexOf(' '); + pos = cmd.indexOf(' '); String param = cmd.substring(pos + 1); - param = param.trim(); + param = param.trim(); return param; } - - public abstract boolean run(); - - public abstract void runPostCommand(); + + public abstract boolean run(); + + public abstract void runPostCommand(); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java index 3ecd2e3..522d2a0 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java @@ -4,79 +4,62 @@ import org.jetbrains.annotations.NotNull; /** - * * @author jmarranz */ -public abstract class CommandCodeChangerBase extends Command -{ +public abstract class CommandCodeChangerBase extends Command { public static final int ERROR_LAST_REQUIRED = -1; - public static final int ERROR_NO_LAST_LINE = -2; - public static final int ERROR_NOT_A_NUMBER = -3; - public static final int ERROR_VALUE_NOT_0_OR_NEGATIVE = -4; - public static final int ERROR_LINE_1_NOT_VALID = -5; - public static final int ERROR_OUT_OF_RANGE = -6; - - - protected int line; - - public CommandCodeChangerBase(JProxyShellProcessor parent,String name,int line) - { - super(parent,name); - this.line = line; - } - - public static int getLineFromParam(@NotNull JProxyShellProcessor parent, String name, @NotNull String cmd) - { - String param = getParameter(name,cmd); - if (param == null) - { + public static final int ERROR_NO_LAST_LINE = -2; + public static final int ERROR_NOT_A_NUMBER = -3; + public static final int ERROR_VALUE_NOT_0_OR_NEGATIVE = -4; + public static final int ERROR_LINE_1_NOT_VALID = -5; + public static final int ERROR_OUT_OF_RANGE = -6; + + + protected int line; + + public CommandCodeChangerBase(JProxyShellProcessor parent, String name, int line) { + super(parent, name); + this.line = line; + } + + public static int getLineFromParam(@NotNull JProxyShellProcessor parent, String name, @NotNull String cmd) { + String param = getParameter(name, cmd); + if (param == null) { return ERROR_LAST_REQUIRED; - } + } int line; - if (param.equals("last")) - { + if (param.equals("last")) { int lastLine = parent.getLastLine(); - if (lastLine == -1) - { + if (lastLine == -1) { return ERROR_NO_LAST_LINE; } line = lastLine; - } - else - { - try - { - line = Integer.parseInt(param); - } - catch(NumberFormatException ex) - { + } else { + try { + line = Integer.parseInt(param); + } catch (NumberFormatException ex) { return ERROR_NOT_A_NUMBER; } // Ojo es el valor dado por el usuario (empezando en 1 y con línea vacía) - if (line <= 0) - { + if (line <= 0) { return ERROR_VALUE_NOT_0_OR_NEGATIVE; - } - else if (line == 1) - { + } else if (line == 1) { return ERROR_LINE_1_NOT_VALID; } - line -= JProxyShellProcessor.LINE_OFFSET; + line -= JProxyShellProcessor.LINE_OFFSET; - if (line >= parent.getCodeBuffer().size()) - { + if (line >= parent.getCodeBuffer().size()) { return ERROR_OUT_OF_RANGE; } - } + } return line; } - - + + @Override - public boolean run() - { + public boolean run() { return true; - } + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandDelete.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandDelete.java index 956501f..8b7331f 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandDelete.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandDelete.java @@ -4,55 +4,48 @@ import org.jetbrains.annotations.NotNull; /** - * * @author jmarranz */ -public class CommandDelete extends CommandCodeChangerBase -{ - public static final String NAME = "delete"; - - public CommandDelete(JProxyShellProcessor parent,int line) - { - super(parent,NAME,line); - } - - public static CommandDelete createCommandDelete(@NotNull JProxyShellProcessor parent, @NotNull String cmd) - { - int line = getLineFromParam(parent,NAME,cmd); - if (line < 0) - { - switch(line) - { - case ERROR_LAST_REQUIRED: +public class CommandDelete extends CommandCodeChangerBase { + public static final String NAME = "delete"; + + public CommandDelete(JProxyShellProcessor parent, int line) { + super(parent, NAME, line); + } + + public static CommandDelete createCommandDelete(@NotNull JProxyShellProcessor parent, @NotNull String cmd) { + int line = getLineFromParam(parent, NAME, cmd); + if (line < 0) { + switch (line) { + case ERROR_LAST_REQUIRED: System.out.println("Command error: parameter \"last\" or a line number is required"); break; case ERROR_NO_LAST_LINE: System.out.println("Command error: no new or edited line code has been introduced"); break; case ERROR_NOT_A_NUMBER: - System.out.println("Command error: line value is not a number"); - break; + System.out.println("Command error: line value is not a number"); + break; case ERROR_VALUE_NOT_0_OR_NEGATIVE: - System.out.println("Command error: line value cannot be 0 or negative"); - break; + System.out.println("Command error: line value cannot be 0 or negative"); + break; case ERROR_LINE_1_NOT_VALID: - System.out.println("Command error: line 1 is ever empty and cannot be deleted"); - break; + System.out.println("Command error: line 1 is ever empty and cannot be deleted"); + break; case ERROR_OUT_OF_RANGE: - System.out.println("Command error: line number out of range"); - break; + System.out.println("Command error: line number out of range"); + break; default: // Para que se calle el FindBugs } return null; } - - return new CommandDelete(parent,line); + + return new CommandDelete(parent, line); } - + @Override - public void runPostCommand() - { + public void runPostCommand() { parent.removeCodeBuffer(line); } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandEdit.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandEdit.java index 6ddb775..5aeb53b 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandEdit.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandEdit.java @@ -4,58 +4,51 @@ import org.jetbrains.annotations.NotNull; /** - * * @author jmarranz */ -public class CommandEdit extends CommandCodeChangerBase -{ +public class CommandEdit extends CommandCodeChangerBase { public static final String NAME = "edit"; - protected String codeLine; - - public CommandEdit(JProxyShellProcessor parent,int line,String codeLine) - { - super(parent,NAME,line); - this.codeLine = codeLine; - } - - public static CommandEdit createCommandEdit(@NotNull JProxyShellProcessor parent, @NotNull String cmd) - { - int line = getLineFromParam(parent,NAME,cmd); - if (line < 0) - { - switch(line) - { - case ERROR_LAST_REQUIRED: + protected String codeLine; + + public CommandEdit(JProxyShellProcessor parent, int line, String codeLine) { + super(parent, NAME, line); + this.codeLine = codeLine; + } + + public static CommandEdit createCommandEdit(@NotNull JProxyShellProcessor parent, @NotNull String cmd) { + int line = getLineFromParam(parent, NAME, cmd); + if (line < 0) { + switch (line) { + case ERROR_LAST_REQUIRED: System.out.println("Command error: parameter \"last\" or a line number is required"); break; case ERROR_NO_LAST_LINE: - System.out.println("Command error: no new or edited line code has been introduced"); + System.out.println("Command error: no new or edited line code has been introduced"); break; case ERROR_NOT_A_NUMBER: - System.out.println("Command error: line value is not a number"); - break; + System.out.println("Command error: line value is not a number"); + break; case ERROR_VALUE_NOT_0_OR_NEGATIVE: - System.out.println("Command error: line value cannot be 0 or negative"); - break; + System.out.println("Command error: line value cannot be 0 or negative"); + break; case ERROR_LINE_1_NOT_VALID: - System.out.println("Command error: line 1 is ever empty and cannot be edited"); - break; + System.out.println("Command error: line 1 is ever empty and cannot be edited"); + break; case ERROR_OUT_OF_RANGE: - System.out.println("Command error: line number out of range"); - break; + System.out.println("Command error: line number out of range"); + break; default: // Para que se calle el FindBugs } return null; - } - - String codeLine = parent.getCodeBuffer().get(line); - return new CommandEdit(parent,line,codeLine); + } + + String codeLine = parent.getCodeBuffer().get(line); + return new CommandEdit(parent, line, codeLine); } - + @Override - public void runPostCommand() - { + public void runPostCommand() { parent.getKeyboard().type(codeLine); parent.setLineEditing(line); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandError.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandError.java index 2c7480e..58a14c8 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandError.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandError.java @@ -1,25 +1,20 @@ package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; /** - * * @author jmarranz */ -public class CommandError extends Command -{ - public CommandError(JProxyShellProcessor parent) - { +public class CommandError extends Command { + public CommandError(JProxyShellProcessor parent) { super(parent, "ERROR"); } @Override - public boolean run() - { + public boolean run() { return false; } @Override - public void runPostCommand() - { + public void runPostCommand() { } - + } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandInsert.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandInsert.java index 5fe5983..79a7245 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandInsert.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandInsert.java @@ -4,56 +4,49 @@ import org.jetbrains.annotations.NotNull; /** - * * @author jmarranz */ -public class CommandInsert extends CommandCodeChangerBase -{ - public static final String NAME = "insert"; - - public CommandInsert(JProxyShellProcessor parent,int line) - { - super(parent,NAME,line); - } - - public static CommandInsert createCommandInsert(@NotNull JProxyShellProcessor parent, @NotNull String cmd) - { - int line = getLineFromParam(parent,NAME,cmd); - if (line < 0) - { - switch(line) - { - case ERROR_LAST_REQUIRED: +public class CommandInsert extends CommandCodeChangerBase { + public static final String NAME = "insert"; + + public CommandInsert(JProxyShellProcessor parent, int line) { + super(parent, NAME, line); + } + + public static CommandInsert createCommandInsert(@NotNull JProxyShellProcessor parent, @NotNull String cmd) { + int line = getLineFromParam(parent, NAME, cmd); + if (line < 0) { + switch (line) { + case ERROR_LAST_REQUIRED: System.out.println("Command error: parameter \"last\" or a line number is required"); break; case ERROR_NO_LAST_LINE: System.out.println("Command error: no new or edited line code has been introduced"); break; case ERROR_NOT_A_NUMBER: - System.out.println("Command error: line value is not a number"); - break; + System.out.println("Command error: line value is not a number"); + break; case ERROR_VALUE_NOT_0_OR_NEGATIVE: - System.out.println("Command error: line value cannot be 0 or negative"); - break; + System.out.println("Command error: line value cannot be 0 or negative"); + break; case ERROR_LINE_1_NOT_VALID: - System.out.println("Command error: line 1 is ever empty and no code can be inserted before"); - break; + System.out.println("Command error: line 1 is ever empty and no code can be inserted before"); + break; case ERROR_OUT_OF_RANGE: - System.out.println("Command error: line number out of range"); - break; + System.out.println("Command error: line number out of range"); + break; default: - // Para que se calle el FindBugs + // Para que se calle el FindBugs } return null; - } - - return new CommandInsert(parent,line); + } + + return new CommandInsert(parent, line); } - + @Override - public void runPostCommand() - { - parent.insertCodeBuffer(line,""); + public void runPostCommand() { + parent.insertCodeBuffer(line, ""); parent.setLineEditing(line); } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandLoad.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandLoad.java index 7afdaf0..e3c2227 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandLoad.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandLoad.java @@ -10,71 +10,59 @@ import java.util.Scanner; /** - * * @author jmarranz */ -public class CommandLoad extends Command -{ +public class CommandLoad extends Command { public static final String NAME = "load"; - protected String url; - - public CommandLoad(JProxyShellProcessor parent,String url) - { - super(parent,NAME); - this.url = url; - } - - public static CommandLoad createCommandLoad(JProxyShellProcessor parent, @NotNull String cmd) - { - String url = getParameter(NAME,cmd); - if (url == null) - { + protected String url; + + public CommandLoad(JProxyShellProcessor parent, String url) { + super(parent, NAME); + this.url = url; + } + + public static CommandLoad createCommandLoad(JProxyShellProcessor parent, @NotNull String cmd) { + String url = getParameter(NAME, cmd); + if (url == null) { System.out.println("Command error: parameter is required"); return null; } - return new CommandLoad(parent,url); + return new CommandLoad(parent, url); } - + @Override - public boolean run() - { - try - { + public boolean run() { + try { byte[] content; URI uri = new URI(url); if (uri.getScheme() == null) // Archivo { File file = new File(url); content = JProxyUtil.readFile(file); - } - else // URL (incluyendo file:///...) + } else // URL (incluyendo file:///...) { URL urlObj = new URL(url); content = JProxyUtil.readURL(urlObj); // Como no conocemos encoding... } - String code = new String(content,parent.getEncoding()); // Como no conocemos encoding... + String code = new String(content, parent.getEncoding()); // Como no conocemos encoding... LinkedList lines = new LinkedList(); Scanner scanner = new Scanner(code); - while (scanner.hasNextLine()) - { + while (scanner.hasNextLine()) { String line = scanner.nextLine(); lines.add(line); - } - + } + parent.setCodeBuffer(lines); return true; - } - catch (Exception ex) - { + } catch (Exception ex) { ex.printStackTrace(); return false; } - } - + } + @Override - public void runPostCommand() - { + public void runPostCommand() { } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandOther.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandOther.java index e93c5e4..cbca514 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandOther.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandOther.java @@ -4,107 +4,84 @@ import com.sillelien.dollar.relproxy.RelProxyException; /** - * * @author jmarranz */ -public class CommandOther extends Command -{ - public CommandOther(JProxyShellProcessor parent,String name) - { - super(parent,name); - } - +public class CommandOther extends Command { + public CommandOther(JProxyShellProcessor parent, String name) { + super(parent, name); + } + @Override - public boolean run() - { - if (name.equals("clear")) - { + public boolean run() { + if (name.equals("clear")) { commandClear(); - } - else if (name.equals("display")) - { + } else if (name.equals("display")) { commandDisplay(); - } - else if (name.equals("exec")) - { + } else if (name.equals("exec")) { commandExec(); - } - else if (name.equals("exit")) - { + } else if (name.equals("exit")) { commandExit(); - } - else if (name.equals("help")) - { + } else if (name.equals("help")) { commandHelp(); - } - else if (name.equals("quit")) - { + } else if (name.equals("quit")) { commandExit(); - } - else throw new RelProxyException("Internal Error"); - + } else throw new RelProxyException("Internal Error"); + return true; - } - + } + @Override - public void runPostCommand() - { + public void runPostCommand() { } - - private void commandClear() - { + + private void commandClear() { parent.clearCodeBuffer(); } - - private void commandExit() - { + + private void commandExit() { System.exit(0); - } - - private void commandDisplay() - { + } + + private void commandDisplay() { System.out.println("001>"); // La primera línea es siempre vacía porque en ella es donde ponemos el "public class /_jproxyShellInMemoryClass_ { " que el usuario ignora, así al dar error el número de línea será correcto respecto al "display" - + int i = 2; - for(String line : parent.getCodeBuffer()) - { - for(int j = 0; j < 3 - String.valueOf(i).length(); j++) System.out.print("0"); + for (String line : parent.getCodeBuffer()) { + for (int j = 0; j < 3 - String.valueOf(i).length(); j++) System.out.print("0"); System.out.print(i + ">"); - System.out.print(line); - System.out.println(); + System.out.print(line); + System.out.println(); i++; - } + } } - - private void commandExec() - { - parent.executeCodeBuffer(); - } - - private void commandHelp() - { + + private void commandExec() { + parent.executeCodeBuffer(); + } + + private void commandHelp() { System.out.println("Everything you write in the prompt is added to a code buffer, code buffer is compiled on the fly and executed by exec command, unless a command is detected"); - System.out.println(""); + System.out.println(""); System.out.println("Available commands:"); - System.out.println(" clear"); - System.out.println(" Clears the buffer"); - System.out.println(" display"); - System.out.println(" Shows the buffer content"); - System.out.println(" edit last | "); - System.out.println(" Edits the last introduced line code or the specified line number"); - System.out.println(" exec"); - System.out.println(" Compile and execute the buffer content"); - System.out.println(" exit"); - System.out.println(" Exits shell"); - System.out.println(" help"); - System.out.println(" This command"); - System.out.println(" insert last | "); - System.out.println(" Insert the next line of code before the last introduced line or the specified line number"); - System.out.println(" load | "); - System.out.println(" Load a file or URL into the buffer"); - System.out.println(" quit"); - System.out.println(" Same as exit"); - System.out.println(" save "); - System.out.println(" Save the current buffer to a file"); - } + System.out.println(" clear"); + System.out.println(" Clears the buffer"); + System.out.println(" display"); + System.out.println(" Shows the buffer content"); + System.out.println(" edit last | "); + System.out.println(" Edits the last introduced line code or the specified line number"); + System.out.println(" exec"); + System.out.println(" Compile and execute the buffer content"); + System.out.println(" exit"); + System.out.println(" Exits shell"); + System.out.println(" help"); + System.out.println(" This command"); + System.out.println(" insert last | "); + System.out.println(" Insert the next line of code before the last introduced line or the specified line number"); + System.out.println(" load | "); + System.out.println(" Load a file or URL into the buffer"); + System.out.println(" quit"); + System.out.println(" Same as exit"); + System.out.println(" save "); + System.out.println(" Save the current buffer to a file"); + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandSave.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandSave.java index 5797667..ff47a30 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandSave.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/CommandSave.java @@ -7,57 +7,46 @@ import java.util.List; /** - * * @author jmarranz */ -public class CommandSave extends Command -{ +public class CommandSave extends Command { public static final String NAME = "save"; - protected String path; - - public CommandSave(JProxyShellProcessor parent,String url) - { - super(parent,NAME); - this.path = url; - } - - public static CommandSave createCommandSave(JProxyShellProcessor parent, @NotNull String cmd) - { - String url = getParameter(NAME,cmd); - if (url == null) - { + protected String path; + + public CommandSave(JProxyShellProcessor parent, String url) { + super(parent, NAME); + this.path = url; + } + + public static CommandSave createCommandSave(JProxyShellProcessor parent, @NotNull String cmd) { + String url = getParameter(NAME, cmd); + if (url == null) { System.out.println("Command error: parameter is required"); return null; } - return new CommandSave(parent,url); + return new CommandSave(parent, url); } - + @Override - public boolean run() - { - try - { + public boolean run() { + try { List codeBuffer = parent.getCodeBuffer(); StringBuilder code = new StringBuilder(); - for(String line : codeBuffer) - { + for (String line : codeBuffer) { code.append(line); - code.append("\n"); + code.append("\n"); } byte[] content = code.toString().getBytes(parent.getEncoding()); // Como no conocemos encoding... - JProxyUtil.saveFile(new File(path),content); + JProxyUtil.saveFile(new File(path), content); return true; - } - catch (Exception ex) - { + } catch (Exception ex) { ex.printStackTrace(); return false; } - } - + } + @Override - public void runPostCommand() - { + public void runPostCommand() { } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java index 488b0d4..6950806 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/JProxyShellProcessor.java @@ -16,13 +16,11 @@ import java.util.Scanner; /** - * * @author jmarranz */ -public class JProxyShellProcessor -{ +public class JProxyShellProcessor { public static final int LINE_OFFSET = 2; // El índice en codeBuffer + este valor = al valor de la línea que se muestra al usuario, hay que tener en cuenta que contamos desde uno y la primera línea es siempre vacía - + protected JProxyShellInteractiveImpl parent; @NotNull protected Charset encoding = Charset.defaultCharset(); @@ -32,192 +30,166 @@ public class JProxyShellProcessor protected Keyboard keyboard = KeyboardNotUsingClipboard.create(encoding); protected int lastLine = -1; // Indice respecto a codeBuffer protected int lineEditing = -1; // Indice respecto a codeBuffer - protected long codeBufferModTimestamp = 0; - protected long lastCodeCompiledTimestamp = 0; - - public JProxyShellProcessor(JProxyShellInteractiveImpl parent) - { + protected long codeBufferModTimestamp = 0; + protected long lastCodeCompiledTimestamp = 0; + + public JProxyShellProcessor(JProxyShellInteractiveImpl parent) { this.parent = parent; } - + @NotNull - public Keyboard getKeyboard() - { + public Keyboard getKeyboard() { return keyboard; } - + @NotNull - public Charset getEncoding() - { + public Charset getEncoding() { return encoding; } - - public int getLastLine() - { + + public int getLastLine() { return lastLine; } - - public void setLineEditing(int lineEditing) - { + + public void setLineEditing(int lineEditing) { this.lineEditing = lineEditing; } - - public void test() - { - try { Thread.sleep(2); } catch (InterruptedException ex){ } + + public void test() { + try { + Thread.sleep(2); + } catch (InterruptedException ex) { + } execute("System.out.println(\"Hello World\");"); // "Object o = null; o.equals(null);" } - - public void loop() - { + + public void loop() { System.out.println("RelProxy Java Shell v" + RelProxy.getVersion()); System.out.println("Write help for help"); - - Scanner sc = new Scanner(System.in,encoding.name()); // No encuentro nada interesante en http://docs.oracle.com/javase/6/docs/api/java/io/Console.html - System.out.print(">"); - while(true) - { + + Scanner sc = new Scanner(System.in, encoding.name()); // No encuentro nada interesante en http://docs.oracle.com/javase/6/docs/api/java/io/Console.html + System.out.print(">"); + while (true) { String line = sc.nextLine(); - Command command = Command.createCommand(this,line); - if (command != null) - { + Command command = Command.createCommand(this, line); + if (command != null) { if (command instanceof CommandError) // Era un comando pero con params erróneos { // Nada que hacer - System.out.print(">"); - } - else - { + System.out.print(">"); + } else { boolean success = command.run(); - System.out.print(">"); + System.out.print(">"); - if (success) - { + if (success) { command.runPostCommand(); // Lo normal es que no haga nada } } - } - else - { - if (lineEditing != -1) - { - setCodeBuffer(lineEditing, line); + } else { + if (lineEditing != -1) { + setCodeBuffer(lineEditing, line); this.lineEditing = -1; + } else { + addCodeBuffer(line); } - else - { - addCodeBuffer(line); - } - - System.out.print(">"); + + System.out.print(">"); } } - } - + } + @NotNull - public List getCodeBuffer() - { + public List getCodeBuffer() { return Collections.unmodifiableList(codeBuffer); - } - - public void setCodeBuffer(int index,String line) - { - codeBuffer.set(index, line); + } + + public void setCodeBuffer(int index, String line) { + codeBuffer.set(index, line); this.codeBufferModTimestamp = System.currentTimeMillis(); - this.lastLine = index; + this.lastLine = index; } - - public void setCodeBuffer(@NotNull LinkedList codeBuffer) - { + + public void setCodeBuffer(@NotNull LinkedList codeBuffer) { codeBuffer.clear(); - this.codeBuffer.addAll(codeBuffer); + this.codeBuffer.addAll(codeBuffer); this.codeBufferModTimestamp = System.currentTimeMillis(); - this.lastLine = codeBuffer.size() - 1; - } - - public void insertCodeBuffer(int index,String line) - { + this.lastLine = codeBuffer.size() - 1; + } + + public void insertCodeBuffer(int index, String line) { codeBuffer.add(index, line); this.codeBufferModTimestamp = System.currentTimeMillis(); - this.lastLine = index; - } - - public void addCodeBuffer(String line) - { - codeBuffer.add(line); + this.lastLine = index; + } + + public void addCodeBuffer(String line) { + codeBuffer.add(line); this.codeBufferModTimestamp = System.currentTimeMillis(); - this.lastLine = codeBuffer.size() - 1; - } - - public void removeCodeBuffer(int index) - { + this.lastLine = codeBuffer.size() - 1; + } + + public void removeCodeBuffer(int index) { codeBuffer.remove(index); this.codeBufferModTimestamp = System.currentTimeMillis(); this.lastLine = -1; // La hemos eliminado, no existe ya - } - - public void clearCodeBuffer() - { - codeBuffer.clear(); + } + + public void clearCodeBuffer() { + codeBuffer.clear(); this.codeBufferModTimestamp = System.currentTimeMillis(); - this.lastLine = - 1; - } - - public void executeCodeBuffer() - { + this.lastLine = -1; + } + + public void executeCodeBuffer() { StringBuilder code = new StringBuilder(); - for(String line : codeBuffer) - { + for (String line : codeBuffer) { code.append(line); - code.append("\n"); - } + code.append("\n"); + } execute(code.toString()); } - - private void execute(String code) - { + + private void execute(String code) { // Este código no es thread safe ni falta que hace. - + ClassDescriptorSourceScript classDescSourceScript = parent.getClassDescriptorSourceScript(); - + if (codeBufferModTimestamp > lastCodeCompiledTimestamp) // Incluimos el = por si acaso va todo muy seguido { - parent.getSourceScriptInMemory().setScriptCode(code,codeBufferModTimestamp); + parent.getSourceScriptInMemory().setScriptCode(code, codeBufferModTimestamp); // Recuerda que cada vez que se obtiene el timestamp se llama a System.currentTimeMillis(), es imposible que el usuario haga algo en menos de 1ms JProxyEngine engine = parent.getJProxyEngine(); ClassDescriptorSourceScript classDescSourceScript2 = null; - try - { + try { classDescSourceScript2 = engine.detectChangesInSourcesAndReload(); - } - catch(JProxyCompilationException ex) - { + } catch (JProxyCompilationException ex) { System.out.println("Compilation error"); return; } if (classDescSourceScript2 != classDescSourceScript) throw new RelProxyException("Internal Error"); - - this.lastCodeCompiledTimestamp = System.currentTimeMillis(); + + this.lastCodeCompiledTimestamp = System.currentTimeMillis(); if (lastCodeCompiledTimestamp == codeBufferModTimestamp) // Demasiado rápido compilando { // El ser humano es muy raro y es posible que a alguien se le ocurra usar el shell de forma automatizada y se genere un siguiente cambio en el // código fuente tan rápido que no cambie el ms, así nos aseguramos con total rotundidad que la modificación posterior de código fuente su timestamp es MAYOR que el de compilación último - try { Thread.sleep(1); } catch (InterruptedException ex) { throw new RelProxyException(ex); } + try { + Thread.sleep(1); + } catch (InterruptedException ex) { + throw new RelProxyException(ex); + } } } - - try - { - classDescSourceScript.callMainMethod(new LinkedList()); - } - catch(Throwable ex) - { + + try { + classDescSourceScript.callMainMethod(new LinkedList()); + } catch (Throwable ex) { ex.printStackTrace(System.out); } - } + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/Keyboard.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/Keyboard.java index b1cb22a..056f6fc 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/Keyboard.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/Keyboard.java @@ -3,23 +3,19 @@ import java.nio.charset.Charset; /** - * * @author jmarranz */ -public abstract class Keyboard -{ +public abstract class Keyboard { public abstract void type(CharSequence characters); - - public static Keyboard create(Charset cs) - { + + public static Keyboard create(Charset cs) { return KeyboardUsingClipboard.create(cs); //return KeyboardNotUsingClipboard.create(cs); - } - - public static void test(String arg) - { - Charset charset = Charset.defaultCharset(); - Keyboard kbd = create(charset); - kbd.type(arg); - } + } + + public static void test(String arg) { + Charset charset = Charset.defaultCharset(); + Keyboard kbd = create(charset); + kbd.type(arg); + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java index 1214e86..4f324a8 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java @@ -6,6 +6,7 @@ import java.awt.AWTException; import java.awt.Robot; + import static java.awt.event.KeyEvent.VK_0; import static java.awt.event.KeyEvent.VK_1; import static java.awt.event.KeyEvent.VK_2; @@ -54,6 +55,7 @@ import static java.awt.event.KeyEvent.VK_X; import static java.awt.event.KeyEvent.VK_Y; import static java.awt.event.KeyEvent.VK_Z; + import java.nio.ByteBuffer; import java.nio.charset.Charset; @@ -61,100 +63,107 @@ * http://stackoverflow.com/questions/1248510/convert-string-to-keyevents * http://en.wikipedia.org/wiki/Unicode_input#Hexadecimal_code_input * http://stackoverflow.com/questions/9814701/accent-with-robot-keypress - * + * * @author jmarranz */ -public abstract class KeyboardNotUsingClipboard extends Keyboard -{ +public abstract class KeyboardNotUsingClipboard extends Keyboard { @NotNull protected final Robot robot; protected Charset cs; - - - public KeyboardNotUsingClipboard(Charset cs) - { + + public KeyboardNotUsingClipboard(Charset cs) { this.cs = cs; - try - { + try { this.robot = new Robot(); - } - catch (AWTException ex) - { + } catch (AWTException ex) { throw new RelProxyException(ex); } } - public static KeyboardNotUsingClipboard create(Charset cs) - { + public static KeyboardNotUsingClipboard create(Charset cs) { String osName = System.getProperty("os.name").toLowerCase(); if (osName.contains("windows")) return new WindowUnicodeKeyboard(cs); - else if (osName.contains("os x")) return new MacOSXUnicodeKeyboard(cs);// https://developer.apple.com/library/mac/technotes/tn2002/tn2110.html + else if (osName.contains("os x")) + return new MacOSXUnicodeKeyboard(cs);// https://developer.apple.com/library/mac/technotes/tn2002/tn2110.html else return new LinuxUnicodeKeyboard(cs); - } + } @NotNull - private int[] getUnicodeInt(char character) - { - if (isUseCodePoint()) - { - char[] charArray = new char[]{character}; - int count = Character.codePointCount(charArray, 0,charArray.length); - int[] res = new int[count]; - for(int i = 0; i < count; i++) - res[i] = Character.codePointAt(charArray,i); - return res; - } - else - { + private int[] getUnicodeInt(char character) { + if (isUseCodePoint()) { + char[] charArray = new char[]{character}; + int count = Character.codePointCount(charArray, 0, charArray.length); + int[] res = new int[count]; + for (int i = 0; i < count; i++) + res[i] = Character.codePointAt(charArray, i); + return res; + } else { ByteBuffer buffer = cs.encode("" + character); int size = buffer.limit(); int[] res = new int[size]; - for(int i = 0; i < size; i++) - { - byte b = buffer.get(); - int bi = b & 0x000000FF; - res[i] = bi; + for (int i = 0; i < size; i++) { + byte b = buffer.get(); + int bi = b & 0x000000FF; + res[i] = bi; } return res; } } - + @NotNull - protected String getUnicodeDigits(char character, int radix) - { + protected String getUnicodeDigits(char character, int radix) { int[] uds = getUnicodeInt(character); StringBuilder res = new StringBuilder(); - for(int i = 0; i < uds.length; i++) - { - int ud = uds[i]; - String digits; - if (radix == 10) - digits = Integer.toString(ud); - else - digits = Integer.toString(ud,radix); // Si es 16 es hexadecimal - res.append(digits); + for (int i = 0; i < uds.length; i++) { + int ud = uds[i]; + String digits; + if (radix == 10) + digits = Integer.toString(ud); + else + digits = Integer.toString(ud, radix); // Si es 16 es hexadecimal + res.append(digits); } return res.toString(); - } + } protected void typeNumPad(int digit) { switch (digit) { - case 0: doType(VK_NUMPAD0); break; - case 1: doType(VK_NUMPAD1); break; - case 2: doType(VK_NUMPAD2); break; - case 3: doType(VK_NUMPAD3); break; - case 4: doType(VK_NUMPAD4); break; - case 5: doType(VK_NUMPAD5); break; - case 6: doType(VK_NUMPAD6); break; - case 7: doType(VK_NUMPAD7); break; - case 8: doType(VK_NUMPAD8); break; - case 9: doType(VK_NUMPAD9); break; - default: // Para que se calle el FindBugs + case 0: + doType(VK_NUMPAD0); + break; + case 1: + doType(VK_NUMPAD1); + break; + case 2: + doType(VK_NUMPAD2); + break; + case 3: + doType(VK_NUMPAD3); + break; + case 4: + doType(VK_NUMPAD4); + break; + case 5: + doType(VK_NUMPAD5); + break; + case 6: + doType(VK_NUMPAD6); + break; + case 7: + doType(VK_NUMPAD7); + break; + case 8: + doType(VK_NUMPAD8); + break; + case 9: + doType(VK_NUMPAD9); + break; + default: // Para que se calle el FindBugs } - } - - + } + + public void type(@NotNull CharSequence characters) { int length = characters.length(); for (int i = 0; i < length; i++) { @@ -164,75 +173,199 @@ public void type(@NotNull CharSequence characters) { } public boolean type(char character) { - + // He quitado todos los símbolos que son susceptibles de cambiar según el teclado pues hay que acertar exactamente la combinación de teclas del teclado // concreto o da error, ej no vale emitir VK_COLON únicamente si en el teclado concreto es necesario un SHIFT // En la clase derivada se procesan los caracteres no contemplados aquí - + switch (character) { - case 'a': doType(VK_A); break; - case 'b': doType(VK_B); break; - case 'c': doType(VK_C); break; - case 'd': doType(VK_D); break; - case 'e': doType(VK_E); break; - case 'f': doType(VK_F); break; - case 'g': doType(VK_G); break; - case 'h': doType(VK_H); break; - case 'i': doType(VK_I); break; - case 'j': doType(VK_J); break; - case 'k': doType(VK_K); break; - case 'l': doType(VK_L); break; - case 'm': doType(VK_M); break; - case 'n': doType(VK_N); break; - case 'o': doType(VK_O); break; - case 'p': doType(VK_P); break; - case 'q': doType(VK_Q); break; - case 'r': doType(VK_R); break; - case 's': doType(VK_S); break; - case 't': doType(VK_T); break; - case 'u': doType(VK_U); break; - case 'v': doType(VK_V); break; - case 'w': doType(VK_W); break; - case 'x': doType(VK_X); break; - case 'y': doType(VK_Y); break; - case 'z': doType(VK_Z); break; - case 'A': doType(VK_SHIFT, VK_A); break; - case 'B': doType(VK_SHIFT, VK_B); break; - case 'C': doType(VK_SHIFT, VK_C); break; - case 'D': doType(VK_SHIFT, VK_D); break; - case 'E': doType(VK_SHIFT, VK_E); break; - case 'F': doType(VK_SHIFT, VK_F); break; - case 'G': doType(VK_SHIFT, VK_G); break; - case 'H': doType(VK_SHIFT, VK_H); break; - case 'I': doType(VK_SHIFT, VK_I); break; - case 'J': doType(VK_SHIFT, VK_J); break; - case 'K': doType(VK_SHIFT, VK_K); break; - case 'L': doType(VK_SHIFT, VK_L); break; - case 'M': doType(VK_SHIFT, VK_M); break; - case 'N': doType(VK_SHIFT, VK_N); break; - case 'O': doType(VK_SHIFT, VK_O); break; - case 'P': doType(VK_SHIFT, VK_P); break; - case 'Q': doType(VK_SHIFT, VK_Q); break; - case 'R': doType(VK_SHIFT, VK_R); break; - case 'S': doType(VK_SHIFT, VK_S); break; - case 'T': doType(VK_SHIFT, VK_T); break; - case 'U': doType(VK_SHIFT, VK_U); break; - case 'V': doType(VK_SHIFT, VK_V); break; - case 'W': doType(VK_SHIFT, VK_W); break; - case 'X': doType(VK_SHIFT, VK_X); break; - case 'Y': doType(VK_SHIFT, VK_Y); break; - case 'Z': doType(VK_SHIFT, VK_Z); break; - // case '`': doType(VK_BACK_QUOTE); break; - case '0': doType(VK_0); break; - case '1': doType(VK_1); break; - case '2': doType(VK_2); break; - case '3': doType(VK_3); break; - case '4': doType(VK_4); break; - case '5': doType(VK_5); break; - case '6': doType(VK_6); break; - case '7': doType(VK_7); break; - case '8': doType(VK_8); break; - case '9': doType(VK_9); break; + case 'a': + doType(VK_A); + break; + case 'b': + doType(VK_B); + break; + case 'c': + doType(VK_C); + break; + case 'd': + doType(VK_D); + break; + case 'e': + doType(VK_E); + break; + case 'f': + doType(VK_F); + break; + case 'g': + doType(VK_G); + break; + case 'h': + doType(VK_H); + break; + case 'i': + doType(VK_I); + break; + case 'j': + doType(VK_J); + break; + case 'k': + doType(VK_K); + break; + case 'l': + doType(VK_L); + break; + case 'm': + doType(VK_M); + break; + case 'n': + doType(VK_N); + break; + case 'o': + doType(VK_O); + break; + case 'p': + doType(VK_P); + break; + case 'q': + doType(VK_Q); + break; + case 'r': + doType(VK_R); + break; + case 's': + doType(VK_S); + break; + case 't': + doType(VK_T); + break; + case 'u': + doType(VK_U); + break; + case 'v': + doType(VK_V); + break; + case 'w': + doType(VK_W); + break; + case 'x': + doType(VK_X); + break; + case 'y': + doType(VK_Y); + break; + case 'z': + doType(VK_Z); + break; + case 'A': + doType(VK_SHIFT, VK_A); + break; + case 'B': + doType(VK_SHIFT, VK_B); + break; + case 'C': + doType(VK_SHIFT, VK_C); + break; + case 'D': + doType(VK_SHIFT, VK_D); + break; + case 'E': + doType(VK_SHIFT, VK_E); + break; + case 'F': + doType(VK_SHIFT, VK_F); + break; + case 'G': + doType(VK_SHIFT, VK_G); + break; + case 'H': + doType(VK_SHIFT, VK_H); + break; + case 'I': + doType(VK_SHIFT, VK_I); + break; + case 'J': + doType(VK_SHIFT, VK_J); + break; + case 'K': + doType(VK_SHIFT, VK_K); + break; + case 'L': + doType(VK_SHIFT, VK_L); + break; + case 'M': + doType(VK_SHIFT, VK_M); + break; + case 'N': + doType(VK_SHIFT, VK_N); + break; + case 'O': + doType(VK_SHIFT, VK_O); + break; + case 'P': + doType(VK_SHIFT, VK_P); + break; + case 'Q': + doType(VK_SHIFT, VK_Q); + break; + case 'R': + doType(VK_SHIFT, VK_R); + break; + case 'S': + doType(VK_SHIFT, VK_S); + break; + case 'T': + doType(VK_SHIFT, VK_T); + break; + case 'U': + doType(VK_SHIFT, VK_U); + break; + case 'V': + doType(VK_SHIFT, VK_V); + break; + case 'W': + doType(VK_SHIFT, VK_W); + break; + case 'X': + doType(VK_SHIFT, VK_X); + break; + case 'Y': + doType(VK_SHIFT, VK_Y); + break; + case 'Z': + doType(VK_SHIFT, VK_Z); + break; + // case '`': doType(VK_BACK_QUOTE); break; + case '0': + doType(VK_0); + break; + case '1': + doType(VK_1); + break; + case '2': + doType(VK_2); + break; + case '3': + doType(VK_3); + break; + case '4': + doType(VK_4); + break; + case '5': + doType(VK_5); + break; + case '6': + doType(VK_6); + break; + case '7': + doType(VK_7); + break; + case '8': + doType(VK_8); + break; + case '9': + doType(VK_9); + break; /* case '-': doType(VK_MINUS); break; case '=': doType(VK_EQUALS); break; @@ -268,11 +401,13 @@ public boolean type(char character) { case '/': doType(VK_SLASH); break; case '?': doType(VK_SHIFT, VK_SLASH); break; */ - case ' ': doType(VK_SPACE); break; - default: - return false; + case ' ': + doType(VK_SPACE); + break; + default: + return false; } - + return true; } @@ -282,26 +417,23 @@ protected void doType(@NotNull int... keyCodes) { private void doTypeArr(@NotNull int[] keyCodes) { int length = keyCodes.length; - if (length == 1) - { - doType(keyCodes[0]); - } - else // 2 + if (length == 1) { + doType(keyCodes[0]); + } else // 2 { robot.keyPress(keyCodes[0]); robot.keyPress(keyCodes[1]); - - robot.keyRelease(keyCodes[1]); + + robot.keyRelease(keyCodes[1]); robot.keyRelease(keyCodes[0]); } } - - protected void doType(int keyCode) - { + + protected void doType(int keyCode) { robot.keyPress(keyCode); - robot.keyRelease(keyCode); - } - + robot.keyRelease(keyCode); + } + public abstract boolean isUseCodePoint(); - + } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java index 3999e14..5649500 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java @@ -18,40 +18,33 @@ * http://stackoverflow.com/questions/1248510/convert-string-to-keyevents * http://en.wikipedia.org/wiki/Unicode_input#Hexadecimal_code_input * http://stackoverflow.com/questions/9814701/accent-with-robot-keypress - * + * * @author jmarranz */ -public class KeyboardUsingClipboard extends Keyboard implements ClipboardOwner -{ +public class KeyboardUsingClipboard extends Keyboard implements ClipboardOwner { @NotNull protected final Robot robot; protected Charset cs; - - - public KeyboardUsingClipboard(Charset cs) - { + + + public KeyboardUsingClipboard(Charset cs) { this.cs = cs; - try - { + try { this.robot = new Robot(); - } - catch (AWTException ex) - { + } catch (AWTException ex) { throw new RelProxyException(ex); } } - public static KeyboardUsingClipboard create(Charset cs) - { + public static KeyboardUsingClipboard create(Charset cs) { return new KeyboardUsingClipboard(cs); - } + } + - @Override - public void type(@NotNull CharSequence characters) - { + public void type(@NotNull CharSequence characters) { Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); - StringSelection stringSelection = new StringSelection( characters.toString() ); + StringSelection stringSelection = new StringSelection(characters.toString()); clipboard.setContents(stringSelection, this); robot.keyPress(KeyEvent.VK_CONTROL); @@ -61,8 +54,7 @@ public void type(@NotNull CharSequence characters) } @Override - public void lostOwnership(Clipboard clipboard, Transferable contents) - { + public void lostOwnership(Clipboard clipboard, Transferable contents) { } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/LinuxUnicodeKeyboard.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/LinuxUnicodeKeyboard.java index b11f86b..2098142 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/LinuxUnicodeKeyboard.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/LinuxUnicodeKeyboard.java @@ -3,59 +3,51 @@ import static java.awt.event.KeyEvent.VK_CONTROL; import static java.awt.event.KeyEvent.VK_SHIFT; import static java.awt.event.KeyEvent.VK_U; + import java.nio.charset.Charset; /** - * * http://superuser.com/questions/59418/how-to-type-special-characters-in-linux - * + * * @author jmarranz */ -public class LinuxUnicodeKeyboard extends KeyboardNotUsingClipboard -{ - public LinuxUnicodeKeyboard(Charset cs) - { +public class LinuxUnicodeKeyboard extends KeyboardNotUsingClipboard { + public LinuxUnicodeKeyboard(Charset cs) { super(cs); } - + @Override - public boolean isUseCodePoint() - { + public boolean isUseCodePoint() { return true; } - + @Override - public boolean type(char character) - { + public boolean type(char character) { if (super.type(character)) return true; - String unicodeDigits = getUnicodeDigits(character,16); // En hexadecimal + String unicodeDigits = getUnicodeDigits(character, 16); // En hexadecimal - robot.keyPress(VK_CONTROL); + robot.keyPress(VK_CONTROL); robot.keyPress(VK_SHIFT); - + doType(VK_U); // 'u' indica que después viene un valor unicode hexadecimal - + // Pero dejamos pulsadas CTRL y SHIFT mientras // Ejemplo: 266A es una nota de solfeo - try - { - for (int i = 0; i < unicodeDigits.length(); i++) - { + try { + for (int i = 0; i < unicodeDigits.length(); i++) { char c = unicodeDigits.charAt(i); if (Character.isDigit(c)) typeNumPad(Integer.parseInt(unicodeDigits.substring(i, i + 1))); else - type(c); + type(c); } + } finally { + robot.keyRelease(VK_CONTROL); + robot.keyRelease(VK_SHIFT); } - finally - { - robot.keyRelease(VK_CONTROL); - robot.keyRelease(VK_SHIFT); - } - + return true; } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/MacOSXUnicodeKeyboard.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/MacOSXUnicodeKeyboard.java index 7a1caf5..a396418 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/MacOSXUnicodeKeyboard.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/MacOSXUnicodeKeyboard.java @@ -1,50 +1,43 @@ package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; import static java.awt.Event.ALT_MASK; + import java.nio.charset.Charset; /** - * * https://discussions.apple.com/thread/1899290 * http://superuser.com/questions/13086/how-do-you-type-unicode-characters-using-hexadecimal-codes (buscar OS X) * http://controlyourmac.com/2012/05/understanding-mac-keyboard.html - * + * * @author jmarranz */ -public class MacOSXUnicodeKeyboard extends KeyboardNotUsingClipboard -{ - public MacOSXUnicodeKeyboard(Charset cs) - { +public class MacOSXUnicodeKeyboard extends KeyboardNotUsingClipboard { + public MacOSXUnicodeKeyboard(Charset cs) { super(cs); } - + @Override - public boolean isUseCodePoint() - { + public boolean isUseCodePoint() { return true; - } - + } + @Override - public boolean type(char character) - { + public boolean type(char character) { if (super.type(character)) return true; - String unicodeDigits = getUnicodeDigits(character,16); // En hexadecimal + String unicodeDigits = getUnicodeDigits(character, 16); // En hexadecimal robot.keyPress(ALT_MASK); // "Since the ALT_MASK modifier is the Option key in OS X" https://developer.apple.com/library/mac/documentation/java/conceptual/java14development/07-NativePlatformIntegration/NativePlatformIntegration.html - - try - { + + try { for (int i = 0; i < unicodeDigits.length(); i++) { - type(unicodeDigits.charAt(i)); + type(unicodeDigits.charAt(i)); } + } finally { + robot.keyRelease(ALT_MASK); } - finally - { - robot.keyRelease(ALT_MASK); - } - + return true; } diff --git a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/WindowUnicodeKeyboard.java b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/WindowUnicodeKeyboard.java index 35d4a47..52fc292 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/WindowUnicodeKeyboard.java +++ b/src/main/java/com/sillelien/dollar/relproxy/impl/jproxy/shell/inter/WindowUnicodeKeyboard.java @@ -1,49 +1,43 @@ package com.sillelien.dollar.relproxy.impl.jproxy.shell.inter; import static java.awt.event.KeyEvent.VK_ALT; + import java.nio.charset.Charset; /** * http://stackoverflow.com/questions/1248510/convert-string-to-keyevents - * + * * @author jmarranz */ -public class WindowUnicodeKeyboard extends KeyboardNotUsingClipboard -{ - public WindowUnicodeKeyboard(Charset cs) - { +public class WindowUnicodeKeyboard extends KeyboardNotUsingClipboard { + public WindowUnicodeKeyboard(Charset cs) { super(cs); } - + @Override - public boolean isUseCodePoint() - { + public boolean isUseCodePoint() { return false; - } - + } + @Override - public boolean type(char character) - { + public boolean type(char character) { if (super.type(character)) return true; // En Windows usar mintty porque usando la consola de MSYS por sí misma, que es realmente la de Windows, hay problemas con el set de caracteres, pues sería Cp1252 para Java pero Cp850 para la consola y salen mal por tanto los caracteres no ASCII - - - String unicodeDigits = getUnicodeDigits(character,10); // En DECIMAL - + + + String unicodeDigits = getUnicodeDigits(character, 10); // En DECIMAL + robot.keyPress(VK_ALT); - try - { + try { for (int i = 0; i < unicodeDigits.length(); i++) { typeNumPad(Integer.parseInt(unicodeDigits.substring(i, i + 1))); } + } finally { + robot.keyRelease(VK_ALT); } - finally - { - robot.keyRelease(VK_ALT); - } - + return true; } diff --git a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxy.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxy.java index 47c9838..1871adf 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxy.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxy.java @@ -8,115 +8,105 @@ /** * Is the class to create Java proxy objects based on Java objects and keep track of source code changes reloading classes when detected. - * + * * @author Jose Maria Arranz Santamaria */ -public class JProxy -{ +public class JProxy { /** * Creates a {@link JProxyConfig} object to be used to configure JProxy and {@link JProxyScriptEngineFactory}. - * + * * @return a new configuration object. * @see #init(JProxyConfig) */ - public static JProxyConfig createJProxyConfig() - { + public static JProxyConfig createJProxyConfig() { return JProxyDefaultImpl.createJProxyConfig(); - } - + } + /** * Initializes JProxy with the provided configuration object. - * - * @param config the configuration - */ - public static void init(JProxyConfig config) - { - JProxyDefaultImpl.initStatic((JProxyConfigImpl)config); + * + * @param config the configuration + */ + public static void init(JProxyConfig config) { + JProxyDefaultImpl.initStatic((JProxyConfigImpl) config); } - - - + + /** * Creates a proxy object using java.lang.reflect.Proxy based on the provided Java object and the class of the implemented Java interface. - * - *

This method is a simplification for a single interface (the most common case) of {@link #create(Object,Class[])} .

- * - * @param the interface implemented by the original object and proxy object returned. - * @param obj the original object to proxy. + *

+ *

This method is a simplification for a single interface (the most common case) of {@link #create(Object, Class[])} .

+ * + * @param the interface implemented by the original object and proxy object returned. + * @param obj the original object to proxy. * @param clasz the class of the interface implemented by the original object and proxy object returned. * @return the java.lang.reflect.Proxy object associated or the original object when GProxy is disabled. - */ + */ @Nullable - public static T create(T obj, Class clasz) - { + public static T create(T obj, Class clasz) { return JProxyDefaultImpl.createStatic(obj, clasz); } - + /** * Creates a proxy object using java.lang.reflect.Proxy based on the provided Java object and the classes of the implemented Java interfaces. - * - *

If JProxy has been configured and is enabled this method returns a java.lang.reflect.Proxy object implementing instead of + *

+ *

If JProxy has been configured and is enabled this method returns a java.lang.reflect.Proxy object implementing instead of * the original object provided. Methods called in proxy object are received by JProxy and forwarded to the original object, if source code * managed by JProxy has been changed, the class of the original object is reloaded based on the new source and the original object * is recreated with the new class and fields are re-set in the new object, then the method is called on the new original object.

- * + *

*

If JProxy is disabled returns the original object provided with no performance penalty.

- * - * @param obj the original object to proxy. + * + * @param obj the original object to proxy. * @param classes the classes of the interfaces implemented by the original object and proxy object returned. * @return the java.lang.reflect.Proxy object associated or the original object when JProxy is disabled. - */ + */ @Nullable - public static Object create(Object obj, @NotNull Class[] classes) - { + public static Object create(Object obj, @NotNull Class[] classes) { return JProxyDefaultImpl.createStatic(obj, classes); - } - + } + /** * Informs whether JProxy is configured and enabled. - * - * @return true if enabled. - */ - public static boolean isEnabled() - { + * + * @return true if enabled. + */ + public static boolean isEnabled() { return JProxyDefaultImpl.isEnabledStatic(); - } - + } + /** * Informs whether JProxy is enabled and started (timed checking for changes). - * - * @return true if running. - */ - public static boolean isRunning() - { + * + * @return true if running. + */ + public static boolean isRunning() { return JProxyDefaultImpl.isRunningStatic(); - } - + } + /** * Stops source code periodic change detection. - * + *

*

Periodicity of change detection is defined by {@link JProxyConfig#setScanPeriod(long)}

- * + * * @return true if source change detection has been stopped, false if it is already stopped or JProxy is not enabled or initialized. * @see #stop() */ - public static boolean stop() - { + public static boolean stop() { return JProxyDefaultImpl.stopStatic(); } - + /** * Starts source code periodic change detection. - * + *

*

Periodicity of change detection is defined by {@link JProxyConfig#setScanPeriod(long)}.

- * + *

*

By default when JProxy is initialized and enabled.

- * + * * @return true if source change detection has been started again, false if it is already started or cannot start because JProxy is not enabled or initialized or scan period is not positive. * @see #start() */ - public static boolean start() - { + public static boolean start() { return JProxyDefaultImpl.startStatic(); - } + } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyCompilerListener.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyCompilerListener.java index 218f16e..d46d7fb 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyCompilerListener.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyCompilerListener.java @@ -4,12 +4,12 @@ /** * Is the interface to monitor the files being compiled. - * - * @see JProxyConfig#setJProxyCompilerListener(JProxyCompilerListener) + * * @author Jose Maria Arranz Santamaria + * @see JProxyConfig#setJProxyCompilerListener(JProxyCompilerListener) */ -public interface JProxyCompilerListener -{ +public interface JProxyCompilerListener { public void beforeCompile(File file); - public void afterCompile(File file); + + public void afterCompile(File file); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyConfig.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyConfig.java index 81e53ea..5e0b0f0 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyConfig.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyConfig.java @@ -6,19 +6,18 @@ /** * Interface implemented by the configuration object needed to initialize JProxy and {@link JProxyScriptEngineFactory}. - * - * @see JProxy#init(JProxyConfig) - * @see JProxyScriptEngine#init(JProxyConfig) + * * @author Jose Maria Arranz Santamaria + * @see JProxy#init(JProxyConfig) + * @see JProxyScriptEngine#init(JProxyConfig) */ -public interface JProxyConfig -{ +public interface JProxyConfig { /** * Sets whether automatic detection of source code changes is enabled. - * + *

*

If set to false other configuration parameters are ignored, there is no automatic source code change detection/reload and original objects are returned * instead of proxies, performance penalty is zero. Setting to false is recommended in production whether source code change detection/reload is not required.

- * + * * @param enabled whether automatic source code change detection and reload is enabled. By default is true. * @return this object for flow API use. */ @@ -27,86 +26,86 @@ public interface JProxyConfig /** * Sets the class reload listener. - * + * * @param relListener the class reload listener. By default is null. * @return this object for flow API use. - */ + */ @NotNull public JProxyConfig setRelProxyOnReloadListener(RelProxyOnReloadListener relListener); /** * Defines the folder root to locate source code Java files. - * + *

*

Structure of the source tree must be the same as a JavaSE application, the only difference is shell scripts, shell scripts must be - * located on the top level of the source tree (default package) and file extension is not required .

- * + * located on the top level of the source tree (default package) and file extension is not required .

+ *

*

Setting some input path is required.

- * + * * @param inputPath the folder root to locate source code Java files. * @return this object for flow API use. - * @see #setInputPaths(java.lang.String[]) + * @see #setInputPaths(java.lang.String[]) */ @NotNull public JProxyConfig setInputPath(String inputPath); - + /** * Defines the folder roots to locate source code Java files. - * + *

*

Structure of the source tree must be the same as a JavaSE application, the only difference is shell scripts, shell scripts must be - * located on the top level of the source tree (default package).

- * + * located on the top level of the source tree (default package).

+ *

*

Setting some input path is required.

- * + * * @param inputPaths the folder roots to locate source code Java files. * @return this object for flow API use. - * @see #setJProxyInputSourceFileExcludedListener(JProxyInputSourceFileExcludedListener) + * @see #setJProxyInputSourceFileExcludedListener(JProxyInputSourceFileExcludedListener) * @see #setRequiredExtraJarPaths(String[]) */ @NotNull public JProxyConfig setInputPaths(String[] inputPaths); - + /** * Defines the extra required jars providing the absolute paths to them. - * + *

*

In some circunstances RelProxy is not able to find some required classes by the compiler because the jar containing them is not found in spite of existing in classpath, * the reason may be due some conflictive configuration of META-INF/MANIFEST.MF of the jar. This problem can be fixed modifying accordingly the META-INF/MANIFEST.MF * file, or alternatively providing the paths to the conflictive jars calling to this method, in this case RelProxy will find the required classes searching on them by using brute force * avoiding the jar modification (not recommended). *

- * + * * @param inputJarPaths the paths of the required extra jars. * @return this object for flow API use. - * @see #setInputPaths(String[]) + * @see #setInputPaths(String[]) */ @NotNull public JProxyConfig setRequiredExtraJarPaths(String[] inputJarPaths); - + /** * Registers the listener implementing excluding rules to filter source files not to be part of the hot reloading system in spite of included in input paths. - * + * * @param listener the listener. By default is null. * @return this object for flow API use. - */ + */ @NotNull public JProxyConfig setJProxyInputSourceFileExcludedListener(JProxyInputSourceFileExcludedListener listener); - + /** * Registers the listener for monitoring files being compiled. - * + * * @param listener the listener. By default is null. * @return this object for flow API use. - */ + */ @NotNull - public JProxyConfig setJProxyCompilerListener(JProxyCompilerListener listener); - - + public JProxyConfig setJProxyCompilerListener(JProxyCompilerListener listener); + + /** * Sets the folder where to save .class files result of recompiling source code changed. - * + *

*

This setting is optional and the folder must be included in Java classpath because the objective is to avoid recompiling.

- * + *

*

Be careful when executing several Java scripts in the same time and source code has been changed, some file write collisions may happen.

- * + * * @param classFolder the folder where to save .class files. By default is null (not defined, .class files are not saved). * @return this object for flow API use. */ @@ -115,22 +114,22 @@ public interface JProxyConfig /** * Sets the delay between source code change checking. - * + *

*

If this value is set to 0 or negative, no periodic source code change detection is executed and only compilation on the fly happens in load time, * this is valid for one shot scripts but it has no sense when using proxies. - * + * * @param scanPeriod the delay between source code change checking. * @return this object for flow API use. */ @NotNull public JProxyConfig setScanPeriod(long scanPeriod); - + /** * Sets the compilation options to be provided to the compiler built-in in JDK like JavaCompiler.getTask() method and the same you would provide to javac. - * + *

*

Example of compilation options:

*

Iterable<String> compilationOptions = Arrays.asList(new String[]{"-source","1.6","-target","1.6"});

- * + * * @param compilationOptions compilation options passed to the internal compiler. By default is null (default compiler settings). * @return this object for flow API use. */ @@ -138,36 +137,36 @@ public interface JProxyConfig public JProxyConfig setCompilationOptions(Iterable compilationOptions); /** - * Sets the diagnostic listener to capture compilation errors and warnings thrown by the internal compiler. - * + * Sets the diagnostic listener to capture compilation errors and warnings thrown by the internal compiler. + *

*

The following is an example similar to the default behavior when this listener is not specified:

- * -
-        JProxyDiagnosticsListener diagnosticsListener = new JProxyDiagnosticsListener()
-        {
-            {@code @}Override
-            public void onDiagnostics(DiagnosticCollector<JavaFileObject> diagnostics)
-            {
-                List<Diagnostic<? extends JavaFileObject>> diagList = diagnostics.getDiagnostics();
-                int i = 1;
-                for (Diagnostic diagnostic : diagList)
-                {
-                   System.err.println("Diagnostic " + i);
-                   System.err.println("  code: " + diagnostic.getCode());
-                   System.err.println("  kind: " + diagnostic.getKind());
-                   System.err.println("  line number: " + diagnostic.getLineNumber());                   
-                   System.err.println("  column number: " + diagnostic.getColumnNumber());
-                   System.err.println("  start position: " + diagnostic.getStartPosition());
-                   System.err.println("  position: " + diagnostic.getPosition());                   
-                   System.err.println("  end position: " + diagnostic.getEndPosition());
-                   System.err.println("  source: " + diagnostic.getSource());
-                   System.err.println("  message: " + diagnostic.getMessage(null));
-                   i++;
-                }
-            }
-        };   
-     
- * + *

+ *

+     * JProxyDiagnosticsListener diagnosticsListener = new JProxyDiagnosticsListener()
+     * {
+     * {@code @}Override
+     * public void onDiagnostics(DiagnosticCollector<JavaFileObject> diagnostics)
+     * {
+     * List<Diagnostic<? extends JavaFileObject>> diagList = diagnostics.getDiagnostics();
+     * int i = 1;
+     * for (Diagnostic diagnostic : diagList)
+     * {
+     * System.err.println("Diagnostic " + i);
+     * System.err.println("  code: " + diagnostic.getCode());
+     * System.err.println("  kind: " + diagnostic.getKind());
+     * System.err.println("  line number: " + diagnostic.getLineNumber());
+     * System.err.println("  column number: " + diagnostic.getColumnNumber());
+     * System.err.println("  start position: " + diagnostic.getStartPosition());
+     * System.err.println("  position: " + diagnostic.getPosition());
+     * System.err.println("  end position: " + diagnostic.getEndPosition());
+     * System.err.println("  source: " + diagnostic.getSource());
+     * System.err.println("  message: " + diagnostic.getMessage(null));
+     * i++;
+     * }
+     * }
+     * };
+     * 
+ * * @param diagnosticsListener the diagnostic listener to capture compilation errors and warnings. By default is null, an internal listener is used logging to System.err. * @return this object for flow API use. */ diff --git a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyDiagnosticsListener.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyDiagnosticsListener.java index 6de8b26..ec01b55 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyDiagnosticsListener.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyDiagnosticsListener.java @@ -5,15 +5,14 @@ /** * Is the interface to implement diagnostic listeners to capture compilation errors and warnings. - * - * @see JProxyConfig#setJProxyDiagnosticsListener(JProxyDiagnosticsListener) + * * @author Jose Maria Arranz Santamaria + * @see JProxyConfig#setJProxyDiagnosticsListener(JProxyDiagnosticsListener) */ -public interface JProxyDiagnosticsListener -{ +public interface JProxyDiagnosticsListener { /** * This method is called when compilation Java code has generated diagnostics. - * + * * @param diagnostics the list of diagnostics. */ public void onDiagnostics(DiagnosticCollector diagnostics); diff --git a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java index def541e..ae16eb9 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyInputSourceFileExcludedListener.java @@ -4,18 +4,17 @@ /** * This interface is provided to developers to implement excluding rules to filter source files not to be part of the hot reloading system in spite of included in input paths - * - * @see JProxyConfig#setJProxyInputSourceFileExcludedListener(JProxyInputSourceFileExcludedListener) + * * @author Jose Maria Arranz Santamaria + * @see JProxyConfig#setJProxyInputSourceFileExcludedListener(JProxyInputSourceFileExcludedListener) */ -public interface JProxyInputSourceFileExcludedListener -{ +public interface JProxyInputSourceFileExcludedListener { /** * This method is called per file when going to be managed by the hot reloading system. - * - * @param file the file to be managed. + * + * @param file the file to be managed. * @param rootFolderOfSources the folder root of sources where this file is located. * @return true whether the file must be ignored. */ - public boolean isExcluded(File file,File rootFolderOfSources); + public boolean isExcluded(File file, File rootFolderOfSources); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyScriptEngine.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyScriptEngine.java index ddc12c1..caa0756 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyScriptEngine.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyScriptEngine.java @@ -6,25 +6,24 @@ /** * Interface implemented by RelProxy to provide javax.script.ScriptEngine objects supporting Java as a scripting language. - * + *

*

The method {@link JProxyScriptEngineFactory#getScriptEngine()} returns an implementation of this interface.

- * + * * @author Jose Maria Arranz Santamaria */ -public interface JProxyScriptEngine extends ScriptEngine -{ +public interface JProxyScriptEngine extends ScriptEngine { /** * Initializes this JProxyScriptEngine instance with the provided configuration object. - * + * * @param config the configuration object. - */ + */ public void init(JProxyConfig config); - + /** * This method is the same as {@link JProxy#create(java.lang.Object, java.lang.Class)} but applied to this JProxyScriptEngine - * - * @param the interface implemented by the original object and proxy object returned. - * @param obj the original object to proxy. + * + * @param the interface implemented by the original object and proxy object returned. + * @param obj the original object to proxy. * @param clasz the class of the interface implemented by the original object and proxy object returned. * @return the java.lang.reflect.Proxy object associated or the original object when is disabled. */ @@ -33,41 +32,41 @@ public interface JProxyScriptEngine extends ScriptEngine /** * This method is the same as {@link JProxy#create(java.lang.Object, java.lang.Class[])} but applied to this JProxyScriptEngine - * - * @param obj the original object to proxy. + * + * @param obj the original object to proxy. * @param classes the classes of the interfaces implemented by the original object and proxy object returned. * @return the java.lang.reflect.Proxy object associated or the original object when is disabled. - */ + */ @Nullable public Object create(Object obj, Class[] classes); - + /** * This method is the same as {@link JProxy#isEnabled()} but applied to this JProxyScriptEngine - * - * @return true if enabled. - */ + * + * @return true if enabled. + */ public boolean isEnabled(); - + /** * This method is the same as {@link JProxy#isRunning()} but applied to this JProxyScriptEngine - * - * @return true if running. - */ - public boolean isRunning(); - + * + * @return true if running. + */ + public boolean isRunning(); + /** * This method is the same as {@link JProxy#stop()} but applied to this JProxyScriptEngine - * + * * @return true if source change detection has been stopped, false if it is already stopped or this JProxyScriptEngine is not enabled or initialized. * @see #stop() - */ + */ public boolean stop(); /** * This method is the same as {@link JProxy#start()} but applied to this JProxyScriptEngine - * + * * @return true if source change detection has been started again, false if it is already started or cannot start because this JProxyScriptEngine is not enabled or initialized or scan period is not positive. * @see #start() */ - public boolean start(); + public boolean start(); } diff --git a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyScriptEngineFactory.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyScriptEngineFactory.java index 175b320..ae22b72 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyScriptEngineFactory.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyScriptEngineFactory.java @@ -1,22 +1,21 @@ package com.sillelien.dollar.relproxy.jproxy; import com.sillelien.dollar.relproxy.impl.jproxy.screngine.JProxyScriptEngineFactoryImpl; + import javax.script.ScriptEngineFactory; /** * Is the root class of JSR-223 Java Scripting API support. - * + * * @author Jose Maria Arranz Santamaria */ -public abstract class JProxyScriptEngineFactory implements ScriptEngineFactory -{ +public abstract class JProxyScriptEngineFactory implements ScriptEngineFactory { /** * Factory method to create a JProxyScriptEngineFactory implementing ScriptEngineFactory. - * + * * @return the new factory. */ - public static JProxyScriptEngineFactory create() - { + public static JProxyScriptEngineFactory create() { return JProxyScriptEngineFactoryImpl.create(); } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyShell.java b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyShell.java index 3ea27a2..4cd6c2c 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyShell.java +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/JProxyShell.java @@ -5,20 +5,18 @@ /** * Is the main class to execute shell scripting based on Java. - * + *

*

You are not going to use directly this class, use instead jproxysh command line.

- * + * * @author Jose Maria Arranz Santamaria */ -public class JProxyShell -{ +public class JProxyShell { /** * The main method. - * + * * @param args arguments with the necessary data to initialize and executing the provided script. */ - public static void main(@NotNull String[] args) - { - JProxyShellImpl.main(args); + public static void main(@NotNull String[] args) { + JProxyShellImpl.main(args); } } diff --git a/src/main/java/com/sillelien/dollar/relproxy/jproxy/package.html b/src/main/java/com/sillelien/dollar/relproxy/jproxy/package.html index 3a1f2ab..e8701f4 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/jproxy/package.html +++ b/src/main/java/com/sillelien/dollar/relproxy/jproxy/package.html @@ -1,9 +1,9 @@ - + diff --git a/src/main/java/com/sillelien/dollar/relproxy/package.html b/src/main/java/com/sillelien/dollar/relproxy/package.html index d8f25f0..01103dd 100644 --- a/src/main/java/com/sillelien/dollar/relproxy/package.html +++ b/src/main/java/com/sillelien/dollar/relproxy/package.html @@ -1,9 +1,9 @@ - + From b0e1b8ea7d443eae3c5cb45f7ed7b39ff88fdc9b Mon Sep 17 00:00:00 2001 From: "hello@neilellis.me" Date: Fri, 7 Jul 2017 22:18:09 +0100 Subject: [PATCH 032/135] Release 0.9.30 [30/f99170b177cfcf037a9abefae2d73b588d7f865b] (nicely-truant-mottos) --- .release | 2 +- .release.details | 2 +- README.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release b/.release index 017ccd0..7a4cc25 100644 --- a/.release +++ b/.release @@ -1 +1 @@ -0.9.29 +0.9.30 diff --git a/.release.details b/.release.details index 14de863..6ff21a7 100644 --- a/.release.details +++ b/.release.details @@ -1 +1 @@ -0.9.29 29 963bc5ff5e05bb4e56d0ad0d3a3482a39b0756a6 tangly-caller-wits +0.9.30 30 f99170b177cfcf037a9abefae2d73b588d7f865b nicely-truant-mottos diff --git a/README.md b/README.md index f1cf4ca..d946ecc 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ RelProxy is a simple Java and Groovy hot class reloader for Java and Groovy prov com.sillelien dollar-relproxy -0.9.29 +0.9.30 jar ``` From 881c060f3893dbaeb390620c76d0fc4c91513df0 Mon Sep 17 00:00:00 2001 From: neilellis Date: Fri, 7 Jul 2017 22:19:40 +0100 Subject: [PATCH 033/135] Renaming --- pom.xml | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/pom.xml b/pom.xml index aaf4c19..8b01e35 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.sillelien - dollar-relproxy + java-as-script 0 relproxy @@ -14,7 +14,7 @@ original project is https://github.com/jmarranz/relproxy - https://github.com/dollar-org/relproxy + https://github.com/dollar-org/dollar-java-as-script The Apache License, Version 2.0 @@ -55,9 +55,9 @@ - scm:git:git@github.com:dollar-org/relproxy.git - scm:git:git@github.com:dollar-org/relproxy.git - git@github.com:dollar-org/relproxy.git + scm:git:git@github.com:dollar-org/dollar-java-as-script.git + scm:git:git@github.com:dollar-org/dollar-java-as-script.git + git@github.com:dollar-org/dollar-java-as-script.git @@ -90,16 +90,16 @@ - - - - - - - - - - + + com.versioneye + versioneye-maven-plugin + 3.11.4 + + 0c797be864338a3649f0 + neilellis_orga + Owners + + org.apache.rat From d430e2528896e0d68c60c2bd8c392c69e868bc55 Mon Sep 17 00:00:00 2001 From: neilellis Date: Fri, 7 Jul 2017 22:20:29 +0100 Subject: [PATCH 034/135] Renaming --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 8b01e35..e9cc26f 100644 --- a/pom.xml +++ b/pom.xml @@ -8,13 +8,13 @@ java-as-script 0 - relproxy + Java-as-Script Simple Java and Groovy hot class reloader,and Java based shell and scripting used by Dollar project, original project is https://github.com/jmarranz/relproxy - https://github.com/dollar-org/dollar-java-as-script + https://github.com/dollar-org/java-as-script The Apache License, Version 2.0 From 242a5ea83e524c9aad0462d786212cbd9967db66 Mon Sep 17 00:00:00 2001 From: neilellis Date: Fri, 7 Jul 2017 22:26:29 +0100 Subject: [PATCH 035/135] Renaming --- README.tmpl.md | 6 +++--- circle.yml | 2 +- pom.xml | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.tmpl.md b/README.tmpl.md index 907af65..8804493 100644 --- a/README.tmpl.md +++ b/README.tmpl.md @@ -1,14 +1,14 @@ ${HEADER} -RelProxy ${STATE_ALPHA} -======== +Java-as-Script ${STATE_ALPHA} +============== RelProxy is a simple Java and Groovy hot class reloader for Java and Groovy providing transparent compilation and class reload on the fly, and scripting support and shell of pure Java code. This version is a fork of [the original project](https://github.com/jmarranz/relproxy) (see the Historical Section below). ```xml com.sillelien -dollar-relproxy +java-as-script ${RELEASE} jar diff --git a/circle.yml b/circle.yml index 8cc01e2..5aa509d 100644 --- a/circle.yml +++ b/circle.yml @@ -15,7 +15,7 @@ dependencies: cache_directories: - ~/.gnupg pre: - - cd ~ && git clone https://github.com/dollar-org/build-utils.git && chmod a+x ~/build-utils/*.sh + - cd ~ && git clone https://github.com/sillelien/build-utils.git && chmod a+x ~/build-utils/*.sh - "[[ ${CIRCLE_BRANCH} != 'master' ]] || ( mvn versions:set -DnewVersion=$(cat .release) && mvn versions:resolve-ranges && mvn versions:lock-snapshots )" - mvn install -e -q -Drat.skip -Dsource.skip=true -DgenerateReports=false -Dmaven.javadoc.skip=true -Dmaven.test.skip diff --git a/pom.xml b/pom.xml index e9cc26f..79241ea 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ original project is https://github.com/jmarranz/relproxy - https://github.com/dollar-org/java-as-script + https://github.com/sillelien/java-as-script The Apache License, Version 2.0 @@ -55,9 +55,9 @@ - scm:git:git@github.com:dollar-org/dollar-java-as-script.git - scm:git:git@github.com:dollar-org/dollar-java-as-script.git - git@github.com:dollar-org/dollar-java-as-script.git + scm:git:git@github.com:sillelien/dollar-java-as-script.git + scm:git:git@github.com:sillelien/dollar-java-as-script.git + git@github.com:sillelien/dollar-java-as-script.git From 37c9323b39b9a3dcc2168449570a3180a60732fa Mon Sep 17 00:00:00 2001 From: neilellis Date: Fri, 7 Jul 2017 22:43:22 +0100 Subject: [PATCH 036/135] Renaming --- README.tmpl.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.tmpl.md b/README.tmpl.md index 8804493..32571e8 100644 --- a/README.tmpl.md +++ b/README.tmpl.md @@ -7,10 +7,10 @@ RelProxy is a simple Java and Groovy hot class reloader for Java and Groovy prov ```xml -com.sillelien -java-as-script -${RELEASE} -jar + com.sillelien + java-as-script + ${RELEASE} + jar ``` From 5b858cfa0f5a902973f7259aa221c70a2323f4e0 Mon Sep 17 00:00:00 2001 From: neilellis Date: Fri, 7 Jul 2017 23:10:25 +0100 Subject: [PATCH 037/135] Renaming --- README.tmpl.md | 4 ++++ pom.xml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/README.tmpl.md b/README.tmpl.md index 32571e8..de69d88 100644 --- a/README.tmpl.md +++ b/README.tmpl.md @@ -1,5 +1,6 @@ ${HEADER} + Java-as-Script ${STATE_ALPHA} ============== RelProxy is a simple Java and Groovy hot class reloader for Java and Groovy providing transparent compilation and class reload on the fly, and scripting support and shell of pure Java code. This version is a fork of [the original project](https://github.com/jmarranz/relproxy) (see the Historical Section below). @@ -14,6 +15,9 @@ RelProxy is a simple Java and Groovy hot class reloader for Java and Groovy prov ``` + +Dependencies: [![Dependency Status](https://www.versioneye.com/user/projects/54ae285534ff3e2204000002/badge.svg?style=flat)](https://www.versioneye.com/user/projects/54ae285534ff3e2204000002) + ${BLURB} Overview diff --git a/pom.xml b/pom.xml index 79241ea..73fdabb 100644 --- a/pom.xml +++ b/pom.xml @@ -96,7 +96,7 @@ 3.11.4 0c797be864338a3649f0 - neilellis_orga + sillelien Owners From eef2e0e17c8838a88879078e518390188f443102 Mon Sep 17 00:00:00 2001 From: neilellis Date: Fri, 7 Jul 2017 23:11:11 +0100 Subject: [PATCH 038/135] Renaming --- README.tmpl.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.tmpl.md b/README.tmpl.md index de69d88..2fa8b5f 100644 --- a/README.tmpl.md +++ b/README.tmpl.md @@ -16,7 +16,7 @@ RelProxy is a simple Java and Groovy hot class reloader for Java and Groovy prov ``` -Dependencies: [![Dependency Status](https://www.versioneye.com/user/projects/54ae285534ff3e2204000002/badge.svg?style=flat)](https://www.versioneye.com/user/projects/54ae285534ff3e2204000002) +Dependencies: [![Dependency Status](https://www.versioneye.com/user/projects/5960064c6725bd0049735d0b/badge.svg?style=flat-square)](https://www.versioneye.com/user/projects/5960064c6725bd0049735d0b) ${BLURB} From 3c43df1fc79f303331e9957c3b8069e61d4b49c9 Mon Sep 17 00:00:00 2001 From: "hello@neilellis.me" Date: Fri, 7 Jul 2017 23:22:15 +0100 Subject: [PATCH 039/135] Release 0.9.36 [36/eef2e0e17c8838a88879078e518390188f443102] (richly-scarce-pock) --- .release | 2 +- .release.details | 2 +- README.md | 24 ++++++++++++++---------- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/.release b/.release index 7a4cc25..c13d8c3 100644 --- a/.release +++ b/.release @@ -1 +1 @@ -0.9.30 +0.9.36 diff --git a/.release.details b/.release.details index 6ff21a7..fc77281 100644 --- a/.release.details +++ b/.release.details @@ -1 +1 @@ -0.9.30 30 f99170b177cfcf037a9abefae2d73b588d7f865b nicely-truant-mottos +0.9.36 36 eef2e0e17c8838a88879078e518390188f443102 richly-scarce-pock diff --git a/README.md b/README.md index d946ecc..c6acfa9 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,30 @@ +Build Status: [![Circle CI](https://circleci.com/gh/sillelien/java-as-script.png?style=badge)](https://circleci.com/gh/sillelien/java-as-script) -RelProxy [![Alpha](https://img.shields.io/badge/Status-Alpha-yellowgreen.svg?style=flat)](http://github.com/dollar-org/relproxy) -======== +Java-as-Script [![Alpha](https://img.shields.io/badge/Status-Alpha-yellowgreen.svg?style=flat)](http://github.com/sillelien/java-as-script) +============== RelProxy is a simple Java and Groovy hot class reloader for Java and Groovy providing transparent compilation and class reload on the fly, and scripting support and shell of pure Java code. This version is a fork of [the original project](https://github.com/jmarranz/relproxy) (see the Historical Section below). ```xml -com.sillelien -dollar-relproxy -0.9.30 -jar + com.sillelien + java-as-script + 0.9.36 + jar ``` + +Dependencies: [![Dependency Status](https://www.versioneye.com/user/projects/5960064c6725bd0049735d0b/badge.svg?style=flat-square)](https://www.versioneye.com/user/projects/5960064c6725bd0049735d0b) + ------- -** If you use this project please consider giving us a star on [GitHub](http://github.com/dollar-org/relproxy). ** +** If you use this project please consider giving us a star on [GitHub](http://github.com/sillelien/java-as-script). ** Please contact me through Gitter (chat) or through GitHub Issues. -[![GitHub Issues](https://img.shields.io/github/issues/dollar-org/relproxy.svg)](https://github.com/dollar-org/relproxy/issues) [![Join the chat at https://gitter.im/dollar-org/relproxy](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/dollar-org/relproxy?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![GitHub Issues](https://img.shields.io/github/issues/sillelien/java-as-script.svg)](https://github.com/sillelien/java-as-script/issues) [![Join the chat at https://gitter.im/sillelien/java-as-script](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/sillelien/java-as-script?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) For commercial support please contact me directly. ------- @@ -93,9 +97,9 @@ This is an open source project, which means that we are giving our time to you f # Copyright and License -[![GitHub License](https://img.shields.io/github/license/dollar-org/relproxy.svg)](https://raw.githubusercontent.com/dollar-org/relproxy/master/LICENSE) +[![GitHub License](https://img.shields.io/github/license/sillelien/java-as-script.svg)](https://raw.githubusercontent.com/sillelien/java-as-script/master/LICENSE) -(c) 2015-2017 Neil Ellis all rights reserved. Please see [LICENSE](https://raw.githubusercontent.com/dollar-org/relproxy/master/LICENSE) for license details of this project. Please visit http://neilellis.me for help and raise issues on [GitHub](https://github.com/dollar-org/relproxy/issues). +(c) 2014-2017 Neil Ellis all rights reserved. Please see [LICENSE](https://raw.githubusercontent.com/sillelien/java-as-script/master/LICENSE) for license details of this project. Please visit http://neilellis.me for help and raise issues on [GitHub](https://github.com/sillelien/java-as-script/issues). For commercial support please contact me directly. From e2a72c6e354272aec88c3c0fce5a1e2f28af357f Mon Sep 17 00:00:00 2001 From: neilellis Date: Fri, 7 Jul 2017 23:45:25 +0100 Subject: [PATCH 040/135] Circle 2.0 --- .circleci/circle.yml | 50 +++++++++++++++++++++++++++++++++++++++++++ circle.yml | 51 -------------------------------------------- 2 files changed, 50 insertions(+), 51 deletions(-) create mode 100644 .circleci/circle.yml delete mode 100644 circle.yml diff --git a/.circleci/circle.yml b/.circleci/circle.yml new file mode 100644 index 0000000..dbd06f6 --- /dev/null +++ b/.circleci/circle.yml @@ -0,0 +1,50 @@ +jobs: + build: + docker: + image: circleci/oraclejdk:1.8 + environment: + MAJOR_VERSION: 0.9 + MAVEN_OPTS: "-Xmx1g -DbuildNumber=${CIRCLE_BUILD_NUM} -Dorg.xml.sax.driver='com.sun.org.apache.xerces.internal.parsers.SAXParser' " + TZ: "/usr/share/zoneinfo/Europe/London" + + branches: + ignore: + - gh-pages + + steps: + + - restore_cache: + key: dependency-cache + + - run: + name: dependencies + command: | + cd ~ && git clone https://github.com/sillelien/build-utils.git && chmod a+x ~/build-utils/*.sh + [[ ${CIRCLE_BRANCH} != 'master' ]] || ( mvn versions:set -DnewVersion=$(cat .release) && mvn versions:resolve-ranges && mvn versions:lock-snapshots ) + mvn install -e -q -Drat.skip -Dsource.skip=true -DgenerateReports=false -Dmaven.javadoc.skip=true -Dmaven.test.skip + + - save_cache: + key: dependency-cache + paths: + - ~/.gnupg + - ~/.m2 + - run: + name: test + command: | + mvn -q -T 1C -Drat.skip -Dsource.skip=true -DgenerateReports=false -Dmaven.javadoc.skip=true integration-test + no_output_timeout: 600 + + - deploy: + command: | + if [ "${CIRCLE_BRANCH}" == "staging" ]; then + ~/build-utils/promote_from_staging.sh + fi + if [ "${CIRCLE_BRANCH}" == "master" ]; then + git config --global user.email "hello@neilellis.me" + git config --global user.name "Neil Ellis" + mvn versions:set -DnewVersion=$(cat .release) + mvn versions:resolve-ranges + mvn versions:lock-snapshots + mvn -T 1C -Dmaven.test.skip=true -Drat.skip=true -DskipEnforcer -Dmaven.javadoc.skip=true -DgenerateReports=false package + mvn -T 2C -Dorg.xml.sax.driver=com.sun.org.apache.xerces.internal.parsers.SAXParser -Dmaven.test.skip=true -Drat.skip=true -DskipEnforcer -Dmaven.javadoc.skip=true -DgenerateReports=false deploy + fi diff --git a/circle.yml b/circle.yml deleted file mode 100644 index 5aa509d..0000000 --- a/circle.yml +++ /dev/null @@ -1,51 +0,0 @@ -machine: - environment: - MAJOR_VERSION: 0.9 - MAVEN_OPTS: "-Xmx1g -DbuildNumber=${CIRCLE_BUILD_NUM} -Dorg.xml.sax.driver='com.sun.org.apache.xerces.internal.parsers.SAXParser' " - java: - version: oraclejdk8 - -general: - branches: - ignore: - - gh-pages - - -dependencies: - cache_directories: - - ~/.gnupg - pre: - - cd ~ && git clone https://github.com/sillelien/build-utils.git && chmod a+x ~/build-utils/*.sh - - "[[ ${CIRCLE_BRANCH} != 'master' ]] || ( mvn versions:set -DnewVersion=$(cat .release) && mvn versions:resolve-ranges && mvn versions:lock-snapshots )" - - mvn install -e -q -Drat.skip -Dsource.skip=true -DgenerateReports=false -Dmaven.javadoc.skip=true -Dmaven.test.skip - - -test: - override: - - sudo ln -fs /usr/share/zoneinfo/Europe/London /etc/localtime - - "mvn -q -T 1C -Drat.skip -Dsource.skip=true -DgenerateReports=false -Dmaven.javadoc.skip=true integration-test": - timeout: 600 - -deployment: - - staging: - branch: staging - commands: - - ~/build-utils/promote_from_staging.sh - - production: - branch: master - commands: - - git config --global user.email "hello@neilellis.me" - - git config --global user.name "Neil Ellis" - - mvn versions:set -DnewVersion=$(cat .release) - - mvn versions:resolve-ranges - - mvn versions:lock-snapshots - - mvn -T 1C -Dmaven.test.skip=true -Drat.skip=true -DskipEnforcer -Dmaven.javadoc.skip=true -DgenerateReports=false package - - mvn -T 2C -Dorg.xml.sax.driver=com.sun.org.apache.xerces.internal.parsers.SAXParser -Dmaven.test.skip=true -Drat.skip=true -DskipEnforcer -Dmaven.javadoc.skip=true -DgenerateReports=false deploy - - - development: - branch: dev - commands: - - echo "dev" From 257a099169af434234fa0aee3e667c6565009c37 Mon Sep 17 00:00:00 2001 From: neilellis Date: Fri, 7 Jul 2017 23:47:57 +0100 Subject: [PATCH 041/135] Circle 2.0 --- .circleci/{circle.yml => config.yml} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename .circleci/{circle.yml => config.yml} (99%) diff --git a/.circleci/circle.yml b/.circleci/config.yml similarity index 99% rename from .circleci/circle.yml rename to .circleci/config.yml index dbd06f6..5c331ab 100644 --- a/.circleci/circle.yml +++ b/.circleci/config.yml @@ -6,7 +6,7 @@ jobs: MAJOR_VERSION: 0.9 MAVEN_OPTS: "-Xmx1g -DbuildNumber=${CIRCLE_BUILD_NUM} -Dorg.xml.sax.driver='com.sun.org.apache.xerces.internal.parsers.SAXParser' " TZ: "/usr/share/zoneinfo/Europe/London" - + branches: ignore: - gh-pages From b02303de85b1b8e62704cf59cffc24b45d2b482a Mon Sep 17 00:00:00 2001 From: neilellis Date: Fri, 7 Jul 2017 23:49:33 +0100 Subject: [PATCH 042/135] Circle 2.0 --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 5c331ab..1b01698 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,7 +1,7 @@ jobs: build: docker: - image: circleci/oraclejdk:1.8 + image: circleci/openjdk:8-jdk environment: MAJOR_VERSION: 0.9 MAVEN_OPTS: "-Xmx1g -DbuildNumber=${CIRCLE_BUILD_NUM} -Dorg.xml.sax.driver='com.sun.org.apache.xerces.internal.parsers.SAXParser' " From 848092b70439a55ccb8b3b01b3bf0f5bc3951fca Mon Sep 17 00:00:00 2001 From: neilellis Date: Fri, 7 Jul 2017 23:51:37 +0100 Subject: [PATCH 043/135] Circle 2.0 --- .circleci/config.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1b01698..49a59ca 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,11 +1,11 @@ jobs: build: docker: - image: circleci/openjdk:8-jdk - environment: - MAJOR_VERSION: 0.9 - MAVEN_OPTS: "-Xmx1g -DbuildNumber=${CIRCLE_BUILD_NUM} -Dorg.xml.sax.driver='com.sun.org.apache.xerces.internal.parsers.SAXParser' " - TZ: "/usr/share/zoneinfo/Europe/London" + - image: circleci/openjdk:8-jdk + environment: + MAJOR_VERSION: 0.9 + MAVEN_OPTS: "-Xmx1g -DbuildNumber=${CIRCLE_BUILD_NUM} -Dorg.xml.sax.driver='com.sun.org.apache.xerces.internal.parsers.SAXParser' " + TZ: "/usr/share/zoneinfo/Europe/London" branches: ignore: From 79bd0fae1703747bb2b3077b074ea97c14453239 Mon Sep 17 00:00:00 2001 From: neilellis Date: Fri, 7 Jul 2017 23:52:46 +0100 Subject: [PATCH 044/135] Circle 2.0 --- .circleci/config.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 49a59ca..1f7e58f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -13,6 +13,8 @@ jobs: steps: + - checkout + - restore_cache: key: dependency-cache From 7acb4802d819c141754e83d161c9ea5f17e8beaa Mon Sep 17 00:00:00 2001 From: neilellis Date: Fri, 7 Jul 2017 23:54:14 +0100 Subject: [PATCH 045/135] Circle 2.0 --- .circleci/config.yml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1f7e58f..5887fe8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -2,10 +2,13 @@ jobs: build: docker: - image: circleci/openjdk:8-jdk - environment: - MAJOR_VERSION: 0.9 - MAVEN_OPTS: "-Xmx1g -DbuildNumber=${CIRCLE_BUILD_NUM} -Dorg.xml.sax.driver='com.sun.org.apache.xerces.internal.parsers.SAXParser' " - TZ: "/usr/share/zoneinfo/Europe/London" + + environment: + MAJOR_VERSION: 0.9 + MAVEN_OPTS: "-Xmx1g -DbuildNumber=${CIRCLE_BUILD_NUM} -Dorg.xml.sax.driver='com.sun.org.apache.xerces.internal.parsers.SAXParser' " + TZ: "/usr/share/zoneinfo/Europe/London" + + working_directory: ~/java-as-script branches: ignore: From 0878b29996cd67e74c65624e33cfdc5a26af4709 Mon Sep 17 00:00:00 2001 From: neilellis Date: Fri, 7 Jul 2017 23:55:33 +0100 Subject: [PATCH 046/135] Circle 2.0 --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 5887fe8..b4cb609 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -24,7 +24,7 @@ jobs: - run: name: dependencies command: | - cd ~ && git clone https://github.com/sillelien/build-utils.git && chmod a+x ~/build-utils/*.sh + cd ~ && git clone https://github.com/sillelien/build-utils.git && chmod a+x ~/build-utils/*.sh && cd - [[ ${CIRCLE_BRANCH} != 'master' ]] || ( mvn versions:set -DnewVersion=$(cat .release) && mvn versions:resolve-ranges && mvn versions:lock-snapshots ) mvn install -e -q -Drat.skip -Dsource.skip=true -DgenerateReports=false -Dmaven.javadoc.skip=true -Dmaven.test.skip From e9a38007a83619487a9548d0ec76924a53a9462a Mon Sep 17 00:00:00 2001 From: neilellis Date: Fri, 7 Jul 2017 23:59:55 +0100 Subject: [PATCH 047/135] Circle 2.0 --- .circleci/config.yml | 1 + pom.xml | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index b4cb609..ed54ec1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -24,6 +24,7 @@ jobs: - run: name: dependencies command: | + mvn -v cd ~ && git clone https://github.com/sillelien/build-utils.git && chmod a+x ~/build-utils/*.sh && cd - [[ ${CIRCLE_BRANCH} != 'master' ]] || ( mvn versions:set -DnewVersion=$(cat .release) && mvn versions:resolve-ranges && mvn versions:lock-snapshots ) mvn install -e -q -Drat.skip -Dsource.skip=true -DgenerateReports=false -Dmaven.javadoc.skip=true -Dmaven.test.skip diff --git a/pom.xml b/pom.xml index 73fdabb..4175779 100644 --- a/pom.xml +++ b/pom.xml @@ -90,16 +90,7 @@ - - com.versioneye - versioneye-maven-plugin - 3.11.4 - - 0c797be864338a3649f0 - sillelien - Owners - - + org.apache.rat @@ -191,7 +182,16 @@ - + + com.versioneye + versioneye-maven-plugin + 3.11.4 + + 0c797be864338a3649f0 + sillelien + Owners + + org.complykit From fecc8c7ee1844089008229240625f9e5569d75aa Mon Sep 17 00:00:00 2001 From: neilellis Date: Sat, 8 Jul 2017 00:00:50 +0100 Subject: [PATCH 048/135] Circle 2.0 --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ed54ec1..3b9179c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -27,7 +27,7 @@ jobs: mvn -v cd ~ && git clone https://github.com/sillelien/build-utils.git && chmod a+x ~/build-utils/*.sh && cd - [[ ${CIRCLE_BRANCH} != 'master' ]] || ( mvn versions:set -DnewVersion=$(cat .release) && mvn versions:resolve-ranges && mvn versions:lock-snapshots ) - mvn install -e -q -Drat.skip -Dsource.skip=true -DgenerateReports=false -Dmaven.javadoc.skip=true -Dmaven.test.skip + mvn install -e -Drat.skip -Dsource.skip=true -DgenerateReports=false -Dmaven.javadoc.skip=true -Dmaven.test.skip - save_cache: key: dependency-cache From c5768fc4fadf49eb2e26ae6ae59f1433ab43e04c Mon Sep 17 00:00:00 2001 From: neilellis Date: Sat, 8 Jul 2017 00:02:49 +0100 Subject: [PATCH 049/135] Circle 2.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4175779..e8857d1 100644 --- a/pom.xml +++ b/pom.xml @@ -265,7 +265,7 @@ - [,${maven.version}] + [${maven.version},] ${jdk.version} From 84e7d7295dab54437d8c5ed479e94a9273c4f153 Mon Sep 17 00:00:00 2001 From: neilellis Date: Sat, 8 Jul 2017 00:04:30 +0100 Subject: [PATCH 050/135] Circle 2.0 --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 3b9179c..eb3f19f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,7 +1,7 @@ jobs: build: docker: - - image: circleci/openjdk:8-jdk + - image: circleci/openjdk:8-jdk-browsers environment: MAJOR_VERSION: 0.9 @@ -27,7 +27,7 @@ jobs: mvn -v cd ~ && git clone https://github.com/sillelien/build-utils.git && chmod a+x ~/build-utils/*.sh && cd - [[ ${CIRCLE_BRANCH} != 'master' ]] || ( mvn versions:set -DnewVersion=$(cat .release) && mvn versions:resolve-ranges && mvn versions:lock-snapshots ) - mvn install -e -Drat.skip -Dsource.skip=true -DgenerateReports=false -Dmaven.javadoc.skip=true -Dmaven.test.skip + mvn install -e -q -Drat.skip -Dsource.skip=true -DgenerateReports=false -Dmaven.javadoc.skip=true -Dmaven.test.skip - save_cache: key: dependency-cache From 79d53afa76be6442be903a8f2a7c21532e266ff1 Mon Sep 17 00:00:00 2001 From: neilellis Date: Sat, 8 Jul 2017 00:07:25 +0100 Subject: [PATCH 051/135] Circle 2.0 --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index eb3f19f..5d68bf5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -43,6 +43,7 @@ jobs: - deploy: command: | if [ "${CIRCLE_BRANCH}" == "staging" ]; then + apt-get -y install gettext-base ~/build-utils/promote_from_staging.sh fi if [ "${CIRCLE_BRANCH}" == "master" ]; then From 0056ba7b210ba90e4d5792c90cd9a7a2dd492cfb Mon Sep 17 00:00:00 2001 From: neilellis Date: Sat, 8 Jul 2017 00:08:35 +0100 Subject: [PATCH 052/135] Circle 2.0 --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 5d68bf5..4250571 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -43,7 +43,7 @@ jobs: - deploy: command: | if [ "${CIRCLE_BRANCH}" == "staging" ]; then - apt-get -y install gettext-base + sudo apt-get -y install gettext-base ~/build-utils/promote_from_staging.sh fi if [ "${CIRCLE_BRANCH}" == "master" ]; then From b2a2f70d36c307a45c8ae755705ffe0bdb89e4f0 Mon Sep 17 00:00:00 2001 From: "hello@neilellis.me" Date: Sat, 8 Jul 2017 00:09:04 +0100 Subject: [PATCH 053/135] Release 0.9.51 [51/0056ba7b210ba90e4d5792c90cd9a7a2dd492cfb] (hooly-afraid-rogues) --- .release | 2 +- .release.details | 2 +- README.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.release b/.release index c13d8c3..a75b09e 100644 --- a/.release +++ b/.release @@ -1 +1 @@ -0.9.36 +0.9.51 diff --git a/.release.details b/.release.details index fc77281..8a4d413 100644 --- a/.release.details +++ b/.release.details @@ -1 +1 @@ -0.9.36 36 eef2e0e17c8838a88879078e518390188f443102 richly-scarce-pock +0.9.51 51 0056ba7b210ba90e4d5792c90cd9a7a2dd492cfb hooly-afraid-rogues diff --git a/README.md b/README.md index c6acfa9..9575598 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ RelProxy is a simple Java and Groovy hot class reloader for Java and Groovy prov com.sillelien java-as-script - 0.9.36 + 0.9.51 jar ``` From 77c8116d795386d15cef1c360e20c60b1852a582 Mon Sep 17 00:00:00 2001 From: neilellis Date: Sat, 8 Jul 2017 00:15:31 +0100 Subject: [PATCH 054/135] Circle 2.0 --- .circleci/config.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 4250571..eb3f19f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -43,7 +43,6 @@ jobs: - deploy: command: | if [ "${CIRCLE_BRANCH}" == "staging" ]; then - sudo apt-get -y install gettext-base ~/build-utils/promote_from_staging.sh fi if [ "${CIRCLE_BRANCH}" == "master" ]; then From f505a701120f4b3632ad07c54b095519b5e6431d Mon Sep 17 00:00:00 2001 From: neilellis Date: Sat, 8 Jul 2017 00:19:47 +0100 Subject: [PATCH 055/135] Circle 2.0 --- LICENSE-2.0.txt => LICENSE | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename LICENSE-2.0.txt => LICENSE (100%) diff --git a/LICENSE-2.0.txt b/LICENSE similarity index 100% rename from LICENSE-2.0.txt rename to LICENSE From 63629e8c862c95c35d1023cc48baedadcc395886 Mon Sep 17 00:00:00 2001 From: neilellis Date: Sat, 8 Jul 2017 00:20:41 +0100 Subject: [PATCH 056/135] Circle 2.0 --- README.tmpl.md | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/README.tmpl.md b/README.tmpl.md index 2fa8b5f..d80556e 100644 --- a/README.tmpl.md +++ b/README.tmpl.md @@ -76,17 +76,6 @@ Bug Reporting Use this GitHub project. -${FOOTER} - - - - - - - - - - Historical Details ================== From 87ca6877c998a30ca90d62809de5040bb7475e82 Mon Sep 17 00:00:00 2001 From: neilellis Date: Sat, 8 Jul 2017 00:25:17 +0100 Subject: [PATCH 057/135] Circle 2.0 --- relproxy_test_itsnat/.gitignore | 5 - relproxy_test_itsnat/build.gradle | 42 ----- .../conf/conf_relproxy.properties | 2 - relproxy_test_itsnat/nb-configuration.xml | 23 --- relproxy_test_itsnat/pom.xml | 153 ------------------ .../example/groovyex/ItsNatGroovyServlet.java | 110 ------------- .../src/main/java/example/javaex/City.java | 17 -- .../src/main/java/example/javaex/FalseDB.java | 22 --- .../example/javaex/JProxyExampleServlet.java | 46 ------ .../javaex/JProxyServletContextListener.java | 137 ---------------- .../javaex/hotreload/JProxyExampleAux2.java | 14 -- .../JProxyExampleAuxIgnored2.java | 14 -- .../JProxyExampleAuxIgnored3.java | 14 -- .../src/main/webapp/META-INF/context.xml | 2 - .../code/example/groovyex/City.groovy | 17 -- .../code/example/groovyex/FalseDB.groovy | 20 --- .../groovyex/GroovyExampleDocument.groovy | 36 ----- .../groovyex/GroovyExampleLoadListener.groovy | 28 ---- .../groovyex/groovy_servlet_init.groovy | 46 ------ .../WEB-INF/groovyex/pages/groovyex.html | 23 --- .../javaex/JProxyExampleAuxIgnored.java | 14 -- .../example/javaex/JProxyExampleDocument.java | 87 ---------- .../javaex/JProxyExampleDocumentBase.java | 13 -- .../javaex/JProxyExampleLoadListener.java | 38 ----- .../example/javaex/JProxyExampleAux.java | 14 -- .../webapp/WEB-INF/javaex/pages/javaex.html | 24 --- .../main/webapp/WEB-INF/lib/ItsNat-1.3.1.jar | Bin 1587553 -> 0 bytes .../src/main/webapp/WEB-INF/web.xml | 42 ----- .../src/main/webapp/index.html | 35 ---- .../src/main/webapp/jsp/test_jproxy_start.jsp | 31 ---- .../src/main/webapp/jsp/test_jproxy_stop.jsp | 31 ---- relproxy_test_itsnat/sync.xml | 32 ---- .../dollar/relproxy/gproxy/GProxy.java | 67 -------- .../dollar/relproxy/gproxy/GProxyConfig.java | 45 ------ .../gproxy/GProxyGroovyScriptEngine.java | 32 ---- .../dollar/relproxy/gproxy/package.html | 13 -- .../impl/gproxy/GProxyConfigImpl.java | 37 ----- .../impl/gproxy/GProxyDefaultImpl.java | 39 ----- .../relproxy/impl/gproxy/core/GProxyImpl.java | 31 ---- .../gproxy/core/GProxyInvocationHandler.java | 20 --- .../gproxy/core/GProxyVersionedObject.java | 44 ----- .../{dollar/relproxy => jas}/RelProxy.java | 2 +- .../relproxy => jas}/RelProxyException.java | 2 +- .../RelProxyOnReloadListener.java | 8 +- .../relproxy => jas}/impl/FileExt.java | 4 +- .../impl/GenericProxyConfigBaseImpl.java | 4 +- .../impl/GenericProxyImpl.java | 6 +- .../impl/GenericProxyInvocationHandler.java | 4 +- .../impl/GenericProxyVersionedObject.java | 4 +- .../impl/jproxy/JProxyConfigImpl.java | 20 +-- .../impl/jproxy/JProxyDefaultImpl.java | 6 +- .../impl/jproxy/JProxyUtil.java | 4 +- .../impl/jproxy/core/JProxyImpl.java | 24 +-- .../jproxy/core/JProxyInvocationHandler.java | 4 +- .../jproxy/core/JProxyVersionedObject.java | 6 +- .../jproxy/core/clsmgr/FolderSourceList.java | 6 +- .../jproxy/core/clsmgr/JProxyClassLoader.java | 8 +- .../impl/jproxy/core/clsmgr/JProxyEngine.java | 24 +-- ...JProxyEngineChangeDetectorAndCompiler.java | 36 ++--- .../jproxy/core/clsmgr/JavaSourcesSearch.java | 30 ++-- .../core/clsmgr/cldesc/ClassDescriptor.java | 2 +- .../clsmgr/cldesc/ClassDescriptorInner.java | 2 +- .../cldesc/ClassDescriptorSourceFileJava.java | 8 +- .../ClassDescriptorSourceFileRegistry.java | 2 +- .../cldesc/ClassDescriptorSourceScript.java | 10 +- .../cldesc/ClassDescriptorSourceUnit.java | 10 +- .../comp/JProxyCompilationException.java | 6 +- .../clsmgr/comp/JProxyCompilerContext.java | 6 +- .../clsmgr/comp/JProxyCompilerInMemory.java | 28 ++-- .../clsmgr/comp/JavaFileManagerInMemory.java | 18 +-- ...leObjectInputClassFinderByClassLoader.java | 18 +-- .../comp/jfo/JProxyJavaFileObjectInput.java | 2 +- .../jfo/JavaFileObjectInputClassInFile.java | 2 +- .../JavaFileObjectInputClassInFileSystem.java | 2 +- .../jfo/JavaFileObjectInputClassInJar.java | 2 +- .../jfo/JavaFileObjectInputClassInMemory.java | 2 +- .../jfo/JavaFileObjectInputSourceBase.java | 4 +- .../jfo/JavaFileObjectInputSourceInFile.java | 4 +- .../JavaFileObjectInputSourceInMemory.java | 2 +- .../comp/jfo/JavaFileObjectOutputClass.java | 4 +- .../clsmgr/srcunit/SourceFileJavaNormal.java | 4 +- .../core/clsmgr/srcunit/SourceScriptRoot.java | 2 +- .../clsmgr/srcunit/SourceScriptRootFile.java | 8 +- .../srcunit/SourceScriptRootFileJavaExt.java | 8 +- .../srcunit/SourceScriptRootFileOtherExt.java | 8 +- .../srcunit/SourceScriptRootInMemory.java | 2 +- .../core/clsmgr/srcunit/SourceUnit.java | 6 +- .../impl/jproxy/screngine/BindingsImpl.java | 2 +- .../JProxyScriptEngineDelegateImpl.java | 22 +-- .../JProxyScriptEngineFactoryImpl.java | 6 +- .../screngine/JProxyScriptEngineImpl.java | 16 +- .../jproxy/shell/JProxyShellClassLoader.java | 6 +- .../shell/JProxyShellCodeSnippetImpl.java | 16 +- .../impl/jproxy/shell/JProxyShellImpl.java | 20 +-- .../shell/JProxyShellInteractiveImpl.java | 18 +-- .../shell/JProxyShellScriptFileImpl.java | 21 +-- .../impl/jproxy/shell/inter/Command.java | 2 +- .../shell/inter/CommandCodeChangerBase.java | 2 +- .../jproxy/shell/inter/CommandDelete.java | 2 +- .../impl/jproxy/shell/inter/CommandEdit.java | 2 +- .../impl/jproxy/shell/inter/CommandError.java | 2 +- .../jproxy/shell/inter/CommandInsert.java | 2 +- .../impl/jproxy/shell/inter/CommandLoad.java | 4 +- .../impl/jproxy/shell/inter/CommandOther.java | 4 +- .../impl/jproxy/shell/inter/CommandSave.java | 4 +- .../shell/inter/JProxyShellProcessor.java | 16 +- .../impl/jproxy/shell/inter/Keyboard.java | 2 +- .../inter/KeyboardNotUsingClipboard.java | 4 +- .../shell/inter/KeyboardUsingClipboard.java | 4 +- .../shell/inter/LinuxUnicodeKeyboard.java | 2 +- .../shell/inter/MacOSXUnicodeKeyboard.java | 2 +- .../shell/inter/WindowUnicodeKeyboard.java | 2 +- .../relproxy => jas}/jproxy/JProxy.java | 6 +- .../jproxy/JProxyCompilerListener.java | 2 +- .../relproxy => jas}/jproxy/JProxyConfig.java | 4 +- .../jproxy/JProxyDiagnosticsListener.java | 2 +- ...JProxyInputSourceFileExcludedListener.java | 2 +- .../jproxy/JProxyScriptEngine.java | 2 +- .../jproxy/JProxyScriptEngineFactory.java | 4 +- .../relproxy => jas}/jproxy/JProxyShell.java | 4 +- .../relproxy => jas}/jproxy/package.html | 0 .../{dollar/relproxy => jas}/package.html | 0 .../JProxyCodeSnippetCompleteClassTest.java | 2 +- .../jproxy/JProxyCodeSnippetTest.java | 2 +- .../JProxyJavaScriptEngineNoManagerTest.java | 11 +- .../jproxy/JProxyJavaScriptEngineTest.java | 17 +- .../JProxyJavaShellCompleteClassTest.java | 8 +- .../JProxyJavaShellInteractiveTest.java | 4 +- .../JProxyJavaShellNormalClassTest.java | 8 +- .../jproxy/JProxyJavaShellTest.java | 7 +- .../jproxy/util/JProxyTestUtil.java | 2 +- .../javashellex/JProxyShellExample.java | 2 +- 132 files changed, 319 insertions(+), 1787 deletions(-) delete mode 100644 relproxy_test_itsnat/.gitignore delete mode 100644 relproxy_test_itsnat/build.gradle delete mode 100644 relproxy_test_itsnat/conf/conf_relproxy.properties delete mode 100644 relproxy_test_itsnat/nb-configuration.xml delete mode 100644 relproxy_test_itsnat/pom.xml delete mode 100644 relproxy_test_itsnat/src/main/java/example/groovyex/ItsNatGroovyServlet.java delete mode 100644 relproxy_test_itsnat/src/main/java/example/javaex/City.java delete mode 100644 relproxy_test_itsnat/src/main/java/example/javaex/FalseDB.java delete mode 100644 relproxy_test_itsnat/src/main/java/example/javaex/JProxyExampleServlet.java delete mode 100644 relproxy_test_itsnat/src/main/java/example/javaex/JProxyServletContextListener.java delete mode 100644 relproxy_test_itsnat/src/main/java/example/javaex/hotreload/JProxyExampleAux2.java delete mode 100644 relproxy_test_itsnat/src/main/java/example/javaex/nothotreload/JProxyExampleAuxIgnored2.java delete mode 100644 relproxy_test_itsnat/src/main/java/example/javaex/nothotreload/JProxyExampleAuxIgnored3.java delete mode 100644 relproxy_test_itsnat/src/main/webapp/META-INF/context.xml delete mode 100644 relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/code/example/groovyex/City.groovy delete mode 100644 relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/code/example/groovyex/FalseDB.groovy delete mode 100644 relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/code/example/groovyex/GroovyExampleDocument.groovy delete mode 100644 relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/code/example/groovyex/GroovyExampleLoadListener.groovy delete mode 100644 relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/code/example/groovyex/groovy_servlet_init.groovy delete mode 100644 relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/pages/groovyex.html delete mode 100644 relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleAuxIgnored.java delete mode 100644 relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleDocument.java delete mode 100644 relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleDocumentBase.java delete mode 100644 relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleLoadListener.java delete mode 100644 relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code2/example/javaex/JProxyExampleAux.java delete mode 100644 relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/pages/javaex.html delete mode 100644 relproxy_test_itsnat/src/main/webapp/WEB-INF/lib/ItsNat-1.3.1.jar delete mode 100644 relproxy_test_itsnat/src/main/webapp/WEB-INF/web.xml delete mode 100644 relproxy_test_itsnat/src/main/webapp/index.html delete mode 100644 relproxy_test_itsnat/src/main/webapp/jsp/test_jproxy_start.jsp delete mode 100644 relproxy_test_itsnat/src/main/webapp/jsp/test_jproxy_stop.jsp delete mode 100644 relproxy_test_itsnat/sync.xml delete mode 100644 src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxy.java delete mode 100644 src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyConfig.java delete mode 100644 src/main/java/com/sillelien/dollar/relproxy/gproxy/GProxyGroovyScriptEngine.java delete mode 100644 src/main/java/com/sillelien/dollar/relproxy/gproxy/package.html delete mode 100644 src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyConfigImpl.java delete mode 100644 src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/GProxyDefaultImpl.java delete mode 100644 src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyImpl.java delete mode 100644 src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyInvocationHandler.java delete mode 100644 src/main/java/com/sillelien/dollar/relproxy/impl/gproxy/core/GProxyVersionedObject.java rename src/main/java/com/sillelien/{dollar/relproxy => jas}/RelProxy.java (88%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/RelProxyException.java (96%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/RelProxyOnReloadListener.java (81%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/FileExt.java (88%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/GenericProxyConfigBaseImpl.java (75%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/GenericProxyImpl.java (90%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/GenericProxyInvocationHandler.java (95%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/GenericProxyVersionedObject.java (98%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/JProxyConfigImpl.java (86%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/JProxyDefaultImpl.java (90%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/JProxyUtil.java (97%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/core/JProxyImpl.java (74%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/core/JProxyInvocationHandler.java (76%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/core/JProxyVersionedObject.java (82%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/core/clsmgr/FolderSourceList.java (94%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/core/clsmgr/JProxyClassLoader.java (95%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/core/clsmgr/JProxyEngine.java (91%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/core/clsmgr/JProxyEngineChangeDetectorAndCompiler.java (90%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/core/clsmgr/JavaSourcesSearch.java (89%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/core/clsmgr/cldesc/ClassDescriptor.java (98%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorInner.java (88%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileJava.java (67%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java (97%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceScript.java (95%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceUnit.java (91%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/core/clsmgr/comp/JProxyCompilationException.java (65%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java (92%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/core/clsmgr/comp/JProxyCompilerInMemory.java (89%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/core/clsmgr/comp/JavaFileManagerInMemory.java (89%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/core/clsmgr/comp/JavaFileObjectInputClassFinderByClassLoader.java (93%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/core/clsmgr/comp/jfo/JProxyJavaFileObjectInput.java (60%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFile.java (93%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java (97%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInJar.java (92%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInMemory.java (95%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java (92%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInFile.java (84%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceInMemory.java (90%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectOutputClass.java (92%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/core/clsmgr/srcunit/SourceFileJavaNormal.java (82%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/core/clsmgr/srcunit/SourceScriptRoot.java (78%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java (81%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileJavaExt.java (67%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFileOtherExt.java (78%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootInMemory.java (95%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/core/clsmgr/srcunit/SourceUnit.java (80%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/screngine/BindingsImpl.java (73%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/screngine/JProxyScriptEngineDelegateImpl.java (82%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/screngine/JProxyScriptEngineFactoryImpl.java (96%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/screngine/JProxyScriptEngineImpl.java (86%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/shell/JProxyShellClassLoader.java (86%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java (76%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/shell/JProxyShellImpl.java (89%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/shell/JProxyShellInteractiveImpl.java (80%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/shell/JProxyShellScriptFileImpl.java (76%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/shell/inter/Command.java (97%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/shell/inter/CommandCodeChangerBase.java (96%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/shell/inter/CommandDelete.java (96%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/shell/inter/CommandEdit.java (96%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/shell/inter/CommandError.java (82%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/shell/inter/CommandInsert.java (96%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/shell/inter/CommandLoad.java (93%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/shell/inter/CommandOther.java (96%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/shell/inter/CommandSave.java (91%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/shell/inter/JProxyShellProcessor.java (92%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/shell/inter/Keyboard.java (88%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/shell/inter/KeyboardNotUsingClipboard.java (99%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/shell/inter/KeyboardUsingClipboard.java (93%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/shell/inter/LinuxUnicodeKeyboard.java (95%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/shell/inter/MacOSXUnicodeKeyboard.java (95%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/impl/jproxy/shell/inter/WindowUnicodeKeyboard.java (94%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/jproxy/JProxy.java (96%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/jproxy/JProxyCompilerListener.java (87%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/jproxy/JProxyConfig.java (98%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/jproxy/JProxyDiagnosticsListener.java (92%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/jproxy/JProxyInputSourceFileExcludedListener.java (94%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/jproxy/JProxyScriptEngine.java (98%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/jproxy/JProxyScriptEngineFactory.java (79%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/jproxy/JProxyShell.java (82%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/jproxy/package.html (100%) rename src/main/java/com/sillelien/{dollar/relproxy => jas}/package.html (100%) rename src/test/java/com/sillelien/{dollar/relproxy => jas}/jproxy/JProxyCodeSnippetCompleteClassTest.java (97%) rename src/test/java/com/sillelien/{dollar/relproxy => jas}/jproxy/JProxyCodeSnippetTest.java (96%) rename src/test/java/com/sillelien/{dollar/relproxy => jas}/jproxy/JProxyJavaScriptEngineNoManagerTest.java (94%) rename src/test/java/com/sillelien/{dollar/relproxy => jas}/jproxy/JProxyJavaScriptEngineTest.java (89%) rename src/test/java/com/sillelien/{dollar/relproxy => jas}/jproxy/JProxyJavaShellCompleteClassTest.java (85%) rename src/test/java/com/sillelien/{dollar/relproxy => jas}/jproxy/JProxyJavaShellInteractiveTest.java (88%) rename src/test/java/com/sillelien/{dollar/relproxy => jas}/jproxy/JProxyJavaShellNormalClassTest.java (85%) rename src/test/java/com/sillelien/{dollar/relproxy => jas}/jproxy/JProxyJavaShellTest.java (85%) rename src/test/java/com/sillelien/{dollar/relproxy => jas}/jproxy/util/JProxyTestUtil.java (86%) diff --git a/relproxy_test_itsnat/.gitignore b/relproxy_test_itsnat/.gitignore deleted file mode 100644 index 8dddca2..0000000 --- a/relproxy_test_itsnat/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -/target/ -/tmp -.gradle/ - -conf/conf_local.properties diff --git a/relproxy_test_itsnat/build.gradle b/relproxy_test_itsnat/build.gradle deleted file mode 100644 index ea572ec..0000000 --- a/relproxy_test_itsnat/build.gradle +++ /dev/null @@ -1,42 +0,0 @@ -import java.util.jar.Attributes.Name; - -apply plugin: 'java' -apply plugin: 'eclipse' -apply plugin: 'war' - -repositories { - mavenCentral() -} - -dependencies { - providedCompile 'javax.servlet:servlet-api:2.5' - providedCompile 'javax.servlet.jsp:jsp-api:2.1' - - compile files('/src/main/webapp/WEB-INF/lib/ItsNat_1.3.1.jar') - compile 'org.apache.xmlgraphics:batik-dom:1.7@jar' - compile 'org.apache.xmlgraphics:batik-xml:1.7@jar' - compile 'org.apache.xmlgraphics:batik-util:1.7@jar' - compile 'net.sourceforge.nekohtml:nekohtml:1.9.12@jar' - compile 'xalan:serializer:2.7.1@jar' - compile 'org.codehaus.groovy:groovy-all:2.1.6@jar' - - runtime files('/src/main/webapp/WEB-INF/lib/ItsNat-1.3.1.jar') - runtime 'org.apache.xmlgraphics:batik-dom:1.7' - runtime 'org.apache.xmlgraphics:batik-xml:1.7' - runtime 'org.apache.xmlgraphics:batik-util:1.7' - runtime 'net.sourceforge.nekohtml:nekohtml:1.9.12' - runtime 'xalan:serializer:2.7.1' - runtime 'org.codehaus.groovy:groovy-all:2.1.6' -} - -sourceSets.main.java.srcDirs 'src/main/webapp/WEB-INF/javaex/code' -sourceSets.main.java.srcDirs 'src/main/webapp/WEB-INF/groovyex/code' - -task explodedWar(type: Copy) { - into "$buildDir/web" - with war -} - - -war.dependsOn explodedWar - diff --git a/relproxy_test_itsnat/conf/conf_relproxy.properties b/relproxy_test_itsnat/conf/conf_relproxy.properties deleted file mode 100644 index 73a72a1..0000000 --- a/relproxy_test_itsnat/conf/conf_relproxy.properties +++ /dev/null @@ -1,2 +0,0 @@ - -webapp_folder=relproxy_test_itsnat-0.1-SNAPSHOT diff --git a/relproxy_test_itsnat/nb-configuration.xml b/relproxy_test_itsnat/nb-configuration.xml deleted file mode 100644 index b92960b..0000000 --- a/relproxy_test_itsnat/nb-configuration.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - 1.5 - Tomcat - all - js/libs - false - true - - diff --git a/relproxy_test_itsnat/pom.xml b/relproxy_test_itsnat/pom.xml deleted file mode 100644 index 56bbd9b..0000000 --- a/relproxy_test_itsnat/pom.xml +++ /dev/null @@ -1,153 +0,0 @@ - - 4.0.0 - - com.innowhere - relproxy_test_itsnat - war - 0.1-SNAPSHOT - - relproxy_test_itsnat - https://github.com/jmarranz/relproxy/ - - - UTF-8 - - - - - - javax.servlet - servlet-api - 2.5 - provided - - - - javax.servlet.jsp - jsp-api - 2.1 - provided - - - - - - - ItsNat - ItsNat-jar - 1.3.1 - system - ${basedir}/src/main/webapp/WEB-INF/lib/ItsNat-1.3.1.jar - - - - org.apache.xmlgraphics - batik-dom - 1.7 - - - - org.apache.xmlgraphics - batik-xml - 1.7 - - - - org.apache.xmlgraphics - batik-util - 1.7 - - - - net.sourceforge.nekohtml - nekohtml - 1.9.12 - - - - xalan - serializer - 2.7.1 - - - - org.codehaus.groovy - groovy-all - 2.1.6 - - - - - - - - - - - org.codehaus.mojo - build-helper-maven-plugin - 1.9.1 - - - add-source - generate-sources - - add-source - - - - ${basedir}/../relproxy/src/main/java - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 2.0.2 - - 1.6 - 1.6 - ${project.build.sourceEncoding} - - - - - org.apache.maven.plugins - maven-resources-plugin - 2.4.3 - - ${project.build.sourceEncoding} - - - - - - - - - ../relproxy/src/main/java - - - - src/main/webapp/WEB-INF/groovyex/code - - - src/main/webapp/WEB-INF/javaex/code - - - src/main/webapp/WEB-INF/javaex/code2 - - - - - diff --git a/relproxy_test_itsnat/src/main/java/example/groovyex/ItsNatGroovyServlet.java b/relproxy_test_itsnat/src/main/java/example/groovyex/ItsNatGroovyServlet.java deleted file mode 100644 index 5a46c71..0000000 --- a/relproxy_test_itsnat/src/main/java/example/groovyex/ItsNatGroovyServlet.java +++ /dev/null @@ -1,110 +0,0 @@ - -package example.groovyex; - -import groovy.lang.Binding; -import groovy.lang.Closure; -import groovy.servlet.ServletCategory; -import groovy.util.GroovyScriptEngine; -import groovy.util.ResourceException; -import groovy.util.ScriptException; -import java.io.File; -import java.io.IOException; -import javax.servlet.ServletConfig; -import javax.servlet.ServletException; -import org.codehaus.groovy.runtime.GroovyCategorySupport; -import org.itsnat.core.http.HttpServletWrapper; - - -/** - * Inspired on: - * https://github.com/groovy/groovy-core/blob/master/subprojects/groovy-servlet/src/main/java/groovy/servlet/GroovyServlet.java - * - * @author jmarranz - */ -public class ItsNatGroovyServlet extends HttpServletWrapper -{ - protected GroovyScriptEngine gse; - - public ItsNatGroovyServlet() - { - } - - public GroovyScriptEngine getGroovyScriptEngine() - { - return gse; - } - - public String getScriptRootPath(ServletConfig config) throws ServletException - { - String scriptRootPath = config.getInitParameter("scriptRootPath"); - if (scriptRootPath == null) throw new ServletException("Missing servlet init param scriptRootPath"); - return getServletContext().getRealPath("/") + "/WEB-INF/" + scriptRootPath + "/"; - } - - public String getInitScript(ServletConfig config) throws ServletException - { - String initScript = config.getInitParameter("initScript"); - if (initScript == null) throw new ServletException("Missing servlet init param initScript"); - return initScript; - } - - @Override - public void init(ServletConfig config) throws ServletException - { - super.init(config); - - // Set up the scripting engine - - String pathPrefix = getScriptRootPath(config); - - try - { - this.gse = new GroovyScriptEngine(new String[]{pathPrefix}); - } - catch(IOException ex) { throw new RuntimeException(ex); } - - //gse.getConfig().setMinimumRecompilationInterval(0); - - //System.out.println("MinimumRecompilationInterval " + gse.getConfig().getMinimumRecompilationInterval()); - - getServletContext().log("Groovy servlet initialized on " + gse + "."); - - String initScript = getInitScript(config); - - File initFile = new File(pathPrefix + initScript); - if (!initFile.exists()) - throw new ServletException(initFile.getAbsolutePath() + " does not exist"); - - final Binding binding = new Binding(); - binding.setVariable("itsNatServlet", itsNatServlet); - binding.setVariable("servlet", this); - binding.setVariable("config", config); - binding.setVariable("context", getServletContext()); - binding.setVariable("application", getServletContext()); - - com.sillelien.dollar.relproxy.gproxy.GProxyGroovyScriptEngine.class.getName(); - com.sillelien.dollar.relproxy.gproxy.GProxyConfig.class.getName(); - com.sillelien.dollar.relproxy.gproxy.GProxy.class.getName(); - - execGroovyScript(initScript,binding); - } - - protected void execGroovyScript(final String filePath,final Binding binding) - { - Closure closure = new Closure(gse) - { - @Override - public Object call() { - try { - return ((GroovyScriptEngine)getDelegate()).run(filePath, binding); - } - catch (ResourceException e) { throw new RuntimeException(e); } - catch (ScriptException e) { throw new RuntimeException(e); } - } - }; - GroovyCategorySupport.use(ServletCategory.class, closure); - } - -} - - diff --git a/relproxy_test_itsnat/src/main/java/example/javaex/City.java b/relproxy_test_itsnat/src/main/java/example/javaex/City.java deleted file mode 100644 index 1c88e5a..0000000 --- a/relproxy_test_itsnat/src/main/java/example/javaex/City.java +++ /dev/null @@ -1,17 +0,0 @@ -package example.javaex; - -/** - * - * @author jmarranz - */ -public class City -{ - protected String name; - - public City(String name) - { - this.name = name; - } - - public String getName() { return name; } -} diff --git a/relproxy_test_itsnat/src/main/java/example/javaex/FalseDB.java b/relproxy_test_itsnat/src/main/java/example/javaex/FalseDB.java deleted file mode 100644 index b92651e..0000000 --- a/relproxy_test_itsnat/src/main/java/example/javaex/FalseDB.java +++ /dev/null @@ -1,22 +0,0 @@ -package example.javaex; - -import java.util.LinkedList; - -/** - * - * @author jmarranz - */ -public class FalseDB -{ - protected LinkedList cities; - - public FalseDB() - { - cities = new LinkedList(); - cities.add(new City("Madrid")); - cities.add(new City("Barcelona")); - cities.add(new City("Bilbao")); - } - - public LinkedList getCityList() { return cities; /*cities;*/ } -} \ No newline at end of file diff --git a/relproxy_test_itsnat/src/main/java/example/javaex/JProxyExampleServlet.java b/relproxy_test_itsnat/src/main/java/example/javaex/JProxyExampleServlet.java deleted file mode 100644 index 86ac5f4..0000000 --- a/relproxy_test_itsnat/src/main/java/example/javaex/JProxyExampleServlet.java +++ /dev/null @@ -1,46 +0,0 @@ - -package example.javaex; - -import com.sillelien.dollar.relproxy.jproxy.JProxy; -import javax.servlet.ServletConfig; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import org.itsnat.core.event.ItsNatServletRequestListener; -import org.itsnat.core.http.HttpServletWrapper; -import org.itsnat.core.tmpl.ItsNatDocumentTemplate; - - -/** - * - * @author jmarranz - */ -public class JProxyExampleServlet extends HttpServletWrapper -{ - public JProxyExampleServlet() - { - } - - @Override - public void init(ServletConfig config) throws ServletException - { - super.init(config); - - ServletContext context = config.getServletContext(); - - String pathPrefix = context.getRealPath("/") + "/WEB-INF/javaex/pages/"; - - final FalseDB db = new FalseDB(); - - ItsNatDocumentTemplate docTemplate; - docTemplate = itsNatServlet.registerItsNatDocumentTemplate("javaex","text/html", pathPrefix + "javaex.html"); - ItsNatServletRequestListener listener = JProxy.create(new example.javaex.JProxyExampleLoadListener(db), ItsNatServletRequestListener.class); - docTemplate.addItsNatServletRequestListener(listener); - - ItsNatServletRequestListener original = new example.javaex.JProxyExampleLoadListener(db); - ItsNatServletRequestListener proxy = JProxy.create(original, ItsNatServletRequestListener.class); - ItsNatServletRequestListener proxy2 = JProxy.create(original, ItsNatServletRequestListener.class); - System.out.println("EQUALS TEST (true if not reloaded): " + (proxy.equals(proxy2))); - } - -} - diff --git a/relproxy_test_itsnat/src/main/java/example/javaex/JProxyServletContextListener.java b/relproxy_test_itsnat/src/main/java/example/javaex/JProxyServletContextListener.java deleted file mode 100644 index 5f6fa74..0000000 --- a/relproxy_test_itsnat/src/main/java/example/javaex/JProxyServletContextListener.java +++ /dev/null @@ -1,137 +0,0 @@ -package example.javaex; - -import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; -import com.sillelien.dollar.relproxy.jproxy.JProxy; -import com.sillelien.dollar.relproxy.jproxy.JProxyCompilerListener; -import com.sillelien.dollar.relproxy.jproxy.JProxyConfig; -import com.sillelien.dollar.relproxy.jproxy.JProxyDiagnosticsListener; -import com.sillelien.dollar.relproxy.jproxy.JProxyInputSourceFileExcludedListener; - -import javax.servlet.ServletContext; -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; -import javax.tools.Diagnostic; -import javax.tools.DiagnosticCollector; -import javax.tools.JavaFileObject; -import java.io.File; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.List; - -/** - * - * @author jmarranz - */ -public class JProxyServletContextListener implements ServletContextListener -{ - @Override - public void contextInitialized(ServletContextEvent sce) - { - System.out.println("ServletContextListener contextInitialized"); - - ServletContext context = sce.getServletContext(); - String realPath = context.getRealPath("/"); - String[] inputPaths = new String[] - { realPath + "/WEB-INF/javaex/code/", - realPath + "/WEB-INF/javaex/code2/", - realPath + "/../../src/main/java/" }; - - JProxyInputSourceFileExcludedListener excludedListener = new JProxyInputSourceFileExcludedListener() - { - @Override - public boolean isExcluded(File file, File rootFolderOfSources) - { - String rootFolderAbsPath = rootFolderOfSources.getAbsolutePath(); - String absPath = file.getAbsolutePath(); - if (rootFolderAbsPath.endsWith(File.separatorChar + "code") || rootFolderAbsPath.endsWith(File.separatorChar + "code2")) - { - return absPath.endsWith(JProxyExampleAuxIgnored.class.getSimpleName() + ".java"); - } - else // /../../src/main/java/ - { - if (file.isDirectory()) - { - return absPath.endsWith(File.separatorChar + "innowhere") || // Por si acaso el código fuente de RelProxy lo tenemos copiado para testear, tenemos que excluirlo - absPath.endsWith(File.separatorChar + "nothotreload"); - } - else - { - return !absPath.contains(File.separatorChar + "hotreload" + File.separatorChar); - } - } - } - }; - - - String classFolder = null; // Optional: context.getRealPath("/") + "/WEB-INF/classes"; - Iterable compilationOptions = Arrays.asList(new String[]{"-source","1.6","-target","1.6"}); - long scanPeriod = 200; - - RelProxyOnReloadListener proxyListener = new RelProxyOnReloadListener() { - @Override - public void onReload(Object objOld, Object objNew, Object proxy, Method method, Object[] args) { - System.out.println("Reloaded " + objNew + " Calling method: " + method); - } - }; - - JProxyCompilerListener compilerListener = new JProxyCompilerListener(){ - @Override - public void beforeCompile(File file) - { - System.out.println("Before compile: " + file); - } - - @Override - public void afterCompile(File file) - { - System.out.println("After compile: " + file); - } - }; - - JProxyDiagnosticsListener diagnosticsListener = new JProxyDiagnosticsListener() - { - @Override - public void onDiagnostics(DiagnosticCollector diagnostics) - { - List> diagList = diagnostics.getDiagnostics(); - int i = 1; - for (Diagnostic diagnostic : diagList) - { - System.err.println("Diagnostic " + i); - System.err.println(" code: " + diagnostic.getCode()); - System.err.println(" kind: " + diagnostic.getKind()); - System.err.println(" line number: " + diagnostic.getLineNumber()); - System.err.println(" column number: " + diagnostic.getColumnNumber()); - System.err.println(" start position: " + diagnostic.getStartPosition()); - System.err.println(" position: " + diagnostic.getPosition()); - System.err.println(" end position: " + diagnostic.getEndPosition()); - System.err.println(" source: " + diagnostic.getSource()); - System.err.println(" message: " + diagnostic.getMessage(null)); - i++; - } - } - }; - - JProxyConfig jpConfig = JProxy.createJProxyConfig(); - jpConfig.setEnabled(true) - .setRelProxyOnReloadListener(proxyListener) - .setInputPaths(inputPaths) - .setJProxyInputSourceFileExcludedListener(excludedListener) - .setScanPeriod(scanPeriod) - .setClassFolder(classFolder) - .setCompilationOptions(compilationOptions) - .setJProxyCompilerListener(compilerListener) - .setJProxyDiagnosticsListener(diagnosticsListener); - - JProxy.init(jpConfig); - - } - - @Override - public void contextDestroyed(ServletContextEvent sce) - { - System.out.println("ServletContextListener contextDestroyed"); - JProxy.stop(); - } - -} diff --git a/relproxy_test_itsnat/src/main/java/example/javaex/hotreload/JProxyExampleAux2.java b/relproxy_test_itsnat/src/main/java/example/javaex/hotreload/JProxyExampleAux2.java deleted file mode 100644 index ceaee39..0000000 --- a/relproxy_test_itsnat/src/main/java/example/javaex/hotreload/JProxyExampleAux2.java +++ /dev/null @@ -1,14 +0,0 @@ -package example.javaex.hotreload; - -/** - * - * @author jmarranz - */ -public class JProxyExampleAux2 -{ - public static void log() - { - System.out.println("JProxyExampleAux2: 1 " + JProxyExampleAux2.class.getClassLoader().hashCode()); - } -} - diff --git a/relproxy_test_itsnat/src/main/java/example/javaex/nothotreload/JProxyExampleAuxIgnored2.java b/relproxy_test_itsnat/src/main/java/example/javaex/nothotreload/JProxyExampleAuxIgnored2.java deleted file mode 100644 index 445aa74..0000000 --- a/relproxy_test_itsnat/src/main/java/example/javaex/nothotreload/JProxyExampleAuxIgnored2.java +++ /dev/null @@ -1,14 +0,0 @@ -package example.javaex.nothotreload; - -/** - * - * @author jmarranz - */ -public class JProxyExampleAuxIgnored2 -{ - public static void log() - { - System.out.println("JProxyExampleAuxIgnored2: 2 " + JProxyExampleAuxIgnored2.class.getClassLoader().hashCode()); - } -} - diff --git a/relproxy_test_itsnat/src/main/java/example/javaex/nothotreload/JProxyExampleAuxIgnored3.java b/relproxy_test_itsnat/src/main/java/example/javaex/nothotreload/JProxyExampleAuxIgnored3.java deleted file mode 100644 index bcbfeba..0000000 --- a/relproxy_test_itsnat/src/main/java/example/javaex/nothotreload/JProxyExampleAuxIgnored3.java +++ /dev/null @@ -1,14 +0,0 @@ -package example.javaex.nothotreload; - -/** - * - * @author jmarranz - */ -public class JProxyExampleAuxIgnored3 -{ - public static void log() - { - System.out.println("JProxyExampleAuxIgnored3: 1 " + JProxyExampleAuxIgnored3.class.getClassLoader().hashCode()); - } -} - diff --git a/relproxy_test_itsnat/src/main/webapp/META-INF/context.xml b/relproxy_test_itsnat/src/main/webapp/META-INF/context.xml deleted file mode 100644 index af070b4..0000000 --- a/relproxy_test_itsnat/src/main/webapp/META-INF/context.xml +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/code/example/groovyex/City.groovy b/relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/code/example/groovyex/City.groovy deleted file mode 100644 index ead1995..0000000 --- a/relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/code/example/groovyex/City.groovy +++ /dev/null @@ -1,17 +0,0 @@ -package example.groovyex; - -/** - * - * @author jmarranz - */ -class City -{ - def name; - - City(String name) - { - this.name = name; - } - - def getName() { return name; } -} diff --git a/relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/code/example/groovyex/FalseDB.groovy b/relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/code/example/groovyex/FalseDB.groovy deleted file mode 100644 index f703dd6..0000000 --- a/relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/code/example/groovyex/FalseDB.groovy +++ /dev/null @@ -1,20 +0,0 @@ -package example.groovyex; - -/** - * - * @author jmarranz - */ -class FalseDB -{ - def cities - - FalseDB() - { - cities = new LinkedList(); - cities.add(new City("Madrid")); - cities.add(new City("Barcelona")); - cities.add(new City("Bilbao")); - } - - def getCityList() { return cities; /*cities;*/ } -} diff --git a/relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/code/example/groovyex/GroovyExampleDocument.groovy b/relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/code/example/groovyex/GroovyExampleDocument.groovy deleted file mode 100644 index a07fbcd..0000000 --- a/relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/code/example/groovyex/GroovyExampleDocument.groovy +++ /dev/null @@ -1,36 +0,0 @@ - -package example.groovyex; - -import org.w3c.dom.events.Event -import org.w3c.dom.events.EventListener - -class GroovyExampleDocument -{ - def itsNatDoc // ItsNatHTMLDocument - def textInput // ItsNatHTMLInputText - def resultsElem // Element - - GroovyExampleDocument(itsNatDoc,db) - { - this.itsNatDoc = itsNatDoc - - if (db.getCityList().size() != 3) - throw new RuntimeException("Unexpected"); - - def doc = itsNatDoc.getHTMLDocument() - - def compMgr = itsNatDoc.getItsNatComponentManager() - this.textInput = compMgr.createItsNatComponentById("inputId") - - def buttonElem = doc.getElementById("buttonId") - buttonElem.addEventListener("click", - { Event evt -> def text = textInput.getText(); resultsElem.setTextContent(text); } as EventListener, false) - - def closure = { println("GroovyExampleDocument closure 2 ") } - closure(); - - this.resultsElem = doc.getElementById("resultsId") - - println("GroovyExampleDocument 2 ") - } -} diff --git a/relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/code/example/groovyex/GroovyExampleLoadListener.groovy b/relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/code/example/groovyex/GroovyExampleLoadListener.groovy deleted file mode 100644 index 66ec2f9..0000000 --- a/relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/code/example/groovyex/GroovyExampleLoadListener.groovy +++ /dev/null @@ -1,28 +0,0 @@ - -package example.groovyex; - -import org.itsnat.core.event.ItsNatServletRequestListener; -import org.itsnat.core.ItsNatServletRequest; -import org.itsnat.core.ItsNatServletResponse; -import example.groovyex.FalseDB; - -class GroovyExampleLoadListener implements ItsNatServletRequestListener -{ - def db - - GroovyExampleLoadListener() - { - } - - GroovyExampleLoadListener(FalseDB db) // Explicit type tells Groovy to reload FalseDB class when changed - { - this.db = db; - } - - void processRequest(ItsNatServletRequest request, ItsNatServletResponse response) - { - println("GroovyExampleLoadListener 4 "); - - new example.groovyex.GroovyExampleDocument(request.getItsNatDocument(),db); - } -} diff --git a/relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/code/example/groovyex/groovy_servlet_init.groovy b/relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/code/example/groovyex/groovy_servlet_init.groovy deleted file mode 100644 index de148d7..0000000 --- a/relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/code/example/groovyex/groovy_servlet_init.groovy +++ /dev/null @@ -1,46 +0,0 @@ - -package example.groovyex - -import org.itsnat.core.event.ItsNatServletRequestListener; -import groovy.util.GroovyScriptEngine; -import java.lang.reflect.Method; -import com.sillelien.dollar.relproxy.RelProxyOnReloadListener; -import com.sillelien.dollar.relproxy.gproxy.GProxy; -import com.sillelien.dollar.relproxy.gproxy.GProxyGroovyScriptEngine - -GroovyScriptEngine groovyEngine = servlet.getGroovyScriptEngine(); - -def gproxyGroovyEngine = { - String scriptName -> return (java.lang.Class)groovyEngine.loadScriptByName(scriptName) - } as GProxyGroovyScriptEngine; - -/* This alternative throws a weird error when called loadScriptByName, why? -GProxyGroovyScriptEngine groovyEngine = - { - loadScriptByName : { String scriptName -> return (java.lang.Class)servlet.getGroovyScriptEngine().loadScriptByName(scriptName) } - } as GProxyGroovyScriptEngine; -*/ - -def reloadListener = { - Object objOld,Object objNew,Object proxy, Method method, Object[] args -> - println("Reloaded " + objNew + " Calling method: " + method) - } as RelProxyOnReloadListener; - -def gpConfig = GProxy.createGProxyConfig(); -gpConfig.setEnabled(true) - .setRelProxyOnReloadListener(reloadListener) - .setGProxyGroovyScriptEngine(gproxyGroovyEngine); - -GProxy.init(gpConfig); - - -String pathPrefix = context.getRealPath("/") + "/WEB-INF/groovyex/pages/"; - -def docTemplate; -docTemplate = itsNatServlet.registerItsNatDocumentTemplate("groovyex","text/html", pathPrefix + "groovyex.html"); - -def db = new FalseDB(); - -ItsNatServletRequestListener listener = GProxy.create(new example.groovyex.GroovyExampleLoadListener(db), ItsNatServletRequestListener.class); -docTemplate.addItsNatServletRequestListener(listener); - diff --git a/relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/pages/groovyex.html b/relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/pages/groovyex.html deleted file mode 100644 index 969460f..0000000 --- a/relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/pages/groovyex.html +++ /dev/null @@ -1,23 +0,0 @@ - - - -GProxy Example (Groovy) - - -

GProxy Example (Groovy)

- -
-
- Say something to GProxy:
- -
- -
-
You said:
-
- -

- RETURN - - - diff --git a/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleAuxIgnored.java b/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleAuxIgnored.java deleted file mode 100644 index eafe6e4..0000000 --- a/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleAuxIgnored.java +++ /dev/null @@ -1,14 +0,0 @@ -package example.javaex; - -/** - * - * @author jmarranz - */ -public class JProxyExampleAuxIgnored -{ - public static void log() - { - System.out.println("JProxyExampleAuxIgnored: 2 " + JProxyExampleAuxIgnored.class.getClassLoader().hashCode()); - } -} - diff --git a/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleDocument.java b/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleDocument.java deleted file mode 100644 index f3d8267..0000000 --- a/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleDocument.java +++ /dev/null @@ -1,87 +0,0 @@ -package example.javaex; - -import com.sillelien.dollar.relproxy.jproxy.JProxy; -import example.javaex.hotreload.JProxyExampleAux2; -import example.javaex.nothotreload.JProxyExampleAuxIgnored2; -import example.javaex.nothotreload.JProxyExampleAuxIgnored3; -import org.itsnat.comp.ItsNatComponentManager; -import org.itsnat.comp.text.ItsNatHTMLInputText; -import org.itsnat.core.ItsNatServletRequest; -import org.itsnat.core.html.ItsNatHTMLDocument; -import org.jetbrains.annotations.NotNull; -import org.w3c.dom.Element; -import org.w3c.dom.events.Event; -import org.w3c.dom.events.EventListener; -import org.w3c.dom.events.EventTarget; -import org.w3c.dom.html.HTMLDocument; - -public class JProxyExampleDocument extends JProxyExampleDocumentBase -{ - protected ItsNatHTMLDocument itsNatDoc; // ItsNatHTMLDocument - protected ItsNatHTMLInputText textInput; // ItsNatHTMLInputText - protected Element resultsElem; // Element - - public static class AuxMember - { - public static void log() - { - System.out.println(AuxMember.class.getName() + ": 1 " + AuxMember.class.getClassLoader().hashCode()); - } - } - - public JProxyExampleDocument() // Requerido por el listener ejemplo anonymous inner class del "dlbclick" - { - } - - public JProxyExampleDocument(ItsNatServletRequest request, @NotNull ItsNatHTMLDocument itsNatDoc, @NotNull FalseDB db) - { - class AuxMemberInMethod - { - public void log() - { - System.out.println("JProxyExampleDocument.AuxMemberInMethod: 1 " + AuxMemberInMethod.class.getClassLoader().hashCode()); - } - } - - this.itsNatDoc = itsNatDoc; - - if (db.getCityList().size() != 3) - throw new RuntimeException("Unexpected"); - - HTMLDocument doc = itsNatDoc.getHTMLDocument(); - - ItsNatComponentManager compMgr = itsNatDoc.getItsNatComponentManager(); - this.textInput = (ItsNatHTMLInputText)compMgr.createItsNatComponentById("inputId"); - - EventListener listener = new EventListener() - { - { - System.out.println("JProxyExampleDocument Anonymous Inner 1 " + this.getClass().getClassLoader().hashCode()); - } - - @Override - public void handleEvent(@NotNull Event evt) - { - String text = textInput.getText(); - String comment = " YES I SAID THIS (" + evt.getType() + ")"; - resultsElem.setTextContent(text + comment); - } - }; - - Element buttonElem = doc.getElementById("buttonId"); - ((EventTarget)buttonElem).addEventListener("click",listener,false); - - ((EventTarget)buttonElem).addEventListener("dblclick", JProxy.create(listener, EventListener.class) ,false); - - this.resultsElem = doc.getElementById("resultsId"); - - System.out.println("JProxyExampleDocument 1 " + this.getClass().getClassLoader().hashCode()); - new AuxMemberInMethod().log(); - AuxMember.log(); - JProxyExampleAux.log(); - JProxyExampleAux2.log(); - JProxyExampleAuxIgnored.log(); - JProxyExampleAuxIgnored2.log(); - JProxyExampleAuxIgnored3.log(); - } -} diff --git a/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleDocumentBase.java b/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleDocumentBase.java deleted file mode 100644 index 4b6c98c..0000000 --- a/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleDocumentBase.java +++ /dev/null @@ -1,13 +0,0 @@ -package example.javaex; - -/** - * - * @author jmarranz - */ -public class JProxyExampleDocumentBase -{ - public JProxyExampleDocumentBase() - { - System.out.println("JProxyExampleDocumentBase 7 " + this.getClass().getClassLoader().hashCode()); - } -} diff --git a/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleLoadListener.java b/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleLoadListener.java deleted file mode 100644 index 15314dc..0000000 --- a/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleLoadListener.java +++ /dev/null @@ -1,38 +0,0 @@ -package example.javaex; - -/** - * - * @author jmarranz - */ -import org.itsnat.core.event.ItsNatServletRequestListener; -import org.itsnat.core.ItsNatServletRequest; -import org.itsnat.core.ItsNatServletResponse; -import org.itsnat.core.html.ItsNatHTMLDocument; -import org.jetbrains.annotations.NotNull; - -public class JProxyExampleLoadListener implements ItsNatServletRequestListener -{ - protected final FalseDB db; - @NotNull - protected static Integer testStatic = 10; - protected static final Integer testStaticFinal = 11; - - public JProxyExampleLoadListener() - { - this(null); - } - - public JProxyExampleLoadListener(FalseDB db) - { - this.db = db; - } - - - @Override - public void processRequest(@NotNull ItsNatServletRequest request, ItsNatServletResponse response) - { - System.out.println("JProxyExampleLoadListener 1 " + this.getClass().getClassLoader().hashCode()); - new example.javaex.JProxyExampleDocument(request,(ItsNatHTMLDocument)request.getItsNatDocument(),db); - } -} - diff --git a/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code2/example/javaex/JProxyExampleAux.java b/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code2/example/javaex/JProxyExampleAux.java deleted file mode 100644 index f04ad4d..0000000 --- a/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code2/example/javaex/JProxyExampleAux.java +++ /dev/null @@ -1,14 +0,0 @@ -package example.javaex; - -/** - * - * @author jmarranz - */ -public class JProxyExampleAux -{ - public static void log() - { - System.out.println("JProxyExampleAux: 1 " + JProxyExampleAux.class.getClassLoader().hashCode()); - } -} - diff --git a/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/pages/javaex.html b/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/pages/javaex.html deleted file mode 100644 index ba0aa8a..0000000 --- a/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/pages/javaex.html +++ /dev/null @@ -1,24 +0,0 @@ - - - -JProxy Example (Java) - - -

JProxy Example (Java)

- -
Note: in NetBeans after every hot reloadable source change, execute Ant sync.xml and reload
-
-
- Say something to JProxy:
- -
- -
-
You said:
-
- -

- RETURN - - - diff --git a/relproxy_test_itsnat/src/main/webapp/WEB-INF/lib/ItsNat-1.3.1.jar b/relproxy_test_itsnat/src/main/webapp/WEB-INF/lib/ItsNat-1.3.1.jar deleted file mode 100644 index e2ff917ec6e4ca67ef52a5f066b55f09920989d5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1587553 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
    NUs3Yj&#IO!7#WqyGRE`0= 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

    &l$^U6eay1^2lK(PxrU`DTq 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

    S^qH6v<^>M$aUg$qL_5WWKF`ZwE7z%I0 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¬AM~f>V9$_4oj9OEbOjX6*WWu5g`ZUw# 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ℜ`5rb^5R?QeqhU7M@>2<6!VgxYj06qX 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

    5dAHc19*nPIiuTM%D&SPFd=a+R7)G-?$LL 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