PageRenderTime 46ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/jruby-1.7.3/src/org/jruby/embed/variable/Constant.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 246 lines | 118 code | 17 blank | 111 comment | 36 complexity | 4e82bc3d81ad6f79d5f8515edbae5935 MD5 | raw file
  1. /**
  2. * **** BEGIN LICENSE BLOCK *****
  3. * Version: EPL 1.0/GPL 2.0/LGPL 2.1
  4. *
  5. * The contents of this file are subject to the Common Public
  6. * License Version 1.0 (the "License"); you may not use this file
  7. * except in compliance with the License. You may obtain a copy of
  8. * the License at http://www.eclipse.org/legal/cpl-v10.html
  9. *
  10. * Software distributed under the License is distributed on an "AS
  11. * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  12. * implied. See the License for the specific language governing
  13. * rights and limitations under the License.
  14. *
  15. * Copyright (C) 2009-2012 Yoko Harada <yokolet@gmail.com>
  16. *
  17. * Alternatively, the contents of this file may be used under the terms of
  18. * either of the GNU General Public License Version 2 or later (the "GPL"),
  19. * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  20. * in which case the provisions of the GPL or the LGPL are applicable instead
  21. * of those above. If you wish to allow use of your version of this file only
  22. * under the terms of either the GPL or the LGPL, and not to allow others to
  23. * use your version of this file under the terms of the EPL, indicate your
  24. * decision by deleting the provisions above and replace them with the notice
  25. * and other provisions required by the GPL or the LGPL. If you do not delete
  26. * the provisions above, a recipient may use your version of this file under
  27. * the terms of any one of the EPL, the GPL or the LGPL.
  28. * **** END LICENSE BLOCK *****
  29. */
  30. package org.jruby.embed.variable;
  31. import java.util.Collection;
  32. import java.util.List;
  33. import java.util.Map;
  34. import org.jruby.RubyModule;
  35. import org.jruby.RubyObject;
  36. import org.jruby.embed.internal.BiVariableMap;
  37. import org.jruby.javasupport.JavaUtil;
  38. import org.jruby.runtime.builtin.IRubyObject;
  39. /**
  40. * An implementation of BiVariable for a Ruby constant.
  41. *
  42. * @author Yoko Harada <yokolet@gmail.com>
  43. */
  44. public class Constant extends AbstractVariable {
  45. private static String pattern = "[A-Z]([a-zA-Z]|_)([a-zA-Z]|_|\\d)*";
  46. private boolean initialized = false;
  47. /**
  48. * Returns an instance of this class. This factory method is used when a constant
  49. * is put in {@link BiVariableMap}.
  50. *
  51. * @param runtime
  52. * @param name a variable name
  53. * @param javaObject Java object that should be assigned to.
  54. * @return the instance of Constant
  55. */
  56. public static BiVariable getInstance(RubyObject receiver, String name, Object... javaObject) {
  57. if (name.matches(pattern)) {
  58. return new Constant(receiver, name, javaObject);
  59. }
  60. return null;
  61. }
  62. private Constant(RubyObject receiver, String name, Object... javaObjects) {
  63. super(receiver, name, false);
  64. updateByJavaObject(receiver.getRuntime(), javaObjects);
  65. }
  66. /**
  67. * A constructor used when constants are retrieved from Ruby.
  68. *
  69. * @param receiver a receiver object that this variable/constant is originally in. When
  70. * the variable/constant is originated from Ruby, receiver may not be null.
  71. * @param name the constant name
  72. * @param irubyObject Ruby constant object
  73. */
  74. Constant(IRubyObject receiver, String name, IRubyObject irubyObject) {
  75. super(receiver, name, true, irubyObject);
  76. }
  77. void markInitialized() {
  78. this.initialized = true;
  79. }
  80. /**
  81. * Retrieves constants from Ruby after the evaluation or method invocation.
  82. *
  83. * @param runtime Ruby runtime
  84. * @param receiver receiver object returned when a script is evaluated.
  85. * @param vars map to save retrieved constants.
  86. */
  87. public static void retrieve(RubyObject receiver, BiVariableMap vars) {
  88. if (vars.isLazy()) return;
  89. // user defined constants of top level go to a super class
  90. updateConstantsOfSuperClass(receiver, vars);
  91. // Constants might have the same names but different receivers.
  92. updateConstants(receiver, vars);
  93. RubyObject topSelf = (RubyObject)receiver.getRuntime().getTopSelf();
  94. updateConstants(topSelf, vars);
  95. }
  96. /*
  97. private static void updateARGV(IRubyObject receiver, BiVariableMap vars) {
  98. String name = "ARGV".intern();
  99. IRubyObject argv = receiver.getRuntime().getTopSelf().getMetaClass().fastGetConstant(name);
  100. if (argv == null || (argv instanceof RubyNil)) return;
  101. BiVariable var; // This var is for ARGV.
  102. // ARGV constant should be only one
  103. if (vars.containsKey((Object)name)) {
  104. var = vars.getVariable((RubyObject)receiver.getRuntime().getTopSelf(), name);
  105. var.setRubyObject(argv);
  106. } else {
  107. var = new Constant(receiver.getRuntime().getTopSelf(), name, argv);
  108. ((Constant) var).markInitialized();
  109. vars.update(name, var);
  110. }
  111. }*/
  112. private static void updateConstantsOfSuperClass(RubyObject receiver, BiVariableMap vars) {
  113. // Super class has many many constants, so this method updates only
  114. // constans in BiVariableMap.
  115. Map<String, RubyModule.ConstantEntry> map =
  116. receiver.getRuntime().getTopSelf().getMetaClass().getSuperClass().getConstantMap();
  117. List<BiVariable> variables = vars.getVariables();
  118. // Need to check that this constant has been stored in BiVariableMap.
  119. for (BiVariable variable : variables) {
  120. if (variable.getType() == Type.Constant) {
  121. if (map.containsKey(variable.getName())) {
  122. IRubyObject value = map.get(variable.getName()).value;
  123. variable.setRubyObject(value);
  124. }
  125. }
  126. }
  127. }
  128. private static void updateConstants(RubyObject receiver, BiVariableMap vars) {
  129. Collection<String> names = receiver.getMetaClass().getConstantNames();
  130. for (String name : names) {
  131. IRubyObject value = receiver.getMetaClass().getConstant(name);
  132. BiVariable var = null;
  133. List<String> savedNames = vars.getNames();
  134. // Need to check that this constant has been stored in BiVariableMap.
  135. for (int i=0; i<savedNames.size(); i++) {
  136. if (name.equals(savedNames.get(i))) {
  137. var = (BiVariable) vars.getVariables().get(i);
  138. if (receiver == var.getReceiver()) {
  139. var.setRubyObject(value);
  140. } else {
  141. var = null;
  142. }
  143. }
  144. }
  145. if (var == null) {
  146. var = new Constant(receiver, name, value);
  147. ((Constant) var).markInitialized();
  148. vars.update(name, var);
  149. }
  150. }
  151. }
  152. /**
  153. * Retrieves a constant by key from Ruby runtime after the evaluation.
  154. * This method is used when eager retrieval is off.
  155. *
  156. * @param receiver receiver object returned when a script is evaluated.
  157. * @param vars map to save retrieved instance variables.
  158. * @param key instace varible name
  159. */
  160. public static void retrieveByKey(RubyObject receiver, BiVariableMap vars, String key) {
  161. // if the specified key doesn't exist, this method is called before the
  162. // evaluation. Don't update value in this case.
  163. IRubyObject value = null;
  164. if (receiver.getMetaClass().getConstantNames().contains(key)) {
  165. value = receiver.getMetaClass().getConstant(key);
  166. } else if (receiver.getRuntime().getTopSelf().getMetaClass().getConstantNames().contains(key)) {
  167. value = receiver.getRuntime().getTopSelf().getMetaClass().getConstant(key);
  168. } else if (receiver.getRuntime().getTopSelf().getMetaClass().getSuperClass().getConstantNames().contains(key)) {
  169. value = receiver.getRuntime().getTopSelf().getMetaClass().getSuperClass().getConstant(key);
  170. }
  171. if (value == null) return;
  172. // the specified key is found, so let's update
  173. BiVariable var = vars.getVariable(receiver, key);
  174. if (var != null) {
  175. var.setRubyObject(value);
  176. } else {
  177. var = new Constant(receiver, key, value);
  178. vars.update(key, var);
  179. }
  180. }
  181. /**
  182. * Returns enum type of this variable defined in {@link BiVariable}.
  183. *
  184. * @return this enum type, BiVariable.Type.Constant.
  185. */
  186. public Type getType() {
  187. return Type.Constant;
  188. }
  189. /**
  190. * Returns true if the given name is a decent Ruby constant. Unless
  191. * returns false.
  192. *
  193. * @param name is a name to be checked.
  194. * @return true if the given name is of a Ruby constant.
  195. */
  196. public static boolean isValidName(Object name) {
  197. return isValidName(pattern, name);
  198. }
  199. /**
  200. * Injects a constant value to a parsed Ruby script. This method is
  201. * invoked during EvalUnit#run() is executed.
  202. */
  203. public void inject() {
  204. if (receiver == receiver.getRuntime().getTopSelf()) {
  205. RubyModule rubyModule = getRubyClass(receiver.getRuntime());
  206. if (rubyModule == null) rubyModule = receiver.getRuntime().getCurrentContext().getRubyClass();
  207. if (rubyModule == null) return;
  208. rubyModule.storeConstant(name, irubyObject);
  209. } else {
  210. receiver.getMetaClass().storeConstant(name, irubyObject);
  211. }
  212. receiver.getRuntime().getConstantInvalidator().invalidate();
  213. initialized = true;
  214. }
  215. /**
  216. * Attempts to remove this constant from top self or receiver.
  217. *
  218. */
  219. public void remove() {
  220. IRubyObject rubyName = JavaUtil.convertJavaToRuby(receiver.getRuntime(), name);
  221. if (receiver.getMetaClass().getConstantNames().contains(name)) {
  222. receiver.getMetaClass().remove_const(receiver.getRuntime().getCurrentContext(), rubyName);
  223. } else if (receiver.getRuntime().getTopSelf().getMetaClass().getConstantNames().contains(name)) {
  224. receiver.getRuntime().getTopSelf().getMetaClass().remove_const(receiver.getRuntime().getCurrentContext(), rubyName);
  225. } else if (receiver.getRuntime().getTopSelf().getMetaClass().getSuperClass().getConstantNames().contains(name)) {
  226. receiver.getRuntime().getTopSelf().getMetaClass().getSuperClass().remove_const(receiver.getRuntime().getCurrentContext(), rubyName);
  227. }
  228. }
  229. }