14 | *
15 | * @param message the detail message
16 | * @param cause the cause
17 | */
18 | public RelProxyException(String message, Throwable cause)
19 | {
20 | super(message, cause);
21 | }
22 |
23 | /**
24 | * Constructs a new exception with the specified message.
25 | *
26 | *
Parameter is passed to the super constructor.
27 | *
28 | * @param message the detail message
29 | */
30 | public RelProxyException(String message)
31 | {
32 | super(message);
33 | }
34 |
35 | /**
36 | * Constructs a new exception with the specified cause.
37 | *
38 | *
Parameter is passed to the super constructor.
39 | *
40 | * @param cause the cause
41 | */
42 | public RelProxyException(Throwable cause)
43 | {
44 | super(cause);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootFile.java:
--------------------------------------------------------------------------------
1 | package com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit;
2 |
3 | import com.innowhere.relproxy.impl.FileExt;
4 | import com.innowhere.relproxy.impl.jproxy.JProxyUtil;
5 | import com.innowhere.relproxy.impl.jproxy.core.clsmgr.FolderSourceList;
6 |
7 | /**
8 | *
9 | * @author jmarranz
10 | */
11 | public abstract class SourceScriptRootFile extends SourceScriptRoot
12 | {
13 | protected FileExt sourceFile;
14 |
15 | public SourceScriptRootFile(FileExt sourceFile,FolderSourceList folderSourceList)
16 | {
17 | super(buildClassNameFromFile(sourceFile,folderSourceList));
18 | this.sourceFile = sourceFile;
19 | }
20 |
21 | public static SourceScriptRootFile createSourceScriptRootFile(FileExt sourceFile,FolderSourceList folderSourceList)
22 | {
23 | String ext = JProxyUtil.getFileExtension(sourceFile.getFile()); // Si no tiene extensión devuelve ""
24 | if ("java".equals(ext))
25 | return new SourceScriptRootFileJavaExt(sourceFile,folderSourceList);
26 | else
27 | return new SourceScriptRootFileOtherExt(sourceFile,folderSourceList); // Caso de archivo script inicial sin extensión .java (puede ser sin extensión)
28 | }
29 |
30 | @Override
31 | public long lastModified()
32 | {
33 | return sourceFile.getFile().lastModified();
34 | }
35 |
36 | public FileExt getFileExt()
37 | {
38 | return sourceFile;
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/relproxy/src/main/java/com/innowhere/relproxy/gproxy/GProxyGroovyScriptEngine.java:
--------------------------------------------------------------------------------
1 | package com.innowhere.relproxy.gproxy;
2 |
3 | /**
4 | * Interface to implement the object implementing the GroovyScriptEngine wrapper used to reload Groovy classes.
5 | *
6 | *
The following is a very simple example of the required implementation, groovyEngine is the groovy.util.GroovyScriptEngine
7 | * object:
8 |
9 | def gproxyGroovyEngine = {
10 | String scriptName -> return (java.lang.Class)groovyEngine.loadScriptByName(scriptName)
11 | } as GProxyGroovyScriptEngine;
12 |
13 | *
14 | *
15 | * @see GProxyConfig#setGProxyGroovyScriptEngine(GProxyGroovyScriptEngine)
16 | * @author Jose Maria Arranz Santamaria
17 | */
18 | public interface GProxyGroovyScriptEngine
19 | {
20 | /**
21 | * The class implementing this method must call the method groovy.util.GroovyScriptEngine.loadScriptByName(String scriptName) passing
22 | * the scriptName.
23 | *
24 | *
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
25 | * has changed because Groovy has reloaded the class when a source code has been detected.
26 | *
27 | * @param scriptName the name of the Groovy script/class.
28 | * @return the class associated to the specified Groovy script.
29 | */
30 | public Class loadScriptByName(String scriptName);
31 | }
32 |
--------------------------------------------------------------------------------
/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellInteractiveTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * To change this license header, choose License Headers in Project Properties.
3 | * To change this template file, choose Tools | Templates
4 | * and open the template in the editor.
5 | */
6 |
7 | package com.innowhere.relproxy.jproxy;
8 |
9 | import org.junit.After;
10 | import org.junit.AfterClass;
11 | import org.junit.Before;
12 | import org.junit.BeforeClass;
13 | import org.junit.Test;
14 | import static org.junit.Assert.*;
15 |
16 | /**
17 | *
18 | * @author jmarranz
19 | */
20 | public class JProxyJavaShellInteractiveTest
21 | {
22 | public JProxyJavaShellInteractiveTest()
23 | {
24 | }
25 |
26 | @BeforeClass
27 | public static void setUpClass()
28 | {
29 | }
30 |
31 | @AfterClass
32 | public static void tearDownClass()
33 | {
34 | }
35 |
36 | @Before
37 | public void setUp()
38 | {
39 |
40 | }
41 |
42 | @After
43 | public void tearDown()
44 | {
45 |
46 | }
47 |
48 | @Test
49 | public void test_java_shell_interactive()
50 | {
51 | String compilationOptions = "-source 1.6 -target 1.6";
52 |
53 | String[] args = new String[]
54 | {
55 | "", // El args[0] esperado
56 | "-DcompilationOptions=" + compilationOptions,
57 | "-Dtest=true"
58 | };
59 |
60 | JProxyShell.main(args);
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/relproxy/src/main/java/com/innowhere/relproxy/RelProxyOnReloadListener.java:
--------------------------------------------------------------------------------
1 | package com.innowhere.relproxy;
2 |
3 | import java.lang.reflect.Method;
4 |
5 | /**
6 | * Is the interface needed to register a class reload listener.
7 | *
8 | *
An object implementing this interface can optionally be registered on RelProxy to listen when the method of a proxy object has been called
9 | * 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).
10 | *
If set to false other configuration parameters are ignored, there is no automatic source code change detection/reload and original objects are returned
19 | * instead of proxies, performance penalty is zero. Setting to false is recommended in production whether source code change detection/reload is not required.
20 | *
21 | * @param enabled whether automatic source code change detection and reload is enabled. By default is true.
22 | * @return this object for flow API use.
23 | */
24 | public GProxyConfig setEnabled(boolean enabled);
25 |
26 | /**
27 | * Sets the class reload listener.
28 | *
29 | * @param relListener the class reload listener. By default is null.
30 | * @return this object for flow API use.
31 | */
32 | public GProxyConfig setRelProxyOnReloadListener(RelProxyOnReloadListener relListener);
33 |
34 | /**
35 | * Sets the object implementing the GroovyScriptEngine wrapper used to reload Groovy classes.
36 | *
37 | *
This parameter is required otherwise there is no bridge between RelProxy and Groovy because there is no explicit Groovy dependency in RelProxy.
38 | *
39 | * @param engine the GroovyScriptEngine wrapper.
40 | * @return this object for flow API use.
41 | */
42 | public GProxyConfig setGProxyGroovyScriptEngine(GProxyGroovyScriptEngine engine);
43 | }
44 |
--------------------------------------------------------------------------------
/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/LinuxUnicodeKeyboard.java:
--------------------------------------------------------------------------------
1 | package com.innowhere.relproxy.impl.jproxy.shell.inter;
2 |
3 | import static java.awt.event.KeyEvent.VK_CONTROL;
4 | import static java.awt.event.KeyEvent.VK_SHIFT;
5 | import static java.awt.event.KeyEvent.VK_U;
6 | import java.nio.charset.Charset;
7 |
8 | /**
9 | *
10 | * http://superuser.com/questions/59418/how-to-type-special-characters-in-linux
11 | *
12 | * @author jmarranz
13 | */
14 | public class LinuxUnicodeKeyboard extends KeyboardNotUsingClipboard
15 | {
16 | public LinuxUnicodeKeyboard(Charset cs)
17 | {
18 | super(cs);
19 | }
20 |
21 | @Override
22 | public boolean isUseCodePoint()
23 | {
24 | return true;
25 | }
26 |
27 | @Override
28 | public boolean type(char character)
29 | {
30 | if (super.type(character))
31 | return true;
32 |
33 | String unicodeDigits = getUnicodeDigits(character,16); // En hexadecimal
34 |
35 | robot.keyPress(VK_CONTROL);
36 | robot.keyPress(VK_SHIFT);
37 |
38 | doType(VK_U); // 'u' indica que después viene un valor unicode hexadecimal
39 |
40 | // Pero dejamos pulsadas CTRL y SHIFT mientras
41 | // Ejemplo: 266A es una nota de solfeo
42 | try
43 | {
44 | for (int i = 0; i < unicodeDigits.length(); i++)
45 | {
46 | char c = unicodeDigits.charAt(i);
47 | if (Character.isDigit(c))
48 | typeNumPad(Integer.parseInt(unicodeDigits.substring(i, i + 1)));
49 | else
50 | type(c);
51 | }
52 | }
53 | finally
54 | {
55 | robot.keyRelease(VK_CONTROL);
56 | robot.keyRelease(VK_SHIFT);
57 | }
58 |
59 | return true;
60 | }
61 |
62 | }
--------------------------------------------------------------------------------
/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/srcunit/SourceScriptRootInMemory.java:
--------------------------------------------------------------------------------
1 | package com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit;
2 |
3 | /**
4 | *
5 | * @author jmarranz
6 | */
7 | public class SourceScriptRootInMemory extends SourceScriptRoot
8 | {
9 | public static final String DEFAULT_CLASS_NAME = "_jproxyMainClass_"; // OJO NO CAMBIAR, está ya documentada
10 |
11 | protected String code;
12 | protected long timestamp;
13 |
14 | private SourceScriptRootInMemory(String className,String code)
15 | {
16 | super(className);
17 | setScriptCode(code,System.currentTimeMillis());
18 | }
19 |
20 | public static SourceScriptRootInMemory createSourceScriptInMemory(String code)
21 | {
22 | return new SourceScriptRootInMemory(DEFAULT_CLASS_NAME,code);
23 | }
24 |
25 | @Override
26 | public long lastModified()
27 | {
28 | return timestamp; // Siempre ha sido modificado
29 | }
30 |
31 | @Override
32 | public String getScriptCode(String encoding,boolean[] hasHashBang)
33 | {
34 | hasHashBang[0] = false;
35 | return code;
36 | }
37 |
38 | public boolean isEmptyCode()
39 | {
40 | // Si code es "" la clase especial se genera pero no hace nada simplemente devuelve un null.
41 | // 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
42 | // en interfaces, pero tiene el inconveniente de generarse un SourceScriptRootInMemory inútil que no hace nada
43 | return code.isEmpty();
44 | }
45 |
46 | public String getScriptCode()
47 | {
48 | return code;
49 | }
50 |
51 | public final void setScriptCode(String code,long timestamp)
52 | {
53 | this.code = code;
54 | this.timestamp = timestamp;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyJavaShellCompleteClassTest.java:
--------------------------------------------------------------------------------
1 | package com.innowhere.relproxy.jproxy;
2 |
3 | import com.innowhere.relproxy.jproxy.util.JProxyTestUtil;
4 | import java.io.File;
5 | import org.junit.After;
6 | import org.junit.AfterClass;
7 | import org.junit.Before;
8 | import org.junit.BeforeClass;
9 | import org.junit.Test;
10 |
11 | /**
12 | *
13 | * @author jmarranz
14 | */
15 | public class JProxyJavaShellCompleteClassTest
16 | {
17 |
18 |
19 |
20 | public JProxyJavaShellCompleteClassTest()
21 | {
22 | }
23 |
24 | @BeforeClass
25 | public static void setUpClass()
26 | {
27 | }
28 |
29 | @AfterClass
30 | public static void tearDownClass()
31 | {
32 | }
33 |
34 | @Before
35 | public void setUp()
36 | {
37 |
38 | }
39 |
40 | @After
41 | public void tearDown()
42 | {
43 |
44 | }
45 |
46 |
47 | @Test
48 | public void test_java_shell()
49 | {
50 | File projectFolder = JProxyTestUtil.getProjectFolder();
51 | File inputFolderFile = new File(projectFolder,JProxyTestUtil.RESOURCES_FOLDER);
52 | File cacheClassFolderFile = new File(projectFolder,JProxyTestUtil.CACHE_CLASS_FOLDER);
53 |
54 | String inputPath = inputFolderFile.getAbsolutePath();
55 | String cacheClassFolder = cacheClassFolderFile.getAbsolutePath();
56 | String compilationOptions = "-source 1.6 -target 1.6";
57 |
58 | String[] args = new String[]
59 | {
60 | inputPath + "/example_java_shell_complete_class",
61 | "HELLO ",
62 | "WORLD!",
63 | "-DcacheClassFolder=" + cacheClassFolder,
64 | "-DcompilationOptions=" + compilationOptions,
65 | };
66 |
67 | JProxyShell.main(args);
68 | }
69 |
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/relproxy/src/main/java/com/innowhere/relproxy/impl/GenericProxyImpl.java:
--------------------------------------------------------------------------------
1 | package com.innowhere.relproxy.impl;
2 |
3 | import com.innowhere.relproxy.RelProxyException;
4 | import com.innowhere.relproxy.RelProxyOnReloadListener;
5 | import java.lang.reflect.InvocationHandler;
6 | import java.lang.reflect.Proxy;
7 |
8 | /**
9 | *
10 | * @author jmarranz
11 | */
12 | public abstract class GenericProxyImpl
13 | {
14 | protected RelProxyOnReloadListener reloadListener;
15 |
16 | public GenericProxyImpl()
17 | {
18 | }
19 |
20 | public static void checkSingletonNull(GenericProxyImpl singleton)
21 | {
22 | if (singleton != null)
23 | throw new RelProxyException("Already initialized");
24 | }
25 |
26 | protected static void checkSingletonExists(GenericProxyImpl singleton)
27 | {
28 | if (singleton == null)
29 | throw new RelProxyException("Execute first the init method");
30 | }
31 |
32 | protected void init(GenericProxyConfigBaseImpl config)
33 | {
34 | this.reloadListener = config.getRelProxyOnReloadListener();
35 | }
36 |
37 | public RelProxyOnReloadListener getRelProxyOnReloadListener()
38 | {
39 | return reloadListener;
40 | }
41 |
42 | public T create(T obj,Class clasz)
43 | {
44 | if (obj == null) return null;
45 |
46 | return (T)create(obj,new Class[] { clasz });
47 | }
48 |
49 | public Object create(Object obj,Class[] classes)
50 | {
51 | if (obj == null) return null;
52 |
53 | InvocationHandler handler = createGenericProxyInvocationHandler(obj);
54 |
55 | Object proxy = Proxy.newProxyInstance(obj.getClass().getClassLoader(),classes, handler);
56 | return proxy;
57 | }
58 |
59 |
60 | public abstract GenericProxyInvocationHandler createGenericProxyInvocationHandler(Object obj);
61 | }
62 |
--------------------------------------------------------------------------------
/relproxy_test_itsnat/src/main/webapp/WEB-INF/groovyex/code/example/groovyex/groovy_servlet_init.groovy:
--------------------------------------------------------------------------------
1 |
2 | package example.groovyex;
3 |
4 | import org.itsnat.core.http.ItsNatHttpServlet;
5 | import org.itsnat.core.tmpl.ItsNatDocumentTemplate;
6 | import org.itsnat.core.event.ItsNatServletRequestListener;
7 | import groovy.util.GroovyScriptEngine;
8 | import java.lang.reflect.Method;
9 | import com.innowhere.relproxy.RelProxyOnReloadListener;
10 | import com.innowhere.relproxy.gproxy.GProxy;
11 | import com.innowhere.relproxy.gproxy.GProxyGroovyScriptEngine;
12 | import com.innowhere.relproxy.gproxy.GProxyConfig;
13 |
14 |
15 | GroovyScriptEngine groovyEngine = servlet.getGroovyScriptEngine();
16 |
17 | def gproxyGroovyEngine = {
18 | String scriptName -> return (java.lang.Class)groovyEngine.loadScriptByName(scriptName)
19 | } as GProxyGroovyScriptEngine;
20 |
21 | /* This alternative throws a weird error when called loadScriptByName, why?
22 | GProxyGroovyScriptEngine groovyEngine =
23 | {
24 | loadScriptByName : { String scriptName -> return (java.lang.Class)servlet.getGroovyScriptEngine().loadScriptByName(scriptName) }
25 | } as GProxyGroovyScriptEngine;
26 | */
27 |
28 | def reloadListener = {
29 | Object objOld,Object objNew,Object proxy, Method method, Object[] args ->
30 | println("Reloaded " + objNew + " Calling method: " + method)
31 | } as RelProxyOnReloadListener;
32 |
33 | def gpConfig = GProxy.createGProxyConfig();
34 | gpConfig.setEnabled(true)
35 | .setRelProxyOnReloadListener(reloadListener)
36 | .setGProxyGroovyScriptEngine(gproxyGroovyEngine);
37 |
38 | GProxy.init(gpConfig);
39 |
40 |
41 | String pathPrefix = context.getRealPath("/") + "/WEB-INF/groovyex/pages/";
42 |
43 | def docTemplate;
44 | docTemplate = itsNatServlet.registerItsNatDocumentTemplate("groovyex","text/html", pathPrefix + "groovyex.html");
45 |
46 | def db = new FalseDB();
47 |
48 | ItsNatServletRequestListener listener = GProxy.create(new example.groovyex.GroovyExampleLoadListener(db), ItsNatServletRequestListener.class);
49 | docTemplate.addItsNatServletRequestListener(listener);
50 |
51 |
--------------------------------------------------------------------------------
/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputSourceBase.java:
--------------------------------------------------------------------------------
1 | package com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo;
2 |
3 | import com.innowhere.relproxy.RelProxyException;
4 | import java.io.ByteArrayInputStream;
5 | import java.io.IOException;
6 | import java.io.InputStream;
7 | import java.io.OutputStream;
8 | import java.io.UnsupportedEncodingException;
9 | import java.net.URI;
10 | import javax.tools.SimpleJavaFileObject;
11 |
12 | /**
13 | * http://www.javablogging.com/dynamic-in-memory-compilation/
14 | *
15 | * @author jmarranz
16 | */
17 | public abstract class JavaFileObjectInputSourceBase extends SimpleJavaFileObject implements JProxyJavaFileObjectInput
18 | {
19 | protected String binaryName;
20 | protected String encoding;
21 |
22 | public JavaFileObjectInputSourceBase(String name,String encoding)
23 | {
24 | super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE); // La extensión .java es necesaria aunque sea falsa sino da error
25 |
26 | this.binaryName = name;
27 | this.encoding = encoding;
28 | }
29 |
30 | protected abstract String getSource();
31 |
32 |
33 | @Override
34 | public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException
35 | {
36 | return getSource();
37 | }
38 |
39 | public byte[] getBytes()
40 | {
41 | try
42 | {
43 | return getSource().getBytes(encoding);
44 | }
45 | catch (UnsupportedEncodingException ex) { throw new RelProxyException(ex); }
46 | }
47 |
48 | @Override
49 | public InputStream openInputStream() throws IOException
50 | {
51 | return new ByteArrayInputStream(getBytes());
52 | }
53 |
54 | @Override
55 | public OutputStream openOutputStream() throws IOException
56 | {
57 | throw new UnsupportedOperationException();
58 | }
59 |
60 | public String getBinaryName()
61 | {
62 | return binaryName;
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/KeyboardUsingClipboard.java:
--------------------------------------------------------------------------------
1 | package com.innowhere.relproxy.impl.jproxy.shell.inter;
2 |
3 |
4 | import com.innowhere.relproxy.RelProxyException;
5 | import java.awt.AWTException;
6 | import java.awt.Robot;
7 | import java.awt.Toolkit;
8 | import java.awt.datatransfer.Clipboard;
9 | import java.awt.datatransfer.ClipboardOwner;
10 | import java.awt.datatransfer.StringSelection;
11 | import java.awt.datatransfer.Transferable;
12 | import java.awt.event.KeyEvent;
13 | import java.nio.charset.Charset;
14 |
15 | /**
16 | * http://stackoverflow.com/questions/1248510/convert-string-to-keyevents
17 | * http://en.wikipedia.org/wiki/Unicode_input#Hexadecimal_code_input
18 | * http://stackoverflow.com/questions/9814701/accent-with-robot-keypress
19 | *
20 | * @author jmarranz
21 | */
22 | public class KeyboardUsingClipboard extends Keyboard implements ClipboardOwner
23 | {
24 | protected final Robot robot;
25 | protected Charset cs;
26 |
27 |
28 | public KeyboardUsingClipboard(Charset cs)
29 | {
30 | this.cs = cs;
31 | try
32 | {
33 | this.robot = new Robot();
34 | }
35 | catch (AWTException ex)
36 | {
37 | throw new RelProxyException(ex);
38 | }
39 | }
40 |
41 | public static KeyboardUsingClipboard create(Charset cs)
42 | {
43 | return new KeyboardUsingClipboard(cs);
44 | }
45 |
46 |
47 | @Override
48 | public void type(CharSequence characters)
49 | {
50 | Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
51 | StringSelection stringSelection = new StringSelection( characters.toString() );
52 | clipboard.setContents(stringSelection, this);
53 |
54 | robot.keyPress(KeyEvent.VK_CONTROL);
55 | robot.keyPress(KeyEvent.VK_V);
56 | robot.keyRelease(KeyEvent.VK_V);
57 | robot.keyRelease(KeyEvent.VK_CONTROL);
58 | }
59 |
60 | @Override
61 | public void lostOwnership(Clipboard clipboard, Transferable contents)
62 | {
63 |
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/relproxy/src/test/java/com/innowhere/relproxy/jproxy/JProxyCodeSnippetCompleteClassTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * To change this license header, choose License Headers in Project Properties.
3 | * To change this template file, choose Tools | Templates
4 | * and open the template in the editor.
5 | */
6 |
7 | package com.innowhere.relproxy.jproxy;
8 |
9 | import org.junit.After;
10 | import org.junit.AfterClass;
11 | import org.junit.Before;
12 | import org.junit.BeforeClass;
13 | import org.junit.Test;
14 | import static org.junit.Assert.*;
15 |
16 | /**
17 | *
18 | * @author jmarranz
19 | */
20 | public class JProxyCodeSnippetCompleteClassTest
21 | {
22 | public static boolean RESULT;
23 |
24 | public JProxyCodeSnippetCompleteClassTest()
25 | {
26 | }
27 |
28 | @BeforeClass
29 | public static void setUpClass()
30 | {
31 | }
32 |
33 | @AfterClass
34 | public static void tearDownClass()
35 | {
36 | }
37 |
38 | @Before
39 | public void setUp()
40 | {
41 | RESULT = false;
42 | }
43 |
44 | @After
45 | public void tearDown()
46 | {
47 | RESULT = false;
48 | }
49 |
50 | @Test
51 | public void test_code_snippet_complete_class()
52 | {
53 | String compilationOptions = "-source 1.6 -target 1.6";
54 |
55 | String[] args = new String[]
56 | {
57 | "-c",
58 | "public class _jproxyMainClass_ { ",
59 | " public static void main(String[] args) { ",
60 | " System.out.print(\"This code snippet says: \");",
61 | " System.out.println(\"Hello World!!\");",
62 | JProxyCodeSnippetCompleteClassTest.class.getName() + ".RESULT = true;",
63 | " }",
64 | "}",
65 | "-DcompilationOptions=" + compilationOptions
66 | };
67 |
68 | JProxyShell.main(args);
69 |
70 | assertTrue(RESULT);
71 |
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandDelete.java:
--------------------------------------------------------------------------------
1 | package com.innowhere.relproxy.impl.jproxy.shell.inter;
2 |
3 |
4 | /**
5 | *
6 | * @author jmarranz
7 | */
8 | public class CommandDelete extends CommandCodeChangerBase
9 | {
10 | public static final String NAME = "delete";
11 |
12 | public CommandDelete(JProxyShellProcessor parent,int line)
13 | {
14 | super(parent,NAME,line);
15 | }
16 |
17 | public static CommandDelete createCommandDelete(JProxyShellProcessor parent,String cmd)
18 | {
19 | int line = getLineFromParam(parent,NAME,cmd);
20 | if (line < 0)
21 | {
22 | switch(line)
23 | {
24 | case ERROR_LAST_REQUIRED:
25 | System.out.println("Command error: parameter \"last\" or a line number is required");
26 | break;
27 | case ERROR_NO_LAST_LINE:
28 | System.out.println("Command error: no new or edited line code has been introduced");
29 | break;
30 | case ERROR_NOT_A_NUMBER:
31 | System.out.println("Command error: line value is not a number");
32 | break;
33 | case ERROR_VALUE_NOT_0_OR_NEGATIVE:
34 | System.out.println("Command error: line value cannot be 0 or negative");
35 | break;
36 | case ERROR_LINE_1_NOT_VALID:
37 | System.out.println("Command error: line 1 is ever empty and cannot be deleted");
38 | break;
39 | case ERROR_OUT_OF_RANGE:
40 | System.out.println("Command error: line number out of range");
41 | break;
42 | default:
43 | // Para que se calle el FindBugs
44 | }
45 | return null;
46 | }
47 |
48 | return new CommandDelete(parent,line);
49 | }
50 |
51 | @Override
52 | public void runPostCommand()
53 | {
54 | parent.removeCodeBuffer(line);
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandInsert.java:
--------------------------------------------------------------------------------
1 | package com.innowhere.relproxy.impl.jproxy.shell.inter;
2 |
3 |
4 | /**
5 | *
6 | * @author jmarranz
7 | */
8 | public class CommandInsert extends CommandCodeChangerBase
9 | {
10 | public static final String NAME = "insert";
11 |
12 | public CommandInsert(JProxyShellProcessor parent,int line)
13 | {
14 | super(parent,NAME,line);
15 | }
16 |
17 | public static CommandInsert createCommandInsert(JProxyShellProcessor parent,String cmd)
18 | {
19 | int line = getLineFromParam(parent,NAME,cmd);
20 | if (line < 0)
21 | {
22 | switch(line)
23 | {
24 | case ERROR_LAST_REQUIRED:
25 | System.out.println("Command error: parameter \"last\" or a line number is required");
26 | break;
27 | case ERROR_NO_LAST_LINE:
28 | System.out.println("Command error: no new or edited line code has been introduced");
29 | break;
30 | case ERROR_NOT_A_NUMBER:
31 | System.out.println("Command error: line value is not a number");
32 | break;
33 | case ERROR_VALUE_NOT_0_OR_NEGATIVE:
34 | System.out.println("Command error: line value cannot be 0 or negative");
35 | break;
36 | case ERROR_LINE_1_NOT_VALID:
37 | System.out.println("Command error: line 1 is ever empty and no code can be inserted before");
38 | break;
39 | case ERROR_OUT_OF_RANGE:
40 | System.out.println("Command error: line number out of range");
41 | break;
42 | default:
43 | // Para que se calle el FindBugs
44 | }
45 | return null;
46 | }
47 |
48 | return new CommandInsert(parent,line);
49 | }
50 |
51 | @Override
52 | public void runPostCommand()
53 | {
54 | parent.insertCodeBuffer(line,"");
55 | parent.setLineEditing(line);
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandEdit.java:
--------------------------------------------------------------------------------
1 | package com.innowhere.relproxy.impl.jproxy.shell.inter;
2 |
3 |
4 | /**
5 | *
6 | * @author jmarranz
7 | */
8 | public class CommandEdit extends CommandCodeChangerBase
9 | {
10 | public static final String NAME = "edit";
11 | protected String codeLine;
12 |
13 | public CommandEdit(JProxyShellProcessor parent,int line,String codeLine)
14 | {
15 | super(parent,NAME,line);
16 | this.codeLine = codeLine;
17 | }
18 |
19 | public static CommandEdit createCommandEdit(JProxyShellProcessor parent,String cmd)
20 | {
21 | int line = getLineFromParam(parent,NAME,cmd);
22 | if (line < 0)
23 | {
24 | switch(line)
25 | {
26 | case ERROR_LAST_REQUIRED:
27 | System.out.println("Command error: parameter \"last\" or a line number is required");
28 | break;
29 | case ERROR_NO_LAST_LINE:
30 | System.out.println("Command error: no new or edited line code has been introduced");
31 | break;
32 | case ERROR_NOT_A_NUMBER:
33 | System.out.println("Command error: line value is not a number");
34 | break;
35 | case ERROR_VALUE_NOT_0_OR_NEGATIVE:
36 | System.out.println("Command error: line value cannot be 0 or negative");
37 | break;
38 | case ERROR_LINE_1_NOT_VALID:
39 | System.out.println("Command error: line 1 is ever empty and cannot be edited");
40 | break;
41 | case ERROR_OUT_OF_RANGE:
42 | System.out.println("Command error: line number out of range");
43 | break;
44 | default:
45 | // Para que se calle el FindBugs
46 | }
47 | return null;
48 | }
49 |
50 | String codeLine = parent.getCodeBuffer().get(line);
51 | return new CommandEdit(parent,line,codeLine);
52 | }
53 |
54 | @Override
55 | public void runPostCommand()
56 | {
57 | parent.getKeyboard().type(codeLine);
58 | parent.setLineEditing(line);
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/JProxyDefaultImpl.java:
--------------------------------------------------------------------------------
1 | package com.innowhere.relproxy.impl.jproxy;
2 |
3 | import com.innowhere.relproxy.impl.jproxy.core.JProxyImpl;
4 | import com.innowhere.relproxy.jproxy.JProxyConfig;
5 |
6 | /**
7 | *
8 | * @author jmarranz
9 | */
10 | public class JProxyDefaultImpl extends JProxyImpl
11 | {
12 | public JProxyDefaultImpl()
13 | {
14 | }
15 |
16 | @Override
17 | public Class getMainParamClass()
18 | {
19 | return null;
20 | }
21 |
22 | public static JProxyConfig createJProxyConfig()
23 | {
24 | return new JProxyConfigImpl();
25 | }
26 |
27 | public static void initStatic(JProxyConfigImpl config)
28 | {
29 | if (!config.isEnabled()) return;
30 |
31 | checkSingletonNull(SINGLETON);
32 | SINGLETON = new JProxyDefaultImpl();
33 | SINGLETON.init(config);
34 | }
35 |
36 |
37 | public static T createStatic(T obj,Class clasz)
38 | {
39 | if (SINGLETON == null)
40 | return obj; // No se ha llamado al init o enabled = false
41 |
42 | return SINGLETON.create(obj, clasz);
43 | }
44 |
45 | public static Object createStatic(Object obj,Class>[] classes)
46 | {
47 | if (SINGLETON == null)
48 | return obj; // No se ha llamado al init o enabled = false
49 |
50 | return SINGLETON.create(obj, classes);
51 | }
52 |
53 |
54 | public static boolean isEnabledStatic()
55 | {
56 | if (SINGLETON == null)
57 | return false;
58 |
59 | return SINGLETON.isEnabled();
60 | }
61 |
62 |
63 | public static boolean isRunningStatic()
64 | {
65 | if (SINGLETON == null)
66 | return false;
67 |
68 | return SINGLETON.isRunning();
69 | }
70 |
71 | public static boolean stopStatic()
72 | {
73 | if (SINGLETON == null)
74 | return false;
75 |
76 | return SINGLETON.stop();
77 | }
78 |
79 | public static boolean startStatic()
80 | {
81 | if (SINGLETON == null)
82 | return false;
83 |
84 | return SINGLETON.start();
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandCodeChangerBase.java:
--------------------------------------------------------------------------------
1 | package com.innowhere.relproxy.impl.jproxy.shell.inter;
2 |
3 |
4 | /**
5 | *
6 | * @author jmarranz
7 | */
8 | public abstract class CommandCodeChangerBase extends Command
9 | {
10 | public static final int ERROR_LAST_REQUIRED = -1;
11 | public static final int ERROR_NO_LAST_LINE = -2;
12 | public static final int ERROR_NOT_A_NUMBER = -3;
13 | public static final int ERROR_VALUE_NOT_0_OR_NEGATIVE = -4;
14 | public static final int ERROR_LINE_1_NOT_VALID = -5;
15 | public static final int ERROR_OUT_OF_RANGE = -6;
16 |
17 |
18 | protected int line;
19 |
20 | public CommandCodeChangerBase(JProxyShellProcessor parent,String name,int line)
21 | {
22 | super(parent,name);
23 | this.line = line;
24 | }
25 |
26 | public static int getLineFromParam(JProxyShellProcessor parent,String name,String cmd)
27 | {
28 | String param = getParameter(name,cmd);
29 | if (param == null)
30 | {
31 | return ERROR_LAST_REQUIRED;
32 | }
33 |
34 | int line;
35 | if (param.equals("last"))
36 | {
37 | int lastLine = parent.getLastLine();
38 | if (lastLine == -1)
39 | {
40 | return ERROR_NO_LAST_LINE;
41 | }
42 | line = lastLine;
43 | }
44 | else
45 | {
46 | try
47 | {
48 | line = Integer.parseInt(param);
49 | }
50 | catch(NumberFormatException ex)
51 | {
52 | return ERROR_NOT_A_NUMBER;
53 | }
54 | // Ojo es el valor dado por el usuario (empezando en 1 y con línea vacía)
55 | if (line <= 0)
56 | {
57 | return ERROR_VALUE_NOT_0_OR_NEGATIVE;
58 | }
59 | else if (line == 1)
60 | {
61 | return ERROR_LINE_1_NOT_VALID;
62 | }
63 | line -= JProxyShellProcessor.LINE_OFFSET;
64 |
65 | if (line >= parent.getCodeBuffer().size())
66 | {
67 | return ERROR_OUT_OF_RANGE;
68 | }
69 | }
70 | return line;
71 | }
72 |
73 |
74 | @Override
75 | public boolean run()
76 | {
77 | return true;
78 | }
79 |
80 | }
81 |
--------------------------------------------------------------------------------
/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandLoad.java:
--------------------------------------------------------------------------------
1 | package com.innowhere.relproxy.impl.jproxy.shell.inter;
2 |
3 | import com.innowhere.relproxy.impl.jproxy.JProxyUtil;
4 | import java.io.File;
5 | import java.net.URI;
6 | import java.net.URL;
7 | import java.util.LinkedList;
8 | import java.util.Scanner;
9 |
10 | /**
11 | *
12 | * @author jmarranz
13 | */
14 | public class CommandLoad extends Command
15 | {
16 | public static final String NAME = "load";
17 | protected String url;
18 |
19 | public CommandLoad(JProxyShellProcessor parent,String url)
20 | {
21 | super(parent,NAME);
22 | this.url = url;
23 | }
24 |
25 | public static CommandLoad createCommandLoad(JProxyShellProcessor parent,String cmd)
26 | {
27 | String url = getParameter(NAME,cmd);
28 | if (url == null)
29 | {
30 | System.out.println("Command error: parameter is required");
31 | return null;
32 | }
33 |
34 | return new CommandLoad(parent,url);
35 | }
36 |
37 | @Override
38 | public boolean run()
39 | {
40 | try
41 | {
42 | byte[] content;
43 | URI uri = new URI(url);
44 | if (uri.getScheme() == null) // Archivo
45 | {
46 | File file = new File(url);
47 | content = JProxyUtil.readFile(file);
48 | }
49 | else // URL (incluyendo file:///...)
50 | {
51 | URL urlObj = new URL(url);
52 | content = JProxyUtil.readURL(urlObj); // Como no conocemos encoding...
53 | }
54 |
55 | String code = new String(content,parent.getEncoding()); // Como no conocemos encoding...
56 | LinkedList lines = new LinkedList();
57 | Scanner scanner = new Scanner(code);
58 | while (scanner.hasNextLine())
59 | {
60 | String line = scanner.nextLine();
61 | lines.add(line);
62 | }
63 |
64 | parent.setCodeBuffer(lines);
65 | return true;
66 | }
67 | catch (Exception ex)
68 | {
69 | ex.printStackTrace();
70 | return false;
71 | }
72 | }
73 |
74 | @Override
75 | public void runPostCommand()
76 | {
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/JProxyShellCodeSnippetImpl.java:
--------------------------------------------------------------------------------
1 | package com.innowhere.relproxy.impl.jproxy.shell;
2 |
3 | import com.innowhere.relproxy.RelProxyException;
4 | import com.innowhere.relproxy.impl.jproxy.JProxyConfigImpl;
5 | import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript;
6 | import com.innowhere.relproxy.impl.jproxy.core.clsmgr.FolderSourceList;
7 | import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot;
8 | import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootInMemory;
9 | import java.util.LinkedList;
10 |
11 | /**
12 | *
13 | * @author jmarranz
14 | */
15 | public class JProxyShellCodeSnippetImpl extends JProxyShellImpl
16 | {
17 | public void init(String[] args)
18 | {
19 | super.init(args, null);
20 | }
21 |
22 | @Override
23 | protected void executeFirstTime(ClassDescriptorSourceScript scriptFileDesc,LinkedList argsToScript,JProxyShellClassLoader classLoader)
24 | {
25 | try
26 | {
27 | scriptFileDesc.callMainMethod(argsToScript);
28 | }
29 | catch(Throwable ex)
30 | {
31 | ex.printStackTrace(System.out);
32 | }
33 | }
34 |
35 | @Override
36 | protected void processConfigParams(String[] args,LinkedList argsToScript,JProxyConfigImpl config)
37 | {
38 | super.processConfigParams(args, argsToScript, config);
39 |
40 | String classFolder = config.getClassFolder();
41 | if (classFolder != null && !classFolder.trim().isEmpty()) throw new RelProxyException("cacheClassFolder is useless to execute a code snippet");
42 | }
43 |
44 | @Override
45 | protected SourceScriptRoot createSourceScriptRoot(String[] args,LinkedList argsToScript,FolderSourceList folderSourceList)
46 | {
47 | // En argsToScript no está el args[0] ni falta que hace porque es el flag "-c"
48 | StringBuilder code = new StringBuilder();
49 | for(String chunk : argsToScript)
50 | code.append(chunk);
51 | return SourceScriptRootInMemory.createSourceScriptInMemory(code.toString());
52 | }
53 |
54 | @Override
55 | protected JProxyShellClassLoader getJProxyShellClassLoader(JProxyConfigImpl config)
56 | {
57 | // No hay classFolder => no hay necesidad de nuevo ClassLoader
58 | return null;
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/relproxy/src/main/java/com/innowhere/relproxy/impl/GenericProxyInvocationHandler.java:
--------------------------------------------------------------------------------
1 | package com.innowhere.relproxy.impl;
2 |
3 | import com.innowhere.relproxy.RelProxyOnReloadListener;
4 | import java.lang.reflect.InvocationHandler;
5 | import java.lang.reflect.Method;
6 | import java.lang.reflect.Proxy;
7 |
8 | /**
9 | *
10 | * @author jmarranz
11 | */
12 | public abstract class GenericProxyInvocationHandler implements InvocationHandler
13 | {
14 | protected GenericProxyImpl root;
15 | protected GenericProxyVersionedObject verObj;
16 |
17 | public GenericProxyInvocationHandler(GenericProxyImpl root)
18 | {
19 | this.root = root;
20 | }
21 |
22 | private Object getCurrent()
23 | {
24 | return verObj.getCurrent();
25 | }
26 |
27 | private Object getNewVersion() throws Throwable
28 | {
29 | return verObj.getNewVersion();
30 | }
31 |
32 | @Override
33 | public synchronized Object invoke(Object proxy, Method method, Object[] args) throws Throwable
34 | {
35 | Object oldObj = getCurrent();
36 | Object obj = getNewVersion();
37 |
38 | RelProxyOnReloadListener reloadListener = root.getRelProxyOnReloadListener();
39 | if (oldObj != obj && reloadListener != null)
40 | reloadListener.onReload(oldObj,obj,proxy,method,args);
41 |
42 | if (args != null && args.length == 1)
43 | {
44 | // Conseguimos que en proxy1.equals(proxy2) se usen los objetos asociados no los propios proxies, para ello obtenemos el objeto asociado al parámetro
45 | // No hace falta que equals forme parte de la interface, pero está ahí implícitamente
46 | // hashCode() como no tiene params es llamado sin problema de conversiones
47 | Object param = args[0];
48 | if (param instanceof Proxy && // Si es una clase generada com.sun.proxy.$ProxyN (N=1,2...) es también derivada de Proxy
49 | method.getName().equals("equals") &&
50 | method.getReturnType().equals(boolean.class))
51 | {
52 | Class>[] paramTypes = method.getParameterTypes();
53 | if (paramTypes.length == 1 && paramTypes[0].equals(Object.class))
54 | {
55 | InvocationHandler paramInvHandler = Proxy.getInvocationHandler(param);
56 | if (paramInvHandler instanceof GenericProxyInvocationHandler)
57 | {
58 | args[0] = ((GenericProxyInvocationHandler)paramInvHandler).getCurrent(); // reemplazamos el Proxy por el objeto asociado
59 | }
60 | }
61 | }
62 | }
63 |
64 | return method.invoke(obj, args);
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/jfo/JavaFileObjectInputClassInFileSystem.java:
--------------------------------------------------------------------------------
1 | package com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp.jfo;
2 |
3 | import java.io.IOException;
4 | import java.io.OutputStream;
5 | import java.io.Reader;
6 | import java.io.Writer;
7 | import java.net.URI;
8 | import javax.lang.model.element.Modifier;
9 | import javax.lang.model.element.NestingKind;
10 | import javax.tools.JavaFileObject;
11 |
12 | /**
13 | *
14 | * @author jmarranz
15 | */
16 | public abstract class JavaFileObjectInputClassInFileSystem implements JavaFileObject,JProxyJavaFileObjectInput
17 | {
18 | protected final String binaryName;
19 | protected final URI uri;
20 | protected final String name;
21 |
22 | public JavaFileObjectInputClassInFileSystem(String binaryName, URI uri,String name)
23 | {
24 | this.uri = uri;
25 | this.binaryName = binaryName;
26 | this.name = name;
27 | }
28 |
29 | @Override
30 | public URI toUri() {
31 | return uri;
32 | }
33 |
34 | @Override
35 | public String getName() {
36 | return name;
37 | }
38 |
39 | @Override
40 | public String getBinaryName() {
41 | return binaryName;
42 | }
43 |
44 | @Override
45 | public OutputStream openOutputStream() throws IOException {
46 | throw new UnsupportedOperationException();
47 | }
48 |
49 | @Override
50 | public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
51 | throw new UnsupportedOperationException();
52 | }
53 |
54 | @Override
55 | public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
56 | throw new UnsupportedOperationException();
57 | }
58 |
59 | @Override
60 | public Writer openWriter() throws IOException {
61 | throw new UnsupportedOperationException();
62 | }
63 |
64 | @Override
65 | public boolean delete() {
66 | throw new UnsupportedOperationException();
67 | }
68 |
69 | @Override
70 | public Kind getKind() {
71 | return Kind.CLASS;
72 | }
73 |
74 | @Override // copied from SimpleJavaFileManager
75 | public boolean isNameCompatible(String simpleName, Kind kind) {
76 | String baseName = simpleName + kind.extension;
77 | return kind.equals(getKind())
78 | && (baseName.equals(getName())
79 | || getName().endsWith("/" + baseName));
80 | }
81 |
82 | @Override
83 | public NestingKind getNestingKind() {
84 | throw new UnsupportedOperationException();
85 | }
86 |
87 | @Override
88 | public Modifier getAccessLevel() {
89 | throw new UnsupportedOperationException();
90 | }
91 |
92 | }
93 |
--------------------------------------------------------------------------------
/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/comp/JProxyCompilerContext.java:
--------------------------------------------------------------------------------
1 | package com.innowhere.relproxy.impl.jproxy.core.clsmgr.comp;
2 |
3 | import com.innowhere.relproxy.RelProxyException;
4 | import com.innowhere.relproxy.jproxy.JProxyDiagnosticsListener;
5 | import java.io.IOException;
6 | import java.util.List;
7 | import javax.tools.Diagnostic;
8 | import javax.tools.DiagnosticCollector;
9 | import javax.tools.JavaFileObject;
10 | import javax.tools.StandardJavaFileManager;
11 |
12 | /**
13 | *
14 | * @author jmarranz
15 | */
16 | public class JProxyCompilerContext
17 | {
18 | protected StandardJavaFileManager standardFileManager;
19 | protected DiagnosticCollector diagnostics;
20 | protected JProxyDiagnosticsListener diagnosticsListener;
21 |
22 | public JProxyCompilerContext(StandardJavaFileManager standardFileManager,DiagnosticCollector diagnostics,JProxyDiagnosticsListener diagnosticsListener)
23 | {
24 | this.standardFileManager = standardFileManager;
25 | this.diagnostics = diagnostics;
26 | this.diagnosticsListener = diagnosticsListener;
27 | }
28 |
29 | public StandardJavaFileManager getStandardFileManager()
30 | {
31 | return standardFileManager;
32 | }
33 |
34 | public DiagnosticCollector getDiagnosticCollector()
35 | {
36 | return diagnostics;
37 | }
38 |
39 | public void close()
40 | {
41 | try { this.standardFileManager.close(); }
42 | catch (IOException ex) { throw new RelProxyException(ex); }
43 |
44 | List> diagList = diagnostics.getDiagnostics();
45 | if (!diagList.isEmpty())
46 | {
47 | if (diagnosticsListener != null)
48 | {
49 | diagnosticsListener.onDiagnostics(diagnostics);
50 | }
51 | else
52 | {
53 | int i = 1;
54 | for (Diagnostic diagnostic : diagList)
55 | {
56 | System.err.println("Diagnostic " + i);
57 | System.err.println(" code: " + diagnostic.getCode());
58 | System.err.println(" kind: " + diagnostic.getKind());
59 | System.err.println(" line number: " + diagnostic.getLineNumber());
60 | System.err.println(" column number: " + diagnostic.getColumnNumber());
61 | System.err.println(" start position: " + diagnostic.getStartPosition());
62 | System.err.println(" position: " + diagnostic.getPosition());
63 | System.err.println(" end position: " + diagnostic.getEndPosition());
64 | System.err.println(" source: " + diagnostic.getSource());
65 | System.err.println(" message: " + diagnostic.getMessage(null));
66 | i++;
67 | }
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/relproxy/src/main/java/com/innowhere/relproxy/jproxy/JProxyScriptEngine.java:
--------------------------------------------------------------------------------
1 | package com.innowhere.relproxy.jproxy;
2 |
3 | import javax.script.ScriptEngine;
4 |
5 | /**
6 | * Interface implemented by RelProxy to provide javax.script.ScriptEngine objects supporting Java as a scripting language.
7 | *
8 | *
The method {@link JProxyScriptEngineFactory#getScriptEngine()} returns an implementation of this interface.
9 | *
10 | * @author Jose Maria Arranz Santamaria
11 | */
12 | public interface JProxyScriptEngine extends ScriptEngine
13 | {
14 | /**
15 | * Initializes this JProxyScriptEngine instance with the provided configuration object.
16 | *
17 | * @param config the configuration object.
18 | */
19 | public void init(JProxyConfig config);
20 |
21 | /**
22 | * This method is the same as {@link JProxy#create(java.lang.Object, java.lang.Class)} but applied to this JProxyScriptEngine
23 | *
24 | * @param the interface implemented by the original object and proxy object returned.
25 | * @param obj the original object to proxy.
26 | * @param clasz the class of the interface implemented by the original object and proxy object returned.
27 | * @return the java.lang.reflect.Proxy object associated or the original object when is disabled.
28 | */
29 | public T create(T obj,Class clasz);
30 |
31 | /**
32 | * This method is the same as {@link JProxy#create(java.lang.Object, java.lang.Class[])} but applied to this JProxyScriptEngine
33 | *
34 | * @param obj the original object to proxy.
35 | * @param classes the classes of the interfaces implemented by the original object and proxy object returned.
36 | * @return the java.lang.reflect.Proxy object associated or the original object when is disabled.
37 | */
38 | public Object create(Object obj,Class>[] classes);
39 |
40 | /**
41 | * This method is the same as {@link JProxy#isEnabled()} but applied to this JProxyScriptEngine
42 | *
43 | * @return true if enabled.
44 | */
45 | public boolean isEnabled();
46 |
47 | /**
48 | * This method is the same as {@link JProxy#isRunning()} but applied to this JProxyScriptEngine
49 | *
50 | * @return true if running.
51 | */
52 | public boolean isRunning();
53 |
54 | /**
55 | * This method is the same as {@link JProxy#stop()} but applied to this JProxyScriptEngine
56 | *
57 | * @return true if source change detection has been stopped, false if it is already stopped or this JProxyScriptEngine is not enabled or initialized.
58 | * @see #stop()
59 | */
60 | public boolean stop();
61 |
62 | /**
63 | * This method is the same as {@link JProxy#start()} but applied to this JProxyScriptEngine
64 | *
65 | * @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.
66 | * @see #start()
67 | */
68 | public boolean start();
69 | }
70 |
--------------------------------------------------------------------------------
/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/FolderSourceList.java:
--------------------------------------------------------------------------------
1 | package com.innowhere.relproxy.impl.jproxy.core.clsmgr;
2 |
3 | import com.innowhere.relproxy.RelProxyException;
4 | import com.innowhere.relproxy.impl.FileExt;
5 | import java.io.File;
6 |
7 | /**
8 | *
9 | * @author jmarranz
10 | */
11 | public class FolderSourceList
12 | {
13 | protected FileExt[] sourceList;
14 |
15 | public FolderSourceList(String[] sourcePathList,boolean expectedDirectory)
16 | {
17 | if (sourcePathList != null) // En el caso de shell interactivo es null
18 | {
19 | // El convertir siempre a File los paths es para normalizar paths
20 | this.sourceList = new FileExt[sourcePathList.length];
21 | for(int i = 0; i < sourcePathList.length; i++)
22 | {
23 | File folder = new File(sourcePathList[i]);
24 | if (!folder.exists())
25 | throw new RelProxyException("Source folder does not exist: " + folder.getAbsolutePath());
26 | boolean isDirectory = folder.isDirectory();
27 | if (expectedDirectory)
28 | {
29 | if (!isDirectory)
30 | throw new RelProxyException("Source folder is not a directory: " + folder.getAbsolutePath());
31 | }
32 | else
33 | {
34 | if (isDirectory)
35 | throw new RelProxyException("Expected a file not a directory: " + folder.getAbsolutePath());
36 | }
37 | sourceList[i] = new FileExt(folder);
38 | }
39 | }
40 | }
41 |
42 | public FileExt[] getArray()
43 | {
44 | return sourceList;
45 | }
46 |
47 | public String buildClassNameFromFile(FileExt sourceFile)
48 | {
49 | for(FileExt rootFolderOfSources : sourceList)
50 | {
51 | String className = buildClassNameFromFile(sourceFile,rootFolderOfSources);
52 | if (className != null)
53 | return className;
54 | }
55 | throw new RelProxyException("File not found in source folders: " + sourceFile.getFile().getAbsolutePath());
56 | }
57 |
58 | public static String buildClassNameFromFile(FileExt sourceFile,FileExt rootFolderOfSources)
59 | {
60 | String path = sourceFile.getCanonicalPath();
61 |
62 | String rootFolderOfSourcesAbsPath = rootFolderOfSources.getCanonicalPath();
63 | int pos = path.indexOf(rootFolderOfSourcesAbsPath);
64 | if (pos == 0) // Está en este source folder
65 | {
66 | path = path.substring(rootFolderOfSourcesAbsPath.length() + 1); // Sumamos +1 para quitar también el / separador del pathInput y el path relativo de la clase
67 | // Puede no tener extensión (script) o bien ser .java o bien ser una inventada (ej .jsh), la quitamos si existe
68 | pos = path.lastIndexOf('.');
69 | if (pos != -1)
70 | path = path.substring(0, pos);
71 | path = path.replace(File.separatorChar, '.'); // getAbsolutePath() normaliza con el caracter de la plataforma
72 | return path;
73 | }
74 | return null;
75 | }
76 |
77 |
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/JProxyShellInteractiveImpl.java:
--------------------------------------------------------------------------------
1 | package com.innowhere.relproxy.impl.jproxy.shell;
2 |
3 | import com.innowhere.relproxy.RelProxyException;
4 | import com.innowhere.relproxy.impl.jproxy.JProxyConfigImpl;
5 | import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript;
6 | import com.innowhere.relproxy.impl.jproxy.core.clsmgr.FolderSourceList;
7 | import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot;
8 | import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootInMemory;
9 | import com.innowhere.relproxy.impl.jproxy.shell.inter.JProxyShellProcessor;
10 | import java.util.LinkedList;
11 |
12 | /**
13 | * Alguna inspiración: http://groovy.codehaus.org/Groovy+Shell
14 | *
15 | * @author jmarranz
16 | */
17 | public class JProxyShellInteractiveImpl extends JProxyShellImpl
18 | {
19 | protected boolean test = false;
20 | protected JProxyShellProcessor processor = new JProxyShellProcessor(this);
21 | protected ClassDescriptorSourceScript classDescSourceScript;
22 |
23 | public void init(String[] args)
24 | {
25 | this.classDescSourceScript = super.init(args, null);
26 |
27 | if (test)
28 | {
29 | processor.test();
30 | return;
31 | }
32 |
33 | processor.loop();
34 | }
35 |
36 | public ClassDescriptorSourceScript getClassDescriptorSourceScript()
37 | {
38 | return classDescSourceScript;
39 | }
40 |
41 | public SourceScriptRootInMemory getSourceScriptInMemory()
42 | {
43 | return (SourceScriptRootInMemory)classDescSourceScript.getSourceScript();
44 | }
45 |
46 | @Override
47 | public ClassDescriptorSourceScript init(JProxyConfigImpl config,SourceScriptRoot scriptFile,ClassLoader classLoader)
48 | {
49 | ClassDescriptorSourceScript script = super.init(config,scriptFile, classLoader);
50 |
51 | this.test = config.isTest();
52 |
53 | return script;
54 | }
55 |
56 | @Override
57 | protected void executeFirstTime(ClassDescriptorSourceScript scriptFileDesc,LinkedList argsToScript,JProxyShellClassLoader classLoader)
58 | {
59 | // La primera vez el script es vacío, no hay nada que ejecutar
60 | }
61 |
62 | @Override
63 | protected void processConfigParams(String[] args,LinkedList argsToScript,JProxyConfigImpl config)
64 | {
65 | super.processConfigParams(args, argsToScript, config);
66 |
67 | String classFolder = config.getClassFolder();
68 | if (classFolder != null && !classFolder.trim().isEmpty()) throw new RelProxyException("cacheClassFolder is useless to execute in interactive mode");
69 | }
70 |
71 | @Override
72 | protected SourceScriptRoot createSourceScriptRoot(String[] args,LinkedList argsToScript,FolderSourceList folderSourceList)
73 | {
74 | return SourceScriptRootInMemory.createSourceScriptInMemory(""); // La primera vez no hace nada, sirve para "calentar" la app
75 | }
76 |
77 | @Override
78 | protected JProxyShellClassLoader getJProxyShellClassLoader(JProxyConfigImpl config)
79 | {
80 | // No hay classFolder => no hay necesidad de nuevo ClassLoader
81 | return null;
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/relproxy/src/main/java/com/innowhere/relproxy/gproxy/GProxy.java:
--------------------------------------------------------------------------------
1 |
2 | package com.innowhere.relproxy.gproxy;
3 |
4 | import com.innowhere.relproxy.impl.gproxy.GProxyConfigImpl;
5 | import com.innowhere.relproxy.impl.gproxy.GProxyDefaultImpl;
6 |
7 | /**
8 | * 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.
9 | *
10 | * @author Jose Maria Arranz Santamaria
11 | */
12 | public class GProxy
13 | {
14 | /**
15 | * Creates a {@link GProxyConfig} object to be used to configure GProxy.
16 | *
17 | * @return a new configuration object.
18 | * @see #init(GProxyConfig)
19 | */
20 | public static GProxyConfig createGProxyConfig()
21 | {
22 | return GProxyDefaultImpl.createGProxyConfig();
23 | }
24 |
25 | /**
26 | * Initializes GProxy with the provided configuration object.
27 | *
28 | * @param config
29 | */
30 | public static void init(GProxyConfig config)
31 | {
32 | GProxyDefaultImpl.initStatic((GProxyConfigImpl)config);
33 | }
34 |
35 | /**
36 | * Creates a proxy object using java.lang.reflect.Proxy based on the provided Groovy object and the class of the implemented Java interface.
37 | *
38 | *
This method is a simplification for a single interface (the most common case) of {@link #create(Object,Class>[])} .
39 | *
40 | * @param the interface implemented by the original object and proxy object returned.
41 | * @param obj the original object to proxy.
42 | * @param clasz the class of the interface implemented by the original object and proxy object returned.
43 | * @return the java.lang.reflect.Proxy object associated or the original object when GProxy is disabled.
44 | */
45 | public static T create(T obj,Class clasz)
46 | {
47 | return GProxyDefaultImpl.createStatic(obj, clasz);
48 | }
49 |
50 | /**
51 | * Creates a proxy object using java.lang.reflect.Proxy based on the provided Groovy object and the classes of the implemented Java interfaces.
52 | *
53 | *
If GProxy has been configured and is enabled this method returns a java.lang.reflect.Proxy object implementing instead of
54 | * the original object provided. Methods called in proxy object are received by GProxy and forwarded to the original object, if source code
55 | * managed by GProxy has been changed, the class of the original object is reloaded based on the new source and the original object
56 | * 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.
57 | *
58 | *
If GProxy is disabled returns the original object provided with no performance penalty.
59 | *
60 | * @param obj the original object to proxy.
61 | * @param classes the classes of the interfaces implemented by the original object and proxy object returned.
62 | * @return the java.lang.reflect.Proxy object associated or the original object when GProxy is disabled.
63 | */
64 | public static Object create(Object obj,Class>[] classes)
65 | {
66 | return GProxyDefaultImpl.createStatic(obj, classes);
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/JProxyShellScriptFileImpl.java:
--------------------------------------------------------------------------------
1 | package com.innowhere.relproxy.impl.jproxy.shell;
2 |
3 | import com.innowhere.relproxy.RelProxyException;
4 | import com.innowhere.relproxy.impl.FileExt;
5 | import com.innowhere.relproxy.impl.jproxy.JProxyConfigImpl;
6 | import com.innowhere.relproxy.impl.jproxy.JProxyUtil;
7 | import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript;
8 | import com.innowhere.relproxy.impl.jproxy.core.clsmgr.FolderSourceList;
9 | import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot;
10 | import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRootFile;
11 | import java.io.File;
12 | import java.util.LinkedList;
13 |
14 | /**
15 | *
16 | * @author jmarranz
17 | */
18 | public class JProxyShellScriptFileImpl extends JProxyShellImpl
19 | {
20 | protected FileExt scriptFile;
21 |
22 | public void init(String[] args)
23 | {
24 | File scriptFile = new File(args[0]);
25 | if (!scriptFile.exists())
26 | throw new RelProxyException("File " + args[0] + " does not exist");
27 |
28 | this.scriptFile = new FileExt(scriptFile);
29 |
30 | File parentDir = JProxyUtil.getParentDir(scriptFile);
31 | String inputPath = parentDir.getAbsolutePath();
32 | super.init(args, inputPath);
33 | }
34 |
35 | @Override
36 | protected void executeFirstTime(ClassDescriptorSourceScript scriptFileDesc,LinkedList argsToScript,JProxyShellClassLoader classLoader)
37 | {
38 | fixLastLoadedClass(scriptFileDesc,classLoader);
39 |
40 | try
41 | {
42 | scriptFileDesc.callMainMethod(argsToScript);
43 | }
44 | catch(Throwable ex)
45 | {
46 | ex.printStackTrace(System.out);
47 | }
48 | }
49 |
50 | @Override
51 | protected SourceScriptRoot createSourceScriptRoot(String[] args,LinkedList argsToScript,FolderSourceList folderSourceList)
52 | {
53 | return SourceScriptRootFile.createSourceScriptRootFile(scriptFile,folderSourceList);
54 | }
55 |
56 | @Override
57 | protected JProxyShellClassLoader getJProxyShellClassLoader(JProxyConfigImpl config)
58 | {
59 | String classFolder = config.getClassFolder();
60 | if (classFolder != null)
61 | return new JProxyShellClassLoader(getDefaultClassLoader(),new File(classFolder));
62 | else
63 | return null;
64 | }
65 |
66 | protected void fixLastLoadedClass(ClassDescriptorSourceScript scriptFileDesc,JProxyShellClassLoader classLoader)
67 | {
68 | Class scriptClass = scriptFileDesc.getLastLoadedClass();
69 | if (scriptClass != null) return;
70 |
71 | // Esto es esperable cuando especificamos un classFolder en donde está ya compilado el script lanzador y es más actual que el fuente
72 | // no ha habido necesidad de crear un class loader "reloader" ni de recargar todos los archivos fuente con él
73 | if (classLoader == null) throw new RelProxyException("INTERNAL ERROR");
74 | if (scriptFileDesc.getClassBytes() == null) throw new RelProxyException("INTERNAL ERROR");
75 | scriptClass = classLoader.defineClass(scriptFileDesc);
76 | scriptFileDesc.setLastLoadedClass(scriptClass);
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/JProxyImpl.java:
--------------------------------------------------------------------------------
1 | package com.innowhere.relproxy.impl.jproxy.core;
2 |
3 | import com.innowhere.relproxy.impl.GenericProxyImpl;
4 | import com.innowhere.relproxy.impl.GenericProxyInvocationHandler;
5 | import com.innowhere.relproxy.impl.jproxy.JProxyConfigImpl;
6 | import com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc.ClassDescriptorSourceScript;
7 | import com.innowhere.relproxy.impl.jproxy.core.clsmgr.FolderSourceList;
8 | import com.innowhere.relproxy.impl.jproxy.core.clsmgr.JProxyEngine;
9 | import com.innowhere.relproxy.impl.jproxy.core.clsmgr.srcunit.SourceScriptRoot;
10 | import com.innowhere.relproxy.jproxy.JProxyCompilerListener;
11 | import com.innowhere.relproxy.jproxy.JProxyDiagnosticsListener;
12 | import com.innowhere.relproxy.jproxy.JProxyInputSourceFileExcludedListener;
13 |
14 | /**
15 | *
16 | * @author jmarranz
17 | */
18 | public abstract class JProxyImpl extends GenericProxyImpl
19 | {
20 | public static JProxyImpl SINGLETON;
21 | protected JProxyEngine engine;
22 |
23 |
24 | protected JProxyImpl()
25 | {
26 | }
27 |
28 | public static ClassLoader getDefaultClassLoader()
29 | {
30 | return Thread.currentThread().getContextClassLoader();
31 | }
32 |
33 | public ClassDescriptorSourceScript init(JProxyConfigImpl config)
34 | {
35 | return init(config,null,null);
36 | }
37 |
38 | public ClassDescriptorSourceScript init(JProxyConfigImpl config,SourceScriptRoot scriptFile,ClassLoader classLoader)
39 | {
40 | super.init(config);
41 |
42 | FolderSourceList folderSourceList = config.getFolderSourceList();
43 | FolderSourceList requiredExtraJarPaths = config.getRequiredExtraJarPaths();
44 | JProxyInputSourceFileExcludedListener excludedListener = config.getJProxyInputSourceFileExcludedListener();
45 | JProxyCompilerListener compilerListener = config.getJProxyCompilerListener();
46 | String classFolder = config.getClassFolder();
47 | long scanPeriod = config.getScanPeriod();
48 | Iterable compilationOptions = config.getCompilationOptions();
49 | JProxyDiagnosticsListener diagnosticsListener = config.getJProxyDiagnosticsListener();
50 | boolean enabled = config.isEnabled();
51 |
52 | classLoader = classLoader != null ? classLoader : getDefaultClassLoader();
53 | this.engine = new JProxyEngine(this,enabled,scriptFile,classLoader,folderSourceList,requiredExtraJarPaths,classFolder,scanPeriod,excludedListener,compilerListener,compilationOptions,diagnosticsListener);
54 |
55 | return engine.init();
56 | }
57 |
58 | public JProxyEngine getJProxyEngine()
59 | {
60 | return engine;
61 | }
62 |
63 | public boolean isEnabled()
64 | {
65 | return engine.isEnabled();
66 | }
67 |
68 | public boolean isRunning()
69 | {
70 | return engine.isRunning();
71 | }
72 |
73 | public boolean stop()
74 | {
75 | return engine.stop();
76 | }
77 |
78 | public boolean start()
79 | {
80 | return engine.start();
81 | }
82 |
83 | @Override
84 | public GenericProxyInvocationHandler createGenericProxyInvocationHandler(Object obj)
85 | {
86 | return new JProxyInvocationHandler(obj,this);
87 | }
88 |
89 | public abstract Class getMainParamClass();
90 | }
91 |
--------------------------------------------------------------------------------
/relproxy/CHANGES.txt:
--------------------------------------------------------------------------------
1 |
2 | RELEASE CHANGES
3 |
4 | * 0.8.8
5 |
6 | - Support of static final fields in reloadable proxies.
7 |
8 | * 0.8.7
9 |
10 | - Some improvement needed when embedding RelProxy Java using the scripting API (avoiding one unnecessary first class reload).
11 | - Added chapter to Manual: "Embedding RelProxy Java in your Java framework to provide hot reload".
12 | - Added new example in RelProxy Examples repository named relproxy_builtin_ex on how to embed RelProxy.
13 |
14 | * 0.8.6
15 |
16 | - Support of class reloading in inner classes including anonymous inner classes. Chapter "JProxy or how to be able..." updated accordingly. This feature
17 | is used by ItsNat 1.4, this release uses RelProxy internally for user class reloading (mainly listeners).
18 |
19 | * 0.8.5
20 |
21 | - Improved performance reducing blocking code when checking source code changes and no change is detected.
22 |
23 | * 0.8.4
24 |
25 | - Added the method JProxyConfig.setRequiredExtraJarPaths(String[] inputJarPaths) to workaround a problem with Liferay 6.2.
26 | - Added JProxy.create(Object,Class>[]), GProxy.create(Object,Class>[]),JProxyScriptEngine.create(Object,Class>[]) for classes implementing multiple interfaces
27 | - The call proxy.equals(proxy2) returns true if both proxies have associated the same original object and there is no reload.
28 | - Added to Manual "Solving jar manifest configuration problems in JProxy" and "Identity of returned proxies"
29 |
30 | * 0.8.3
31 |
32 | - First release published on bintray.com/JCenter and Maven Central. In Maven just add to your POM:
33 |
34 |
35 | com.innowhere
36 | relproxy
37 | 0.8.3
38 |
39 |
40 | * 0.8.2
41 |
42 | - Optimization: method JProxyInputSourceFileExcludedListener.isExcluded(File file,File) is called being parameter file also a directory, if the directory is fully
43 | excluded, RelProxy doesn't call isExcluded for files into the folder. Useful for big source code bases and used RelProxy for normal source code folders.
44 | - Reload reloadable classes using a new ClassLoader is done only when a exposed method of a singleton registered on JProxy is called.
45 | - Added JProxy.isEnabled()
46 | - API for configuration of JProxyScriptEngineFactory and JProxyScriptEngine has changed.
47 | - JProxyScriptEngine has now the same methods (and same behavior) as JProxy.
48 | - Removed JPROXYSH_SCAN_PERIOD, has no sense in shell scripting.
49 | - Bug fix in case of paths with spaces in JProxy.
50 | - Bug fix in case of ".." in paths in JProxy.
51 | - Manual has been very improved documenting new features and new chapters.
52 | - A lot of examples of using RelProxy with popular Java web frameworks.
53 |
54 | * 0.8.1
55 |
56 | - Fixed a problem with class localization and loading of javax.* classes not included in Java core (ex javax.servlet classes)
57 | - Support of multiple input folder roots for sources: JProxyConfig.setInputPaths(String[] inputPaths)
58 | - Added listener JProxyConfig.setRelProxyOnReloadListener(RelProxyOnReloadListener) to expecify excluded files
59 | - Added listener JProxyConfig.setJProxyCompilerListener(JProxyCompilerListener) to monitor when files are compiled
60 | - Added JProxyConfig.isRunning() to detect whether JProxy is configured and running
61 | - Added new chapters to manual:
62 | "Setting up a web project based on a Maven POM in NetBeans to use JProxy or GProxy"
63 | "How JProxy can help you only in development time (GWT example)"
64 |
65 | * 0.8 First release
66 |
67 |
--------------------------------------------------------------------------------
/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/core/clsmgr/cldesc/ClassDescriptorSourceFileRegistry.java:
--------------------------------------------------------------------------------
1 | package com.innowhere.relproxy.impl.jproxy.core.clsmgr.cldesc;
2 |
3 | import java.util.Collection;
4 | import java.util.HashMap;
5 | import java.util.LinkedList;
6 | import java.util.Map;
7 |
8 | /**
9 | *
10 | * @author jmarranz
11 | */
12 | public class ClassDescriptorSourceFileRegistry
13 | {
14 | protected final Map sourceUnitMapByClassName;
15 |
16 | public ClassDescriptorSourceFileRegistry()
17 | {
18 | this.sourceUnitMapByClassName = new HashMap();
19 | }
20 |
21 | public ClassDescriptorSourceFileRegistry(ClassDescriptorSourceFileRegistry origin)
22 | {
23 | this.sourceUnitMapByClassName = new HashMap( origin.sourceUnitMapByClassName );
24 | }
25 |
26 | public boolean isEmpty()
27 | {
28 | return sourceUnitMapByClassName.isEmpty();
29 | }
30 |
31 | public Collection getClassDescriptorSourceFileColl()
32 | {
33 | return sourceUnitMapByClassName.values();
34 | }
35 |
36 | public ClassDescriptorSourceUnit getClassDescriptorSourceUnit(String className)
37 | {
38 | return sourceUnitMapByClassName.get(className);
39 | }
40 |
41 | public ClassDescriptorSourceUnit removeClassDescriptorSourceUnit(String className)
42 | {
43 | return sourceUnitMapByClassName.remove(className);
44 | }
45 |
46 | public void addClassDescriptorSourceUnit(ClassDescriptorSourceUnit sourceFile)
47 | {
48 | sourceUnitMapByClassName.put(sourceFile.getClassName(), sourceFile);
49 | }
50 |
51 | public void setAllClassDescriptorSourceFilesPendingToRemove(boolean pending)
52 | {
53 | for(Map.Entry entries : sourceUnitMapByClassName.entrySet())
54 | entries.getValue().setPendingToRemove(pending);
55 | }
56 |
57 | public LinkedList getAllClassDescriptorSourceFilesPendingToRemove(LinkedList deletedSourceFiles)
58 | {
59 | for(Map.Entry entries : sourceUnitMapByClassName.entrySet())
60 | {
61 | ClassDescriptorSourceUnit classDesc = entries.getValue();
62 | boolean pending = classDesc.isPendingToRemove();
63 | if (pending)
64 | deletedSourceFiles.add(classDesc);
65 | }
66 | return deletedSourceFiles;
67 | }
68 |
69 | public ClassDescriptor getClassDescriptor(String className)
70 | {
71 | // Puede ser el de una innerclass
72 | // Las innerclasses no están como tales en sourceFileMap pues sólo está la clase contenedora pero también la consideramos hotloadable
73 | String parentClassName;
74 | int pos = className.lastIndexOf('$');
75 | boolean inner;
76 | if (pos != -1)
77 | {
78 | parentClassName = className.substring(0, pos);
79 | inner = true;
80 | }
81 | else
82 | {
83 | parentClassName = className;
84 | inner = false;
85 | }
86 | ClassDescriptorSourceUnit sourceDesc = sourceUnitMapByClassName.get(parentClassName);
87 | if (sourceDesc == null)
88 | return null;
89 | if (!inner) return sourceDesc;
90 | return sourceDesc.getInnerClassDescriptor(className,true);
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/Command.java:
--------------------------------------------------------------------------------
1 | package com.innowhere.relproxy.impl.jproxy.shell.inter;
2 |
3 | /**
4 | *
5 | * @author jmarranz
6 | */
7 | public abstract class Command
8 | {
9 | protected JProxyShellProcessor parent;
10 | protected String name;
11 |
12 | public Command(JProxyShellProcessor parent,String name)
13 | {
14 | this.parent = parent;
15 | this.name = name;
16 | }
17 |
18 | public static Command createCommand(JProxyShellProcessor parent,String cmd)
19 | {
20 | cmd = cmd.trim();
21 | if (cmd.equals("clear"))
22 | {
23 | return new CommandOther(parent,cmd);
24 | }
25 | else if (cmd.startsWith("delete"))
26 | {
27 | CommandDelete command = CommandDelete.createCommandDelete(parent,cmd);
28 | if (command != null)
29 | return command;
30 | else
31 | return new CommandError(parent);
32 | }
33 | else if (cmd.equals("display"))
34 | {
35 | return new CommandOther(parent,cmd);
36 | }
37 | else if (cmd.startsWith("edit"))
38 | {
39 | CommandEdit command = CommandEdit.createCommandEdit(parent,cmd);
40 | if (command != null)
41 | return command;
42 | else
43 | return new CommandError(parent);
44 | }
45 | else if (cmd.equals("exec"))
46 | {
47 | return new CommandOther(parent,cmd);
48 | }
49 | else if (cmd.equals("exit"))
50 | {
51 | return new CommandOther(parent,cmd);
52 | }
53 | else if (cmd.equals("help"))
54 | {
55 | return new CommandOther(parent,cmd);
56 | }
57 | else if (cmd.startsWith("insert"))
58 | {
59 | CommandInsert command = CommandInsert.createCommandInsert(parent,cmd);
60 | if (command != null)
61 | return command;
62 | else
63 | return new CommandError(parent);
64 | }
65 | else if (cmd.startsWith("load"))
66 | {
67 | CommandLoad command = CommandLoad.createCommandLoad(parent,cmd);
68 | if (command != null)
69 | return command;
70 | else
71 | return new CommandError(parent);
72 | }
73 | else if (cmd.equals("quit"))
74 | {
75 | return new CommandOther(parent,cmd);
76 | }
77 | else if (cmd.startsWith("save"))
78 | {
79 | CommandSave command = CommandSave.createCommandSave(parent,cmd);
80 | if (command != null)
81 | return command;
82 | else
83 | return new CommandError(parent);
84 | }
85 |
86 | return null; // No es un comando
87 | }
88 |
89 | protected static String getParameter(String cmdName,String cmd)
90 | {
91 | int pos = cmd.indexOf(cmdName + " ");
92 | if (pos != 0)
93 | return null;
94 | pos = cmd.indexOf(' ');
95 | String param = cmd.substring(pos + 1);
96 | param = param.trim();
97 | return param;
98 | }
99 |
100 | public abstract boolean run();
101 |
102 | public abstract void runPostCommand();
103 | }
104 |
--------------------------------------------------------------------------------
/relproxy_test_itsnat/src/main/webapp/WEB-INF/javaex/code/example/javaex/JProxyExampleDocument.java:
--------------------------------------------------------------------------------
1 | package example.javaex;
2 |
3 | import com.innowhere.relproxy.jproxy.JProxy;
4 | import example.javaex.hotreload.JProxyExampleAux2;
5 | import example.javaex.nothotreload.JProxyExampleAuxIgnored2;
6 | import example.javaex.nothotreload.JProxyExampleAuxIgnored3;
7 | import org.itsnat.comp.ItsNatComponentManager;
8 | import org.itsnat.comp.text.ItsNatHTMLInputText;
9 | import org.itsnat.core.ItsNatServletRequest;
10 | import org.itsnat.core.event.ItsNatServletRequestListener;
11 | import org.itsnat.core.html.ItsNatHTMLDocument;
12 | import org.w3c.dom.Element;
13 | import org.w3c.dom.events.Event;
14 | import org.w3c.dom.events.EventListener;
15 | import org.w3c.dom.events.EventTarget;
16 | import org.w3c.dom.html.HTMLDocument;
17 |
18 | public class JProxyExampleDocument extends JProxyExampleDocumentBase
19 | {
20 | protected ItsNatHTMLDocument itsNatDoc; // ItsNatHTMLDocument
21 | protected ItsNatHTMLInputText textInput; // ItsNatHTMLInputText
22 | protected Element resultsElem; // Element
23 |
24 | public static class AuxMember
25 | {
26 | public static void log()
27 | {
28 | System.out.println(AuxMember.class.getName() + ": 1 " + AuxMember.class.getClassLoader().hashCode());
29 | }
30 | }
31 |
32 | public JProxyExampleDocument() // Requerido por el listener ejemplo anonymous inner class del "dlbclick"
33 | {
34 | }
35 |
36 | public JProxyExampleDocument(ItsNatServletRequest request,ItsNatHTMLDocument itsNatDoc,FalseDB db)
37 | {
38 | class AuxMemberInMethod
39 | {
40 | public void log()
41 | {
42 | System.out.println("JProxyExampleDocument.AuxMemberInMethod: 1 " + AuxMemberInMethod.class.getClassLoader().hashCode());
43 | }
44 | }
45 |
46 | this.itsNatDoc = itsNatDoc;
47 |
48 | if (db.getCityList().size() != 3)
49 | throw new RuntimeException("Unexpected");
50 |
51 | HTMLDocument doc = itsNatDoc.getHTMLDocument();
52 |
53 | ItsNatComponentManager compMgr = itsNatDoc.getItsNatComponentManager();
54 | this.textInput = (ItsNatHTMLInputText)compMgr.createItsNatComponentById("inputId");
55 |
56 | EventListener listener = new EventListener()
57 | {
58 | {
59 | System.out.println("JProxyExampleDocument Anonymous Inner 1 " + this.getClass().getClassLoader().hashCode());
60 | }
61 |
62 | @Override
63 | public void handleEvent(Event evt)
64 | {
65 | String text = textInput.getText();
66 | String comment = " YES I SAID THIS (" + evt.getType() + ")";
67 | resultsElem.setTextContent(text + comment);
68 | }
69 | };
70 |
71 | Element buttonElem = doc.getElementById("buttonId");
72 | ((EventTarget)buttonElem).addEventListener("click",listener,false);
73 |
74 | ((EventTarget)buttonElem).addEventListener("dblclick", JProxy.create(listener, EventListener.class) ,false);
75 |
76 | this.resultsElem = doc.getElementById("resultsId");
77 |
78 | System.out.println("JProxyExampleDocument 1 " + this.getClass().getClassLoader().hashCode());
79 | new AuxMemberInMethod().log();
80 | AuxMember.log();
81 | JProxyExampleAux.log();
82 | JProxyExampleAux2.log();
83 | JProxyExampleAuxIgnored.log();
84 | JProxyExampleAuxIgnored2.log();
85 | JProxyExampleAuxIgnored3.log();
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/screngine/JProxyScriptEngineImpl.java:
--------------------------------------------------------------------------------
1 | package com.innowhere.relproxy.impl.jproxy.screngine;
2 |
3 | import com.innowhere.relproxy.RelProxyException;
4 | import com.innowhere.relproxy.impl.GenericProxyImpl;
5 | import com.innowhere.relproxy.impl.jproxy.JProxyConfigImpl;
6 | import com.innowhere.relproxy.impl.jproxy.JProxyUtil;
7 | import com.innowhere.relproxy.jproxy.JProxyConfig;
8 | import com.innowhere.relproxy.jproxy.JProxyScriptEngine;
9 | import java.io.Reader;
10 | import javax.script.AbstractScriptEngine;
11 | import javax.script.Bindings;
12 | import javax.script.ScriptContext;
13 | import javax.script.ScriptEngineFactory;
14 | import javax.script.ScriptException;
15 |
16 | /**
17 | * Methods of this class are similar to JProxyDefaultImpl
18 | *
19 | * @author jmarranz
20 | */
21 | public class JProxyScriptEngineImpl extends AbstractScriptEngine implements JProxyScriptEngine
22 | {
23 | protected JProxyScriptEngineDelegateImpl jproxy;
24 | protected JProxyScriptEngineFactoryImpl factory;
25 |
26 | public JProxyScriptEngineImpl(JProxyScriptEngineFactoryImpl factory)
27 | {
28 | this.factory = factory;
29 | }
30 |
31 | @Override
32 | public void init(JProxyConfig config)
33 | {
34 | JProxyConfigImpl configImpl = (JProxyConfigImpl)config;
35 | if (!configImpl.isEnabled()) return; // jproxy quedará null
36 |
37 | GenericProxyImpl.checkSingletonNull(jproxy);
38 | this.jproxy = new JProxyScriptEngineDelegateImpl(this);
39 | jproxy.init(configImpl);
40 | }
41 |
42 |
43 | @Override
44 | public Object eval(String script, ScriptContext context) throws ScriptException
45 | {
46 | if (jproxy == null)
47 | throw new RelProxyException("Engine is disabled");
48 |
49 | return jproxy.execute(script,context);
50 | }
51 |
52 | @Override
53 | public Object eval(Reader reader, ScriptContext context) throws ScriptException
54 | {
55 | String script = JProxyUtil.readTextFile(reader);
56 | return eval(script,context);
57 | }
58 |
59 | @Override
60 | public Bindings createBindings()
61 | {
62 | return new BindingsImpl();
63 | }
64 |
65 | @Override
66 | public ScriptEngineFactory getFactory()
67 | {
68 | return factory;
69 | }
70 |
71 | @Override
72 | public T create(T obj,Class clasz)
73 | {
74 | if (jproxy == null)
75 | return obj; // No se ha llamado al init o enabled = false
76 | return jproxy.create(obj, clasz);
77 | }
78 |
79 | @Override
80 | public Object create(Object obj,Class>[] classes)
81 | {
82 | if (jproxy == null)
83 | return obj; // No se ha llamado al init o enabled = false
84 | return jproxy.create(obj, classes);
85 | }
86 |
87 | @Override
88 | public boolean isEnabled()
89 | {
90 | if (jproxy == null)
91 | return false;
92 |
93 | return jproxy.isEnabled();
94 | }
95 |
96 | @Override
97 | public boolean isRunning()
98 | {
99 | if (jproxy == null)
100 | return false;
101 |
102 | return jproxy.isRunning();
103 | }
104 |
105 | @Override
106 | public boolean start()
107 | {
108 | if (jproxy == null)
109 | return false;
110 |
111 | return jproxy.start();
112 | }
113 |
114 | @Override
115 | public boolean stop()
116 | {
117 | if (jproxy == null)
118 | return false;
119 |
120 | return jproxy.stop();
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/relproxy/src/main/java/com/innowhere/relproxy/impl/jproxy/shell/inter/CommandOther.java:
--------------------------------------------------------------------------------
1 |
2 | package com.innowhere.relproxy.impl.jproxy.shell.inter;
3 |
4 | import com.innowhere.relproxy.RelProxyException;
5 |
6 | /**
7 | *
8 | * @author jmarranz
9 | */
10 | public class CommandOther extends Command
11 | {
12 | public CommandOther(JProxyShellProcessor parent,String name)
13 | {
14 | super(parent,name);
15 | }
16 |
17 | @Override
18 | public boolean run()
19 | {
20 | if (name.equals("clear"))
21 | {
22 | commandClear();
23 | }
24 | else if (name.equals("display"))
25 | {
26 | commandDisplay();
27 | }
28 | else if (name.equals("exec"))
29 | {
30 | commandExec();
31 | }
32 | else if (name.equals("exit"))
33 | {
34 | commandExit();
35 | }
36 | else if (name.equals("help"))
37 | {
38 | commandHelp();
39 | }
40 | else if (name.equals("quit"))
41 | {
42 | commandExit();
43 | }
44 | else throw new RelProxyException("Internal Error");
45 |
46 | return true;
47 | }
48 |
49 | @Override
50 | public void runPostCommand()
51 | {
52 | }
53 |
54 | private void commandClear()
55 | {
56 | parent.clearCodeBuffer();
57 | }
58 |
59 | private void commandExit()
60 | {
61 | System.exit(0);
62 | }
63 |
64 | private void commandDisplay()
65 | {
66 | 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"
67 |
68 | int i = 2;
69 | for(String line : parent.getCodeBuffer())
70 | {
71 | for(int j = 0; j < 3 - String.valueOf(i).length(); j++) System.out.print("0");
72 | System.out.print(i + ">");
73 | System.out.print(line);
74 | System.out.println();
75 | i++;
76 | }
77 | }
78 |
79 | private void commandExec()
80 | {
81 | parent.executeCodeBuffer();
82 | }
83 |
84 | private void commandHelp()
85 | {
86 | 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");
87 | System.out.println("");
88 | System.out.println("Available commands:");
89 | System.out.println(" clear");
90 | System.out.println(" Clears the buffer");
91 | System.out.println(" display");
92 | System.out.println(" Shows the buffer content");
93 | System.out.println(" edit last | ");
94 | System.out.println(" Edits the last introduced line code or the specified line number");
95 | System.out.println(" exec");
96 | System.out.println(" Compile and execute the buffer content");
97 | System.out.println(" exit");
98 | System.out.println(" Exits shell");
99 | System.out.println(" help");
100 | System.out.println(" This command");
101 | System.out.println(" insert last | ");
102 | System.out.println(" Insert the next line of code before the last introduced line or the specified line number");
103 | System.out.println(" load | ");
104 | System.out.println(" Load a file or URL into the buffer");
105 | System.out.println(" quit");
106 | System.out.println(" Same as exit");
107 | System.out.println(" save ");
108 | System.out.println(" Save the current buffer to a file");
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/relproxy_test_itsnat/src/main/java/example/groovyex/ItsNatGroovyServlet.java:
--------------------------------------------------------------------------------
1 |
2 | package example.groovyex;
3 |
4 | import groovy.lang.Binding;
5 | import groovy.lang.Closure;
6 | import groovy.servlet.ServletCategory;
7 | import groovy.util.GroovyScriptEngine;
8 | import groovy.util.ResourceException;
9 | import groovy.util.ScriptException;
10 | import java.io.File;
11 | import java.io.IOException;
12 | import javax.servlet.ServletConfig;
13 | import javax.servlet.ServletException;
14 | import org.codehaus.groovy.runtime.GroovyCategorySupport;
15 | import org.itsnat.core.http.HttpServletWrapper;
16 |
17 |
18 | /**
19 | * Inspired on:
20 | * https://github.com/groovy/groovy-core/blob/master/subprojects/groovy-servlet/src/main/java/groovy/servlet/GroovyServlet.java
21 | *
22 | * @author jmarranz
23 | */
24 | public class ItsNatGroovyServlet extends HttpServletWrapper
25 | {
26 | protected GroovyScriptEngine gse;
27 |
28 | public ItsNatGroovyServlet()
29 | {
30 | }
31 |
32 | public GroovyScriptEngine getGroovyScriptEngine()
33 | {
34 | return gse;
35 | }
36 |
37 | public String getScriptRootPath(ServletConfig config) throws ServletException
38 | {
39 | String scriptRootPath = config.getInitParameter("scriptRootPath");
40 | if (scriptRootPath == null) throw new ServletException("Missing servlet init param scriptRootPath");
41 | return getServletContext().getRealPath("/") + "/WEB-INF/" + scriptRootPath + "/";
42 | }
43 |
44 | public String getInitScript(ServletConfig config) throws ServletException
45 | {
46 | String initScript = config.getInitParameter("initScript");
47 | if (initScript == null) throw new ServletException("Missing servlet init param initScript");
48 | return initScript;
49 | }
50 |
51 | @Override
52 | public void init(ServletConfig config) throws ServletException
53 | {
54 | super.init(config);
55 |
56 | // Set up the scripting engine
57 |
58 | String pathPrefix = getScriptRootPath(config);
59 |
60 | try
61 | {
62 | this.gse = new GroovyScriptEngine(new String[]{pathPrefix});
63 | }
64 | catch(IOException ex) { throw new RuntimeException(ex); }
65 |
66 | //gse.getConfig().setMinimumRecompilationInterval(0);
67 |
68 | //System.out.println("MinimumRecompilationInterval " + gse.getConfig().getMinimumRecompilationInterval());
69 |
70 | getServletContext().log("Groovy servlet initialized on " + gse + ".");
71 |
72 | String initScript = getInitScript(config);
73 |
74 | File initFile = new File(pathPrefix + initScript);
75 | if (!initFile.exists())
76 | throw new ServletException(initFile.getAbsolutePath() + " does not exist");
77 |
78 | final Binding binding = new Binding();
79 | binding.setVariable("itsNatServlet", itsNatServlet);
80 | binding.setVariable("servlet", this);
81 | binding.setVariable("config", config);
82 | binding.setVariable("context", getServletContext());
83 | binding.setVariable("application", getServletContext());
84 |
85 | com.innowhere.relproxy.gproxy.GProxyGroovyScriptEngine.class.getName();
86 | com.innowhere.relproxy.gproxy.GProxyConfig.class.getName();
87 | com.innowhere.relproxy.gproxy.GProxy.class.getName();
88 |
89 | execGroovyScript(initScript,binding);
90 | }
91 |
92 | protected void execGroovyScript(final String filePath,final Binding binding)
93 | {
94 | Closure